42_SYSMON.pm 185 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301
  1. ################################################################
  2. #
  3. # Copyright notice
  4. #
  5. # (c) 2013 Alexander Schulz
  6. #
  7. # This script is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # The GNU General Public License can be found at
  13. # http://www.gnu.org/copyleft/gpl.html.
  14. # A copy is found in the textfile GPL.txt and important notices to the license
  15. # from the author is found in LICENSE.txt distributed with these scripts.
  16. #
  17. # This script is distributed in the hope that it will be useful,
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. # GNU General Public License for more details.
  21. #
  22. # This copyright notice MUST APPEAR in all copies of the script!
  23. #
  24. ################################################################
  25. # $Id: 42_SYSMON.pm 12951 2017-01-04 09:39:43Z hexenmeister $
  26. package main;
  27. use strict;
  28. use warnings;
  29. use Scalar::Util qw(looks_like_number);
  30. use Blocking;
  31. use Data::Dumper;
  32. my $missingModulRemote;
  33. eval "use Net::Telnet;1" or $missingModulRemote .= "Net::Telnet ";
  34. my $VERSION = "2.2.8";
  35. use constant {
  36. PERL_VERSION => "perl_version",
  37. DATE => "date",
  38. UPTIME => "uptime",
  39. UPTIME_TEXT => "uptime_text",
  40. STARTTIME_TEXT => "starttime_text",
  41. STARTTIME => "starttime",
  42. FHEMSTARTTIME_TEXT => "fhemstarttime_text",
  43. FHEMSTARTTIME => "fhemstarttime",
  44. FHEMUPTIME => "fhemuptime",
  45. FHEMUPTIME_TEXT => "fhemuptime_text",
  46. IDLETIME => "idletime",
  47. IDLETIME_TEXT => "idletime_text"
  48. };
  49. use constant {
  50. CPU_CORE_CNT => "cpu_core_count",
  51. CPU_FREQ => "cpu_freq",
  52. CPU0_FREQ => "cpu0_freq",
  53. CPU1_FREQ => "cpu1_freq",
  54. CPU2_FREQ => "cpu2_freq",
  55. CPU3_FREQ => "cpu3_freq",
  56. CPU4_FREQ => "cpu4_freq",
  57. CPU5_FREQ => "cpu5_freq",
  58. CPU6_FREQ => "cpu6_freq",
  59. CPU7_FREQ => "cpu7_freq",
  60. CPU_BOGOMIPS => "cpu_bogomips",
  61. CPU_MODEL_NAME=>"cpu_model_name",
  62. CPU_TEMP => "cpu_temp",
  63. CPU0_TEMP => "cpu0_temp",
  64. CPU1_TEMP => "cpu1_temp",
  65. CPU2_TEMP => "cpu2_temp",
  66. CPU3_TEMP => "cpu3_temp",
  67. CPU4_TEMP => "cpu4_temp",
  68. CPU5_TEMP => "cpu5_temp",
  69. CPU6_TEMP => "cpu6_temp",
  70. CPU7_TEMP => "cpu7_temp",
  71. CPU_TEMP_AVG => "cpu_temp_avg",
  72. CPU0_TEMP_AVG => "cpu0_temp_avg",
  73. CPU1_TEMP_AVG => "cpu1_temp_avg",
  74. CPU2_TEMP_AVG => "cpu2_temp_avg",
  75. CPU3_TEMP_AVG => "cpu3_temp_avg",
  76. CPU4_TEMP_AVG => "cpu4_temp_avg",
  77. CPU5_TEMP_AVG => "cpu5_temp_avg",
  78. CPU6_TEMP_AVG => "cpu6_temp_avg",
  79. CPU7_TEMP_AVG => "cpu7_temp_avg",
  80. LOADAVG => "loadavg"
  81. };
  82. use constant {
  83. RAM => "ram",
  84. SWAP => "swap"
  85. };
  86. use constant {
  87. ETH0 => "eth0",
  88. WLAN0 => "wlan0",
  89. DIFF_SUFFIX => "_diff",
  90. SPEED_SUFFIX => "_speed",
  91. IP_SUFFIX => "_ip",
  92. IP6_SUFFIX => "_ip6",
  93. FB_WLAN_STATE => "wlan_state",
  94. FB_WLAN_GUEST_STATE => "wlan_guest_state",
  95. FB_INET_IP => "internet_ip",
  96. FB_INET_STATE => "internet_state",
  97. FB_N_TIME_CTRL => "night_time_ctrl",
  98. FB_NUM_NEW_MESSAGES => "num_new_messages",
  99. FB_FW_VERSION => "fw_version_info",
  100. FB_DECT_TEMP => "dect_temp",
  101. FB_DSL_RATE => "dsl_rate",
  102. FB_DSL_SYNCTIME => "dsl_synctime",
  103. FB_DSL_FEC_15 => "dsl_fec_15",
  104. FB_DSL_CRC_15 => "dsl_crc_15",
  105. };
  106. use constant FS_PREFIX => "~ ";
  107. #use constant FS_PREFIX_N => "fs_";
  108. my $DEFAULT_INTERVAL_BASE = 60;
  109. sub
  110. SYSMON_Initialize($)
  111. {
  112. my ($hash) = @_;
  113. SYSMON_Log($hash, 5, "");
  114. $hash->{DefFn} = "SYSMON_Define";
  115. $hash->{UndefFn} = "SYSMON_Undefine";
  116. $hash->{GetFn} = "SYSMON_Get";
  117. $hash->{SetFn} = "SYSMON_Set";
  118. $hash->{AttrFn} = "SYSMON_Attr";
  119. $hash->{AttrList} = "filesystems network-interfaces user-defined disable:0,1 nonblocking:0,1 ".
  120. "telnet-time-out ".
  121. "user-fn2 user-fn ".
  122. "telnet-prompt-regx telnet-login-prompt-regx ".
  123. "exclude ".
  124. $readingFnAttributes;
  125. }
  126. ### attr NAME user-defined osUpdates:1440:Aktualisierungen:cat ./updates.txt [,<readingsName>:<Interval_Minutes>:<Comment>:<Cmd>]
  127. sub
  128. SYSMON_Define($$)
  129. {
  130. my ($hash, $def) = @_;
  131. SYSMON_Log($hash, 5, "$def");
  132. my @a = split("[ \t][ \t]*", $def);
  133. return "Usage: define <name> SYSMON [MODE[:[USER@]HOST][:PORT]] [M1 [M2 [M3 [M4]]]]" if(@a < 2);
  134. # define sysmon SYSMON local
  135. # define sysmon SYSMON local 1 1 1 10
  136. # define sysmon SYSMON telnet:fritz.box
  137. # define sysmon SYSMON telnet:fritz.box:23
  138. # define sysmon SYSMON telnet:fritz.box:23 10 10 10 60
  139. # define sysmon SYSMON telnet:user@fritz.box:23
  140. if(int(@a)>=3)
  141. {
  142. my @na = @a[2..scalar(@a)-1];
  143. # wenn das erste Element nicht numerisch
  144. if(!($na[0] =~ /^\d+$/)) {
  145. # set mode/host/port
  146. my($mode, $host, $port) = split(/:/, $na[0]);
  147. $mode=lc($mode);
  148. # TODO SSH
  149. if(defined($mode)&&($mode eq 'local' || $mode eq 'telnet')) {
  150. $hash->{MODE} = $mode;
  151. delete($hash->{HOST});
  152. delete($hash->{USER});
  153. # erkennen, wenn User angegeben ist
  154. if($host) {
  155. my($user,$th) = split(/@/,$host);
  156. if(defined($th)) {
  157. $hash->{USER} = lc($user);
  158. $host = $th;
  159. }
  160. $hash->{HOST} = lc($host) if(defined($host));
  161. # DefaultPort je nach Protokol
  162. if(!defined($port)) {
  163. $port = '23' if($mode eq 'telnet');
  164. $port = '22' if($mode eq 'ssh');
  165. }
  166. $hash->{PORT} = lc($port);
  167. }
  168. } else {
  169. return "unexpected mode. use local or telnet only."; # TODO: SSH
  170. }
  171. shift @na;
  172. } else {
  173. $hash->{MODE}='local';
  174. }
  175. SYSMON_setInterval($hash, @na);
  176. } else {
  177. $hash->{MODE}='local';
  178. SYSMON_setInterval($hash, undef);
  179. }
  180. $hash->{STATE} = "Initialized";
  181. #$hash->{DEF_TIME} = time() unless defined($hash->{DEF_TIME});
  182. #SYSMON_updateCurrentReadingsMap($hash);
  183. RemoveInternalTimer($hash);
  184. InternalTimer(gettimeofday()+$hash->{INTERVAL_BASE}, "SYSMON_Update", $hash, 0);
  185. #$hash->{LOCAL} = 1;
  186. #SYSMON_Update($hash); #-> so nicht. hat im Startvorgang gelegentlich (oft) den Server 'aufgehaengt'
  187. #delete $hash->{LOCAL};
  188. return undef;
  189. }
  190. sub
  191. SYSMON_setInterval($@)
  192. {
  193. my ($hash, @a) = @_;
  194. my $interval = $DEFAULT_INTERVAL_BASE;
  195. $hash->{INTERVAL_BASE} = $interval;
  196. my $p1=1;
  197. my $p2=1;
  198. my $p3=1;
  199. my $p4=10;
  200. if(defined($a[0]) && int($a[0]) eq $a[0]) {$p1 = $a[0];}
  201. if(defined($a[1]) && int($a[1]) eq $a[1]) {$p2 = $a[1];} else {$p2 = $p1;}
  202. if(defined($a[2]) && int($a[2]) eq $a[2]) {$p3 = $a[2];} else {$p3 = $p1;}
  203. if(defined($a[3]) && int($a[3]) eq $a[3]) {$p4 = $a[3];} else {$p4 = $p1*10;}
  204. $hash->{INTERVAL_MULTIPLIERS} = $p1." ".$p2." ".$p3." ".$p4;
  205. }
  206. #my $cur_readings_map; => $hash->{helper}{cur_readings_map}
  207. sub
  208. SYSMON_updateCurrentReadingsMap($) {
  209. my ($hash) = @_;
  210. my $name = $hash->{NAME};
  211. if( AttrVal($name, "disable", "") eq "1" ) {
  212. return undef;
  213. }
  214. my $rMap;
  215. # Map aktueller Namen erstellen
  216. # Feste Werte
  217. my $mode = $hash->{MODE};#AttrVal( $name, 'mode', 'local');
  218. if($mode eq 'local'){
  219. $rMap->{+PERL_VERSION} = "Perl Version";
  220. }
  221. $rMap->{+DATE} = "Date";
  222. $rMap->{+CPU_BOGOMIPS} = "BogoMIPS";
  223. $rMap->{+CPU_MODEL_NAME} = "CPU model name";
  224. if(SYSMON_isCPUFreqRPiBBB($hash)) {
  225. $rMap->{"cpu_freq"} = "CPU frequency";
  226. $rMap->{"cpu0_freq"} = "CPU frequency";
  227. $rMap->{"cpu_freq_stat"} = "CPU frequency stat";
  228. $rMap->{"cpu0_freq_stat"} = "CPU frequency stat";
  229. }
  230. foreach my $li (0..7) {
  231. if(SYSMON_isCPUXFreq($hash, $li)) {
  232. $rMap->{"cpu".$li."_freq"} = "CPU frequency (core $li)";
  233. $rMap->{"cpu".$li."_freq_stat"} = "CPU frequency (core $li) stat";
  234. }
  235. }
  236. if(SYSMON_isCPUTempRPi($hash) || SYSMON_isCPUTempBBB($hash) || SYSMON_isCPUTempFB($hash)) {
  237. #$rMap->{+CPU_TEMP} = "CPU Temperatur";
  238. #$rMap->{"cpu_temp_avg"} = "Durchschnittliche CPU Temperatur";
  239. $rMap->{+CPU_TEMP} = "CPU temperature";
  240. $rMap->{+CPU_TEMP.'_stat'}= "CPU temperature stat";
  241. #$rMap->{"cpu0_temp"} = "CPU temperature (core 0)";
  242. $rMap->{"cpu_temp_avg"} = "Average CPU temperature";
  243. #$rMap->{"cpu0_temp_avg"} = "Average CPU temperature (core 0)";
  244. }
  245. foreach my $li (0..7) {
  246. if(SYSMON_isCPUTemp_X($hash, $li)) {
  247. $rMap->{"cpu".$li."_temp"} = "CPU temperature (core $li)";
  248. $rMap->{"cpu".$li."_temp_avg"} = "Average CPU temperature (core $li)";
  249. $rMap->{"cpu".$li."_temp_stat"} = "CPU temperature stat (core $li)";
  250. }
  251. }
  252. $rMap->{+CPU_CORE_CNT} = "Number of CPU cores";
  253. if(SYSMON_isSysPowerAc($hash)) {
  254. #$rMap->{"power_ac_online"} = "AC-Versorgung Status";
  255. #$rMap->{"power_ac_present"} = "AC-Versorgung vorhanden";
  256. #$rMap->{"power_ac_current"} = "AC-Versorgung Strom";
  257. #$rMap->{"power_ac_voltage"} = "AC-Versorgung Spannung";
  258. $rMap->{"power_ac_stat"} = "AC-Versorgung Info";
  259. $rMap->{"power_ac_text"} = "AC-Versorgung Info";
  260. }
  261. if(SYSMON_isSysPowerUsb($hash)) {
  262. #$rMap->{"power_usb_online"} = "USB-Versorgung Status";
  263. #$rMap->{"power_usb_present"} = "USB-Versorgung vorhanden";
  264. #$rMap->{"power_usb_current"} = "USB-Versorgung Strom";
  265. #$rMap->{"power_usb_voltage"} = "USB-Versorgung Spannung";
  266. $rMap->{"power_usb_stat"} = "USB-Versorgung Info";
  267. $rMap->{"power_usb_text"} = "USB-Versorgung Info";
  268. }
  269. if(SYSMON_isSysPowerBat($hash)) {
  270. #$rMap->{"power_battery_online"} = "Batterie-Versorgung Status";
  271. #$rMap->{"power_battery_present"} = "Batterie-Versorgung vorhanden";
  272. #$rMap->{"power_battery_current"} = "Batterie-Versorgung Strom";
  273. #$rMap->{"power_battery_voltage"} = "Batterie-Versorgung Spannung";
  274. $rMap->{"power_battery_stat"} = "Batterie-Versorgung Info";
  275. $rMap->{"power_battery_text"} = "Batterie-Versorgung Info";
  276. $rMap->{"power_battery_info"} = "Batterie-Versorgung Zusatzinfo";
  277. }
  278. #$rMap->{"fhemuptime"} = "Betriebszeit FHEM";
  279. #$rMap->{"fhemuptime_text"} = "Betriebszeit FHEM";
  280. #$rMap->{"idletime"} = "Leerlaufzeit";
  281. #$rMap->{"idletime_text"} = "Leerlaufzeit";
  282. #$rMap->{"loadavg"} = "Durchschnittliche Auslastung";
  283. #$rMap->{"ram"} = "RAM";
  284. #$rMap->{"swap"} = "Swap";
  285. #$rMap->{"uptime"} = "Betriebszeit";
  286. #$rMap->{"uptime_text"} = "Betriebszeit";
  287. $rMap->{"fhemuptime"} = "System up time";
  288. $rMap->{"fhemuptime_text"} = "FHEM up time";
  289. $rMap->{"idletime"} = "Idle time";
  290. $rMap->{"idletime_text"} = "Idle time";
  291. $rMap->{"loadavg"} = "Load average";
  292. $rMap->{"loadavg_1"} = "Load average 1";
  293. $rMap->{"loadavg_5"} = "Load average 5";
  294. $rMap->{"loadavg_15"} = "Load average 15";
  295. $rMap->{"ram"} = "RAM";
  296. $rMap->{"ram_used_stat"} = "RAM used stat";
  297. $rMap->{"ram_total"} = "RAM total";
  298. $rMap->{"ram_used"} = "RAM used";
  299. $rMap->{"ram_free"} = "RAM free";
  300. $rMap->{"ram_free_percent"}= "RAM free %";
  301. $rMap->{"swap"} = "swap";
  302. $rMap->{"swap_used_stat"} = "swap used stat";
  303. $rMap->{"swap_total"} = "swap total";
  304. $rMap->{"swap_used"} = "swap used";
  305. $rMap->{"swap_free"} = "swap free";
  306. $rMap->{"swap_used_percent"}= "swap used %";
  307. $rMap->{"uptime"} = "System up time";
  308. $rMap->{"uptime_text"} = "System up time";
  309. $rMap->{+STARTTIME_TEXT} = "System start time";
  310. $rMap->{+STARTTIME} = "System start time";
  311. $rMap->{+FHEMSTARTTIME} = "Fhem start time";
  312. $rMap->{+FHEMSTARTTIME_TEXT} = "Fhem start time";
  313. # Werte fuer GesamtCPU
  314. $rMap->{"stat_cpu"} = "CPU statistics";
  315. $rMap->{"stat_cpu_diff"} = "CPU statistics (diff)";
  316. $rMap->{"stat_cpu_percent"} = "CPU statistics (diff, percent)";
  317. $rMap->{"stat_cpu_text"} = "CPU statistics (text)";
  318. $rMap->{"cpu_idle_stat"} = "CPU min/max/avg (idle)";
  319. $rMap->{"stat_cpu_user_percent"} = "CPU statistics user %";
  320. $rMap->{"stat_cpu_nice_percent"} = "CPU statistics nice %";
  321. $rMap->{"stat_cpu_sys_percent"} = "CPU statistics sys %";
  322. $rMap->{"stat_cpu_idle_percent"} = "CPU statistics idle %";
  323. $rMap->{"stat_cpu_io_percent"} = "CPU statistics io %";
  324. $rMap->{"stat_cpu_irq_percent"} = "CPU statistics irq %";
  325. $rMap->{"stat_cpu_sirq_percent"} = "CPU statistics sirq %";
  326. # CPU 0-7 (sollte reichen)
  327. for my $i (0..7) {
  328. $rMap->{"stat_cpu".$i} = "CPU".$i." statistics";
  329. $rMap->{"stat_cpu".$i."_diff"} = "CPU".$i." statistics (diff)";
  330. $rMap->{"stat_cpu".$i."_percent"} = "CPU".$i." statistics (diff, percent)";
  331. $rMap->{"stat_cpu".$i."_text"} = "CPU".$i." statistics (text)";
  332. $rMap->{"cpu".$i."_idle_stat"} = "CPU".$i." min/max/avg (idle)";
  333. }
  334. # Filesystems <readingName>[:<mountPoint>[:<Comment>]]
  335. my $filesystems = AttrVal($name, "filesystems", undef);
  336. if(defined $filesystems) {
  337. my @filesystem_list = split(/,\s*/, trim($filesystems));
  338. foreach (@filesystem_list) {
  339. my($fName, $fDef, $nComment) = split(/:/, $_);
  340. my $fPt;
  341. if(defined $nComment) {
  342. $fPt = $nComment;
  343. } else {
  344. if(defined $fDef) {
  345. # Benannte
  346. $fPt = "Filesystem ".$fDef;
  347. } else {
  348. # Unbenannte
  349. $fPt = "Mount point ".$fName;
  350. }
  351. }
  352. $rMap->{$fName} = $fPt;
  353. $rMap->{$fName."_used"} = $fPt." (used)";
  354. $rMap->{$fName."_used_percent"} = $fPt." (used %)";
  355. $rMap->{$fName."_free"} = $fPt." (free)";
  356. }
  357. } else {
  358. $rMap->{"root"} = "Filesystem /";
  359. }
  360. # Networkadapters: <readingName>[:<interfaceName>[:<Comment>]]
  361. my $networkadapters = AttrVal($name, "network-interfaces", undef);
  362. if(defined $networkadapters) {
  363. my @networkadapters_list = split(/,\s*/, trim($networkadapters));
  364. foreach (@networkadapters_list) {
  365. my($nName, $nDef, $nComment) = split(/:/, $_);
  366. my $nPt;
  367. if(defined $nComment) {
  368. $nPt = $nComment;
  369. } else {
  370. if(defined $nDef) {
  371. # Benannte
  372. $nPt = "Network ".$nDef;
  373. } else {
  374. # Unbenannte
  375. $nPt = "Network adapter ".$nName;
  376. }
  377. }
  378. $rMap->{$nName} = $nPt;
  379. $rMap->{$nName."_diff"} = $nPt." (diff)";
  380. $rMap->{$nName."_speed"} = $nPt." (speed)";
  381. $rMap->{$nName."_rx"} = $nPt." (RX)";
  382. $rMap->{$nName."_tx"} = $nPt." (TX)";
  383. $rMap->{$nName."_ip"} = $nPt." (IP)";
  384. $rMap->{$nName."_ip6"} = $nPt." (IP6)";
  385. }
  386. } else {
  387. # Default Networkadapters
  388. # Wenn nichts definiert, werden Default-Werte verwendet
  389. if(SYSMON_isFB($hash)) {
  390. my $nName = "ath0";
  391. $rMap->{$nName} = "Network adapter ".$nName;
  392. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  393. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  394. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  395. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  396. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  397. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  398. $nName = "ath1";
  399. $rMap->{$nName} = "Network adapter ".$nName;
  400. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  401. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  402. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  403. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  404. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  405. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  406. $nName = "cpmac0";
  407. $rMap->{$nName} = "Network adapter ".$nName;
  408. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  409. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  410. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  411. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  412. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  413. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  414. $nName = "dsl";
  415. $rMap->{$nName} = "Network adapter ".$nName;
  416. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  417. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  418. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  419. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  420. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  421. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  422. $nName = ETH0;
  423. $rMap->{$nName} = "Network adapter ".$nName;
  424. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  425. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  426. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  427. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  428. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  429. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  430. $nName = "guest";
  431. $rMap->{$nName} = "Network adapter ".$nName;
  432. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  433. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  434. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  435. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  436. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  437. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  438. $nName = "hotspot";
  439. $rMap->{$nName} = "Network adapter ".$nName;
  440. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  441. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  442. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  443. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  444. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  445. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  446. $nName = "lan";
  447. $rMap->{$nName} = "Network adapter ".$nName;
  448. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  449. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  450. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  451. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  452. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  453. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  454. $nName = "vdsl";
  455. $rMap->{$nName} = "Network adapter ".$nName;
  456. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  457. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  458. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  459. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  460. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  461. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  462. } else {
  463. my $nName = ETH0;
  464. $rMap->{$nName} = "Network adapter ".$nName;
  465. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  466. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  467. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  468. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  469. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  470. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  471. $nName = WLAN0;
  472. $rMap->{$nName} = "Network adapter ".$nName;
  473. $rMap->{$nName."_diff"} = "Network adapter ".$nName." (diff)";
  474. $rMap->{$nName."_speed"} = "Network adapter ".$nName." (speed)";
  475. $rMap->{$nName."_rx"} = "Network adapter ".$nName." (RX)";
  476. $rMap->{$nName."_tx"} = "Network adapter ".$nName." (TX)";
  477. $rMap->{$nName."_ip"} = "Network adapter ".$nName." (IP)";
  478. $rMap->{$nName."_ip6"} = "Network adapter ".$nName." (IP6)";
  479. }
  480. }
  481. if(SYSMON_isFB($hash)) {
  482. # FB WLAN state
  483. $rMap->{+FB_WLAN_STATE} = "WLAN State";
  484. $rMap->{+FB_WLAN_GUEST_STATE} = "WLAN Guest State";
  485. $rMap->{+FB_INET_IP} = "Internet IP";
  486. $rMap->{+FB_INET_STATE} = "Internet connection state";
  487. $rMap->{+FB_N_TIME_CTRL} = "night time control";
  488. $rMap->{+FB_NUM_NEW_MESSAGES} = "new messages";
  489. $rMap->{+FB_FW_VERSION} = "firmware info";
  490. $rMap->{+FB_DECT_TEMP} = "DECT temperatur";
  491. $rMap->{+FB_DSL_RATE} = "DSL rate",
  492. $rMap->{+FB_DSL_SYNCTIME} = "DSL synctime";
  493. $rMap->{+FB_DSL_FEC_15} = "DSL recoverable errors per 15 minutes"; # forward error correction
  494. $rMap->{+FB_DSL_CRC_15} = "DSL unrecoverable errors per 15 minutes"; # cyclic redundancy check
  495. }
  496. # User defined
  497. my $userdefined = AttrVal($name, "user-defined", undef);
  498. if(defined $userdefined) {
  499. my @userdefined_list = split(/,\s*/, trim($userdefined));
  500. foreach (@userdefined_list) {
  501. # <readingName>:<Interval_Minutes>:<Comment>:<Cmd>
  502. my($uName, $uInterval, $uComment, $uCmd) = split(/:/, $_);
  503. if(defined $uComment) {
  504. # Nur gueltige
  505. $rMap->{$uName} = $uComment;
  506. }
  507. }
  508. }
  509. # User defined functions
  510. my $userfn = AttrVal($name, "user-fn", undef);
  511. if(defined $userfn) {
  512. my @userfn_list = split(/,\s*/, trim($userfn));
  513. foreach (@userfn_list) {
  514. # <fnName>:<Interval_Minutes>:<reading1>:<reading2>...
  515. my($fnName, $uInterval, @readings) = split(/:/, $_);
  516. foreach my $rName (@readings) {
  517. $rMap->{$rName} = "user defined: $fnName";
  518. }
  519. }
  520. }
  521. # TEST: TODO
  522. $rMap->{"io_sda_raw"} = "TEST";
  523. $rMap->{"io_sda_diff"} = "TEST";
  524. $rMap->{"io_sda"} = "TEST";
  525. $hash->{helper}{cur_readings_map} = $rMap;
  526. return $rMap;
  527. }
  528. sub
  529. SYSMON_getObsoleteReadingsMap($) {
  530. my ($hash) = @_;
  531. my $name = $hash->{NAME};
  532. my $rMap;
  533. #return $rMap; # TODO TEST
  534. if(!defined($hash->{helper}{cur_readings_map})) {
  535. SYSMON_updateCurrentReadingsMap($hash);
  536. }
  537. # alle READINGS durchgehen
  538. my @cKeys=keys (%{$defs{$name}{READINGS}});
  539. foreach my $aName (@cKeys) {
  540. if(defined ($aName)) {
  541. # alles hinzufuegen, was nicht in der Aktuellen Liste ist
  542. if(!defined($hash->{helper}{cur_readings_map}->{$aName})) {
  543. #Log 3, "SYSMON>>>>>>>>>>>>>>>>> SYSMON_getObsoleteReadingsMap >>> $aName";
  544. $rMap->{$aName} = 1;
  545. }
  546. }
  547. }
  548. return $rMap;
  549. }
  550. sub
  551. SYSMON_Undefine($$)
  552. {
  553. my ($hash, $arg) = @_;
  554. SYSMON_Log($hash, 5, "$arg");
  555. RemoveInternalTimer($hash);
  556. BlockingKill( $hash->{helper}{READOUT_RUNNING_PID} )
  557. if exists $hash->{helper}{READOUT_RUNNING_PID};
  558. return undef;
  559. }
  560. sub
  561. SYSMON_Get($@)
  562. {
  563. my ($hash, @a) = @_;
  564. my $name = $a[0];
  565. if(@a < 2)
  566. {
  567. SYSMON_Log($hash, 3, "@a: get needs at least one parameter");
  568. return "$name: get needs at least one parameter";
  569. }
  570. my $cmd= $a[1];
  571. SYSMON_Log($hash, 5, "@a");
  572. if($cmd eq "update")
  573. {
  574. #$hash->{LOCAL} = 1;
  575. SYSMON_Update($hash, 1);
  576. #delete $hash->{LOCAL};
  577. return undef;
  578. }
  579. if($cmd eq "list") {
  580. my $map = SYSMON_obtainParameters($hash, 1);
  581. my $ret = "";
  582. foreach my $name (keys %{$map}) {
  583. my $value = $map->{$name};
  584. $ret = "$ret\n".sprintf("%-20s %s", $name, $value);
  585. }
  586. my $msg = $hash->{helper}{error_msg};
  587. if($msg) {
  588. # Problem mit der Verbindung
  589. return $msg;
  590. }
  591. return $ret;
  592. }
  593. if($cmd eq "version")
  594. {
  595. return $VERSION;
  596. }
  597. if($cmd eq "interval_base")
  598. {
  599. return $hash->{INTERVAL_BASE};
  600. }
  601. if($cmd eq "interval_multipliers")
  602. {
  603. return $hash->{INTERVAL_MULTIPLIERS};
  604. }
  605. if($cmd eq "list_lan_devices")
  606. {
  607. my $ret='';
  608. my $map = SYSMON_getFBLanDeviceList($hash);
  609. if(defined($map)) {
  610. foreach my $dname (sort keys %{$map}) {
  611. my $dev_ip = $map->{$dname}{ip};
  612. $dev_ip='' unless defined $dev_ip;
  613. my $dev_mac = $map->{$dname}{mac};
  614. my $dev_active = $map->{$dname}{active};
  615. my $dev_active_txt = $dev_active?'true':'false';
  616. #$ret.="\n"."$dname : active: $dev_active_txt, IP: $dev_ip, MAC: $dev_mac";
  617. $ret = "$ret\n".sprintf("%-25s : active: %-5s IP: %-16s MAC: %-17s", $dname, $dev_active_txt, $dev_ip, $dev_mac);
  618. }
  619. }
  620. return $ret;
  621. }
  622. my $sfb='';
  623. if(SYSMON_isFB($hash)) {
  624. $sfb=' list_lan_devices:noArg';
  625. }
  626. return "Unknown argument $cmd, choose one of list:noArg update:noArg interval_base:noArg interval_multipliers:noArg version:noArg".$sfb;
  627. }
  628. sub
  629. SYSMON_Set($@)
  630. {
  631. my ($hash, @a) = @_;
  632. my $name = $a[0];
  633. if(@a < 2)
  634. {
  635. SYSMON_Log($hash, 3, "@a: set needs at least one parameter");
  636. return "$name: set needs at least one parameter";
  637. }
  638. my $cmd= $a[1];
  639. SYSMON_Log($hash, 5, "@a");
  640. if($cmd eq "interval_multipliers")
  641. {
  642. if(@a < 3) {
  643. SYSMON_Log($hash, 3, "$name: not enought parameters");
  644. return "$name: not enought parameters";
  645. }
  646. my @na = @a[2..scalar(@a)-1];
  647. SYSMON_setInterval($hash, @na);
  648. return $cmd ." set to ".($hash->{INTERVAL_MULTIPLIERS});
  649. }
  650. if($cmd eq "clean") {
  651. # Nicht mehr benoetigte Readings loeschen
  652. my $omap = SYSMON_getObsoleteReadingsMap($hash);
  653. foreach my $aName (keys %{$omap}) {
  654. delete $defs{$name}{READINGS}{$aName};
  655. }
  656. return;
  657. }
  658. if($cmd eq "clear")
  659. {
  660. my $subcmd = my $cmd= $a[2];
  661. if(defined $subcmd) {
  662. delete $defs{$name}{READINGS}{$subcmd};
  663. return;
  664. }
  665. return "missing parameter. use clear <reading name>";
  666. }
  667. if ( lc $cmd eq 'password') {
  668. my $subcmd = $a[2];
  669. if(defined $subcmd) {
  670. my $ret = SYSMON_storePassword ($hash, $subcmd);
  671. if(!defined($hash->{helper}{error_msg})) {
  672. SYSMON_Update($hash, 1);
  673. }
  674. return $ret;
  675. }
  676. }
  677. # TEST
  678. if($cmd eq "reset")
  679. {
  680. delete $defs{$name}->{helper};
  681. return 'ok';
  682. }
  683. return "Unknown argument $cmd, choose one of password interval_multipliers clean:noArg clear";
  684. }
  685. sub
  686. SYSMON_Attr($$$)
  687. {
  688. my ($cmd, $name, $attrName, $attrVal) = @_;
  689. my $hash = $main::defs{$name};
  690. SYSMON_Log($hash, 5, "SYSMON Attr: $cmd $name ".$attrName?$attrName:''." $attrVal");
  691. $attrVal= "" unless defined($attrVal);
  692. my $orig = AttrVal($name, $attrName, "");
  693. if( $orig ne $attrVal ) {
  694. if( $cmd eq "set" ) {# set, del
  695. if($attrName eq "exclude") {
  696. my @elist = split(/,\s*/, trim($attrVal));
  697. my %ehash = map { $_ => 1 } @elist;
  698. $hash->{helper}->{excludes}=\%ehash;
  699. }
  700. if($attrName eq "disable")
  701. {
  702. RemoveInternalTimer($hash);
  703. if($attrVal ne "1")
  704. {
  705. InternalTimer(gettimeofday()+$hash->{INTERVAL_BASE}, "SYSMON_Update", $hash, 0);
  706. $hash->{STATE} = "Active";
  707. } else {
  708. $hash->{STATE} = "Inactive";
  709. }
  710. #$hash->{LOCAL} = 1;
  711. #SYSMON_Update($hash);
  712. #delete $hash->{LOCAL};
  713. }
  714. $attr{$name}{$attrName} = $attrVal;
  715. SYSMON_updateCurrentReadingsMap($hash);
  716. #return $attrName ." set to ". $attrVal;
  717. return undef;
  718. } elsif( $cmd eq "del" ) {
  719. if($attrName eq "exclude") {
  720. $hash->{helper}->{excludes}=undef;
  721. }
  722. }
  723. }
  724. return;
  725. }
  726. #my $u_first_mark = undef;
  727. sub
  728. SYSMON_Update($;$)
  729. {
  730. my ($hash, $refresh_all) = @_;
  731. $refresh_all="0" unless defined $refresh_all;
  732. #SYSMON_Log($hash, 5, "refresh_all: ".$refresh_all);
  733. my $name = $hash->{NAME};
  734. if(!$hash->{LOCAL}) {
  735. RemoveInternalTimer($hash);
  736. InternalTimer(gettimeofday()+$hash->{INTERVAL_BASE}, "SYSMON_Update", $hash, 1);
  737. }
  738. if( AttrVal($name, "disable", "") eq "1" )
  739. {
  740. #SYSMON_Log($hash, 5, "disabled");
  741. #$hash->{STATE} = "Inactive";
  742. } else {
  743. # Beim ersten mal alles aktualisieren!
  744. if(!$hash->{helper}{u_first_mark}) {
  745. $refresh_all = 1;
  746. }
  747. SYSMON_obtainLocalCPUFreq($hash);
  748. my $map;
  749. if(!AttrVal($name, "nonblocking", 1)) {
  750. # direkt call
  751. # Parameter holen
  752. $map = SYSMON_obtainParameters($hash, $refresh_all);
  753. # Mark setzen
  754. if(!$hash->{helper}{u_first_mark}) {
  755. $hash->{helper}{u_first_mark} = 1;
  756. }
  757. SYSMON_updateReadings($hash,$map);
  758. #$hash->{STATE} = "Active";
  759. } else {
  760. # blocking call
  761. if ( exists( $hash->{helper}{READOUT_RUNNING_PID} ) ) {
  762. SYSMON_Log($hash, 5, "blockingCall: Old readout process still running. Killing old process ".$hash->{helper}{READOUT_RUNNING_PID});
  763. BlockingKill( $hash->{helper}{READOUT_RUNNING_PID} );
  764. delete($hash->{helper}{READOUT_RUNNING_PID});
  765. }
  766. $hash->{helper}{READOUT_RUNNING_PID} = BlockingCall("SYSMON_blockingCall", $name."|".$refresh_all, "SYSMON_blockingFinish", 55, "SYSMON_blockingAbort", $hash);
  767. }
  768. }
  769. }
  770. sub SYSMON_obtainLocalCPUFreq($) {
  771. my ($hash) = @_;
  772. my $map;
  773. #--------------------------------------------------------------------------
  774. my $base=$DEFAULT_INTERVAL_BASE;
  775. my $im = "1 1 1 10";
  776. # Wenn wesentliche Parameter nicht definiert sind, soll aktualisierung immer vorgenommen werden
  777. if((defined $hash->{INTERVAL_BASE})) {
  778. $base = $hash->{INTERVAL_BASE};
  779. }
  780. if((defined $hash->{INTERVAL_MULTIPLIERS})) {
  781. $im = $hash->{INTERVAL_MULTIPLIERS};
  782. }
  783. my $ref = int(time()/$base);
  784. my ($m1, $m2, $m3, $m4) = split(/\s+/, $im);
  785. if($m1 gt 0) { # Nur wenn > 0
  786. # M1: cpu_freq, cpu_temp, cpu_temp_avg, loadavg, procstat, iostat
  787. if(($ref % $m1) eq 0) {
  788. # Sonderlocke: CPUFreq
  789. my $mode = $hash->{MODE};
  790. if ($mode eq 'local') {
  791. foreach my $li (0..7) {
  792. if(SYSMON_isCPUXFreq($hash, $li)) {
  793. $map = SYSMON_getCPUFreqLocal($hash, $map, $li);
  794. }
  795. }
  796. }
  797. }
  798. }
  799. #--------------------------------------------------------------------------
  800. SYSMON_updateReadings($hash,$map);
  801. }
  802. sub SYSMON_blockingCall($) {
  803. my ($tparam) = @_;
  804. my ($name, $refresh_all) = split(/\|/,$tparam);
  805. my $hash = $main::defs{$name};
  806. SYSMON_Log($hash, 5, "$name, ".($refresh_all?$refresh_all:''));
  807. my $map = SYSMON_obtainParameters($hash, $refresh_all);
  808. # Device-Name mitnehmen
  809. my $ret = "name|".$name;
  810. my $msg = $hash->{helper}{error_msg};
  811. if($msg) {
  812. # Problem mit der Verbindung
  813. return $ret."|error|".$msg;
  814. }
  815. # to String
  816. foreach my $aName (keys %{$map}) {
  817. my $value = $map->{$aName};
  818. # Nur wenn ein gueltiges Value vorliegt
  819. if(defined $value) {
  820. # Zeichen maskieren
  821. $value=~s/#/§²§/g;
  822. $value=~s/\|/§³§/g;
  823. $ret.="|".$aName."|".$value;
  824. }
  825. }
  826. return $ret;
  827. }
  828. sub SYSMON_test() {
  829. #foreach my $d (sort keys %defs) {
  830. # my $h = $defs{$d};
  831. # if(defined ($h->{TYPE})) {} else {return $d."-".Dumper($h);}
  832. #}
  833. my $map;
  834. my $name="TESTNAME";
  835. $map->{test1}="val1";
  836. $map->{test2}="val2";
  837. $map->{test3}="val3";
  838. #return Dumper($map);
  839. my $ret = "name|".$name;
  840. # to ret String
  841. foreach my $aName (keys %{$map}) {
  842. my $value = $map->{$aName};
  843. # Nur wenn ein gueltiges Value vorliegt
  844. if(defined $value) {
  845. $value=~s/#/§²§/g;
  846. $ret.="|".$aName."|".$value;
  847. }
  848. }
  849. my @ta = split(/\|/,$ret);
  850. #return Dumper(@ta);
  851. my %map2 = @ta;
  852. return Dumper(\%map2);
  853. return $ret;
  854. }
  855. sub SYSMON_blockingAbort($) {
  856. my ($hash) = @_;
  857. delete($hash->{helper}{READOUT_RUNNING_PID});
  858. SYSMON_Log($hash, 5, "");
  859. $hash->{STATE} = "Error: Blocking call aborted (timeout)";
  860. }
  861. sub SYSMON_blockingFinish($) {
  862. my ($map_str) = @_;
  863. my $map;
  864. # to map
  865. my @ta = split(/\|/,$map_str);
  866. my %tm = @ta;
  867. $map = \%tm;
  868. my $name=$map->{name};
  869. delete $map->{name};
  870. my $hash = $main::defs{$name};
  871. delete($hash->{helper}{READOUT_RUNNING_PID});
  872. SYSMON_Log($hash, 5, $map_str);
  873. # Mark setzen
  874. if(!$hash->{helper}{u_first_mark}) {
  875. $hash->{helper}{u_first_mark} = 1;
  876. }
  877. my $msg = $map->{error};
  878. if($msg) {
  879. # Im Fehlerfall State ebtsprechend setzen und nichts aktualisieren.
  880. $hash->{STATE} = "Error: ".$msg;
  881. return;
  882. }
  883. SYSMON_updateReadings($hash,$map);
  884. #$hash->{STATE} = "Active";
  885. }
  886. sub SYSMON_updateReadings($$) {
  887. my ($hash,$map) = @_;
  888. SYSMON_Log($hash, 5, "");
  889. my $name = $hash->{NAME};
  890. readingsBeginUpdate($hash);
  891. # Wenn UserFn benutzt wird, werden die erstellten Eintraege erfasst und die entsprechenden Readings nicht erhalten
  892. my $h_keys;
  893. my $uFnReadings = $map->{"xuser_fnr"};
  894. my @a_keys;
  895. if(defined($uFnReadings)) {
  896. delete $map->{"xuser_fnr"};
  897. @a_keys = split(/,\s*/, trim($uFnReadings));
  898. #$h_keys = map { $_ => "1" } @a_keys;
  899. }
  900. foreach my $aName (keys %{$map}) {
  901. my $value = $map->{$aName};
  902. # Nur aktualisieren, wenn ein gueltiges Value vorliegt
  903. if(defined $value) {
  904. # Maskierte Zeichen zuruechersetzen
  905. $value=~s/§²§/#/g;
  906. $value=~s/§³§/\|/g;
  907. readingsBulkUpdate($hash,$aName,$value);
  908. }
  909. }
  910. # Nicht mehr benoetigte Readings loeschen
  911. my $omap = SYSMON_getObsoleteReadingsMap($hash);
  912. # UserFn Keys entfernen
  913. foreach my $aName (@a_keys) {
  914. delete($omap->{$aName});
  915. }
  916. foreach my $aName (keys %{$omap}) {
  917. # SYSMON_Log($hash, 5, ">>>>>>>>>>>>>>>>>>>> ".$aName."->".Dumper($defs{$name}{READINGS}{$aName}));
  918. delete $defs{$name}{READINGS}{$aName};
  919. }
  920. readingsEndUpdate($hash,defined($hash->{LOCAL}) ? 0 : 1);
  921. }
  922. sub SYSMON_obtainParameters($$) {
  923. my ($hash, $refresh_all) = @_;
  924. my $name = $hash->{NAME};
  925. # ---
  926. #TODO: SSH
  927. my $msg = undef;
  928. my $openedTelnet = 0;
  929. my $telnet = $hash->{".telnet"};
  930. #$telnet = undef;
  931. my $mode = $hash->{MODE};
  932. # Wenn remote: open connection
  933. if ($mode eq 'telnet') {
  934. unless (defined $telnet) {
  935. SYSMON_Log($hash, 5, "$name: Open shared telnet connection");
  936. $msg = SYSMON_Open_Connection($hash);
  937. $hash->{helper}{error_msg}=$msg;
  938. if (!$msg) {
  939. $openedTelnet = 1;
  940. $hash->{helper}{error_msg}=undef;
  941. }
  942. }
  943. }
  944. # ---
  945. my $map;
  946. if (!$msg) {
  947. $map = SYSMON_obtainParameters_intern($hash, $refresh_all);
  948. }
  949. # ---
  950. # Wenn remote: close connection
  951. if ($mode eq 'telnet') {
  952. if($openedTelnet) {
  953. SYSMON_Log($hash, 5, "$name: Close shared telnet connection");
  954. SYSMON_Close_Connection( $hash );
  955. }
  956. }
  957. # ---
  958. return $map;
  959. }
  960. # Schattenmap mit den zuletzt gesammelten Werten (merged)
  961. #my %shadow_map;
  962. sub
  963. SYSMON_obtainParameters_intern($$)
  964. {
  965. my ($hash, $refresh_all) = @_;
  966. my $name = $hash->{NAME};
  967. my $map;
  968. my $base=$DEFAULT_INTERVAL_BASE;
  969. my $im = "1 1 1 10";
  970. # Wenn wesentliche Parameter nicht definiert sind, soll aktualisierung immer vorgenommen werden
  971. if((defined $hash->{INTERVAL_BASE})) {
  972. $base = $hash->{INTERVAL_BASE};
  973. }
  974. if((defined $hash->{INTERVAL_MULTIPLIERS})) {
  975. $im = $hash->{INTERVAL_MULTIPLIERS};
  976. }
  977. my $ref = int(time()/$base);
  978. my ($m1, $m2, $m3, $m4) = split(/\s+/, $im);
  979. my $mode = $hash->{MODE};#AttrVal( $name, 'mode', 'local');
  980. # Einmaliges
  981. if(!$hash->{helper}{u_first_mark}) {
  982. # nur lokal abfragen (macht remote keinen Sinn)
  983. if ($mode eq 'local') {
  984. # Perl version
  985. $map->{+PERL_VERSION} = "$^V";
  986. }
  987. if(SYSMON_isProcFS($hash)) {
  988. $map = SYSMON_getCPUInfo($hash, $map);
  989. }
  990. if(SYSMON_isFB($hash)) {
  991. $map = SYSMON_FBVersionInfo($hash, $map);
  992. }
  993. }
  994. # immer aktualisieren: uptime, uptime_text, fhemuptime, fhemuptime_text, idletime, idletime_text
  995. if(SYSMON_isProcFS($hash)) {
  996. $map = SYSMON_getUptime($hash, $map);
  997. } else {
  998. $map = SYSMON_getUptime2($hash, $map);
  999. }
  1000. # nur lokal abfragen
  1001. if ($mode eq 'local') {
  1002. $map = SYSMON_getFHEMUptime($hash, $map);
  1003. }
  1004. if($m1 gt 0) { # Nur wenn > 0
  1005. # M1: cpu_freq, cpu_temp, cpu_temp_avg, loadavg, procstat, iostat
  1006. if($refresh_all || ($ref % $m1) eq 0) {
  1007. $map = SYSMON_getCPUCoreNum($hash, $map);
  1008. #Log 3, "SYSMON -----------> DEBUG: read CPU-Temp";
  1009. if(SYSMON_isCPUTempRPi($hash)) { # Rasp
  1010. $map = SYSMON_getCPUTemp_RPi($hash, $map);
  1011. }
  1012. if (SYSMON_isCPUTempBBB($hash)) {
  1013. $map = SYSMON_getCPUTemp_BBB($hash, $map);
  1014. }
  1015. foreach my $li (0..7) {
  1016. if(SYSMON_isCPUTemp_X($hash, $li)) {
  1017. $map = SYSMON_getCPUTemp_X($hash, $map, $li);
  1018. }
  1019. }
  1020. if (SYSMON_isCPUTempFB($hash)) {
  1021. $map = SYSMON_getCPUTemp_FB($hash, $map);
  1022. }
  1023. #if(SYSMON_isCPUFreqRPiBBB($hash)) {
  1024. # $map = SYSMON_getCPUFreq($hash, $map, 0);
  1025. #}
  1026. foreach my $li (0..7) {
  1027. if(SYSMON_isCPUXFreq($hash, $li)) {
  1028. $map = SYSMON_getCPUFreq($hash, $map, $li);
  1029. }
  1030. }
  1031. if(SYSMON_isProcFS($hash)) {
  1032. $map = SYSMON_getLoadAvg($hash, $map);
  1033. $map = SYSMON_getCPUProcStat($hash, $map);
  1034. } else {
  1035. #TODO: Ohne ProcFS
  1036. }
  1037. #$map = SYSMON_getDiskStat($hash, $map);
  1038. # Power info (cubietruck)
  1039. if(SYSMON_isSysPowerAc($hash)) {
  1040. $map = SYSMON_PowerAcInfo($hash, $map);
  1041. }
  1042. if(SYSMON_isSysPowerUsb($hash)) {
  1043. $map = SYSMON_PowerUsbInfo($hash, $map);
  1044. }
  1045. if(SYSMON_isSysPowerBat($hash)) {
  1046. $map = SYSMON_PowerBatInfo($hash, $map);
  1047. }
  1048. }
  1049. }
  1050. if($m2 gt 0) { # Nur wenn > 0
  1051. # M2: ram, swap
  1052. if($refresh_all || ($ref % $m2) eq 0) {
  1053. if(SYSMON_isOSX()){
  1054. $map = SYSMON_getRamAndSwapOSX($hash, $map);
  1055. } else {
  1056. $map = SYSMON_getRamAndSwap($hash, $map);
  1057. }
  1058. }
  1059. }
  1060. if($m3 gt 0) { # Nur wenn > 0
  1061. # M3: eth0, eth0_diff, wlan0, wlan0_diff, wlan_on (FritzBox)
  1062. my $update_ns = ($refresh_all || ($ref % $m3) eq 0);
  1063. #if($refresh_all || ($ref % $m3) eq 0) {
  1064. my $networks = AttrVal($name, "network-interfaces", undef);
  1065. if($update_ns) {
  1066. if(defined $networks) {
  1067. my @networks_list = split(/,\s*/, trim($networks));
  1068. foreach (@networks_list) {
  1069. $map = SYSMON_getNetworkInfo($hash, $map, $_);
  1070. }
  1071. } else {
  1072. # Wenn nichts definiert, werden Default-Werte verwendet
  1073. #Log 3, "SYSMON>>>>>>>>>>>>>>>>>>>>>>>>> NETWORK";
  1074. if(SYSMON_isFB($hash)) {
  1075. $map = SYSMON_getNetworkInfo($hash, $map, "ath0");
  1076. $map = SYSMON_getNetworkInfo($hash, $map, "ath1");
  1077. $map = SYSMON_getNetworkInfo($hash, $map, "cpmac0");
  1078. $map = SYSMON_getNetworkInfo($hash, $map, "dsl");
  1079. $map = SYSMON_getNetworkInfo($hash, $map, "eth0");
  1080. $map = SYSMON_getNetworkInfo($hash, $map, "guest");
  1081. $map = SYSMON_getNetworkInfo($hash, $map, "hotspot");
  1082. $map = SYSMON_getNetworkInfo($hash, $map, "lan");
  1083. $map = SYSMON_getNetworkInfo($hash, $map, "vdsl");
  1084. } else {
  1085. #Log 3, "SYSMON>>>>>>>>>>>>>>>>>>>>>>>>> ".ETH0;
  1086. $map = SYSMON_getNetworkInfo($hash, $map, ETH0);
  1087. #Log 3, "SYSMON>>>>>>>>>>>>>>>>>>>>>>>>> ".$map->{+ETH0};
  1088. #Log 3, "SYSMON>>>>>>>>>>>>>>>>>>>>>>>>> ".WLAN0;
  1089. $map = SYSMON_getNetworkInfo($hash, $map, WLAN0);
  1090. #Log 3, "SYSMON>>>>>>>>>>>>>>>>>>>>>>>>> ".$map->{+WLAN0};
  1091. }
  1092. }
  1093. if(SYSMON_isFB($hash)) {
  1094. $map = SYSMON_getFBWLANState($hash, $map);
  1095. $map = SYSMON_getFBWLANGuestState($hash, $map);
  1096. $map = SYSMON_getFBInetIP($hash, $map);
  1097. $map = SYSMON_getFBInetConnectionState($hash, $map);
  1098. $map = SYSMON_getFBNightTimeControl($hash, $map);
  1099. $map = SYSMON_getFBNumNewMessages($hash, $map);
  1100. $map = SYSMON_getFBDECTTemp($hash, $map);
  1101. #DSL-Downstream und DSL-Upstream abfragen
  1102. $map = SYSMON_getFBStreamRate($hash, $map);
  1103. #Sync-Zeit mit Vermittlungsstelle abfragen
  1104. $map = SYSMON_getFBSyncTime($hash, $map);
  1105. #Uebertragungsfehler abfragen (nicht behebbar und behebbar)
  1106. $map = SYSMON_getFBCRCFEC($hash, $map);
  1107. }
  1108. }
  1109. }
  1110. if($m4 gt 0) { # Nur wenn > 0
  1111. # M4: Filesystem-Informationen
  1112. my $update_fs = ($refresh_all || ($ref % $m4) eq 0);
  1113. my $filesystems = AttrVal($name, "filesystems", undef);
  1114. if($update_fs) {
  1115. if(defined $filesystems)
  1116. {
  1117. my @filesystem_list = split(/,\s*/, trim($filesystems));
  1118. foreach (@filesystem_list)
  1119. {
  1120. $map = SYSMON_getFileSystemInfo($hash, $map, $_);
  1121. }
  1122. } else {
  1123. $map = SYSMON_getFileSystemInfo($hash, $map, "root:/");
  1124. }
  1125. } else {
  1126. # Workaround: Damit die Readings zw. den Update-Punkten nicht geloescht werden, werden die Schluessel leer angelegt
  1127. # Wenn noch keine Update notwendig, dan einfach alte Schluessel (mit undef als Wert) angeben,
  1128. # damit werden die Readings in der Update-Methode nicht geloescht.
  1129. # Die ggf. notwendige Loeschung findet nur bei tatsaechlichen Update statt.
  1130. my @cKeys=keys (%{$defs{$name}{READINGS}});
  1131. foreach my $aName (@cKeys) {
  1132. #if(defined ($aName) && (index($aName, FS_PREFIX) == 0 || index($aName, FS_PREFIX_N) == 0)) {
  1133. if(defined ($aName) && (index($aName, FS_PREFIX) == 0 )) {
  1134. $map->{$aName} = undef;
  1135. }
  1136. }
  1137. }
  1138. }
  1139. #Log 3, "SYSMON >>> USER_DEFINED >>>>>>>>>>>>>>> START";
  1140. my $userdefined = AttrVal($name, "user-defined", undef);
  1141. if(defined $userdefined) {
  1142. my @userdefined_list = split(/,\s*/, trim($userdefined));
  1143. foreach (@userdefined_list) {
  1144. # <readingName>:<Interval_Minutes>:<Comment>:<Cmd>
  1145. my $ud = $_;
  1146. my($uName, $uInterval, $uComment, $uCmd) = split(/:/, $ud);
  1147. SYSMON_Log($hash, 5, "User-Defined Reading: [$uName][$uInterval][$uComment][$uCmd]");
  1148. if(defined $uCmd) { # Also, wenn alle Parameter vorhanden
  1149. my $iInt = int($uInterval);
  1150. if($iInt>0) {
  1151. my $update_ud = ($refresh_all || ($ref % $iInt) eq 0);
  1152. if($update_ud) {
  1153. $map = SYSMON_getUserDefined($hash, $map, $uName, $uCmd);
  1154. } else {
  1155. SYSMON_Log($hash, 5, "User-Defined Reading: [$uName][$uInterval][$uComment][$uCmd] out of refresh interval");
  1156. }
  1157. }
  1158. }
  1159. }
  1160. }
  1161. #Log 3, "SYSMON >>> USER_DEFINED FUNCTIONS >>>>>>>>>>>>>>> START";
  1162. my $userfn = AttrVal($name, "user-fn", undef);
  1163. if(defined $userfn) {
  1164. my @userfn_list = split(/,\s+/, trim($userfn));
  1165. foreach my $ud (@userfn_list) {
  1166. # <fnName>:<Interval_Minutes>:<reading1>:<reading2>..., [<fn-name>:...]
  1167. my($fnName, $uInterval, @readings) = split(/:/, $ud);
  1168. SYSMON_Log($hash, 5, "User-Defined Fn: [$fnName][$uInterval]");
  1169. if(defined $uInterval) {
  1170. my $iInt = int($uInterval);
  1171. if($iInt>0) {
  1172. my $update_ud = ($refresh_all || ($ref % $iInt) eq 0);
  1173. if($update_ud) {
  1174. $map = SYSMON_getUserDefinedFn($hash, $map, $fnName, @readings);
  1175. } else {
  1176. SYSMON_Log($hash, 5, "User-Defined Fn: [$fnName][$uInterval] out of refresh interval");
  1177. }
  1178. }
  1179. }
  1180. }
  1181. }
  1182. # User Functions2
  1183. my $uMap;
  1184. $userfn = AttrVal($name, "user-fn2", undef);
  1185. #TEST$userfn=undef;
  1186. if(defined $userfn) {
  1187. my @userfn_list = split(/,\s*/, trim($userfn));
  1188. foreach (@userfn_list) {
  1189. my $ufn = $_;
  1190. SYSMON_Log($hash, 5, "User-Function Reading: [$ufn]");
  1191. if(defined $ufn) {
  1192. no strict "refs";
  1193. $uMap = &{$ufn}($hash, $uMap);
  1194. use strict "refs";
  1195. }
  1196. }
  1197. }
  1198. # Werte umverpacken, KeyNamen sichern
  1199. my $uNames='';
  1200. if(defined($uMap)) {
  1201. foreach my $uName (keys %{$uMap}) {
  1202. $uNames.=','.$uName;
  1203. $map->{$uName}=$uMap->{$uName};
  1204. }
  1205. # Erste Komma entfernen
  1206. $uNames=substr($uNames,1);
  1207. $map->{"xuser_fnr"}=$uNames;
  1208. }
  1209. #TEST
  1210. #my $rt = "#";
  1211. #$rt=~s/#/[]/g;
  1212. #$map->{SYS_TEST}=$rt;
  1213. # Aktuelle Werte in ShattenHash mergen
  1214. my %hashT = %{$map};
  1215. #@shadow_map{ keys %hashT } = values %hashT;
  1216. my %shadow_map;
  1217. @shadow_map{ keys %hashT } = values %hashT;
  1218. $hash->{helper}{shadow_map} = \%shadow_map;
  1219. return $map;
  1220. }
  1221. # For test purpose only
  1222. sub SYSMON_TestUserFn($$) {
  1223. my ($hash, $map) = @_;
  1224. $map->{"my_test_reading"}="my test";
  1225. #$map->{"my"}="my";
  1226. return $map;
  1227. }
  1228. #------------------------------------------------------------------------------
  1229. # Liefert gesammelte Werte ( = Readings)
  1230. # Parameter: array der gewuenschten keys (Readings names)
  1231. # Beispiele:
  1232. # {(SYSMON_getValues("sysmon"))->{'cpu_temp'}}
  1233. # {(SYSMON_getValues("sysmon",("cpu_freq","cpu_temp")))->{"cpu_temp"}}
  1234. # {join(" ", values (SYSMON_getValues("sysmon")))}
  1235. # {join(" ", values (SYSMON_getValues("sysmon",("cpu_freq","cpu_temp"))))}
  1236. #------------------------------------------------------------------------------
  1237. sub
  1238. SYSMON_getValues($;@)
  1239. {
  1240. my ($name,@filter_keys) = @_;
  1241. my $hash = $main::defs{$name};
  1242. my %shadow_map = %{$hash->{helper}{shadow_map}};
  1243. if(scalar(@filter_keys)>0) {
  1244. my %clean_hash;
  1245. #@clean_hash{ @filter_keys } = @shadow_map{ @filter_keys };
  1246. @clean_hash{ @filter_keys } = @shadow_map{ @filter_keys };
  1247. return \%clean_hash;
  1248. }
  1249. # alles liefern
  1250. return \%shadow_map;
  1251. }
  1252. sub SYSMON_getComputeStat($$$$) {
  1253. my ($hash, $map, $val, $name) = @_;
  1254. my $t = ReadingsVal($hash->{NAME},$name,"$val $val $val");
  1255. my($min, $max, $avg) = split(/ /,$t);
  1256. $min = $val if $min>$val;
  1257. $max = $val if $max<$val;
  1258. $avg = (3*$avg + $val)/4;
  1259. $t = sprintf( "%.2f %.2f %.2f", $min, $max, $avg );
  1260. $map->{$name} = $t;
  1261. #SYSMON_Log($hash, 3, ">>>>>>>>>>>>>>>>> ".$name." => $t");
  1262. return $map;
  1263. }
  1264. #------------------------------------------------------------------------------
  1265. # Liest Benutzerdefinierte Eintraege
  1266. #------------------------------------------------------------------------------
  1267. sub
  1268. SYSMON_getUserDefined($$$$)
  1269. {
  1270. my ($hash, $map, $uName, $uCmd) = @_;
  1271. SYSMON_Log($hash, 5, "Name=[$uName] Cmd=[$uCmd]");
  1272. if($hash->{helper}->{excludes}{'user-defined'}) {return $map;}
  1273. my @out_arr = SYSMON_execute($hash, $uCmd);
  1274. my $out_str = "";
  1275. foreach my $k (@out_arr) {
  1276. if(defined($k)) {
  1277. chomp($k);
  1278. $out_str.=$k." ";
  1279. }
  1280. }
  1281. #my $out_str = join(" ",@out_arr);
  1282. ##my $out_str = SYSMON_execute($hash, $uCmd);
  1283. ##chomp $out_str;
  1284. #$out_str=~s/\n/ /g;
  1285. #$out_str=~s/\r/ /g;
  1286. $map->{$uName} = $out_str;
  1287. SYSMON_Log($hash, 5, "User-Defined Result: $uName='$out_str'");
  1288. return $map;
  1289. }
  1290. sub SYSMON_getUserDefinedFn($$$@) {
  1291. my($hash, $map, $fnName, @readings) = @_;
  1292. #SYSMON_Log($hash, 3, ">>>>>>>>>>>>>>>>>>>>> exclude: ".Dumper($hash->{helper}->{excludes}));
  1293. if($hash->{helper}->{excludes}{'user-defined'}) {return $map;}
  1294. SYSMON_Log($hash, 5, "call User-Function: [$fnName]");
  1295. if(defined $fnName) {
  1296. no strict "refs";
  1297. my @rarr;
  1298. if($fnName=~/^{/) {
  1299. my $HASH = $hash;
  1300. my $NAME = $hash->{NAME};
  1301. @rarr = eval($fnName);
  1302. } else {
  1303. @rarr = &{$fnName}($hash);
  1304. }
  1305. use strict "refs";
  1306. SYSMON_Log($hash, 5, "result User-Function [$fnName]: ".Dumper(@rarr));
  1307. my $cnt1 = scalar(@readings);
  1308. my $cnt2 = scalar(@rarr);
  1309. my $cnt = min($cnt1,$cnt2);
  1310. if($cnt1!=$cnt2) { # zu wenig readings geliefert ($cnt1>$cnt2) oder zu viel
  1311. SYSMON_Log($hash, 3, "User-Function [$fnName]: expected readings: [$cnt1], provided [$cnt2]");
  1312. }
  1313. #SYSMON_Log($hash, 5, ">>>> User-Function [$fnName]: $cnt1 / $cnt2: $rarr[0]");
  1314. for (my $i=0;$i<$cnt;$i++) {
  1315. if(defined($rarr[$i])) {
  1316. my $val = trim($rarr[$i]);
  1317. #SYSMON_Log($hash, 5, ">>>> User-Function [$fnName]: put: '".$readings[$i]."' => '".$val."'");
  1318. $map->{$readings[$i]} = $val;
  1319. #$map->{$readings[$i]}="Dead OWTHERM devices: none";
  1320. #SYSMON_Log($hash, 5, ">>>> User-Function [$fnName]: ok");
  1321. }
  1322. }
  1323. }
  1324. return $map;
  1325. }
  1326. #my $sys_cpu_core_num = undef;
  1327. sub
  1328. SYSMON_getCPUCoreNum_intern($) {
  1329. my ($hash) = @_;
  1330. return $hash->{helper}{sys_cpu_core_num} if $hash->{helper}{sys_cpu_core_num};
  1331. # TODO: Umstellung auf
  1332. # cat /sys/devices/system/cpu/present
  1333. # cat /sys/devices/system/cpu/online
  1334. # nur wenn verfuegbar
  1335. if(SYSMON_isSysCpuNum($hash)) {
  1336. my $str = SYSMON_execute($hash, "cat /sys/devices/system/cpu/kernel_max");
  1337. if(defined($str)) {
  1338. if($str ne "") {
  1339. if(int($str)!=0) {
  1340. $hash->{helper}{sys_cpu_core_num} = int($str)+1;
  1341. return $hash->{helper}{sys_cpu_core_num};
  1342. }
  1343. }
  1344. }
  1345. }
  1346. # Default / unbekannt
  1347. $hash->{helper}{sys_cpu_core_num} = 1;
  1348. return $hash->{helper}{sys_cpu_core_num};
  1349. }
  1350. #------------------------------------------------------------------------------
  1351. # leifert Anzahl CPU Kerne
  1352. #------------------------------------------------------------------------------
  1353. sub SYSMON_getCPUCoreNum($$) {
  1354. my ($hash, $map) = @_;
  1355. if($hash->{helper}->{excludes}{'cpucount'}) {return $map;}
  1356. my $cpuCoreCnt = SYSMON_getCPUCoreNum_intern($hash);
  1357. $map->{+CPU_CORE_CNT}=$cpuCoreCnt;
  1358. return $map;
  1359. }
  1360. #------------------------------------------------------------------------------
  1361. # leifert Zeit seit dem Systemstart
  1362. #------------------------------------------------------------------------------
  1363. sub
  1364. SYSMON_getUptime($$)
  1365. {
  1366. my ($hash, $map) = @_;
  1367. if($hash->{helper}->{excludes}{'uptime'}) {return $map;}
  1368. #my $uptime_str = qx(cat /proc/uptime );
  1369. my $uptime_str = SYSMON_execute($hash, "cat /proc/uptime");
  1370. if(defined($uptime_str)) {
  1371. my ($uptime, $idle) = split(/\s+/, trim($uptime_str));
  1372. if(defined($uptime) && int($uptime)!=0) {
  1373. # Anzahl Cores beruecksichtigen
  1374. my $core_num = SYSMON_getCPUCoreNum_intern($hash);
  1375. my $idle_percent = $idle/($uptime*$core_num)*100;
  1376. $idle = $idle/$core_num;
  1377. $map->{+UPTIME}=sprintf("%d",$uptime);
  1378. #$map->{+UPTIME_TEXT} = sprintf("%d days, %02d hours, %02d minutes, %02d seconds",SYSMON_decode_time_diff($uptime));
  1379. $map->{+UPTIME_TEXT} = sprintf("%d days, %02d hours, %02d minutes",SYSMON_decode_time_diff($uptime));
  1380. my $startTime = time()-$uptime;
  1381. $map->{+STARTTIME} = sprintf("%d",$startTime);
  1382. $map->{+STARTTIME_TEXT} = strftime("%d.%m.%Y %H:%M:%S", localtime($startTime));
  1383. $map->{+IDLETIME}=sprintf("%d %.2f %%",$idle, $idle_percent);
  1384. $map->{+IDLETIME_TEXT} = sprintf("%d days, %02d hours, %02d minutes",SYSMON_decode_time_diff($idle)).sprintf(" (%.2f %%)",$idle_percent);
  1385. #$map->{+IDLETIME_PERCENT} = sprintf ("%.2f %",$idle_percent);
  1386. }
  1387. }
  1388. return $map;
  1389. }
  1390. #------------------------------------------------------------------------------
  1391. # leifert Zeit seit dem Systemstart.
  1392. # Alternative Version fuer Systemen ohne procfs (z.B. MACOS)
  1393. #------------------------------------------------------------------------------
  1394. sub
  1395. SYSMON_getUptime2($$)
  1396. {
  1397. my ($hash, $map) = @_;
  1398. if($hash->{helper}->{excludes}{'uptime'}) {return $map;}
  1399. #TODO
  1400. my $uptime = SYSMON_execute($hash,"uptime");
  1401. if(defined($uptime)){
  1402. #SYSMON_Log($hash, 5, ">>>>>>>>>>>>>>>>>>>>>>".$uptime."<");
  1403. #$uptime = $1 if( $uptime && $uptime =~ m/[[:alpha:]]{2}\s+(((\d+)\D+,?\s+)?(\d+):(\d+))/ );
  1404. $uptime = $1 if( $uptime && $uptime =~ m/[[:alpha:]]{2}\s+(((\d+)\D+,?\s+)?(\d+):(\d+)).*load.*: (.*)/ );
  1405. $uptime = "0 days, $uptime" if( $uptime && !$2);
  1406. my $days = $3?$3:0;
  1407. my $hours = $4;
  1408. my $minutes = $5;
  1409. if(defined($days) && defined($hours) && defined($minutes)) {
  1410. $uptime = $days * 24;
  1411. $uptime += $hours;
  1412. $uptime *= 60;
  1413. $uptime += $minutes;
  1414. $uptime *= 60;
  1415. } else {
  1416. $uptime = 0;
  1417. }
  1418. $map->{+UPTIME}=sprintf("%d",$uptime);
  1419. $map->{+UPTIME_TEXT} = sprintf("%d days, %02d hours, %02d minutes",SYSMON_decode_time_diff($uptime));
  1420. my $startTime = time()-$uptime;
  1421. $map->{+STARTTIME} = sprintf("%d",$startTime);
  1422. $map->{+STARTTIME_TEXT} = strftime("%d.%m.%Y %H:%M:%S", localtime($startTime));
  1423. my $loadavg=$6;
  1424. if(defined($loadavg)) {
  1425. my ($la1, $la5, $la15, $prc, $lastpid) = split(/\s+/, trim($loadavg));
  1426. if(defined($la1) && defined($la5) && defined($la15)) {
  1427. $la1 =~ s/,$//;
  1428. $la5 =~ s/,$//;
  1429. $la1 =~ s/,/./;
  1430. $la5 =~ s/,/./;
  1431. $la15 =~ s/,/./;
  1432. $map->{+LOADAVG}="$la1 $la5 $la15";
  1433. }
  1434. }
  1435. }
  1436. return $map;
  1437. }
  1438. #------------------------------------------------------------------------------
  1439. # leifert Zeit seit FHEM-Start
  1440. #------------------------------------------------------------------------------
  1441. sub
  1442. SYSMON_getFHEMUptime($$)
  1443. {
  1444. my ($hash, $map) = @_;
  1445. if($hash->{helper}->{excludes}{'fhemuptime'}) {return $map;}
  1446. #if(defined ($hash->{DEF_TIME})) {
  1447. if(defined($fhem_started)) {
  1448. #my $fhemuptime = time()-$hash->{DEF_TIME};
  1449. my $fhemuptime = time()-$fhem_started;
  1450. $map->{+FHEMUPTIME} = sprintf("%d",$fhemuptime);
  1451. $map->{+FHEMUPTIME_TEXT} = sprintf("%d days, %02d hours, %02d minutes",SYSMON_decode_time_diff($fhemuptime));
  1452. my $startTime = time()-$fhemuptime;
  1453. $map->{+FHEMSTARTTIME} = sprintf("%d",$startTime);
  1454. $map->{+FHEMSTARTTIME_TEXT} = strftime("%d.%m.%Y %H:%M:%S", localtime($startTime));
  1455. }
  1456. return $map;
  1457. }
  1458. #------------------------------------------------------------------------------
  1459. # leifert CPU-Auslastung
  1460. #------------------------------------------------------------------------------
  1461. sub
  1462. SYSMON_getLoadAvg($$)
  1463. {
  1464. my ($hash, $map) = @_;
  1465. if($hash->{helper}->{excludes}{'loadavg'}) {return $map;}
  1466. my $la_str = SYSMON_execute($hash, "cat /proc/loadavg");
  1467. if(defined($la_str)) {
  1468. my ($la1, $la5, $la15, $prc, $lastpid) = split(/\s+/, trim($la_str));
  1469. if(defined($la1) && defined($la5) && defined($la15)) {
  1470. $map->{+LOADAVG}="$la1 $la5 $la15";
  1471. #$map->{"load"}="$la1";
  1472. #$map->{"load5"}="$la5";
  1473. #$map->{"load15"}="$la15";
  1474. }
  1475. }
  1476. return $map;
  1477. }
  1478. #------------------------------------------------------------------------------
  1479. # leifert CPU Temperature (Raspberry Pi)
  1480. #------------------------------------------------------------------------------
  1481. sub
  1482. SYSMON_getCPUTemp_RPi($$) {
  1483. my ($hash, $map) = @_;
  1484. if($hash->{helper}->{excludes}{'cputemp'}) {return $map;}
  1485. my $val = SYSMON_execute($hash, "cat /sys/class/thermal/thermal_zone0/temp 2>&1");
  1486. $val = int($val);
  1487. if($val>1000) { # Manche Systeme scheinen die Daten verschieden zu skalieren (z.B. utilite)...
  1488. $val = $val/1000;
  1489. }
  1490. my $val_txt = sprintf("%.2f", $val);
  1491. $map->{+CPU_TEMP}="$val_txt";
  1492. my $t_avg = sprintf( "%.1f", (3 * ReadingsVal($hash->{NAME},CPU_TEMP_AVG,$val_txt) + $val_txt ) / 4 );
  1493. $map->{+CPU_TEMP_AVG}="$t_avg";
  1494. $map = SYSMON_getComputeStat($hash, $map, $val_txt, CPU_TEMP."_stat");
  1495. return $map;
  1496. }
  1497. #------------------------------------------------------------------------------
  1498. # leifert CPU Temperature (BeagleBone Black)
  1499. #------------------------------------------------------------------------------
  1500. sub
  1501. SYSMON_getCPUTemp_BBB($$) {
  1502. my ($hash, $map) = @_;
  1503. if($hash->{helper}->{excludes}{'cputemp'}) {return $map;}
  1504. my $val = SYSMON_execute($hash, "cat /sys/class/hwmon/hwmon0/device/temp1_input 2>&1");
  1505. if(!looks_like_number($val)) {return $map;}
  1506. $val = int($val);
  1507. my $val_txt = sprintf("%.2f", $val/1000);
  1508. $map->{+CPU_TEMP}="$val_txt";
  1509. $map->{"cpu0_temp"}="$val_txt";
  1510. my $t_avg = sprintf( "%.1f", (3 * ReadingsVal($hash->{NAME},CPU_TEMP_AVG,$val_txt) + $val_txt ) / 4 );
  1511. $map->{+CPU_TEMP_AVG}=$t_avg;
  1512. $t_avg = sprintf( "%.1f", (3 * ReadingsVal($hash->{NAME},"cpu0_temp_avg",$val_txt) + $val_txt ) / 4 );
  1513. $map->{"cpu0_temp_avg"}=$t_avg;
  1514. $map = SYSMON_getComputeStat($hash, $map, $val_txt, CPU_TEMP."_stat");
  1515. return $map;
  1516. }
  1517. #------------------------------------------------------------------------------
  1518. # leifert CPU Temperature (mehrere Kerne eines ?)
  1519. #------------------------------------------------------------------------------
  1520. sub
  1521. SYSMON_getCPUTemp_X($$;$) {
  1522. my ($hash, $map, $cpuNum) = @_;
  1523. if($hash->{helper}->{excludes}{'cputemp'}) {return $map;}
  1524. $cpuNum = 0 unless defined $cpuNum;
  1525. my $val = SYSMON_execute($hash, "cat /sys/class/hwmon/hwmon0/device/hwmon/hwmon0/temp".($cpuNum+1)."_input 2>&1");
  1526. $val = int($val);
  1527. my $val_txt = sprintf("%.2f", $val/1000);
  1528. $map->{"cpu".$cpuNum."_temp"}="$val_txt";
  1529. my $t_avg = sprintf( "%.1f", (3 * ReadingsVal($hash->{NAME},"cpu".$cpuNum."_temp_avg",$val_txt) + $val_txt ) / 4 );
  1530. $map->{"cpu".$cpuNum."_temp_avg"}=$t_avg;
  1531. $map = SYSMON_getComputeStat($hash, $map, $val_txt, "cpu".$cpuNum."_temp"."_stat");
  1532. return $map;
  1533. }
  1534. #------------------------------------------------------------------------------
  1535. # leifert CPU Temperature (FritzBox)
  1536. #------------------------------------------------------------------------------
  1537. sub
  1538. SYSMON_getCPUTemp_FB($$) {
  1539. my ($hash, $map) = @_;
  1540. if($hash->{helper}->{excludes}{'cputemp'}) {return $map;}
  1541. my $val = SYSMON_execute($hash, "ctlmgr_ctl r cpu status/StatTemperature");
  1542. if(defined($val)) {
  1543. if($val=~m/(\d+),/) {
  1544. my $fval = $1;
  1545. my $val_txt = sprintf("%.2f", $fval);
  1546. $map->{+CPU_TEMP}="$val_txt";
  1547. my $t_avg = sprintf( "%.1f", (3 * ReadingsVal($hash->{NAME},CPU_TEMP_AVG,$val_txt) + $val_txt ) / 4 );
  1548. $map->{+CPU_TEMP_AVG}="$t_avg";
  1549. $map = SYSMON_getComputeStat($hash, $map, $val_txt, CPU_TEMP."_stat");
  1550. }
  1551. }
  1552. return $map;
  1553. }
  1554. #------------------------------------------------------------------------------
  1555. # leifert CPU Frequenz (Raspberry Pi, BeagleBone Black, Cubietruck, etc.)
  1556. # Sonderlocke fuer lokale Erfassung (damit die CPU nicht auf Max. gefahren wird)
  1557. # Dazu darf nicht in BlockingCall und keine System-Aufrufe wie 'cat' etc.
  1558. #------------------------------------------------------------------------------
  1559. sub
  1560. SYSMON_getCPUFreqLocal($$;$) {
  1561. my ($hash, $map, $cpuNum) = @_;
  1562. if($hash->{helper}->{excludes}{'cpufreq'}) {return $map;}
  1563. $cpuNum = 0 unless defined $cpuNum;
  1564. my $val;
  1565. if(open(my $fh, '<', "/sys/devices/system/cpu/cpu".$cpuNum."/cpufreq/scaling_cur_freq")) {
  1566. $val = <$fh>;
  1567. close($fh);
  1568. }
  1569. $val = int($val);
  1570. my $val_txt = sprintf("%d", $val/1000);
  1571. if($cpuNum == 0) {
  1572. # aus Kompatibilitaetsgruenden
  1573. $map->{+CPU_FREQ}="$val_txt";
  1574. $map = SYSMON_getComputeStat($hash, $map, $val_txt, CPU_FREQ."_stat");
  1575. }
  1576. $map->{"cpu".$cpuNum."_freq"}="$val_txt";
  1577. $map = SYSMON_getComputeStat($hash, $map, $val_txt, "cpu".$cpuNum."_freq"."_stat");
  1578. return $map;
  1579. }
  1580. #------------------------------------------------------------------------------
  1581. # leifert CPU Frequenz (Raspberry Pi, BeagleBone Black, Cubietruck, etc.)
  1582. # Nur Remote Aufrufe
  1583. #------------------------------------------------------------------------------
  1584. sub
  1585. SYSMON_getCPUFreq($$;$) {
  1586. my ($hash, $map, $cpuNum) = @_;
  1587. if($hash->{helper}->{excludes}{'cpufreq'}) {return $map;}
  1588. $cpuNum = 0 unless defined $cpuNum;
  1589. my $val;
  1590. my $mode = $hash->{MODE};
  1591. if ($mode eq 'local') {
  1592. # do nothing
  1593. return $map;
  1594. }
  1595. # XXX Hack: Versuch zu vermeiden, dass Frequenz immer als Maximum gelesen wird
  1596. #my $mode = $hash->{MODE};#AttrVal( $name, 'mode', 'local');
  1597. #if ($mode eq 'local') {
  1598. # if(open(my $fh, '<', "/sys/devices/system/cpu/cpu".$cpuNum."/cpufreq/scaling_cur_freq")) {
  1599. # $val = <$fh>;
  1600. # close($fh);
  1601. # }
  1602. #} else {
  1603. $val = SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu".$cpuNum."/cpufreq/scaling_cur_freq ] && cat /sys/devices/system/cpu/cpu".$cpuNum."/cpufreq/scaling_cur_freq 2>&1 || echo 0");
  1604. #}
  1605. $val = int($val);
  1606. my $val_txt = sprintf("%d", $val/1000);
  1607. if($cpuNum == 0) {
  1608. # aus Kompatibilitaetsgruenden
  1609. $map->{+CPU_FREQ}="$val_txt";
  1610. $map = SYSMON_getComputeStat($hash, $map, $val_txt, CPU_FREQ."_stat");
  1611. }
  1612. $map->{"cpu".$cpuNum."_freq"}="$val_txt";
  1613. $map = SYSMON_getComputeStat($hash, $map, $val_txt, "cpu".$cpuNum."_freq"."_stat");
  1614. return $map;
  1615. }
  1616. #------------------------------------------------------------------------------
  1617. # leifert CPU Frequenz fuer 2te CPU (Cubietruck, etc.)
  1618. #------------------------------------------------------------------------------
  1619. #sub
  1620. #SYSMON_getCPU1Freq($$)
  1621. #{
  1622. # my ($hash, $map) = @_;
  1623. # my $val = SYSMON_execute($hash, "cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq 2>&1");
  1624. # $val = int($val);
  1625. # my $val_txt = sprintf("%d", $val/1000);
  1626. # $map->{+CPU1_FREQ}="$val_txt";
  1627. # return $map;
  1628. #}
  1629. #------------------------------------------------------------------------------
  1630. # leifert CPU Infos (Model name & Speed in BogoMIPS)
  1631. # TEST: {Dumper(SYSMON_getCPUInfo($defs{sysmon},undef))}
  1632. #------------------------------------------------------------------------------
  1633. sub
  1634. SYSMON_getCPUInfo($$) {
  1635. my ($hash, $map) = @_;
  1636. if($hash->{helper}->{excludes}{'cpuinfo'}) {return $map;}
  1637. my $old_val1 = ReadingsVal($hash->{NAME},CPU_BOGOMIPS,undef);
  1638. my $old_val2 = ReadingsVal($hash->{NAME},CPU_MODEL_NAME,undef);
  1639. # nur einmalig ermitteln (wird sich ja nicht aendern
  1640. if(!defined($old_val1) || !defined($old_val2)) {
  1641. #my @aval = SYSMON_execute($hash, "cat /proc/cpuinfo | grep 'BogoMIPS'");
  1642. my @aval = SYSMON_execute($hash, "cat /proc/cpuinfo");
  1643. foreach my $line (@aval) {
  1644. my($key, $val) = split(/\s*:\s+/, $line);
  1645. if(defined($key)) {
  1646. if($key=~m/Processor/ || $key=~m/model name/) {
  1647. if($val) {
  1648. $val = trim($val);
  1649. $map->{+CPU_MODEL_NAME}=$val;
  1650. }
  1651. } elsif ($key=~m/BogoMIPS/) {
  1652. if($val) {
  1653. $val = trim($val);
  1654. $map->{+CPU_BOGOMIPS}=$val;
  1655. }
  1656. }
  1657. }
  1658. }
  1659. } else {
  1660. $map->{+CPU_BOGOMIPS}=$old_val1;
  1661. $map->{+CPU_MODEL_NAME}=$old_val2;
  1662. }
  1663. return $map;
  1664. }
  1665. #------------------------------------------------------------------------------
  1666. # leifert Werte aus /proc/diskstat
  1667. # Werte:
  1668. # 1 - major number
  1669. # 2 - minor mumber
  1670. # 3 - device name
  1671. # Dann Datenwerte:
  1672. # Field 1 -- # of reads issued
  1673. # Field 2 -- # of reads merged
  1674. # Field 3 -- # of sectors read
  1675. # Field 4 -- # of milliseconds spent reading
  1676. # Field 5 -- # of writes completed
  1677. # Field 6 -- # of writes merged
  1678. # Field 7 -- # of sectors written
  1679. # Field 8 -- # of milliseconds spent writing
  1680. # Field 9 -- # of I/Os currently in progress
  1681. # Field 10 -- # of milliseconds spent doing I/Os
  1682. # Field 11 -- weighted # of milliseconds spent doing I/Os
  1683. # Interessant sind eigentlich "nur" Feld 2 (readin), Feld 5 (write)
  1684. # Wenn es eher "um die zeit" geht, Feld 4 (reading), Feld 8 (writing), Feld 10 (Komplett)
  1685. # Kleiner Hinweis, Fled 1 ist das 4. der Liste, das 3. Giebt den Namen an.
  1686. # Es giebt fuer jedes Devine und jede Partition ein Eintrag.
  1687. # A /proc/diskstats continuously updated and all that is necessary for us -
  1688. # make measurements for "second field" and "fourth field" in two different moment of time,
  1689. # receiving a difference of values and dividing it into an interval of time,
  1690. # we shall have Disk I/O stats in sectors/sec. Multiply this result on 512 (number of bytes in one sector)
  1691. # we shall have Disk I/O stats in bytes/sec.
  1692. #
  1693. # ...
  1694. # https://www.kernel.org/doc/Documentation/iostats.txt
  1695. # Field 1 -- # of reads completed
  1696. # This is the total number of reads completed successfully.
  1697. # Field 2 -- # of reads merged, field 6 -- # of writes merged
  1698. # Reads and writes which are adjacent to each other may be merged for
  1699. # efficiency. Thus two 4K reads may become one 8K read before it is
  1700. # ultimately handed to the disk, and so it will be counted (and queued)
  1701. # as only one I/O. This field lets you know how often this was done.
  1702. # Field 3 -- # of sectors read
  1703. # This is the total number of sectors read successfully.
  1704. # Field 4 -- # of milliseconds spent reading
  1705. # This is the total number of milliseconds spent by all reads (as
  1706. # measured from __make_request() to end_that_request_last()).
  1707. # Field 5 -- # of writes completed
  1708. # This is the total number of writes completed successfully.
  1709. # Field 6 -- # of writes merged
  1710. # See the description of field 2.
  1711. # Field 7 -- # of sectors written
  1712. # This is the total number of sectors written successfully.
  1713. # Field 8 -- # of milliseconds spent writing
  1714. # This is the total number of milliseconds spent by all writes (as
  1715. # measured from __make_request() to end_that_request_last()).
  1716. # Field 9 -- # of I/Os currently in progress
  1717. # The only field that should go to zero. Incremented as requests are
  1718. # given to appropriate struct request_queue and decremented as they finish.
  1719. # Field 10 -- # of milliseconds spent doing I/Os
  1720. # This field increases so long as field 9 is nonzero.
  1721. # Field 11 -- weighted # of milliseconds spent doing I/Os
  1722. # This field is incremented at each I/O start, I/O completion, I/O
  1723. # merge, or read of these stats by the number of I/Os in progress
  1724. # (field 9) times the number of milliseconds spent doing I/O since the
  1725. # last update of this field. This can provide an easy measure of both
  1726. # I/O completion time and the backlog that may be accumulating.
  1727. #
  1728. #
  1729. # Disks vs Partitions
  1730. # -------------------
  1731. #
  1732. # There were significant changes between 2.4 and 2.6 in the I/O subsystem.
  1733. # As a result, some statistic information disappeared. The translation from
  1734. # a disk address relative to a partition to the disk address relative to
  1735. # the host disk happens much earlier. All merges and timings now happen
  1736. # at the disk level rather than at both the disk and partition level as
  1737. # in 2.4. Consequently, you'll see a different statistics output on 2.6 for
  1738. # partitions from that for disks. There are only *four* fields available
  1739. # for partitions on 2.6 machines. This is reflected in the examples above.
  1740. #
  1741. # Field 1 -- # of reads issued
  1742. # This is the total number of reads issued to this partition.
  1743. # Field 2 -- # of sectors read
  1744. # This is the total number of sectors requested to be read from this
  1745. # partition.
  1746. # Field 3 -- # of writes issued
  1747. # This is the total number of writes issued to this partition.
  1748. # Field 4 -- # of sectors written
  1749. # This is the total number of sectors requested to be written to
  1750. # this partition.
  1751. #------------------------------------------------------------------------------
  1752. sub SYSMON_getDiskStat($$) {
  1753. my ($hash, $map) = @_;
  1754. if($hash->{helper}->{excludes}{'diskstat'}) {return $map;}
  1755. my @values = SYSMON_execute($hash, "cat /proc/diskstats");
  1756. for my $entry (@values){
  1757. $map = SYSMON_getDiskStat_intern($hash, $map, $entry);
  1758. #Log 3, "SYSMON-DEBUG-IOSTAT: ".$entry;
  1759. }
  1760. return $map;
  1761. }
  1762. sub
  1763. SYSMON_getDiskStat_intern($$$)
  1764. {
  1765. my ($hash, $map, $entry) = @_;
  1766. my ($d1, $d2, $pName, $nf1, $nf2, $nf3, $nf4, $nf5, $nf6, $nf7, $nf8, $nf9, $nf10, $nf11) = split(/\s+/, trim($entry));
  1767. SYSMON_Log($hash, 5, "SYSMON-DEBUG-IOSTAT: ".$pName." = ".$nf1." ".$nf2." ".$nf3." ".$nf4." ".$nf5." ".$nf6." ".$nf7." ".$nf8." ".$nf9." ".$nf10." ".$nf11);
  1768. # Nur nicht-null-Werte
  1769. if($nf1 eq "0") {
  1770. return $map;
  1771. }
  1772. $pName = "io_".$pName;
  1773. #Log 3, "SYSMON-DEBUG-IOSTAT: ".$pName;
  1774. # Partition and 2.6-Kernel?
  1775. if(defined($nf5)) {
  1776. # no
  1777. $map->{$pName."_raw"}=$nf1." ".$nf2." ".$nf3." ".$nf4." ".$nf5." ".$nf6." ".$nf7." ".$nf8." ".$nf9." ".$nf10." ".$nf11;
  1778. } else {
  1779. $map->{$pName."_raw"}=$nf1." ".$nf2." ".$nf3." ".$nf4;
  1780. }
  1781. #$map->{"iostat_test"}="TEST";
  1782. my $lastVal = ReadingsVal($hash->{NAME},$pName."_raw",undef);
  1783. if(defined($lastVal)) {
  1784. SYSMON_Log($hash,5, "SYSMON-DEBUG-IOSTAT: lastVal: $pName=".$lastVal);
  1785. }
  1786. if(defined $lastVal) {
  1787. # Diff. ausrechnen, falls vorherigen Werte vorhanden sind.
  1788. my($af1, $af2, $af3, $af4, $af5, $af6, $af7, $af8, $af9, $af10, $af11) = split(/\s+/, $lastVal);
  1789. SYSMON_Log($hash,5, "SYSMON-DEBUG-IOSTAT: X: ".$pName." = ".$af1." ".$af2." ".$af3." ".$af4." ".$af5." ".$af6." ".$af7." ".$af8." ".$af9." ".$af10." ".$af11);
  1790. my $sectorsRead;
  1791. my $sectorsWritten;
  1792. my $df1 = $nf1-$af1;
  1793. my $df2 = $nf2-$af2;
  1794. my $df3 = $nf3-$af3;
  1795. my $df4 = $nf4-$af4;
  1796. # Partition and 2.6-Kernel?
  1797. if(defined($nf5)) {
  1798. # no
  1799. my $df5 = $nf5-$af5;
  1800. my $df6 = $nf6-$af6;
  1801. my $df7 = $nf7-$af7;
  1802. my $df8 = $nf8-$af8;
  1803. my $df9 = $nf9-$af9;
  1804. my $df10 = $nf10-$af10;
  1805. my $df11 = $nf11-$af11;
  1806. $map->{$pName."_diff"}=$df1." ".$df2." ".$df3." ".$df4." ".$df5." ".$df6." ".$df7." ".$df8." ".$df9." ".$df10." ".$df11;
  1807. $sectorsRead = $df3;
  1808. $sectorsWritten = $df7;
  1809. } else {
  1810. $map->{$pName."_diff"}=$df1." ".$df2." ".$df3." ".$df4;
  1811. $sectorsRead = $df2;
  1812. $sectorsWritten = $df4;
  1813. }
  1814. my $sectorBytes = 512;
  1815. my $BytesRead = $sectorsRead*$sectorBytes;
  1816. my $BytesWritten = $sectorsWritten*$sectorBytes;
  1817. # TODO: Summenwerte
  1818. $map->{$pName.""}=sprintf("bytes read: %d bytes written: %d",$BytesRead, $BytesWritten);
  1819. }
  1820. return $map;
  1821. }
  1822. #------------------------------------------------------------------------------
  1823. # leifert Werte aus /proc/stat
  1824. # Werte:
  1825. # neuCPUuser, neuCPUnice, neuCPUsystem, neuCPUidle, neuCPUiowait, neuCPUirq, neuCPUsoftirq
  1826. # Differenzberechnung:
  1827. # CPUuser = neuCPUuser - altCPUuser (fuer alle anderen analog)
  1828. # GesammtCPU = CPUuser + CPUnice + CPUsystem + CPUidle + CPUiowait + CPUirq + CPUsoftirq
  1829. # Belastung in %:
  1830. # ProzCPUuser = (CPUuser / GesammtCPU) * 100
  1831. #------------------------------------------------------------------------------
  1832. sub
  1833. SYSMON_getCPUProcStat($$) {
  1834. my ($hash, $map) = @_;
  1835. if($hash->{helper}->{excludes}{'cpustat'}) {return $map;}
  1836. my @values = SYSMON_execute($hash, "cat /proc/stat");
  1837. for my $entry (@values){
  1838. if (index($entry, "cpu") < 0){
  1839. last;
  1840. }
  1841. $map = SYSMON_getCPUProcStat_intern($hash, $map, $entry);
  1842. }
  1843. # Wenn nur eine CPU vorhanden ist, loeschen Werte fuer CPU0 (nur Gesamt belassen)
  1844. if(!defined($map->{"stat_cpu1"})){
  1845. delete $map->{"stat_cpu0"};
  1846. delete $map->{"stat_cpu0_diff"};
  1847. delete $map->{"stat_cpu0_percent"};
  1848. }
  1849. return $map;
  1850. }
  1851. sub
  1852. SYSMON_getCPUProcStat_intern($$$)
  1853. {
  1854. my ($hash, $map, $entry) = @_;
  1855. my($tName, $neuCPUuser, $neuCPUnice, $neuCPUsystem, $neuCPUidle, $neuCPUiowait, $neuCPUirq, $neuCPUsoftirq) = split(/\s+/, trim($entry));
  1856. my $pName = "stat_".$tName;
  1857. $map->{$pName}=$neuCPUuser." ".$neuCPUnice." ".$neuCPUsystem." ".$neuCPUidle." ".$neuCPUiowait." ".$neuCPUirq." ".$neuCPUsoftirq;
  1858. my $lastVal = ReadingsVal($hash->{NAME},$pName,undef);
  1859. if(defined $lastVal) {
  1860. # Diff. ausrechnen, falls vorherigen Werte vorhanden sind.
  1861. my($altCPUuser, $altCPUnice, $altCPUsystem, $altCPUidle, $altCPUiowait, $altCPUirq, $altCPUsoftirq) = split(/\s+/, $lastVal);
  1862. my ($CPUuser, $CPUnice, $CPUsystem, $CPUidle, $CPUiowait, $CPUirq, $CPUsoftirq);
  1863. if($neuCPUuser < $altCPUuser) {
  1864. $CPUuser = $neuCPUuser;
  1865. $CPUnice = $neuCPUnice;
  1866. $CPUsystem = $neuCPUsystem;
  1867. $CPUidle = $neuCPUidle;
  1868. $CPUiowait = $neuCPUiowait;
  1869. $CPUirq = $neuCPUirq;
  1870. $CPUsoftirq = $neuCPUsoftirq;
  1871. }
  1872. else {
  1873. $CPUuser = $neuCPUuser - $altCPUuser;
  1874. $CPUnice = $neuCPUnice - $altCPUnice;
  1875. $CPUsystem = $neuCPUsystem - $altCPUsystem;
  1876. $CPUidle = $neuCPUidle - $altCPUidle;
  1877. $CPUiowait = $neuCPUiowait - $altCPUiowait;
  1878. $CPUirq = $neuCPUirq - $altCPUirq;
  1879. $CPUsoftirq = $neuCPUsoftirq - $altCPUsoftirq;
  1880. }
  1881. $map->{$pName."_diff"}=$CPUuser." ".$CPUnice." ".$CPUsystem." ".$CPUidle." ".$CPUiowait." ".$CPUirq." ".$CPUsoftirq;
  1882. my $GesammtCPU = $CPUuser + $CPUnice + $CPUsystem + $CPUidle + $CPUiowait + $CPUirq + $CPUsoftirq;
  1883. my $PercentCPUuser = ($CPUuser / $GesammtCPU) * 100;
  1884. my $PercentCPUnice = ($CPUnice / $GesammtCPU) * 100;
  1885. my $PercentCPUsystem = ($CPUsystem / $GesammtCPU) * 100;
  1886. my $PercentCPUidle = ($CPUidle / $GesammtCPU) * 100;
  1887. my $PercentCPUiowait = ($CPUiowait / $GesammtCPU) * 100;
  1888. my $PercentCPUirq = ($CPUirq / $GesammtCPU) * 100;
  1889. my $PercentCPUsoftirq = ($CPUsoftirq / $GesammtCPU) * 100;
  1890. $map->{$pName."_percent"}=sprintf ("%.2f %.2f %.2f %.2f %.2f %.2f %.2f",$PercentCPUuser,$PercentCPUnice,$PercentCPUsystem,$PercentCPUidle,$PercentCPUiowait,$PercentCPUirq,$PercentCPUsoftirq);
  1891. $map->{$pName."_text"}=sprintf ("user: %.2f %%, nice: %.2f %%, sys: %.2f %%, idle: %.2f %%, io: %.2f %%, irq: %.2f %%, sirq: %.2f %%",$PercentCPUuser,$PercentCPUnice,$PercentCPUsystem,$PercentCPUidle,$PercentCPUiowait,$PercentCPUirq,$PercentCPUsoftirq);
  1892. $map = SYSMON_getComputeStat($hash, $map, $PercentCPUidle, $tName."_idle_stat");
  1893. }
  1894. return $map;
  1895. }
  1896. #------------------------------------------------------------------------------
  1897. # Liefert Werte fuer RAM und SWAP (Gesamt, Verwendet, Frei).
  1898. #------------------------------------------------------------------------------
  1899. sub SYSMON_getRamAndSwap($$) {
  1900. my ($hash, $map) = @_;
  1901. if($hash->{helper}->{excludes}{'ramswap'}) {return $map;}
  1902. #my @speicher = qx(free -m);
  1903. my @speicher = SYSMON_execute($hash, "free");
  1904. if(!@speicher) {
  1905. return $map;
  1906. }
  1907. shift @speicher;
  1908. my ($fs_desc, $total, $used, $free, $shared, $buffers, $cached);
  1909. if(defined ($speicher[0])) {
  1910. ($fs_desc, $total, $used, $free, $shared, $buffers, $cached) = split(/\s+/, trim($speicher[0]));
  1911. }
  1912. shift @speicher;
  1913. my ($fs_desc2, $total2, $used2, $free2, $shared2, $buffers2, $cached2);
  1914. if(defined ($speicher[0])) {
  1915. ($fs_desc2, $total2, $used2, $free2, $shared2, $buffers2, $cached2) = split(/\s+/, trim($speicher[0]))
  1916. }
  1917. if(defined($fs_desc2)) {
  1918. if($fs_desc2 ne "Swap:") {
  1919. shift @speicher;
  1920. if(defined ($speicher[0])) {
  1921. ($fs_desc2, $total2, $used2, $free2, $shared2, $buffers2, $cached2) = split(/\s+/, trim($speicher[0]));
  1922. }
  1923. }
  1924. }
  1925. my $ram;
  1926. my $swap;
  1927. #my $percentage_ram;
  1928. #my $percentage_swap;
  1929. my $used_clean;
  1930. if(defined($total) && $total > 0) {
  1931. $total = $total / 1024;
  1932. $used = $used / 1024;
  1933. $free = $free / 1024;
  1934. $buffers = $buffers / 1024;
  1935. if(defined($cached)) {
  1936. $cached = $cached / 1024;
  1937. } else {
  1938. # Bei FritzBox wird dieser Wert nicht ausgageben
  1939. $cached = 0;
  1940. }
  1941. $used_clean = $used - $buffers - $cached;
  1942. $ram = sprintf("Total: %.2f MB, Used: %.2f MB, %.2f %%, Free: %.2f MB", $total, $used_clean, ($used_clean / $total * 100), ($free + $buffers + $cached));
  1943. }
  1944. else
  1945. {
  1946. $ram = "n/a";
  1947. }
  1948. $map->{+RAM} = $ram;
  1949. $map = SYSMON_getComputeStat($hash, $map, $used_clean, "ram_used_stat");
  1950. # wenn kein swap definiert ist, ist die Groesse (total2) gleich Null. Dies wuerde eine Exception (division by zero) ausloesen
  1951. if(defined($total2) && $total2 > 0 && defined($used2) && defined($free2)) {
  1952. $total2 = $total2 / 1024;
  1953. $used2 = $used2 / 1024;
  1954. $free2 = $free2 / 1024;
  1955. $swap = sprintf("Total: %.2f MB, Used: %.2f MB, %.2f %%, Free: %.2f MB", $total2, $used2, ($used2 / $total2 * 100), $free2);
  1956. } else {
  1957. $swap = "n/a"
  1958. }
  1959. $map->{+SWAP} = $swap;
  1960. $map = SYSMON_getComputeStat($hash, $map, $used2, "swap_used_stat");
  1961. return $map;
  1962. }
  1963. #------------------------------------------------------------------------------
  1964. # Prueft, ob das Host-System OSX ist (darvin).
  1965. #------------------------------------------------------------------------------
  1966. sub SYSMON_isOSX()
  1967. {
  1968. return $^O eq 'darwin';
  1969. }
  1970. #------------------------------------------------------------------------------
  1971. # Prueft, ob das Host-System Linux ist (linux).
  1972. #------------------------------------------------------------------------------
  1973. sub SYSMON_isLinux()
  1974. {
  1975. return $^O eq 'linux';
  1976. }
  1977. #------------------------------------------------------------------------------
  1978. # Liefert Werte fuer RAM und SWAP (Gesamt, Verwendet, Frei).
  1979. #------------------------------------------------------------------------------
  1980. sub SYSMON_getRamAndSwapOSX($$) {
  1981. my ($hash, $map) = @_;
  1982. if($hash->{helper}->{excludes}{'ramswap'}) {return $map;}
  1983. my $debug = 0; # Nur zum Testen!
  1984. #my @speicher = qx(free -m);
  1985. my @amemsize = SYSMON_execute($hash, "sysctl hw.memsize");
  1986. if($debug) {
  1987. @amemsize = ("hw.memsize: 8589934592");
  1988. }
  1989. if($amemsize[0]=~m/hw.memsize:\s+(.+)/) {
  1990. my $total = $1;
  1991. my @avmstat = SYSMON_execute($hash, "vm_stat");
  1992. if($debug) {
  1993. @avmstat = ('Mach Virtual Memory Statistics: (page size of 4096 bytes)',
  1994. 'Pages free: 5268.',
  1995. 'Pages active: 440314.',
  1996. 'Pages inactive: 430905.',
  1997. 'Pages speculative: 878.',
  1998. 'Pages throttled: 0.',
  1999. 'Pages wired down: 398445.',
  2000. 'Pages purgeable: 69.',
  2001. '"Translation faults": 508984629.',
  2002. 'Pages copy-on-write: 5668036.',
  2003. 'Pages zero filled: 347281743.',
  2004. 'Pages reactivated: 114745855.',
  2005. 'Pages purged: 13495647.',
  2006. 'File-backed pages: 88747.',
  2007. 'Anonymous pages: 783350.',
  2008. 'Pages stored in compressor: 1760568.',
  2009. 'Pages occupied by compressor: 820444.',
  2010. 'Decompressions: 48558417.',
  2011. 'Compressions: 63022425.',
  2012. 'Pageins: 3754238.',
  2013. 'Pageouts: 589840.',
  2014. 'Swapins: 714378.',
  2015. 'Swapouts: 1017813.');
  2016. }
  2017. #wired down, active, inactive
  2018. my $wired_down=0;
  2019. my $active=0;
  2020. my $inactive=0;
  2021. my $blockSize = 4096;
  2022. foreach my $k (@avmstat) {
  2023. if($k=~m/page\s+size\s+of\s+(\d+)\s+bytes/) {
  2024. $blockSize = $1;
  2025. }
  2026. if($k=~m/Pages\s+wired\s+down:\s+(.+)\./) {
  2027. $wired_down = $1;
  2028. }
  2029. if($k=~m/Pages\s+active:\s+(.+)\./) {
  2030. $active = $1;
  2031. }
  2032. if($k=~m/Pages\s+inactive:\s+(.+)\./) {
  2033. $inactive = $1;
  2034. }
  2035. }
  2036. $wired_down = $wired_down * $blockSize / 1048576; # In Megabyte umrechnen
  2037. $active = $active * $blockSize / 1048576;
  2038. $inactive = $inactive * $blockSize / 1048576;
  2039. my $used = $wired_down+$active+$inactive;
  2040. $total = $total/1048576;
  2041. my $free = $total-$used;
  2042. my $ram = sprintf("Total: %.2f MB, Used: %.2f MB, %.2f %%, Free: %.2f MB", $total, $used , ($used / $total * 100), $free);
  2043. #Log 3, "SYSMON >>>>>>>>>>>>>>>>>>>>>>>>> OSX: RAM: ".$ram;
  2044. $map->{+RAM} = $ram;
  2045. $map = SYSMON_getComputeStat($hash, $map, $used, "ram_used_stat");
  2046. my @avm = SYSMON_execute($hash, "sysctl vm.swapusage");
  2047. if($debug) {
  2048. @avm=(
  2049. #'vm.loadavg: { 2.45 2.19 3.34 }',
  2050. 'vm.swapusage: total = 1024.00M used = 529.25M free = 494.75M (encrypted)',
  2051. #'vm.cs_force_kill: 0',
  2052. #'vm.cs_force_hard: 0',
  2053. #'vm.cs_debug: 0',
  2054. #'vm.cs_all_vnodes: 0',
  2055. #'vm.cs_enforcement: 0',
  2056. #'vm.cs_enforcement_panic: 0',
  2057. #'vm.sigpup_disable: 0',
  2058. #'vm.global_no_user_wire_amount: 67108864',
  2059. #'vm.global_user_wire_limit: 8522825728',
  2060. #'vm.user_wire_limit: 8522825728',
  2061. #'vm.vm_copy_src_not_internal: 129',
  2062. #'vm.vm_copy_src_not_symmetric: 14994',
  2063. #'vm.vm_copy_src_large: 0',
  2064. #'vm.vm_page_external_count: 355255',
  2065. #'vm.vm_page_filecache_min: 104857',
  2066. #'vm.compressor_mode: 4',
  2067. #'vm.compressor_bytes_used: 2984467096',
  2068. #'vm.compressor_swapout_target_age: 0',
  2069. #'vm.compressor_eval_period_in_msecs: 250',
  2070. #'vm.compressor_sample_min_in_msecs: 500',
  2071. #'vm.compressor_sample_max_in_msecs: 10000',
  2072. #'vm.compressor_thrashing_threshold_per_10msecs: 50',
  2073. #'vm.compressor_thrashing_min_per_10msecs: 20',
  2074. #'vm.compressor_minorcompact_threshold_divisor: 20',
  2075. #'vm.compressor_majorcompact_threshold_divisor: 25',
  2076. #'vm.compressor_unthrottle_threshold_divisor: 35',
  2077. #'vm.compressor_catchup_threshold_divisor: 50',
  2078. #'vm.cs_validation: 1',
  2079. #'vm.cs_blob_count: 616',
  2080. #'vm.cs_blob_size: 8053170',
  2081. #'vm.cs_blob_count_peak: 693',
  2082. #'vm.cs_blob_size_peak: 8389641',
  2083. #'vm.cs_blob_size_max: 1675264',
  2084. #'vm.vm_debug_events: 0',
  2085. #'vm.allow_stack_exec: 0',
  2086. #'vm.allow_data_exec: 1',
  2087. #'vm.shared_region_unnest_logging: 1',
  2088. #'vm.shared_region_trace_level: 1',
  2089. #'vm.shared_region_version: 3',
  2090. #'vm.shared_region_persistence: 0',
  2091. #'vm.vm_page_free_target: 2000',
  2092. #'vm.memory_pressure: 0',
  2093. #'vm.page_free_wanted: 86',
  2094. #'vm.page_purgeable_count: 1055',
  2095. #'vm.page_purgeable_wired_count: 0',
  2096. #'vm.madvise_free_debug: 0',
  2097. #'vm.page_reusable_count: 39048',
  2098. #'vm.reusable_success: 11350536',
  2099. #'vm.reusable_failure: 1060241',
  2100. #'vm.reusable_shared: 248771',
  2101. #'vm.all_reusable_calls: 290574',
  2102. #'vm.partial_reusable_calls: 11142306',
  2103. #'vm.reuse_success: 9593371',
  2104. #'vm.reuse_failure: 5124',
  2105. #'vm.all_reuse_calls: 257820',
  2106. #'vm.partial_reuse_calls: 9684238',
  2107. #'vm.can_reuse_success: 6171792',
  2108. #'vm.can_reuse_failure: 79183',
  2109. #'vm.reusable_reclaimed: 0',
  2110. #'vm.page_free_count: 1914',
  2111. #'vm.page_speculative_count: 810',
  2112. #'vm.page_cleaned_count: 0',
  2113. #'vm.pageout_inactive_dirty_internal: 63170734',
  2114. #'vm.pageout_inactive_dirty_external: 465495',
  2115. #'vm.pageout_inactive_clean: 18967682',
  2116. #'vm.pageout_speculative_clean: 32929182',
  2117. #'vm.pageout_inactive_used: 115155398',
  2118. #'vm.pageout_freed_from_inactive_clean: 18423099',
  2119. #'vm.pageout_freed_from_speculative: 32929182',
  2120. #'vm.pageout_freed_from_cleaned: 568334',
  2121. #'vm.pageout_enqueued_cleaned: 1010912',
  2122. #'vm.pageout_enqueued_cleaned_from_inactive_clean: 0',
  2123. #'vm.pageout_enqueued_cleaned_from_inactive_dirty: 1011010',
  2124. #'vm.pageout_cleaned: 568334',
  2125. #'vm.pageout_cleaned_reactivated: 407922',
  2126. #'vm.pageout_cleaned_reference_reactivated: 4',
  2127. #'vm.pageout_cleaned_volatile_reactivated: 0',
  2128. #'vm.pageout_cleaned_fault_reactivated: 557',
  2129. #'vm.pageout_cleaned_commit_reactivated: 407361',
  2130. #'vm.pageout_cleaned_busy: 33',
  2131. #'vm.pageout_cleaned_nolock: 12931'
  2132. );
  2133. }
  2134. #vm.swapusage: total = 1024.00M used = 529.25M free = 494.75M (encrypted)
  2135. if($avm[0]=~m/vm.swapusage:\s+total\s+=\s+(\S*)\s+used\s+=\s+(\S*)\s+free\s+=\s+(\S*)\s+(.*)/) {
  2136. my $total2 = SYSMON_fmtStorageAmount_($1);
  2137. my $used2 = SYSMON_fmtStorageAmount_($2);
  2138. my $free2 = SYSMON_fmtStorageAmount_($3);
  2139. my $swap = sprintf("Total: %.2f MB, Used: %.2f MB, %.2f %%, Free: %.2f MB", $total2, $used2, ($used2 / $total2 * 100), $free2);
  2140. $map->{+SWAP} = $swap;
  2141. $map = SYSMON_getComputeStat($hash, $map, $used2, "swap_used_stat");
  2142. #Log 3, "SYSMON >>>>>>>>>>>>>>>>>>>>>>>>> OSX: SWAP: ".$swap;
  2143. }
  2144. }
  2145. return $map;
  2146. }
  2147. sub SYSMON_fmtStorageAmount_($) {
  2148. my ($t) = @_;
  2149. if($t=~m/([\d|\.]+)(.*)/) {
  2150. my $r=$1;
  2151. my $m=$2;
  2152. if($m) {
  2153. # Modifier testen
  2154. if($m eq 'M') {
  2155. # Megabyte ist OK,so lassen
  2156. return $r;
  2157. }
  2158. if($m eq 'G') {
  2159. # Gigabyte: in MB umwandeln
  2160. $r=$r*1024;
  2161. }
  2162. # K, oder P nehmen ich nicht mehr bzw. noch nicht an ;)
  2163. return $r;
  2164. }
  2165. }
  2166. return $t;
  2167. }
  2168. #------------------------------------------------------------------------------
  2169. # Liefert Fuellstand fuer das angegebene Dateisystem (z.B. '/dev/root', '/dev/sda1' (USB stick)).
  2170. # Eingabeparameter: HASH; MAP; FS-Bezeichnung
  2171. #------------------------------------------------------------------------------
  2172. sub SYSMON_getFileSystemInfo ($$$) {
  2173. my ($hash, $map, $fs) = @_;
  2174. if($hash->{helper}->{excludes}{'filesystem'}) {return $map;}
  2175. SYSMON_Log($hash, 5, "get $fs");
  2176. # Neue Syntax: benannte Filesystems: <name>:<definition>
  2177. my($fName, $fDef, $fComment) = split(/:/, $fs);
  2178. if(defined $fDef) {
  2179. $fs = $fDef;
  2180. }
  2181. #my $disk = "df ".$fs." -m 2>&1"; # in case of failure get string from stderr
  2182. my $disk = "df ".$fs." -m 2>/dev/null";
  2183. SYSMON_Log($hash, 5, "exec $disk");
  2184. #my @filesystems = qx($disk);
  2185. my @filesystems = SYSMON_execute($hash, $disk);
  2186. SYSMON_Log($hash, 5, "recieved ".scalar(scalar(@filesystems))." lines");
  2187. # - DEBUG -
  2188. #if($fs eq "/test") {
  2189. # @filesystems=(
  2190. # "Filesystem 1M-blocks Used Available Use% Mounted on",
  2191. # "/dev/mapper/n40l-root",
  2192. # " 226741 22032 193192 11% /"
  2193. # );
  2194. # $fs = "/";
  2195. #}
  2196. #- DEBUG -
  2197. #if(!defined @filesystems) { return $map; } # Ausgabe leer
  2198. #if(scalar(@filesystems) == 0) { return $map; } # Array leer
  2199. if(defined($filesystems[0])) {
  2200. SYSMON_Log($hash, 5, "recieved line0 $filesystems[0]");
  2201. } else {
  2202. SYSMON_Log($hash, 5, "recieved empty line");
  2203. }
  2204. shift @filesystems;
  2205. # Falls kein Eintrag gefunden (z.B: kein Medium im Laufwerk), mit Nullen fuellen (damit die Plots richtig funktionieren).
  2206. if(defined $fDef) {
  2207. $map->{$fName} = "Total: 0 MB, Used: 0 MB, 0 %, Available: 0 MB at ".$fs." (not available)";
  2208. } else {
  2209. $map->{+FS_PREFIX.$fs} = "Total: 0 MB, Used: 0 MB, 0 %, Available: 0 MB at ".$fs." (not available)";
  2210. }
  2211. #return $map unless defined(@filesystems);
  2212. return $map unless int(@filesystems)>0;
  2213. #if(!defined $filesystems[0]) { return $map; } # Ausgabe leer
  2214. SYSMON_Log($hash, 5, "analyse line $filesystems[0] for $fs");
  2215. #if (!($filesystems[0]=~ /$fs\s*$/)){ shift @filesystems; }
  2216. if (!($filesystems[0]=~ /$fs$/)){
  2217. shift @filesystems;
  2218. if(int(@filesystems)>0) {
  2219. SYSMON_Log($hash, 5, "analyse line $filesystems[0] for $fs");
  2220. }
  2221. } else {
  2222. SYSMON_Log($hash, 5, "pattern ($fs) found");
  2223. }
  2224. #if (index($filesystems[0], $fs) < 0) { shift @filesystems; } # Wenn die Bezeichnung so lang ist, dass die Zeile umgebrochen wird...
  2225. #if (index($filesystems[0], $fs) >= 0) # check if filesystem available -> gives failure on console
  2226. if (int(@filesystems)>0 && $filesystems[0]=~ /$fs$/)
  2227. {
  2228. SYSMON_Log($hash, 5, "use line $filesystems[0]");
  2229. my ($fs_desc, $total, $used, $available, $percentage_used, $mnt_point) = split(/\s+/, $filesystems[0]);
  2230. $percentage_used =~ /^(.+)%$/;
  2231. $percentage_used = $1;
  2232. my $out_txt = "Total: ".$total." MB, Used: ".$used." MB, ".$percentage_used." %, Available: ".$available." MB at ".$mnt_point;
  2233. if(defined $fDef) {
  2234. $map->{$fName} = $out_txt;
  2235. } else {
  2236. $map->{+FS_PREFIX.$mnt_point} = $out_txt;
  2237. }
  2238. }
  2239. # else {
  2240. # if(defined $fDef) {
  2241. # $map->{$fName} = "not available";
  2242. # } else {
  2243. # $map->{+FS_PREFIX.$fs} = "not available";
  2244. # }
  2245. #}
  2246. return $map;
  2247. }
  2248. #------------------------------------------------------------------------------
  2249. # Liefert Netztwerkinformationen
  2250. # Parameter: HASH; MAP; DEVICE (eth0 or wlan0)
  2251. #------------------------------------------------------------------------------
  2252. sub SYSMON_getNetworkInfo ($$$) {
  2253. my ($hash, $map, $device) = @_;
  2254. if($hash->{helper}->{excludes}{'network'}) {return $map;}
  2255. SYSMON_Log($hash, 5, "get $device");
  2256. my($nName, $nDef) = split(/:/, $device);
  2257. if(!defined $nDef) {
  2258. $nDef = $nName;
  2259. }
  2260. $device = $nDef;
  2261. # in case of network not present get failure from stderr (2>&1)
  2262. my $cmd="ifconfig ".$device." 2>&1";
  2263. #my @dataThroughput = qx($cmd);
  2264. my @dataThroughput = SYSMON_execute($hash, $cmd);
  2265. SYSMON_Log ($hash, 5, "SYSMON_getNetworkInfo>>>>>>>>>>>>>>>>".Dumper(@dataThroughput));
  2266. #--- DEBUG ---
  2267. if($device eq "_test1") {
  2268. @dataThroughput = (
  2269. "enp4s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1492",
  2270. " inet 192.168.2.7 netmask 255.255.255.0 broadcast 192.168.2.255",
  2271. " ether 00:21:85:5a:0d:e0 txqueuelen 1000 (Ethernet)",
  2272. " RX packets 1553313 bytes 651891540 (621.6 MiB)",
  2273. " RX errors 0 dropped 0 overruns 0 frame 0",
  2274. " TX packets 1915387 bytes 587386206 (560.1 MiB)",
  2275. " TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0");
  2276. }
  2277. if($device eq "_test2") {
  2278. @dataThroughput = (
  2279. "eth0 Link encap:Ethernet Hardware Adresse b8:27:eb:47:a9:8d",
  2280. " inet Adresse:192.168.2.118 Bcast:192.168.2.255 Maske:255.255.255.0",
  2281. " inet6-Adresse: 2003:46:b6b:3100:ba27:ebff:fe47:a98d/64 Gültigkeitsbereich:Global",
  2282. " inet6-Adresse: fe80::ba27:ebff:fe47:a98d/64 Gültigkeitsbereich:Verbindung",
  2283. " UP BROADCAST RUNNING MULTICAST MTU:1500 Metrik:1",
  2284. " RX packets:1224709 errors:0 dropped:0 overruns:0 frame:0",
  2285. " TX packets:1156620 errors:0 dropped:0 overruns:0 carrier:0",
  2286. " Kollisionen:0 Sendewarteschlangenlänge:1000",
  2287. " RX bytes:180806073 (172.4 MiB) TX bytes:108919337 (103.8 MiB)");
  2288. }
  2289. #--- DEBUG ---
  2290. # check if network available
  2291. if (defined($dataThroughput[0]) && index($dataThroughput[0], 'Fehler') < 0 && index($dataThroughput[0], 'error') < 0)
  2292. {
  2293. #Log 3, "SYSMON>>>>>>>>>>>>>>>>> OK >>>".$dataThroughput[0];
  2294. my $dataThroughput = undef;
  2295. # Suche nach der Daten in Form:
  2296. # eth0 Link encap:Ethernet Hardware Adresse b8:27:eb:a5:e0:85
  2297. # inet Adresse:192.168.0.10 Bcast:192.168.0.255 Maske:255.255.255.0
  2298. # UP BROADCAST RUNNING MULTICAST MTU:1500 Metrik:1
  2299. # RX packets:339826 errors:0 dropped:45 overruns:0 frame:0
  2300. # TX packets:533293 errors:0 dropped:0 overruns:0 carrier:0
  2301. # Kollisionen:0 Sendewarteschlangenlaenge:1000
  2302. # RX bytes:25517384 (24.3 MiB) TX bytes:683970999 (652.2 MiB)
  2303. my $ip = undef; my $ip6 = undef;
  2304. foreach (@dataThroughput) {
  2305. if($_=~ m/inet\s+(Adresse:)*(\S*)/) {
  2306. $ip=$2;
  2307. }
  2308. if(!$ip && $_=~ m/inet\s+(addr:)*(\S*)/) {
  2309. $ip=$2;
  2310. }
  2311. if($_=~ m/inet6-(Adresse:)*\s*(\S*)\s+G.ltigkeitsbereich:Verbindung/) {
  2312. $ip6=$2;
  2313. }
  2314. if(!$ip && $_=~ m/inet6\s+(addr:)*\s*(\S*)\s+Scope:Link/) {
  2315. $ip6=$2;
  2316. }
  2317. if(!$ip && $_=~ m/inet6\s+(addr:)*\s*(\S*)/) {
  2318. $ip6=$2;
  2319. }
  2320. if(index($_, 'RX bytes') >= 0) {
  2321. $dataThroughput = $_;
  2322. last;
  2323. }
  2324. }
  2325. if(defined $ip) {
  2326. $ip =~ s/addr://;
  2327. $map->{$nName.IP_SUFFIX} = $ip;
  2328. }
  2329. if(defined $ip6) {
  2330. $ip6 =~ s/addr://;
  2331. $map->{$nName.IP6_SUFFIX} = $ip6;
  2332. }
  2333. my $rxRaw = -1;
  2334. my $txRaw = -1;
  2335. # if(-e "/sys/class/net/$nName/statistics/rx_bytes" && -e "/sys/class/net/$nName/statistics/tx_bytes") {
  2336. if(SYSMON_isNetStatClass($hash, $nName)) {
  2337. $rxRaw = SYSMON_execute($hash, "cat /sys/class/net/$nName/statistics/rx_bytes");
  2338. $rxRaw = -1 unless (defined($rxRaw) && looks_like_number($rxRaw));
  2339. $txRaw = SYSMON_execute($hash, "cat /sys/class/net/$nName/statistics/tx_bytes");
  2340. $txRaw = -1 unless (defined($txRaw) && looks_like_number($txRaw));
  2341. }
  2342. if($rxRaw<0||$txRaw<0) {
  2343. if(defined $dataThroughput) {
  2344. # remove RX bytes or TX bytes from string
  2345. $dataThroughput =~ s/RX bytes://;
  2346. $dataThroughput =~ s/TX bytes://;
  2347. $dataThroughput = trim($dataThroughput);
  2348. @dataThroughput = split(/ /, $dataThroughput); # return of split is array
  2349. $rxRaw = $dataThroughput[0] if(defined $dataThroughput[0]);
  2350. $txRaw = $dataThroughput[4] if(defined $dataThroughput[4]);
  2351. } else {
  2352. #
  2353. # an manchen Systemen kann die Ausgabe leider auch anders aussehen:
  2354. # enp4s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1492
  2355. # inet 192.168.2.7 netmask 255.255.255.0 broadcast 192.168.2.255
  2356. # ether 00:21:85:5a:0d:e0 txqueuelen 1000 (Ethernet)
  2357. # RX packets 1553313 bytes 651891540 (621.6 MiB)
  2358. # RX errors 0 dropped 0 overruns 0 frame 0
  2359. # TX packets 1915387 bytes 587386206 (560.1 MiB)
  2360. # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  2361. #
  2362. my $d;
  2363. foreach $d (@dataThroughput) {
  2364. if($d =~ m/RX\s.*\sbytes\s(\d*)\s/) {
  2365. $rxRaw = $1;
  2366. }
  2367. if($d =~ m/TX\s.*\sbytes\s(\d*)\s/) {
  2368. $txRaw = $1;
  2369. }
  2370. }
  2371. }
  2372. }
  2373. if($rxRaw<0) {
  2374. # Daten nicht gefunden / Format unbekannt
  2375. $map->{$nName} = "unexpected format";
  2376. $map->{$nName.DIFF_SUFFIX} = "unexpected format";
  2377. } else {
  2378. $map->{$nName."_rx"} = $rxRaw;
  2379. $map->{$nName."_tx"} = $txRaw;
  2380. $rxRaw = $rxRaw / 1048576; # Bytes in MB
  2381. $txRaw = $txRaw / 1048576;
  2382. my $rx = sprintf ("%.2f", $rxRaw);
  2383. my $tx = sprintf ("%.2f", $txRaw);
  2384. my $totalRxTx = $rx + $tx;
  2385. my $out_txt = "RX: ".$rx." MB, TX: ".$tx." MB, Total: ".$totalRxTx." MB";
  2386. $map->{$nName} = $out_txt;
  2387. my $lastVal = ReadingsVal($hash->{NAME},$nName,"RX: 0 MB, TX: 0 MB, Total: 0 MB");
  2388. my ($d0, $o_rx, $d1, $d2, $o_tx, $d3, $d4, $o_tt, $d5) = split(/\s+/, trim($lastVal));
  2389. if(defined($o_tx) && defined($o_tt)) {
  2390. my $d_rx = $rx-$o_rx;
  2391. if($d_rx<0) {$d_rx=0;}
  2392. my $d_tx = $tx-$o_tx;
  2393. if($d_tx<0) {$d_tx=0;}
  2394. my $d_tt = $totalRxTx-$o_tt;
  2395. if($d_tt<0) {$d_tt=0;}
  2396. my $out_txt_diff = "RX: ".sprintf ("%.2f", $d_rx)." MB, TX: ".sprintf ("%.2f", $d_tx)." MB, Total: ".sprintf ("%.2f", $d_tt)." MB";
  2397. $map->{$nName.DIFF_SUFFIX} = $out_txt_diff;
  2398. }
  2399. my $speed = SYSMON_execute($hash, "[ -f /sys/class/net/$nName/speed ] && cat /sys/class/net/$nName/speed 2>/dev/null || echo not available");
  2400. if(defined($speed)) {
  2401. $map->{$nName.SPEED_SUFFIX} = $speed;
  2402. }
  2403. }
  2404. } else {
  2405. #Log 3, "SYSMON>>>>>>>>>>>>>>>>> NOK ";
  2406. #Log 3, "SYSMON>>>>>>>>>>>>>>>>> >>> ".$nName;
  2407. $map->{$nName} = "not available";
  2408. $map->{$nName.DIFF_SUFFIX} = "not available";
  2409. }
  2410. return $map;
  2411. }
  2412. #------------------------------------------------------------------------------
  2413. # Liefert Informationen, ob WLAN an oder aus ist (nur FritzBox)
  2414. # Parameter: HASH; MAP
  2415. #------------------------------------------------------------------------------
  2416. sub SYSMON_getFBWLANState($$) {
  2417. my ($hash, $map) = @_;
  2418. if($hash->{helper}->{excludes}{'network'}) {return $map;}
  2419. #SYSMON_Log($hash, 5, "");
  2420. $map->{+FB_WLAN_STATE}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r wlan settings/ap_enabled",1);
  2421. return $map;
  2422. }
  2423. #------------------------------------------------------------------------------
  2424. # Liefert Informationen, ob WLAN-Gastzugang an oder aus ist (nur FritzBox)
  2425. # Parameter: HASH; MAP
  2426. #------------------------------------------------------------------------------
  2427. sub SYSMON_getFBWLANGuestState($$) {
  2428. my ($hash, $map) = @_;
  2429. if($hash->{helper}->{excludes}{'network'}) {return $map;}
  2430. #SYSMON_Log($hash, 5, "");
  2431. $map->{+FB_WLAN_GUEST_STATE}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r wlan settings/guest_ap_enabled",1);
  2432. return $map;
  2433. }
  2434. #------------------------------------------------------------------------------
  2435. # Liefert IP Adresse im Internet (nur FritzBox)
  2436. # Parameter: HASH; MAP
  2437. #------------------------------------------------------------------------------
  2438. sub SYSMON_getFBInetIP($$) {
  2439. my ($hash, $map) = @_;
  2440. if($hash->{helper}->{excludes}{'network'}) {return $map;}
  2441. $map->{+FB_INET_IP}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r dslstatistic status/ifacestat0/ipaddr");
  2442. return $map;
  2443. }
  2444. #------------------------------------------------------------------------------
  2445. # Liefert Status Internet-Verbindung (nur FritzBox)
  2446. # Parameter: HASH; MAP
  2447. #------------------------------------------------------------------------------
  2448. sub SYSMON_getFBInetConnectionState($$) {
  2449. my ($hash, $map) = @_;
  2450. if($hash->{helper}->{excludes}{'network'}) {return $map;}
  2451. $map->{+FB_INET_STATE}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r dslstatistic status/ifacestat0/connection_status");
  2452. return $map;
  2453. }
  2454. #------------------------------------------------------------------------------
  2455. # Liefert Status Klingelsperre (nur FritzBox)
  2456. # Parameter: HASH; MAP
  2457. #------------------------------------------------------------------------------
  2458. sub SYSMON_getFBNightTimeControl($$) {
  2459. my ($hash, $map) = @_;
  2460. if($hash->{helper}->{excludes}{'fbnightctrl'}) {return $map;}
  2461. $map->{+FB_N_TIME_CTRL}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r box settings/night_time_control_enabled",1);
  2462. return $map;
  2463. }
  2464. #------------------------------------------------------------------------------
  2465. # Liefert Anzahl der nicht abgehoerten Nachrichten auf dem Anrufbeantworter (nur FritzBox)
  2466. # Parameter: HASH; MAP
  2467. #------------------------------------------------------------------------------
  2468. sub SYSMON_getFBNumNewMessages($$) {
  2469. my ($hash, $map) = @_;
  2470. if($hash->{helper}->{excludes}{'fbnewmessages'}) {return $map;}
  2471. $map->{+FB_NUM_NEW_MESSAGES}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r tam status/NumNewMessages");
  2472. return $map;
  2473. }
  2474. #------------------------------------------------------------------------------
  2475. # Liefert DECT-Temperatur einer FritzBox.
  2476. # Parameter: HASH; MAP
  2477. #------------------------------------------------------------------------------
  2478. sub SYSMON_getFBDECTTemp($$) {
  2479. my ($hash, $map) = @_;
  2480. if($hash->{helper}->{excludes}{'fbdecttemp'}) {return $map;}
  2481. $map->{+FB_DECT_TEMP}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r dect status/Temperature");
  2482. return $map;
  2483. }
  2484. #------------------------------------------------------------------------------
  2485. # Liefert Liste an der FritzBox bekannter Devices.
  2486. # Parameter: HASH
  2487. # Return Hash mit Devices
  2488. #------------------------------------------------------------------------------
  2489. sub SYSMON_getFBLanDeviceList($) {
  2490. my ($hash) = @_;
  2491. if(!SYSMON_isFB($hash)) {
  2492. return undef;
  2493. }
  2494. my $map;
  2495. my $name = $hash->{NAME};
  2496. # ---
  2497. #TODO: SSH
  2498. my $msg = undef;
  2499. my $openedTelnet = 0;
  2500. my $telnet = $hash->{".telnet"};
  2501. #$telnet = undef;
  2502. my $mode = $hash->{MODE};
  2503. # Wenn remote: open connection
  2504. if ($mode eq 'telnet') {
  2505. unless (defined $telnet) {
  2506. SYSMON_Log($hash, 5, "$name: Open single telnet connection");
  2507. $msg = SYSMON_Open_Connection($hash);
  2508. $hash->{helper}{error_msg}=$msg;
  2509. if (!$msg) {
  2510. $openedTelnet = 1;
  2511. $hash->{helper}{error_msg}=undef;
  2512. }
  2513. }
  2514. }
  2515. # ---
  2516. my $count = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice/count");
  2517. if(defined($count)) {
  2518. for (my $i=0;$i<$count;$i++) {
  2519. #landevice0/...
  2520. # ip=192.168.178.12, mac=00:1F:3F:MM:AA:CC, name=PC-192-168-178-12, manu_name=0,
  2521. # dhcp=0, static_dhcp=0, wlan=0, ethernet=1, active=1, online=0, speed=100,
  2522. # deleteable=2, wakeup=0, source=4096, neighbour_name=, is_double_neighbour_name=0
  2523. # ipv6addrs=, ipv6_ifid=
  2524. my $dev_name = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice".$i."/name");
  2525. my $dev_ip = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice".$i."/ip");
  2526. my $dev_mac = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice".$i."/mac");
  2527. my $dev_active = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice".$i."/active");
  2528. $map->{$dev_name}{id} = $i;
  2529. $map->{$dev_name}{name} = $dev_name;
  2530. $map->{$dev_name}{ip} = $dev_ip;
  2531. $map->{$dev_name}{mac} = $dev_mac;
  2532. $map->{$dev_name}{active} = $dev_active;
  2533. }
  2534. }
  2535. # ---
  2536. # Wenn remote: close connection
  2537. if ($mode eq 'telnet') {
  2538. if($openedTelnet) {
  2539. SYSMON_Log($hash, 5, "$name: Close shared telnet connection");
  2540. SYSMON_Close_Connection( $hash );
  2541. }
  2542. }
  2543. # ---
  2544. return $map;
  2545. }
  2546. # TODO: FritzBox-Infos: Dateien /var/env oder /proc/sys/urlader/environment.
  2547. #------------------------------------------------------------------------------
  2548. # Liefert Informationen zu verschiedenen Eigenschaften durch Aufruf von entsprechenden Befehlen
  2549. # Parameter: HASH; cmd; Art (Interpretieren als: 1=on/off)
  2550. #------------------------------------------------------------------------------
  2551. sub SYSMON_acquireInfo_intern($$;$)
  2552. {
  2553. my ($hash, $cmd, $art) = @_;
  2554. SYSMON_Log($hash, 5, "cmd: ".$cmd);
  2555. my $str = SYSMON_execute($hash, $cmd);
  2556. if(defined($str)) {
  2557. $str = trim($str);
  2558. }
  2559. my $ret;
  2560. if(!defined($art)) { $art= 0; }
  2561. $ret = $str;
  2562. no warnings;
  2563. if($art == 1) {
  2564. if($str+0 == 1) {
  2565. $ret="on";
  2566. } else {
  2567. if($str+0 == 0) {
  2568. $ret="off";
  2569. } else {
  2570. $ret="unknown";
  2571. }
  2572. }
  2573. }
  2574. use warnings;
  2575. return $ret;
  2576. }
  2577. sub SYSMON_FBVersionInfo($$) {
  2578. my ($hash, $map) = @_;
  2579. if($hash->{helper}->{excludes}{'fbversion'}) {return $map;}
  2580. my @ar = SYSMON_execute($hash, "/etc/version --version --date");
  2581. my $data = $ar[0];
  2582. my($v, $d, $t) = split(/\s+/, $data);
  2583. my $version = "";
  2584. if(defined($v)) { $version = $v; }
  2585. if(defined($d)) { $version.= " ".$d; }
  2586. if(defined($t)) { $version.= " ".$t; }
  2587. #if(defined($data[0])) {
  2588. # #Version
  2589. # $version = $data[0];
  2590. #}
  2591. #if(defined($data[1])) {
  2592. # #Date
  2593. # $version = $version." ".$data[1];
  2594. #}
  2595. if($version ne "") {
  2596. $map->{+FB_FW_VERSION}=$version;
  2597. }
  2598. return $map;
  2599. }
  2600. #DSL-Downstream und DSL-Upstream abfragen
  2601. sub SYSMON_getFBStreamRate($$) {
  2602. my ($hash, $map) = @_;
  2603. if($hash->{helper}->{excludes}{'fbdsl'}) {return $map;}
  2604. my $ds_rate = SYSMON_execute($hash, "ctlmgr_ctl r sar status/dsl_ds_rate");
  2605. unless($ds_rate) {
  2606. return SYSMON_getFBStreamRate2($hash, $map);
  2607. }
  2608. my $us_rate = SYSMON_execute($hash, "ctlmgr_ctl r sar status/dsl_us_rate");
  2609. if($ds_rate ne "" && $us_rate ne "") {
  2610. $map->{+FB_DSL_RATE}="down: ".int($ds_rate)." kBit/s, up: ".int($us_rate)." kBit/s";
  2611. }
  2612. return $map;
  2613. }
  2614. # DSL-Geschwindigkeit mit neuer FritzOS (6.23)
  2615. sub SYSMON_getFBStreamRate2($$) {
  2616. my ($hash, $map) = @_;
  2617. if($hash->{helper}->{excludes}{'fbdsl'}) {return $map;}
  2618. my $ds_rate = SYSMON_execute($hash, "ctlmgr_ctl r dslstatglobal status/in");
  2619. my $us_rate = SYSMON_execute($hash, "ctlmgr_ctl r dslstatglobal status/out");
  2620. if(defined($ds_rate) && defined($us_rate) && $ds_rate ne "" && $us_rate ne "") {
  2621. $ds_rate = $ds_rate/1000;
  2622. $us_rate = $us_rate/1000;
  2623. $map->{+FB_DSL_RATE}="down: ".int($ds_rate)." kBit/s, up: ".int($us_rate)." kBit/s";
  2624. }
  2625. return $map;
  2626. }
  2627. # Ausrechnet aus der Zahl der Sekunden Anzeige in Tagen:Stunden:Minuten:Sekunden.
  2628. sub SYSMON_sec2Dauer($){
  2629. my ($t) = @_;
  2630. my $d = int($t/86400);
  2631. my $r = $t-($d*86400);
  2632. my $h = int($r/3600);
  2633. $r = $r - ($h*3600);
  2634. my $m = int($r/60);
  2635. my $s = $r - $m*60;
  2636. return sprintf("%02d Tage %02d Std. %02d Min. %02d Sec.",$d,$h,$m,$s);
  2637. }
  2638. #Sync-Zeit mit Vermittlungsstelle abfragen
  2639. sub SYSMON_getFBSyncTime($$) {
  2640. my ($hash, $map) = @_;
  2641. if($hash->{helper}->{excludes}{'fbdsl'}) {return $map;}
  2642. my $data = SYSMON_execute($hash, "ctlmgr_ctl r sar status/modem_ShowtimeSecs");
  2643. unless($data) {
  2644. return SYSMON_getFBSyncTime2($hash, $map);
  2645. }
  2646. if($data ne "") {
  2647. my $idata = int($data);
  2648. $map->{+FB_DSL_SYNCTIME}=SYSMON_sec2Dauer($idata);
  2649. }
  2650. return $map;
  2651. }
  2652. #Sync-Zeit mit Vermittlungsstelle abfragen mit neuer FritzOS (6.23)
  2653. sub SYSMON_getFBSyncTime2($$) {
  2654. my ($hash, $map) = @_;
  2655. if($hash->{helper}->{excludes}{'fbdsl'}) {return $map;}
  2656. my $data = SYSMON_execute($hash, "ctlmgr_ctl r dslstatistic status/ifacestat0/connect_time");
  2657. if(defined($data) && $data ne "") {
  2658. $map->{+FB_DSL_SYNCTIME}=$data;
  2659. }
  2660. return $map;
  2661. }
  2662. #Uebertragungsfehler abfragen (nicht behebbar und behebbar)
  2663. sub SYSMON_getFBCRCFEC($$) {
  2664. my ($hash, $map) = @_;
  2665. if($hash->{helper}->{excludes}{'fbdsl'}) {return $map;}
  2666. my $ds_crc = SYSMON_execute($hash, "ctlmgr_ctl r sar status/ds_crc_per15min");
  2667. my $us_crc = SYSMON_execute($hash, "ctlmgr_ctl r sar status/us_crc_per15min");
  2668. my $ds_fec = SYSMON_execute($hash, "ctlmgr_ctl r sar status/ds_fec_per15min");
  2669. my $us_fec = SYSMON_execute($hash, "ctlmgr_ctl r sar status/us_fec_per15min");
  2670. if(defined($ds_crc) && $ds_crc ne "") {
  2671. # FB_DSL_CRC_15
  2672. $map->{+FB_DSL_CRC_15}="down: ".int($ds_crc)." up: ".int($us_crc);
  2673. }
  2674. if(defined($ds_fec) && $ds_fec ne "") {
  2675. # FB_DSL_FEC_15
  2676. $map->{+FB_DSL_FEC_15}="down: ".int($ds_fec)." up: ".int($us_fec);
  2677. }
  2678. return $map;
  2679. }
  2680. #------------------------------------------------------------------------------
  2681. # Systemparameter als HTML-Tabelle ausgeben
  2682. # Parameter: Name des SYSMON-Geraetes (muss existieren, kann auch anderer Modul genutzt werden), dessen Daten zur Anzeige gebracht werden sollen.
  2683. # (optional) Liste der anzuzeigenden Werte (ReadingName[:Comment:[Postfix[:FormatString]]],...)
  2684. # Beispiel: define sysv weblink htmlCode {SYSMON_ShowValuesHTML('sysmon', ('date:Datum', 'cpu_temp:CPU Temperatur: °C', 'cpu_freq:CPU Frequenz: MHz'))}
  2685. #------------------------------------------------------------------------------
  2686. sub SYSMON_ShowValuesHTML ($;@)
  2687. {
  2688. my ($name, @data) = @_;
  2689. return SYSMON_ShowValuesFmt($name, undef, 1, @data);
  2690. }
  2691. #------------------------------------------------------------------------------
  2692. # Systemparameter als HTML-Tabelle ausgeben. Zusaetzlich wird eine Ueberschrift ausgegeben.
  2693. # Parameter: Name des SYSMON-Geraetes (muss existieren, kann auch anderer Modul genutzt werden), dessen Daten zur Anzeige gebracht werden sollen.
  2694. # Title: Ueberschrift (Text)
  2695. # (optional) Liste der anzuzeigenden Werte (ReadingName[:Comment:[Postfix[:FormatString]]],...)
  2696. # Beispiel: define sysv weblink htmlCode {SYSMON_ShowValuesHTML('sysmon', ('date:Datum', 'cpu_temp:CPU Temperatur: °C', 'cpu_freq:CPU Frequenz: MHz'))}
  2697. #------------------------------------------------------------------------------
  2698. sub SYSMON_ShowValuesHTMLTitled ($;$@)
  2699. {
  2700. my ($name, $title, @data) = @_;
  2701. $title = $attr{$name}{'alias'} unless $title;
  2702. $title = $name unless $title;
  2703. return SYSMON_ShowValuesFmt($name, $title, 1, @data);
  2704. }
  2705. #------------------------------------------------------------------------------
  2706. # Systemparameter im Textformat ausgeben
  2707. # Parameter: Name des SYSMON-Geraetes (muss existieren, kann auch anderer Modul genutzt werden), dessen Daten zur Anzeige gebracht werden sollen.
  2708. # (optional) Liste der anzuzeigenden Werte (ReadingName[:Comment:[Postfix[:FormatString]]],...)
  2709. # Beispiel: define sysv weblink htmlCode {SYSMON_ShowValuesText('sysmon', ('date:Datum', 'cpu_temp:CPU Temperatur: °C', 'cpu_freq:CPU Frequenz: MHz'))}
  2710. #------------------------------------------------------------------------------
  2711. sub SYSMON_ShowValuesText ($;@)
  2712. {
  2713. my ($name, @data) = @_;
  2714. return SYSMON_ShowValuesFmt($name, undef, 0, @data);
  2715. }
  2716. #------------------------------------------------------------------------------
  2717. # Systemparameter im Textformat ausgeben
  2718. # Parameter: Name des SYSMON-Geraetes (muss existieren, kann auch anderer Modul genutzt werden), dessen Daten zur Anzeige gebracht werden sollen.
  2719. # Title: Ueberschrift (Text)
  2720. # (optional) Liste der anzuzeigenden Werte (ReadingName[:Comment:[Postfix[:FormatString]]],...)
  2721. # Beispiel: define sysv weblink htmlCode {SYSMON_ShowValuesText('sysmon', ('date:Datum', 'cpu_temp:CPU Temperatur: °C', 'cpu_freq:CPU Frequenz: MHz'))}
  2722. #------------------------------------------------------------------------------
  2723. sub SYSMON_ShowValuesTextTitled ($;$@)
  2724. {
  2725. my ($name, $title, @data) = @_;
  2726. $title = $attr{$name}{'alias'} unless $title;
  2727. $title = $name unless $title;
  2728. return SYSMON_ShowValuesFmt($name, $title, 0, @data);
  2729. }
  2730. #------------------------------------------------------------------------------
  2731. # Systemparameter formatiert ausgeben
  2732. # Parameter:
  2733. # Name des SYSMON-Geraetes (muss existieren), dessen Daten zur Anzeige gebracht werden sollen.
  2734. # Title: Ueberschrift
  2735. # Format: 0 = Text, 1 = HTML
  2736. # (optional) Liste der anzuzeigenden Werte (ReadingName[:Comment:[Postfix[:FormatString]]],...)
  2737. #------------------------------------------------------------------------------
  2738. sub SYSMON_ShowValuesFmt ($$$;@)
  2739. {
  2740. my ($name, $title, $format, @data) = @_;
  2741. if($format != 0 && $format != 1) {
  2742. return "unknown output format\r\n";
  2743. }
  2744. my $hash = $main::defs{$name};
  2745. # nur, wenn es sich um eine SYSMON Instanz handelt
  2746. if($hash->{TYPE} eq 'SYSMON') {
  2747. SYSMON_updateCurrentReadingsMap($hash);
  2748. }
  2749. #Log 3, "SYSMON $>name, @data<";
  2750. my @dataDescription = @data;
  2751. if(scalar(@data)<=0) {
  2752. # Array mit anzuzeigenden Parametern (Prefix, Name (in Map), Postfix)
  2753. my $deg = "°";
  2754. if($format == 1) {
  2755. $deg = "&deg;";
  2756. }
  2757. # bei der Benutzung mit CloneDummies ist $cur_readings_map nicht unbedingt definiert
  2758. @dataDescription = (DATE,
  2759. #CPU_TEMP.":".$hash->{helper}{cur_readings_map}->{+CPU_TEMP}.": ".$deg."C",
  2760. CPU_TEMP.":"."CPU temperature".": ".$deg."C".":%.1f",
  2761. #CPU_FREQ.":".$hash->{helper}{cur_readings_map}->{+CPU_FREQ}.": "."MHz",
  2762. CPU_FREQ.":"."CPU frequency".": "."MHz",
  2763. CPU_MODEL_NAME, CPU_BOGOMIPS,
  2764. UPTIME_TEXT, FHEMUPTIME_TEXT, LOADAVG, RAM, SWAP,
  2765. "power_ac_text", "power_usb_text", "power_battery_text");
  2766. # network-interfaces
  2767. my $networks = AttrVal($name, "network-interfaces", undef);
  2768. if(defined $networks) {
  2769. my @networks_list = split(/,\s*/, trim($networks));
  2770. foreach (@networks_list) {
  2771. my($nName, $nDef, $nComment) = split(/:/, $_);
  2772. push(@dataDescription, $nName);
  2773. }
  2774. }
  2775. # named filesystems
  2776. my $filesystems = AttrVal($name, "filesystems", undef);
  2777. if(defined $filesystems) {
  2778. my @filesystem_list = split(/,\s*/, trim($filesystems));
  2779. foreach (@filesystem_list) {
  2780. my($fName, $fDef, $fComment) = split(/:/, $_);
  2781. push(@dataDescription, $fName);
  2782. }
  2783. }
  2784. # User defined
  2785. my $userdefined = AttrVal($name, "user-defined", undef);
  2786. if(defined $userdefined) {
  2787. my @userdefined_list = split(/,\s*/, trim($userdefined));
  2788. foreach (@userdefined_list) {
  2789. # <readingName>:<Interval_Minutes>:<Comment>:<Cmd>
  2790. my($uName, $uInterval, $uComment, $uCmd) = split(/:/, $_);
  2791. push(@dataDescription, $uName);
  2792. }
  2793. }
  2794. }
  2795. #TODO: UserDefinedFn?
  2796. my $map;
  2797. if($hash->{TYPE} eq 'SYSMON') {
  2798. $map = SYSMON_obtainParameters($hash, 1);
  2799. } else {
  2800. # Wenn nicht SYSMON, dann versuchen, die Daten aus den Readings auszulesen
  2801. #$map = SYSMON_obtainReadings($hash);
  2802. foreach my $rname (keys %{$hash->{READINGS}}) {
  2803. my $rval=$hash->{READINGS}->{$rname}->{VAL};
  2804. $map->{$rname}=$rval;
  2805. }
  2806. }
  2807. my $div_class="sysmon";
  2808. my $htmlcode;
  2809. if($format == 1) {
  2810. $htmlcode = "<div class='".$div_class."'><table>";
  2811. } else {
  2812. if($format == 0) {
  2813. $htmlcode = "";
  2814. }
  2815. }
  2816. if(defined $title) {
  2817. if($format == 1) {
  2818. $htmlcode .= "<tr><td valign='top' colspan='2'>".$title."</td></tr>";
  2819. } else {
  2820. if($format == 0) {
  2821. $htmlcode .= sprintf("%s\r\n", $title);
  2822. }
  2823. }
  2824. }
  2825. # oben definierte Werte anzeigen
  2826. foreach (@dataDescription) {
  2827. my($rName, $rComment, $rPostfix, $fmtStr) = split(/:/, $_);
  2828. if(defined $rName) {
  2829. if(!defined $rComment) {
  2830. $rComment = $hash->{helper}{cur_readings_map}->{$rName};
  2831. }
  2832. my $rVal = $map->{$rName};
  2833. if(!defined $rVal) {
  2834. # ggf. userReadings verarbeiten
  2835. $rVal = ReadingsVal($name,$rName,undef);
  2836. }
  2837. if($rName eq DATE) {
  2838. # Datum anzeigen
  2839. $rVal = strftime("%d.%m.%Y %H:%M:%S", localtime());
  2840. }
  2841. if(!defined $rPostfix) { $rPostfix = ""; }
  2842. if(defined $rVal) {
  2843. if(defined($fmtStr)) {
  2844. $rVal = sprintf($fmtStr,$rVal);
  2845. }
  2846. if($format == 1) {
  2847. $htmlcode .= "<tr><td valign='top'>".$rComment.":&nbsp;</td><td>".$rVal.$rPostfix."</td></tr>";
  2848. } else {
  2849. if($format == 0) {
  2850. $htmlcode .= sprintf("%-24s: %s%s\r\n", $rComment, $rVal,$rPostfix);
  2851. }
  2852. }
  2853. }
  2854. }
  2855. }
  2856. # nur Default (also alles anzeigen)
  2857. if(scalar(@data)<=0) {
  2858. # File systems
  2859. foreach my $aName (sort keys %{$map}) {
  2860. if(defined ($aName) && index($aName, FS_PREFIX) == 0) {
  2861. $aName =~ /^~ (.+)/;
  2862. if($format == 1) {
  2863. $htmlcode .= "<tr><td valign='top'>File System: ".$1."&nbsp;</td><td>".$map->{$aName}."</td></tr>";
  2864. } else {
  2865. if($format == 0) {
  2866. $htmlcode .= sprintf("%-24s: %s\r\n", "File System: ".$1,$map->{$aName});
  2867. }
  2868. }
  2869. }
  2870. }
  2871. }
  2872. if($format == 1) {
  2873. $htmlcode .= "</table></div><br>";
  2874. } else {
  2875. if($format == 0) {
  2876. $htmlcode .= "";
  2877. }
  2878. }
  2879. return $htmlcode;
  2880. }
  2881. #sub SYSMON_first($) {
  2882. # my (@d) = @_;
  2883. # return @d[0];
  2884. #
  2885. # #my ($d) = @_;
  2886. # #
  2887. # #return undef unless defined $d;
  2888. #
  2889. # ##return ref ($d)." - ".ref(\$d);
  2890. # #if (ref $d eq "ARRAY") {
  2891. # # return @{$d}[0];
  2892. # #} else {
  2893. # # return $d;
  2894. # #}
  2895. #}
  2896. #
  2897. #sub SYSMON_last($) {
  2898. # my (@d) = @_;
  2899. #
  2900. # return undef unless defined @d;
  2901. #
  2902. # return @d[-1];
  2903. #
  2904. # #return ref ($d)." - ".ref(\$d);
  2905. # #if (ref $d eq "ARRAY") {
  2906. # # return @{$d}[-1];
  2907. # #} else {
  2908. # # return $d;
  2909. # #}
  2910. #}
  2911. #my $proc_fs = undef;
  2912. sub
  2913. SYSMON_isProcFS($) {
  2914. my ($hash) = @_;
  2915. if(!defined $hash->{helper}{proc_fs}) {
  2916. $hash->{helper}{proc_fs} = int(SYSMON_execute($hash, "[ -d /proc/ ] && echo 1 || echo 0"));
  2917. }
  2918. return $hash->{helper}{proc_fs};
  2919. }
  2920. #my $sys_cpu_temp_rpi = undef;
  2921. sub
  2922. SYSMON_isCPUTempRPi($) {
  2923. my ($hash) = @_;
  2924. if(!defined $hash->{helper}{sys_cpu_temp_rpi}) {
  2925. $hash->{helper}{sys_cpu_temp_rpi} = int(SYSMON_execute($hash, "[ -f /sys/class/thermal/thermal_zone0/temp ] && echo 1 || echo 0"));
  2926. }
  2927. return $hash->{helper}{sys_cpu_temp_rpi};
  2928. }
  2929. #my $sys_cpu_temp_bbb = undef;
  2930. sub
  2931. SYSMON_isCPUTempBBB($) {
  2932. my ($hash) = @_;
  2933. if(!defined $hash->{helper}{sys_cpu_temp_bbb}) {
  2934. $hash->{helper}{sys_cpu_temp_bbb} = int(SYSMON_execute($hash, "[ -f /sys/class/hwmon/hwmon0/device/temp1_input ] && echo 1 || echo 0"));
  2935. }
  2936. return $hash->{helper}{sys_cpu_temp_bbb};
  2937. }
  2938. #my $sys_cpu_freq_rpi_bbb = undef;
  2939. sub
  2940. SYSMON_isCPUFreqRPiBBB($) {
  2941. my ($hash) = @_;
  2942. if(!defined $hash->{helper}{sys_cpu_freq_rpi_bbb}) {
  2943. #$hash->{helper}{sys_cpu_freq_rpi_bbb} = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ] && echo 1 || echo 0"));
  2944. # Diese abenteuerliche Konstruktion ist noetig, weil bei zu langen Zeilen ueber Telnet der Rest der Zeile als erstes Element kommt
  2945. my @t = SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ] && echo 1 || echo 0");
  2946. if(@t) {
  2947. $hash->{helper}{sys_cpu_freq_rpi_bbb} = int($t[-1]);
  2948. }
  2949. }
  2950. return $hash->{helper}{sys_cpu_freq_rpi_bbb};
  2951. }
  2952. # DUMMY
  2953. sub SYSMON_isCPUTempFB($) {
  2954. my ($hash) = @_;
  2955. return SYSMON_isFB($hash);
  2956. }
  2957. sub
  2958. SYSMON_isCPUTemp_X($$) {
  2959. my ($hash, $cpuNum) = @_;
  2960. if(!defined $hash->{helper}{"sys_cpu".$cpuNum."_temp"}) {
  2961. #/sys/class/hwmon/hwmon0/device/hwmon/hwmon0/temp2_input
  2962. #$hash->{helper}{"sys_cpu".$cpuNum."_temp"} = int(SYSMON_execute($hash, "[ -f /sys/class/hwmon/hwmon0/device/hwmon/hwmon0/temp".$cpuNum."_input ] && echo 1 || echo 0"));
  2963. # s. o.
  2964. my @t = SYSMON_execute($hash, "[ -f /sys/class/hwmon/hwmon0/device/hwmon/hwmon0/temp".($cpuNum+1)."_input ] && echo 1 || echo 0");
  2965. if(@t) {
  2966. $hash->{helper}{"sys_cpu".$cpuNum."_temp"} = int($t[-1]);
  2967. }
  2968. }
  2969. return $hash->{helper}{"sys_cpu".$cpuNum."_temp"};
  2970. }
  2971. sub
  2972. SYSMON_isCPUXFreq($$) {
  2973. my ($hash, $cpuNum) = @_;
  2974. if(!defined $hash->{helper}{"sys_cpu".$cpuNum."_freq"}) {
  2975. #$hash->{helper}{"sys_cpu".$cpuNum."_freq"} = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu".$cpuNum."/cpufreq/scaling_cur_freq ] && echo 1 || echo 0"));
  2976. # s. o.
  2977. my @t = SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu".$cpuNum."/cpufreq/scaling_cur_freq ] && echo 1 || echo 0");
  2978. if(@t) {
  2979. $hash->{helper}{"sys_cpu".$cpuNum."_freq"} = int($t[-1]);
  2980. }
  2981. }
  2982. return $hash->{helper}{"sys_cpu".$cpuNum."_freq"};
  2983. }
  2984. #my $sys_fb = undef;
  2985. sub
  2986. SYSMON_isFB($) {
  2987. my ($hash) = @_;
  2988. if(!defined ($hash->{helper}{sys_fb})) {
  2989. $hash->{helper}{sys_fb} = int(SYSMON_execute($hash, "[ -f /usr/bin/ctlmgr_ctl ] && echo 1 || echo 0"));
  2990. }
  2991. return $hash->{helper}{sys_fb};
  2992. }
  2993. #-Power-------
  2994. #my $sys_power_ac = undef;
  2995. sub
  2996. SYSMON_isSysPowerAc($) {
  2997. my ($hash) = @_;
  2998. if(!defined $hash->{helper}{sys_power_ac}) {
  2999. $hash->{helper}{sys_power_ac} = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/ac/online ] && echo 1 || echo 0"));
  3000. }
  3001. return $hash->{helper}{sys_power_ac};
  3002. }
  3003. #my $sys_power_usb = undef;
  3004. sub
  3005. SYSMON_isSysPowerUsb($) {
  3006. my ($hash) = @_;
  3007. if(!defined $hash->{helper}{sys_power_usb}) {
  3008. $hash->{helper}{sys_power_usb} = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/usb/online ] && echo 1 || echo 0"));
  3009. }
  3010. return $hash->{helper}{sys_power_usb};
  3011. }
  3012. #my $sys_power_bat = undef;
  3013. sub
  3014. SYSMON_isSysPowerBat($) {
  3015. my ($hash) = @_;
  3016. if(!defined $hash->{helper}{sys_power_bat}) {
  3017. $hash->{helper}{sys_power_bat} = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/battery/online ] && echo 1 || echo 0"));
  3018. }
  3019. return $hash->{helper}{sys_power_bat};
  3020. }
  3021. #my $sys_cpu_num = undef;
  3022. sub
  3023. SYSMON_isSysCpuNum($) {
  3024. my ($hash) = @_;
  3025. if(!defined $hash->{helper}{sys_cpu_num}) {
  3026. $hash->{helper}{sys_cpu_num} = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/kernel_max ] && echo 1 || echo 0"));
  3027. }
  3028. return $hash->{helper}{sys_cpu_num};
  3029. }
  3030. sub
  3031. SYSMON_isNetStatClass($$) {
  3032. my ($hash, $nName) = @_;
  3033. if(!defined $hash->{helper}{'net_'.$nName.'_stat_class'}) {
  3034. $hash->{helper}{'net_'.$nName.'_stat_class'} = int(SYSMON_execute($hash, "[ -f /sys/class/net/$nName/statistics/rx_bytes ] && echo 1 || echo 0"));
  3035. # /sys/class/net/$nName/statistics/tx_bytes
  3036. }
  3037. return $hash->{helper}{'net_'.$nName.'_stat_class'};
  3038. }
  3039. sub SYSMON_PowerAcInfo($$) {
  3040. #online, present, current_now (/1000 =>mA), voltage_now (/1000000 => V)
  3041. my ($hash, $map) = @_;
  3042. if($hash->{helper}->{excludes}{'powerinfo'}) {return $map;}
  3043. my $type="ac";
  3044. my $base = "cat /sys/class/power_supply/".$type."/";
  3045. my $d_online = trim(SYSMON_execute($hash, $base."online"));
  3046. my $d_present = trim(SYSMON_execute($hash, $base."present"));
  3047. my $d_current = SYSMON_execute($hash, $base."current_now");
  3048. if(defined $d_current) {$d_current/=1000;}
  3049. my $d_voltage = SYSMON_execute($hash, $base."voltage_now");
  3050. if(defined $d_voltage) {$d_voltage/=1000000;}
  3051. #$map->{"power_".$type."_online"}=$d_online;
  3052. #$map->{"power_".$type."_present"}=$d_present;
  3053. #$map->{"power_".$type."_current"}=$d_current;
  3054. #$map->{"power_".$type."_voltage"}=$d_voltage;
  3055. $map->{"power_".$type."_stat"}="$d_online $d_present $d_voltage $d_current";
  3056. $map->{"power_".$type."_text"}=$type.": ".(($d_present eq "1") ? "present" : "absent")." / ".($d_online eq "1" ? "online" : "offline").", voltage: ".$d_voltage." V, current: ".$d_current." mA, ".(int(($d_voltage*$d_current/100+0.5))/10)." W";
  3057. return $map;
  3058. }
  3059. sub SYSMON_PowerUsbInfo($$) {
  3060. #online, present, current_now (/1000 =>mA), voltage_now (/1000000 => V)
  3061. my ($hash, $map) = @_;
  3062. if($hash->{helper}->{excludes}{'powerinfo'}) {return $map;}
  3063. my $type="usb";
  3064. my $base = "cat /sys/class/power_supply/".$type."/";
  3065. my $d_online = trim(SYSMON_execute($hash, $base."online"));
  3066. my $d_present = trim(SYSMON_execute($hash, $base."present"));
  3067. my $d_current = SYSMON_execute($hash, $base."current_now");
  3068. if(defined $d_current) {$d_current/=1000;}
  3069. my $d_voltage = SYSMON_execute($hash, $base."voltage_now");
  3070. if(defined $d_voltage) {$d_voltage/=1000000;}
  3071. #$map->{"power_".$type."_online"}=$d_online;
  3072. #$map->{"power_".$type."_present"}=$d_present;
  3073. #$map->{"power_".$type."_current"}=$d_current;
  3074. #$map->{"power_".$type."_voltage"}=$d_voltage;
  3075. $map->{"power_".$type."_stat"}="$d_online $d_present $d_voltage $d_current";
  3076. $map->{"power_".$type."_text"}=$type.": ".(($d_present eq "1") ? "present" : "absent")." / ".($d_online eq "1" ? "online" : "offline").", voltage: ".$d_voltage." V, current: ".$d_current." mA, ".(int(($d_voltage*$d_current/100+0.5))/10)." W";
  3077. return $map;
  3078. }
  3079. sub SYSMON_PowerBatInfo($$) {
  3080. #online, present, current_now (/1000 =>mA), voltage_now (/1000000 => V)
  3081. my ($hash, $map) = @_;
  3082. if($hash->{helper}->{excludes}{'powerinfo'}) {return $map;}
  3083. my $type="battery";
  3084. my $base = "cat /sys/class/power_supply/".$type."/";
  3085. my $d_online = trim(SYSMON_execute($hash, $base."online"));
  3086. my $d_present = trim(SYSMON_execute($hash, $base."present"));
  3087. my $d_current = SYSMON_execute($hash, $base."current_now");
  3088. if(defined $d_current) {$d_current/=1000;}
  3089. my $d_voltage = SYSMON_execute($hash, $base."voltage_now");
  3090. if(defined $d_voltage) {$d_voltage/=1000000;}
  3091. my $d_capacity = trim(SYSMON_execute($hash, $base."capacity"));
  3092. if($d_present ne "1") {
  3093. $d_capacity = "0";
  3094. }
  3095. #$map->{"power_".$type."_online"}=$d_online;
  3096. #$map->{"power_".$type."_present"}=$d_present;
  3097. #$map->{"power_".$type."_current"}=$d_current;
  3098. #$map->{"power_".$type."_voltage"}=$d_voltage;
  3099. $map->{"power_".$type."_stat"}="$d_online $d_present $d_voltage $d_current $d_capacity";
  3100. $map->{"power_".$type."_text"}=$type.": ".(($d_present eq "1") ? "present" : "absent")." / ".($d_online eq "1" ? "online" : "offline").", voltage: ".$d_voltage." V, current: ".$d_current." mA, ".(int(($d_voltage*$d_current/100+0.5))/10)." W, "."capacity: ".$d_capacity." %";
  3101. if($d_present eq "1") {
  3102. # Zusaetzlich: technology, capacity, status, health, temp (/10 => °C)
  3103. my $d_technology = trim(SYSMON_execute($hash, $base."technology"));
  3104. my $d_status = trim(SYSMON_execute($hash, $base."status"));
  3105. my $d_health = trim(SYSMON_execute($hash, $base."health"));
  3106. my $d_energy_full_design = trim(SYSMON_execute($hash, $base."energy_full_design"));
  3107. $map->{"power_".$type."_info"}=$type." info: ".$d_technology." , capacity: ".$d_capacity." %, status: ".$d_status." , health: ".$d_health." , total capacity: ".$d_energy_full_design." mAh";
  3108. # ggf. noch irgendwann: model_name, voltage_max_design, voltage_min_design
  3109. } else {
  3110. $map->{"power_".$type."_info"}=$type." info: n/a , capacity: n/a %, status: n/a , health: n/a , total capacity: n/a mAh";
  3111. }
  3112. return $map;
  3113. }
  3114. #-------------
  3115. sub SYSMON_execute($$)
  3116. {
  3117. my ($hash, $cmd) = @_;
  3118. return SYSMON_Exec($hash, $cmd);
  3119. #return qx($cmd);
  3120. }
  3121. #------------------------------------------------------------------------------
  3122. # checks and stores password used for remote connection
  3123. sub SYSMON_storePassword($$)
  3124. {
  3125. my ($hash, $password) = @_;
  3126. my $index = $hash->{TYPE}."_".$hash->{NAME}."_passwd";
  3127. my $key = getUniqueId().$index;
  3128. my $enc_pwd = "";
  3129. if(eval "use Digest::MD5;1")
  3130. {
  3131. $key = Digest::MD5::md5_hex(unpack "H*", $key);
  3132. $key .= Digest::MD5::md5_hex($key);
  3133. }
  3134. for my $char (split //, $password)
  3135. {
  3136. my $encode=chop($key);
  3137. $enc_pwd.=sprintf("%.2x",ord($char)^ord($encode));
  3138. $key=$encode.$key;
  3139. }
  3140. my $err = setKeyValue($index, $enc_pwd);
  3141. $hash->{helper}{error_msg}=$err;
  3142. return "error while saving the password - $err" if(defined($err));
  3143. return "password successfully saved";
  3144. }
  3145. # read password
  3146. sub SYSMON_readPassword($)
  3147. {
  3148. my ($hash) = @_;
  3149. my $name = $hash->{NAME};
  3150. my $index = $hash->{TYPE}."_".$hash->{NAME}."_passwd";
  3151. my $key = getUniqueId().$index;
  3152. my ($password, $err);
  3153. SYSMON_Log($hash, 5, "Read password from file");
  3154. ($err, $password) = getKeyValue($index);
  3155. if(defined($err))
  3156. {
  3157. SYSMON_Log($hash, 3, "unable to read password from file: $err");
  3158. return undef;
  3159. }
  3160. if(defined($password))
  3161. {
  3162. if(eval "use Digest::MD5;1")
  3163. {
  3164. $key = Digest::MD5::md5_hex(unpack "H*", $key);
  3165. $key .= Digest::MD5::md5_hex($key);
  3166. }
  3167. my $dec_pwd = '';
  3168. for my $char (map { pack('C', hex($_)) } ($password =~ /(..)/g))
  3169. {
  3170. my $decode=chop($key);
  3171. $dec_pwd.=chr(ord($char)^ord($decode));
  3172. $key=$decode.$key;
  3173. }
  3174. return $dec_pwd;
  3175. }
  3176. else
  3177. {
  3178. SYSMON_Log($hash, 2, "No password in file");
  3179. return undef;
  3180. }
  3181. }
  3182. # Opens a Telnet Connection to an external Machine
  3183. ############################################
  3184. sub SYSMON_Open_Connection($)
  3185. {
  3186. my ($hash) = @_;
  3187. my $name = $hash->{NAME};
  3188. my $msg;
  3189. my $mode = $hash->{MODE};#AttrVal( $name, 'mode', 'local');
  3190. if ($mode eq 'local') {
  3191. return undef;
  3192. }
  3193. if($missingModulRemote) {
  3194. $msg="Error: Perl modul ".$missingModulRemote."is missing on this system. Please install before using this modul.";
  3195. SYSMON_Log($hash, 3, $msg);
  3196. return $msg;
  3197. }
  3198. my $host = $hash->{HOST};#AttrVal( $name, "remote_host", undef );
  3199. if(!defined $host) {
  3200. $msg="Error: no remote host provided";
  3201. SYSMON_Log($hash, 3, $msg);
  3202. return $msg unless defined $host;
  3203. }
  3204. my $port = $hash->{PORT};#AttrVal( $name, "remote_port", 23 );
  3205. my $pwd = SYSMON_readPassword($hash);#AttrVal( $name, "remote_password", undef );
  3206. my $user = $hash->{USER};#AttrVal( $name, "remote_user", "" );
  3207. $user="" unless defined($user);
  3208. #test
  3209. #$pwd="dummy";
  3210. #test
  3211. my $before;
  3212. my $match;
  3213. #if(!defined($pwd)) {
  3214. # my $pwdFile = AttrVal( $name, "pwdFile", undef);
  3215. # if(defined($pwdFile)) {
  3216. # SYSMON_Log($hash, 5, "Open password file '$pwdFile' to extract password");
  3217. # if (open(IN, "<" . $pwdFile)) {
  3218. # $pwd = <IN>;
  3219. # close(IN);
  3220. # SYSMON_Log($hash, 5, "Close password file");
  3221. # } else {
  3222. # $msg = "Error: Cannot open password file '$pwdFile': $!";
  3223. # SYSMON_Log($hash, 2, $msg);
  3224. # return $msg;
  3225. # }
  3226. # }
  3227. #}
  3228. if(!defined($pwd)) {
  3229. $msg="Error: no passwort provided";
  3230. SYSMON_Log($hash, 3, $msg);
  3231. return $msg unless defined $pwd;
  3232. }
  3233. SYSMON_Log($hash, 5, "Open Telnet connection to $host:$port");
  3234. my $timeout = AttrVal( $name, "telnet-time-out", "10");
  3235. my $t_prompt=AttrVal($name,'telnet-prompt-regx','(#|\$)\s*$');
  3236. #my $telnet = new Net::Telnet ( Host=>$host, Port => $port, Timeout=>$timeout, Errmode=>'return', Prompt=>'/(#|\$) $/');
  3237. my $telnet = new Net::Telnet ( Host=>$host, Port => $port, Timeout=>$timeout, Errmode=>'return', Prompt=>'/'.$t_prompt.'/');
  3238. if (!$telnet) {
  3239. $msg = "Could not open telnet connection to $host:$port";
  3240. SYSMON_Log($hash, 2, $msg);
  3241. $telnet = undef;
  3242. $hash->{".telnet"}=$telnet;
  3243. return $msg;
  3244. }
  3245. $hash->{".telnet"}=$telnet;
  3246. SYSMON_Log($hash, 5, "Wait for user or password prompt.");
  3247. unless ( ($before,$match) = $telnet->waitfor('/(user|login|password): $/i') )
  3248. {
  3249. $msg = "Telnet error while waiting for user or password prompt: ".$telnet->errmsg;
  3250. SYSMON_Log($hash, 2, $msg);
  3251. $telnet->close;
  3252. $telnet = undef;
  3253. return $msg;
  3254. }
  3255. if ( $match =~ /(user|login): / && $user eq "")
  3256. {
  3257. $msg = "Telnet login requires user name but attribute 'telnetUser' not defined";
  3258. SYSMON_Log($hash, 2, $msg);
  3259. $telnet->close;
  3260. $telnet = undef;
  3261. return $msg;
  3262. }
  3263. elsif ( $match =~ /(user|login): /)
  3264. {
  3265. SYSMON_Log($hash, 5, "Entering user name");
  3266. $telnet->print( $user );
  3267. SYSMON_Log($hash, 5, "Wait for password prompt");
  3268. unless ($telnet->waitfor( '/password: $/i' ))
  3269. {
  3270. $msg = "Telnet error while waiting for password prompt: ".$telnet->errmsg;
  3271. SYSMON_Log($hash, 2, $msg);
  3272. $telnet->close;
  3273. $telnet = undef;
  3274. return $msg;
  3275. }
  3276. }
  3277. elsif ( $match eq "password: " && $user ne "")
  3278. {
  3279. SYSMON_Log($hash, 3, "remote user was defined but telnet login did not prompt for user name.");
  3280. }
  3281. SYSMON_Log($hash, 5, "Entering password");
  3282. $telnet->print( $pwd );
  3283. SYSMON_Log($hash, 5, "Wait for command prompt");
  3284. my $tlogin_prompt=AttrVal($name,'telnet-login-prompt-regx','(#|\$|>)\s*$|Login failed.');
  3285. #unless ( ($before,$match) = $telnet->waitfor( '/# $|Login failed./i' ))
  3286. unless ( ($before,$match) = $telnet->waitfor( '/'.$tlogin_prompt.'/i' ))
  3287. {
  3288. $msg = "Telnet error while waiting for command prompt: ".$telnet->errmsg;
  3289. SYSMON_Log($hash, 2, $msg);
  3290. $telnet->close;
  3291. $telnet = undef;
  3292. return $msg;
  3293. }
  3294. elsif ( $match eq "Login failed.")
  3295. {
  3296. $msg = "Telnet error: Login failed. Wrong password.";
  3297. SYSMON_Log($hash, 2, $msg);
  3298. $telnet->close;
  3299. $telnet = undef;
  3300. return $msg;
  3301. }
  3302. #SYSMON_Log($hash, 2, "Prompt: ".Dumper($before)." > ".$match);
  3303. # Promptzeile erkenen
  3304. if(!($hash->{helper}{recognized_prompt})) {
  3305. my @prompt = SYSMON_Exec_Remote($hash, '');
  3306. if(scalar(@prompt) == 1) {
  3307. $hash->{helper}{recognized_prompt}=$prompt[0];
  3308. }
  3309. }
  3310. #SYSMON_Log($hash, 2, "Prompt: '".Dumper(@retVal)."'");
  3311. return undef;
  3312. } # end SYSMON_Open_Connection
  3313. # Closes a Telnet Connection to an external Machine
  3314. ############################################
  3315. sub SYSMON_Close_Connection($)
  3316. {
  3317. my ($hash) = @_;
  3318. my $name = $hash->{NAME};
  3319. my $mode = $hash->{MODE};#AttrVal( $name, 'mode', 'local');
  3320. if (!defined($mode) || $mode eq 'local') {
  3321. return undef;
  3322. }
  3323. my $telnet = $hash->{".telnet"};
  3324. if (defined $telnet)
  3325. {
  3326. SYSMON_Log ($hash, 5, "Close Telnet connection");
  3327. $telnet->close;
  3328. $telnet = undef;
  3329. $hash->{".telnet"}=$telnet;
  3330. }
  3331. else
  3332. {
  3333. SYSMON_Log($hash, 1, "Cannot close an undefined Telnet connection");
  3334. }
  3335. } # end SYSMON_Close_Connection
  3336. # Executed the command on the remote Shell
  3337. ############################################
  3338. sub SYSMON_Exec($$;$)
  3339. {
  3340. my ($hash, $cmd,$is_arr) = @_;
  3341. my $openedTelnet = 0;
  3342. my $telnet = $hash->{".telnet"};
  3343. #TODO: SSH
  3344. my $name = $hash->{NAME};
  3345. my $mode = $hash->{MODE};#AttrVal( $name, 'mode', 'local');
  3346. if ($mode eq 'telnet') {
  3347. unless (defined $telnet)
  3348. {
  3349. SYSMON_Log($hash, 5, "$name: Open single telnet connection");
  3350. my $msg = SYSMON_Open_Connection($hash);
  3351. $hash->{helper}{error_msg}=$msg;
  3352. if ($msg) {
  3353. return undef;
  3354. }
  3355. $openedTelnet = 1;
  3356. $hash->{helper}{error_msg}=undef;
  3357. }
  3358. my @retVal = SYSMON_Exec_Remote($hash, $cmd);
  3359. if($openedTelnet) {
  3360. SYSMON_Log($hash, 5, "$name: Close single telnet connection");
  3361. SYSMON_Close_Connection( $hash );
  3362. }
  3363. #Prompt-Zeile entfernen, falls vorhanden
  3364. my $recognized_prompt = $hash->{helper}{recognized_prompt};
  3365. if(defined($recognized_prompt)) {
  3366. if(scalar(@retVal)>=1) {
  3367. if($retVal[-1] eq $recognized_prompt) {
  3368. SYSMON_Log ($hash, 5, "remove prompt: ".$retVal[-1]."'");
  3369. splice @retVal, -1, 1;# $retVal[-1];
  3370. }
  3371. }
  3372. }
  3373. # Arrays als solche zurueckgeben
  3374. #if($is_arr && scalar(@retVal)>1) {
  3375. if(scalar(@retVal)>1) {
  3376. SYSMON_Log ($hash, 5, "Result A: '".Dumper(@retVal)."'");
  3377. return @retVal;
  3378. }
  3379. # Einzeiler als normale Scalars
  3380. my $line = $retVal[0];
  3381. if(defined($line)) {
  3382. chomp $line;
  3383. SYSMON_Log ($hash, 5, "Result L: '$line'");
  3384. } else {
  3385. SYSMON_Log ($hash, 5, "Result undef");
  3386. }
  3387. return $line;
  3388. #return $retVal;
  3389. } else {
  3390. return SYSMON_Exec_Local($hash, $cmd);
  3391. }
  3392. }
  3393. sub MYTEST() {
  3394. my @output=(
  3395. '',
  3396. '[~] ',
  3397. '',
  3398. '[~] # ',
  3399. '',
  3400. '',
  3401. '',
  3402. ' Interrupt:16 Memory:c0100000-c0120000 ',
  3403. '',
  3404. ' RX bytes:483322579219 (450.1 GiB) TX bytes:3757348645531 (3.4 TiB)',
  3405. '',
  3406. ' collisions:0 txqueuelen:1000 ',
  3407. '',
  3408. ' TX packets:3656315540 errors:0 dropped:0 overruns:0 carrier:0',
  3409. '',
  3410. ' RX packets:2817622543 errors:8 dropped:265294 overruns:0 frame:8',
  3411. '',
  3412. ' UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1',
  3413. '',
  3414. ' inet addr:192.168.178.80 Bcast:192.168.178.255 Mask:255.255.255.0',
  3415. '',
  3416. 'eth0 Link encap:Ethernet HWaddr 00:08:9B:D3:8D:9E'
  3417. );
  3418. @output = reverse(@output);
  3419. for (my $i=0;$i<scalar(@output);$i++) {
  3420. if($output[$i]=~ /^\[~\]/) {undef ($output[$i]);}
  3421. }
  3422. @output = grep{ defined($_) && trim($_) ne '' }@output;
  3423. return Dumper(@output);
  3424. }
  3425. # Executed the command via Telnet
  3426. sub ############################################
  3427. SYSMON_Exec_Remote($$)
  3428. {
  3429. my ($hash, $cmd) = @_;
  3430. my @output;
  3431. my $result;
  3432. my $telnet = $hash->{".telnet"};
  3433. SYSMON_Log($hash, 5, "Execute '".$cmd."'");
  3434. @output=$telnet->cmd($cmd);
  3435. #SYSMON_Log($hash, 5, "Result '".Dumper(@output)."'"); # TODO: remove
  3436. # Sonderlocke fuer QNAP: letzten Zeilen mit "[~] " am Anfang entfernen
  3437. #while((scalar(@output)>0) && ($output[-1]=~ /^\[~\]/)) {
  3438. # SYSMON_Log ($hash, 5, "Remove line: '".$output[-1]."'");
  3439. # splice @output, -1, 1;
  3440. #}
  3441. for (my $i=0;$i<scalar(@output);$i++) {
  3442. #SYSMON_Log($hash, 5, "Result >>> Line >>> '".$output[$i]."'"); # TODO: remove
  3443. if($output[$i]=~ /^\[~\]/) {undef ($output[$i]);}
  3444. }
  3445. #SYSMON_Log($hash, 5, "Result >>> vgrep >>>'".Dumper(@output)."'"); # TODO: remove
  3446. @output = grep{ defined($_) && trim($_) ne '' }@output;
  3447. #SYSMON_Log($hash, 5, "Result >>> ngrep >>>'".Dumper(@output)."'"); # TODO: remove
  3448. return @output;
  3449. ## Arrays als solche zurueckgeben
  3450. #if(scalar(@output)>1) {
  3451. # SYSMON_Log ($hash, 5, "Result '".Dumper(@output)."'");
  3452. # return @output;
  3453. #}
  3454. ## Einzeiler als normale Scalars
  3455. #my $line = @output[0];
  3456. #chomp $line;
  3457. #SYSMON_Log ($hash, 5, "Result '$line'");
  3458. #return $line;
  3459. #$result = $output[0];
  3460. ##chomp $result;
  3461. #my $log = join " ", @output;
  3462. #chomp $log;
  3463. #SYSMON_Log($hash, 5, "Result '$log'");
  3464. #return $result;
  3465. }
  3466. # Executed the command on the remote Shell
  3467. sub ############################################
  3468. SYSMON_Exec_Local($$)
  3469. {
  3470. my ($hash, $cmd) = @_;
  3471. SYSMON_Log($hash, 5, "Execute '".$cmd."'");
  3472. #return qx($cmd);
  3473. my @result = qx($cmd);
  3474. # Arrays als solche zurueckgeben
  3475. if(scalar(@result)>1) {
  3476. SYSMON_Log ($hash, 5, "Result '".Dumper(@result)."'");
  3477. return @result;
  3478. }
  3479. # Einzeiler als normale Scalars
  3480. my $line = $result[0];
  3481. if(defined($line)) {
  3482. chomp $line;
  3483. SYSMON_Log ($hash, 5, "Result '$line'");
  3484. } else {
  3485. SYSMON_Log ($hash, 5, "Result undef");
  3486. }
  3487. return $line;
  3488. #chomp $result;
  3489. #SYSMON_Log ($hash, 5, "Result '$result'");
  3490. #return $result;
  3491. }
  3492. #------------------------------------------------------------------------------
  3493. #------------------------------------------------------------------------------
  3494. # Uebersetzt Sekunden (Dauer) in Tage/Stunden/Minuten/Sekunden
  3495. #------------------------------------------------------------------------------
  3496. sub SYSMON_decode_time_diff($)
  3497. {
  3498. my $s = shift;
  3499. my $d = int($s/86400);
  3500. $s -= $d*86400;
  3501. my $h = int($s/3600);
  3502. $s -= $h*3600;
  3503. my $m = int($s/60);
  3504. #$s -= $m*60;
  3505. #return ($d,$h,$m,$s);
  3506. return ($d,$h,$m);
  3507. }
  3508. #------------------------------------------------------------------------------
  3509. # Logging: Funkrionsaufrufe
  3510. # Parameter: HASH, Funktionsname, Message
  3511. #------------------------------------------------------------------------------
  3512. #sub logF($$$)
  3513. #{
  3514. # my ($hash, $fname, $msg) = @_;
  3515. # #Log 5, "SYSMON $fname (".$hash->{NAME}."): $msg";
  3516. # Log 5, "SYSMON $fname $msg";
  3517. #}
  3518. sub SYSMON_Log($$$) {
  3519. my ( $hash, $loglevel, $text ) = @_;
  3520. my $xline = ( caller(0) )[2];
  3521. my $xsubroutine = ( caller(1) )[3];
  3522. my $sub = ( split( ':', $xsubroutine ) )[2];
  3523. $sub =~ s/SYSMON_//;
  3524. my $instName = ( ref($hash) eq "HASH" ) ? $hash->{NAME} : $hash;
  3525. $instName="" unless $instName;
  3526. Log3 $hash, $loglevel, "SYSMON $instName: $sub.$xline " . $text;
  3527. }
  3528. # -----------------------------------------------------------------------------
  3529. 1;
  3530. =pod
  3531. =item device
  3532. =item summary provides some statistics about the system
  3533. =item summary_DE liefert einige Statistiken ueber das Host-System
  3534. =begin html
  3535. <!-- ================================ -->
  3536. <a name="SYSMON"></a>
  3537. <h3>SYSMON</h3>
  3538. (en | <a href="commandref_DE.html#SYSMON">de</a>)
  3539. <ul>
  3540. This module provides statistics about the system running FHEM server. Furthermore, remote systems can be accessed (Telnet). Only Linux-based systems are supported.
  3541. Some informations are hardware specific and are not available on every platform.
  3542. So far, this module has been tested on the following systems:
  3543. Raspberry Pi (Debian Wheezy), BeagleBone Black, FritzBox 7390, WR703N under OpenWrt, CubieTruck and some others.
  3544. <br><br>
  3545. For more information on a FritzBox check other moduls: <a href="#FRITZBOX">FRITZBOX</a> and <a href="#FB_CALLMONITOR">FB_CALLMONITOR</a>.
  3546. <br>
  3547. <i>The modul uses the Perl modul 'Net::Telnet' for remote access. Please make sure that this module is installed.</i>
  3548. <br><br>
  3549. <b>Define</b>
  3550. <br><br>
  3551. <code>define &lt;name&gt; SYSMON [MODE[:[USER@]HOST][:PORT]] [&lt;M1&gt;[ &lt;M2&gt;[ &lt;M3&gt;[ &lt;M4&gt;]]]]</code><br>
  3552. <br>
  3553. This statement creates a new SYSMON instance. The parameters M1 to M4 define the refresh interval for various Readings (statistics). The parameters are to be understood as multipliers for the time defined by INTERVAL_BASE. Because this time is fixed at 60 seconds, the Mx-parameter can be considered as time intervals in minutes.<br>
  3554. If one (or more) of the multiplier is set to zero, the corresponding readings is deactivated.
  3555. <br>
  3556. <br>
  3557. The parameters are responsible for updating the readings according to the following scheme:
  3558. <ul>
  3559. <li>M1: (Default: 1)<br>
  3560. cpu_freq, cpu_temp, cpu_temp_avg, loadavg, stat_cpu, stat_cpu_diff, stat_cpu_percent, stat_cpu_text, power readings<br><br>
  3561. </li>
  3562. <li>M2: (Default: M1)<br>
  3563. ram, swap<br>
  3564. </li>
  3565. <li>M3: (Default: M1)<br>
  3566. eth0, eth0_diff, wlan0, wlan0_diff<br><br>
  3567. </li>
  3568. <li>M4: (Default: 10*M1)<br>
  3569. Filesystem informations<br><br>
  3570. </li>
  3571. <li>The following parameters are always updated with the base interval (regardless of the Mx-parameter):<br>
  3572. fhemuptime, fhemuptime_text, idletime, idletime_text, uptime, uptime_text, starttime, starttime_text<br><br>
  3573. </li>
  3574. </ul>
  3575. To query a remote system at least the address (HOST) must be specified. Accompanied by the port and / or user name, if necessary. The password (if needed) has to be defined once with the command 'set password &lt;password&gt;'. For MODE parameter are 'telnet' and 'local' only allowed. 'local' does not require any other parameters and can also be omitted.
  3576. <br>
  3577. <br>
  3578. <b>Readings:</b>
  3579. <br><br>
  3580. <ul>
  3581. <li>cpu_core_count<br>
  3582. CPU core count
  3583. </li>
  3584. <li>cpu_model_name<br>
  3585. CPU model name
  3586. </li>
  3587. <li>cpu_bogomips<br>
  3588. CPU Speed: BogoMIPS
  3589. </li>
  3590. <li>cpu_freq (and cpu1_freq for dual core systems)<br>
  3591. CPU frequency
  3592. </li>
  3593. <br>
  3594. <li>cpu_temp<br>
  3595. CPU temperature
  3596. </li>
  3597. <br>
  3598. <li>cpu_temp_avg<br>
  3599. Average of the CPU temperature, formed over the last 4 values.
  3600. </li>
  3601. <br>
  3602. <li>fhemuptime<br>
  3603. Time (in seconds) since the start of FHEM server.
  3604. </li>
  3605. <br>
  3606. <li>fhemuptime_text<br>
  3607. Time since the start of the FHEM server: human-readable output (text representation).
  3608. </li>
  3609. <br>
  3610. <li>fhemstarttime<br>
  3611. Start time (in seconds since 1.1.1970 1:00:00) of FHEM server.
  3612. </li>
  3613. <br>
  3614. <li>fhemstarttime_text<br>
  3615. Start time of the FHEM server: human-readable output (text representation).
  3616. </li>
  3617. <br>
  3618. <li>idletime<br>
  3619. Time spent by the system since the start in the idle mode (period of inactivity).
  3620. </li>
  3621. <br>
  3622. <li>idletime_text<br>
  3623. The inactivity time of the system since system start in human readable form.
  3624. </li>
  3625. <br>
  3626. <li>loadavg<br>
  3627. System load (load average): 1 minute, 5 minutes and 15 minutes.
  3628. </li>
  3629. <br>
  3630. <li>ram<br>
  3631. memory usage.
  3632. </li>
  3633. <br>
  3634. <li>swap<br>
  3635. swap usage.
  3636. </li>
  3637. <br>
  3638. <li>uptime<br>
  3639. System uptime.
  3640. </li>
  3641. <br>
  3642. <li>uptime_text<br>
  3643. System uptime (human readable).
  3644. </li>
  3645. <br>
  3646. <li>starttime<br>
  3647. System starttime.
  3648. </li>
  3649. <br>
  3650. <li>starttime_text<br>
  3651. System starttime (human readable).
  3652. </li>
  3653. <br>
  3654. <li>Network statistics<br>
  3655. Statistics for the specified network interface about the data volumes transferred and the difference since the previous measurement.
  3656. <br>
  3657. Examples:<br>
  3658. Amount of the transmitted data via interface eth0.<br>
  3659. <code>eth0: RX: 940.58 MB, TX: 736.19 MB, Total: 1676.77 MB</code><br>
  3660. Change of the amount of the transferred data in relation to the previous call (for eth0).<br>
  3661. <code>eth0_diff: RX: 0.66 MB, TX: 0.06 MB, Total: 0.72 MB</code><br>
  3662. IP and IP v6 adresses
  3663. <code>eth0_ip 192.168.0.15</code><br>
  3664. <code>eth0_ip6 fe85::49:4ff:fe85:f885/64</code><br>
  3665. </li>
  3666. <br>
  3667. <li>Network Speed (if avialable)<br>
  3668. speed of the network connection.
  3669. <br>
  3670. Examples:<br>
  3671. <code>eth0_speed 100</code><br>
  3672. </li>
  3673. <br>
  3674. <li>File system information<br>
  3675. Usage of the desired file systems.<br>
  3676. Example:<br>
  3677. <code>fs_root: Total: 7340 MB, Used: 3573 MB, 52 %, Available: 3425 MB at /</code>
  3678. </li>
  3679. <br>
  3680. <li>CPU utilization<br>
  3681. Information about the utilization of CPUs.<br>
  3682. Example:<br>
  3683. <code>stat_cpu: 10145283 0 2187286 90586051 542691 69393 400342</code><br>
  3684. <code>stat_cpu_diff: 2151 0 1239 2522 10 3 761</code><br>
  3685. <code>stat_cpu_percent: 4.82 0.00 1.81 93.11 0.05 0.00 0.20</code><br>
  3686. <code>stat_cpu_text: user: 32.17 %, nice: 0.00 %, sys: 18.53 %, idle: 37.72 %, io: 0.15 %, irq: 0.04 %, sirq: 11.38 %</code>
  3687. </li>
  3688. <br>
  3689. <li>user defined<br>
  3690. These readings provide output of commands, which are passed to the operating system or delivered by user defined functions.
  3691. </li>
  3692. <br>
  3693. <b>FritzBox specific Readings</b>
  3694. <li>wlan_state<br>
  3695. WLAN state: on/off
  3696. </li>
  3697. <br>
  3698. <li>wlan_guest_state<br>
  3699. GuestWLAN state: on/off
  3700. </li>
  3701. <br>
  3702. <li>internet_ip<br>
  3703. current IP-Adresse
  3704. </li>
  3705. <br>
  3706. <li>internet_state<br>
  3707. state of the Internet connection: connected/disconnected
  3708. </li>
  3709. <br>
  3710. <li>night_time_ctrl<br>
  3711. state night time control (do not disturb): on/off
  3712. </li>
  3713. <br>
  3714. <li>num_new_messages<br>
  3715. Number of new Voice Mail messages
  3716. </li>
  3717. <br>
  3718. <li>fw_version_info<br>
  3719. Information on the installed firmware version: &lt;VersionNum&gt; &lt;creation date&gt; &lt;time&gt;
  3720. </li>
  3721. <br>
  3722. <b>DSL Informations (FritzBox)</b>
  3723. <li>dsl_rate<br>
  3724. Information about the down und up stream rate
  3725. </li>
  3726. <br>
  3727. <li>dsl_synctime<br>
  3728. sync time with DSLAM
  3729. </li>
  3730. <br>
  3731. <li>dsl_crc_15<br>
  3732. number of uncorrectable errors (CRC) for the last 15 minutes
  3733. </li>
  3734. <br>
  3735. <li>dsl_fec_15<br>
  3736. number of correctable errors (FEC) for the last 15 minutes
  3737. </li>
  3738. <br>
  3739. <b>Power Supply Readings</b>
  3740. <li>power_ac_stat<br>
  3741. status information to the AC socket: online (0|1), present (0|1), voltage, current<br>
  3742. Example:<br>
  3743. <code>power_ac_stat: 1 1 4.807 264</code><br>
  3744. </li>
  3745. <br>
  3746. <li>power_ac_text<br>
  3747. human readable status information to the AC socket<br>
  3748. Example:<br>
  3749. <code>power_ac_text ac: present / online, voltage: 4.807 V, current: 264 mA</code><br>
  3750. </li>
  3751. <br>
  3752. <li>power_usb_stat<br>
  3753. status information to the USB socket
  3754. </li>
  3755. <br>
  3756. <li>power_usb_text<br>
  3757. human readable status information to the USB socket
  3758. </li>
  3759. <br>
  3760. <li>power_battery_stat<br>
  3761. status information to the battery (if installed): online (0|1), present (0|1), voltage, current, actual capacity<br>
  3762. Example:<br>
  3763. <code>power_battery_stat: 1 1 4.807 264 100</code><br>
  3764. </li>
  3765. <br>
  3766. <li>power_battery_text<br>
  3767. human readable status information to the battery (if installed)
  3768. </li>
  3769. <br>
  3770. <li>power_battery_info<br>
  3771. human readable additional information to the battery (if installed): technology, capacity, status, health, total capacity<br>
  3772. Example:<br>
  3773. <code>power_battery_info: battery info: Li-Ion , capacity: 100 %, status: Full , health: Good , total capacity: 2100 mAh</code><br>
  3774. The capacity must be defined in script.bin (e.g. ct-hdmi.bin). Parameter name pmu_battery_cap. Convert with bin2fex (bin2fex -> script.fex -> edit -> fex2bin -> script.bin).<br>
  3775. </li>
  3776. <br>
  3777. <li>cpuX_freq_stat<br>
  3778. Frequency statistics for CPU X: minimum, maximum and average values<br>
  3779. Example:<br>
  3780. <code>cpu0_freq_stat: 100 1000 900</code><br>
  3781. </li>
  3782. <br>
  3783. <li>cpuX_idle_stat<br>
  3784. Idle statistik for CPU X: minimum, maximum and average values<br>
  3785. Example:<br>
  3786. <code>cpu0_freq_stat: 23.76 94.74 90.75</code><br>
  3787. </li>
  3788. <br>
  3789. <li>cpu[X]_temp_stat<br>
  3790. Temperature statistik for CPU: minimum, maximum and average values<br>
  3791. Example:<br>
  3792. <code>cpu_temp_stat: 41.00 42.50 42.00</code><br>
  3793. </li>
  3794. <br>
  3795. <li>ram_used_stat<br>
  3796. RAM usage statistics: minimum, maximum and average values<br>
  3797. Example:<br>
  3798. <code>ram_used_stat: 267.55 1267.75 855.00</code><br>
  3799. </li>
  3800. <br>
  3801. <li>swap_used_stat<br>
  3802. SWAP usage statistics: minimum, maximum and average values<br>
  3803. Example:<br>
  3804. <code>swap_used_stat: 0 1024.00 250.00</code><br>
  3805. </li>
  3806. <br>
  3807. <br>
  3808. </ul>
  3809. <br>
  3810. <b>Get:</b><br><br>
  3811. <ul>
  3812. <li>interval_base<br>
  3813. Lists the specified polling intervalls.
  3814. </li>
  3815. <br>
  3816. <li>interval_multipliers<br>
  3817. Displays update intervals.
  3818. </li>
  3819. <br>
  3820. <li>list<br>
  3821. Lists all readings.
  3822. </li>
  3823. <br>
  3824. <li>update<br>
  3825. Refreshs all readings.
  3826. </li>
  3827. <br>
  3828. <li>version<br>
  3829. Displays the version of SYSMON module.
  3830. </li>
  3831. <br>
  3832. <li>list_lan_devices<br>
  3833. Displays known LAN Devices (FritzBox only).
  3834. </li>
  3835. <br>
  3836. </ul>
  3837. <br>
  3838. <b>Set:</b><br><br>
  3839. <ul>
  3840. <li>interval_multipliers<br>
  3841. Defines update intervals (as in the definition of the device).
  3842. </li>
  3843. <br>
  3844. <li>clean<br>
  3845. Clears user-definable Readings. After an update (manual or automatic) new readings are generated.<br>
  3846. </li>
  3847. <br>
  3848. <li>clear &lt;reading name&gt;<br>
  3849. Deletes the Reading entry with the given name. After an update this entry is possibly re-created (if defined). This mechanism allows the selective deleting unnecessary custom entries.<br>
  3850. </li>
  3851. <br>
  3852. <li>password &lt;Passwort&gt;<br>
  3853. Specify the password for remote access (usually only necessary once).
  3854. </li>
  3855. <br>
  3856. </ul>
  3857. <br>
  3858. <b>Attributes:</b><br><br>
  3859. <ul>
  3860. <li>filesystems &lt;reading name&gt;[:&lt;mountpoint&gt;[:&lt;comment&gt;]],...<br>
  3861. Specifies the file system to be monitored (a comma-separated list). <br>
  3862. Reading-name is used in the display and logging, the mount point is the basis of the evaluation, comment is relevant to the HTML display (see SYSMON_ShowValuesHTML)<br>
  3863. Examples: <br>
  3864. <code>/boot,/,/media/usb1</code><br>
  3865. <code>fs_boot:/boot,fs_root:/:Root,fs_usb1:/media/usb1:USB-Stick</code><br>
  3866. </li>
  3867. <br>
  3868. <li>network-interfaces &lt;name&gt;[:&lt;interface&gt;[:&lt;comment&gt;]],...<br>
  3869. Comma-separated list of network interfaces that are to be monitored. Each entry consists of the Reading-name, the name of the Netwerk adapter and a comment for the HTML output (see SYSMON_ShowValuesHTML). If no colon is used, the value is used simultaneously as a Reading-name and interface name.<br>
  3870. Example <code>ethernet:eth0:Ethernet,wlan:wlan0:WiFi</code><br>
  3871. </li>
  3872. <br>
  3873. <li>user-defined &lt;readingsName&gt;:&lt;Interval_Minutes&gt;:&lt;Comment&gt;:&lt;Cmd&gt;,...<br>
  3874. This comma-separated list defines user defined Readings with the following data: Reading name, refresh interval (in minutes), a Comment, and operating system command.
  3875. <br>The os commands are executed according to the specified Intervals and are noted as Readings with the specified name. Comments are used for the HTML output (see SYSMON_ShowValuesHTML)..
  3876. <br>All parameter parts are required!
  3877. <br>It is important that the specified commands are executed quickly, because at this time the entire FHEM server is blocked!<br>
  3878. If results of the long-running operations required, these should be set up as a CRON job and store results as a text file.<br><br>
  3879. Example: Display of package updates for the operating system:<br>
  3880. cron-Job:<br>
  3881. <code> sudo apt-get update 2>/dev/null >/dev/null</code>
  3882. <code> apt-get upgrade --dry-run| perl -ne '/(\d*)\s[upgraded|aktualisiert]\D*(\d*)\D*install|^ \S+.*/ and print "$1 aktualisierte, $2 neue Pakete"' 2>/dev/null &gt; /opt/fhem/data/updatestatus.txt</code>
  3883. <br>
  3884. <code>uder-defined</code> attribute<br><code>sys_updates:1440:System Aktualisierungen:cat /opt/fhem/data/updatestatus.txt</code><br>
  3885. the number of available updates is daily recorded as 'sys_updates'.
  3886. </li>
  3887. <br>
  3888. <li>user-fn &lt;fn_name&gt;:&lt;interval_minutes&gt;:&lt;reading_name1&gt;:&lt;reading_name2&gt;...[:&lt;reading_nameX&gt;], ...<br>
  3889. List of perl user subroutines.<br>
  3890. As &lt;fn_name&gt; can be used either the name of a Perl subroutine or a Perl expression.
  3891. The perl function gets the device hash as parameter and must provide an array of values.
  3892. These values are taken according to the parameter &lt;reading_nameX&gt; in Readings.<br>
  3893. A Perl expression must be enclosed in curly braces and can use the following parameters: $ HASH (device hash) and $ NAME (device name).
  3894. Return is expected analogous to a Perl subroutine.<br>
  3895. Important! The separation between multiple user functions must be done with a comma AND a space! Within the function definition commas may not be followed by spaces.
  3896. </li>
  3897. <br>
  3898. <li>disable<br>
  3899. Possible values: 0 and 1. '1' means that the update is stopped.
  3900. </li>
  3901. <br>
  3902. <li>telnet-prompt-regx, telnet-login-prompt-regx<br>
  3903. RegExp to detect login and command line prompt. (Only for access via Telnet.)
  3904. </li>
  3905. <br>
  3906. <li>exclude<br>
  3907. Allows to suppress reading certain information. <br>
  3908. supported values: user-defined (s. user-defined und user-fn), cpucount, uptime, fhemuptime,
  3909. loadavg, cputemp, cpufreq, cpuinfo, diskstat, cpustat, ramswap, filesystem, network,
  3910. fbwlan, fbnightctrl, fbnewmessages, fbdecttemp, fbversion, fbdsl, powerinfo
  3911. </li>
  3912. <br>
  3913. </ul>
  3914. <br>
  3915. <b>Plots:</b><br><br>
  3916. <ul>
  3917. predefined gplot files:<br>
  3918. <ul>
  3919. FileLog versions:<br>
  3920. <code>
  3921. SM_RAM.gplot<br>
  3922. SM_CPUTemp.gplot<br>
  3923. SM_FS_root.gplot<br>
  3924. SM_FS_usb1.gplot<br>
  3925. SM_Load.gplot<br>
  3926. SM_Network_eth0.gplot<br>
  3927. SM_Network_eth0t.gplot<br>
  3928. SM_Network_wlan0.gplot<br>
  3929. SM_CPUStat.gplot<br>
  3930. SM_CPUStatSum.gplot<br>
  3931. SM_CPUStatTotal.gplot<br>
  3932. SM_power_ac.gplot<br>
  3933. SM_power_usb.gplot<br>
  3934. SM_power_battery.gplot<br>
  3935. </code>
  3936. DbLog versions:<br>
  3937. <code>
  3938. SM_DB_all.gplot<br>
  3939. SM_DB_CPUFreq.gplot<br>
  3940. SM_DB_CPUTemp.gplot<br>
  3941. SM_DB_Load.gplot<br>
  3942. SM_DB_Network_eth0.gplot<br>
  3943. SM_DB_RAM.gplot<br>
  3944. </code>
  3945. </ul>
  3946. </ul>
  3947. <br>
  3948. <b>HTML output method (see Weblink): SYSMON_ShowValuesHTML(&lt;SYSMON-Instance&gt;[,&lt;Liste&gt;])</b><br><br>
  3949. <ul>
  3950. The module provides a function that returns selected Readings as HTML.<br>
  3951. As a parameter the name of the defined SYSMON device is expected.<br>
  3952. It can also Reading Group, Clone dummy or other modules be used. Their readings are simple used for display. <br>
  3953. The second parameter is optional and specifies a list of readings to be displayed in the format <code>&lt;ReadingName&gt;[:&lt;Comment&gt;[:&lt;Postfix&gt;[:&lt;FormatString&gt;]]]</code>.<br>
  3954. <code>ReadingName</code> is the Name of desired Reading, <code>Comment</code> is used as the display name and postfix is displayed after the value (such as units or as MHz can be displayed).
  3955. If FormatString is specified, the output is formatted with sprintf (s. sprintf in Perl documentation).<br>
  3956. If no <code>Comment</code> is specified, an internally predefined description is used.<br>
  3957. If no list specified, a predefined selection is used (all values are displayed).<br><br>
  3958. <code>define sysv1 weblink htmlCode {SYSMON_ShowValuesHTML('sysmon')}</code><br>
  3959. <code>define sysv2 weblink htmlCode {SYSMON_ShowValuesHTML('sysmon', ('date:Datum', 'cpu_temp:CPU Temperatur: &deg;C:%.1f'', 'cpu_freq:CPU Frequenz: MHz'))}</code>
  3960. </ul>
  3961. <br>
  3962. <b>Text output method (see Weblink): SYSMON_ShowValuesHTMLTitled(&lt;SYSMON-Instance&gt;[,&lt;Title&gt;,&lt;Liste&gt;])</b><br><br>
  3963. <ul>
  3964. According to SYSMON_ShowValuesHTML, but with a Title text above. If no title provided, device alias will be used (if any)<br>
  3965. </ul>
  3966. <br>
  3967. <b>Text output method (see Weblink): SYSMON_ShowValuesText(&lt;SYSMON-Instance&gt;[,&lt;Liste&gt;])</b><br><br>
  3968. <ul>
  3969. According to SYSMON_ShowValuesHTML, but formatted as plain text.<br>
  3970. </ul>
  3971. <br>
  3972. <b>Text output method (see Weblink): SYSMON_ShowValuesTextTitled(&lt;SYSMON-Instance&gt;[,&lt;Title&gt;,&lt;Liste&gt;])</b><br><br>
  3973. <ul>
  3974. According to SYSMON_ShowValuesHTMLTitled, but formatted as plain text.<br>
  3975. </ul>
  3976. <br>
  3977. <b>Reading values with perl: SYSMON_getValues(&lt;name&gt;[, &lt;array of desired keys&gt;])</b><br><br>
  3978. <ul>
  3979. Returns a hash ref with desired values. If no array is passed, all values are returned.<br>
  3980. {(SYSMON_getValues("sysmon"))->{'cpu_temp'}}<br>
  3981. {(SYSMON_getValues("sysmon",("cpu_freq","cpu_temp")))->{"cpu_temp"}}<br>
  3982. {join(" ", values (SYSMON_getValues("sysmon")))}<br>
  3983. {join(" ", values (SYSMON_getValues("sysmon",("cpu_freq","cpu_temp"))))}<br>
  3984. </ul>
  3985. <br>
  3986. <b>Examples:</b><br><br>
  3987. <ul>
  3988. <code>
  3989. # Modul-Definition<br>
  3990. define sysmon SYSMON 1 1 1 10<br>
  3991. #attr sysmon event-on-update-reading cpu_temp,cpu_temp_avg,cpu_freq,eth0_diff,loadavg,ram,^~ /.*usb.*,~ /$<br>
  3992. attr sysmon event-on-update-reading cpu_temp,cpu_temp_avg,cpu_freq,eth0_diff,loadavg,ram,fs_.*,stat_cpu_percent<br>
  3993. attr sysmon filesystems fs_boot:/boot,fs_root:/:Root,fs_usb1:/media/usb1:USB-Stick<br>
  3994. attr sysmon network-interfaces eth0:eth0:Ethernet,wlan0:wlan0:WiFi<br>
  3995. attr sysmon group RPi<br>
  3996. attr sysmon room 9.03_Tech<br>
  3997. <br>
  3998. # Log<br>
  3999. define FileLog_sysmon FileLog ./log/sysmon-%Y-%m.log sysmon<br>
  4000. attr FileLog_sysmon group RPi<br>
  4001. attr FileLog_sysmon logtype SM_CPUTemp:Plot,text<br>
  4002. attr FileLog_sysmon room 9.03_Tech<br>
  4003. <br>
  4004. # Visualisierung: CPU-Temperatur<br>
  4005. define wl_sysmon_temp SVG FileLog_sysmon:SM_CPUTemp:CURRENT<br>
  4006. attr wl_sysmon_temp group RPi<br>
  4007. attr wl_sysmon_temp label "CPU Temperatur: Min $data{min2}, Max $data{max2}, Last $data{currval2}"<br>
  4008. attr wl_sysmon_temp room 9.03_Tech<br>
  4009. <br>
  4010. # Visualisierung: Netzwerk-Daten&uuml;bertragung f&uuml;r eth0<br>
  4011. define wl_sysmon_eth0 SVG FileLog_sysmon:SM_Network_eth0:CURRENT<br>
  4012. attr wl_sysmon_eth0 group RPi<br>
  4013. attr wl_sysmon_eth0 label "Netzwerk-Traffic eth0: $data{min1}, Max: $data{max1}, Aktuell: $data{currval1}"<br>
  4014. attr wl_sysmon_eth0 room 9.03_Tech<br>
  4015. <br>
  4016. # Visualisierung: Netzwerk-Daten&uuml;bertragung f&uuml;r wlan0<br>
  4017. define wl_sysmon_wlan0 SVG FileLog_sysmon:SM_Network_wlan0:CURRENT<br>
  4018. attr wl_sysmon_wlan0 group RPi<br>
  4019. attr wl_sysmon_wlan0 label "Netzwerk-Traffic wlan0: $data{min1}, Max: $data{max1}, Aktuell: $data{currval1}"<br>
  4020. attr wl_sysmon_wlan0 room 9.03_Tech<br>
  4021. <br>
  4022. # Visualisierung: CPU-Auslastung (load average)<br>
  4023. define wl_sysmon_load SVG FileLog_sysmon:SM_Load:CURRENT<br>
  4024. attr wl_sysmon_load group RPi<br>
  4025. attr wl_sysmon_load label "Load Min: $data{min1}, Max: $data{max1}, Aktuell: $data{currval1}"<br>
  4026. attr wl_sysmon_load room 9.03_Tech<br>
  4027. <br>
  4028. # Visualisierung: RAM-Nutzung<br>
  4029. define wl_sysmon_ram SVG FileLog_sysmon:SM_RAM:CURRENT<br>
  4030. attr wl_sysmon_ram group RPi<br>
  4031. attr wl_sysmon_ram label "RAM-Nutzung Total: $data{max1}, Min: $data{min2}, Max: $data{max2}, Aktuell: $data{currval2}"<br>
  4032. attr wl_sysmon_ram room 9.03_Tech<br>
  4033. <br>
  4034. # Visualisierung: Dateisystem: Root-Partition<br>
  4035. define wl_sysmon_fs_root SVG FileLog_sysmon:SM_FS_root:CURRENT<br>
  4036. attr wl_sysmon_fs_root group RPi<br>
  4037. attr wl_sysmon_fs_root label "Root Partition Total: $data{max1}, Min: $data{min2}, Max: $data{max2}, Aktuell: $data{currval2}"<br>
  4038. attr wl_sysmon_fs_root room 9.03_Tech<br>
  4039. <br>
  4040. # Visualisierung: Dateisystem: USB-Stick<br>
  4041. define wl_sysmon_fs_usb1 SVG FileLog_sysmon:SM_FS_usb1:CURRENT<br>
  4042. attr wl_sysmon_fs_usb1 group RPi<br>
  4043. attr wl_sysmon_fs_usb1 label "USB1 Total: $data{max1}, Min: $data{min2}, Max: $data{max2}, Aktuell: $data{currval2}"<br>
  4044. attr wl_sysmon_fs_usb1 room 9.03_Tech<br>
  4045. <br>
  4046. # Anzeige der Readings zum Einbinden in ein 'Raum'.<br>
  4047. define SysValues weblink htmlCode {SYSMON_ShowValuesHTML('sysmon')}<br>
  4048. attr SysValues group RPi<br>
  4049. attr SysValues room 9.03_Tech<br>
  4050. <br>
  4051. # Anzeige CPU Auslasung<br>
  4052. define wl_sysmon_cpustat SVG FileLog_sysmon:SM_CPUStat:CURRENT<br>
  4053. attr wl_sysmon_cpustat label "CPU(min/max): user:$data{min1}/$data{max1} nice:$data{min2}/$data{max2} sys:$data{min3}/$data{max3} idle:$data{min4}/$data{max4} io:$data{min5}/$data{max5} irq:$data{min6}/$data{max6} sirq:$data{min7}/$data{max7}"<br>
  4054. attr wl_sysmon_cpustat group RPi<br>
  4055. attr wl_sysmon_cpustat room 9.99_Test<br>
  4056. attr wl_sysmon_cpustat plotsize 840,420<br>
  4057. define wl_sysmon_cpustat_s SVG FileLog_sysmon:SM_CPUStatSum:CURRENT<br>
  4058. attr wl_sysmon_cpustat_s label "CPU(min/max): user:$data{min1}/$data{max1} nice:$data{min2}/$data{max2} sys:$data{min3}/$data{max3} idle:$data{min4}/$data{max4} io:$data{min5}/$data{max5} irq:$data{min6}/$data{max6} sirq:$data{min7}/$data{max7}"<br>
  4059. attr wl_sysmon_cpustat_s group RPi<br>
  4060. attr wl_sysmon_cpustat_s room 9.99_Test<br>
  4061. attr wl_sysmon_cpustat_s plotsize 840,420<br>
  4062. define wl_sysmon_cpustatT SVG FileLog_sysmon:SM_CPUStatTotal:CURRENT<br>
  4063. attr wl_sysmon_cpustatT label "CPU-Auslastung"<br>
  4064. attr wl_sysmon_cpustatT group RPi<br>
  4065. attr wl_sysmon_cpustatT plotsize 840,420<br>
  4066. attr wl_sysmon_cpustatT room 9.99_Test<br>
  4067. <br>
  4068. # Anzeige Stromversorgung AC<br>
  4069. define wl_sysmon_power_ac SVG FileLog_sysmon:SM_power_ac:CURRENT<br>
  4070. attr wl_sysmon_power_ac label "Stromversorgung (ac) Spannung: $data{min1} - $data{max1} V, Strom: $data{min2} - $data{max2} mA"<br>
  4071. attr wl_sysmon_power_ac room Technik<br>
  4072. attr wl_sysmon_power_ac group system<br>
  4073. # Anzeige Stromversorgung Battery<br>
  4074. define wl_sysmon_power_bat SVG FileLog_sysmon:SM_power_battery:CURRENT<br>
  4075. attr wl_sysmon_power_bat label "Stromversorgung (bat) Spannung: $data{min1} - $data{max1} V, Strom: $data{min2} - $data{max2} mA"<br>
  4076. attr wl_sysmon_power_bat room Technik<br>
  4077. attr wl_sysmon_power_bat group system<br>
  4078. </code>
  4079. </ul>
  4080. </ul>
  4081. <!-- ================================ -->
  4082. =end html
  4083. =begin html_DE
  4084. <a name="SYSMON"></a>
  4085. <h3>SYSMON</h3>
  4086. (<a href="commandref.html#SYSMON">en</a> | de)
  4087. <ul>
  4088. Dieses Modul liefert diverse Informationen und Statistiken zu dem System, auf dem FHEM-Server ausgef&uuml;hrt wird.
  4089. Weiterhin k&ouml;nnen auch Remote-Systeme abgefragt werden (Telnet).
  4090. Es werden nur Linux-basierte Systeme unterst&uuml;tzt. Manche Informationen sind hardwarespezifisch und sind daher nicht auf jeder Plattform
  4091. verf&uuml;gbar.
  4092. Bis jetzt wurde dieses Modul auf folgenden Systemen getestet: Raspberry Pi (Debian Wheezy), BeagleBone Black,
  4093. FritzBox 7390, WR703N unter OpenWrt, CubieTruck und einige andere.
  4094. <br>
  4095. <br>
  4096. F&uuml;r Informationen zu einer FritzBox beachten Sie bitte auch Module: <a href="#FRITZBOX">FRITZBOX</a> und <a href="#FB_CALLMONITOR">FB_CALLMONITOR</a>.
  4097. <i>Das Modul nutzt das Perlmodule 'Net::Telnet' f&uuml;r den Fernzugriff. Dieses muss ggf. nachinstalliert werden.</i>
  4098. <br><br>
  4099. <b>Define</b>
  4100. <br><br>
  4101. <code>define &lt;name&gt; SYSMON [MODE[:[USER@]HOST][:PORT]] [&lt;M1&gt;[ &lt;M2&gt;[ &lt;M3&gt;[ &lt;M4&gt;]]]]</code><br>
  4102. <br>
  4103. Diese Anweisung erstellt eine neue SYSMON-Instanz.
  4104. Die Parameter M1 bis M4 legen die Aktualisierungsintervalle f&uuml;r verschiedenen Readings (Statistiken) fest.
  4105. Die Parameter sind als Multiplikatoren f&uuml;r die Zeit, die durch INTERVAL_BASE definiert ist, zu verstehen.
  4106. Da diese Zeit fest auf 60 Sekunden gesetzt ist, k&ouml;nnen die Mx-Parameters als Zeitintervalle in Minuten angesehen werden.<br>
  4107. Wird einer (oder mehrere) Multiplikatoren auf Null gesetzt werden, wird das entsprechende Readings deaktiviert.<br>
  4108. <br>
  4109. Die Parameter sind f&uuml;r die Aktualisierung der Readings nach folgender Schema zust&auml;ndig:
  4110. <ul>
  4111. <li>M1: (Default-Wert: 1)<br>
  4112. cpu_freq, cpu_temp, cpu_temp_avg, loadavg, stat_cpu, stat_cpu_diff, stat_cpu_percent, stat_cpu_text, power readings<br><br>
  4113. </li>
  4114. <li>M2: (Default-Wert: M1)<br>
  4115. ram, swap<br>
  4116. </li>
  4117. <li>M3: (Default-Wert: M1)<br>
  4118. eth0, eth0_diff, wlan0, wlan0_diff<br><br>
  4119. </li>
  4120. <li>M4: (Default-Wert: 10*M1)<br>
  4121. Filesystem-Informationen<br><br>
  4122. </li>
  4123. <li>folgende Parameter werden immer anhand des Basisintervalls (unabh&auml;ngig von den Mx-Parameters) aktualisiert:<br>
  4124. fhemuptime, fhemuptime_text, idletime, idletime_text, uptime, uptime_text, starttime, starttime_text<br><br>
  4125. </li>
  4126. </ul>
  4127. F&uuml;r Abfrage eines entfernten Systems muss mindestens deren Adresse (HOST) angegeben werden, bei Bedarf erg&auml;nzt durch den Port und/oder den Benutzernamen.
  4128. Das eventuell ben&ouml;tigte Passwort muss einmalig mit dem Befehl 'set password &lt;pass&gt;' definiert werden.
  4129. Als MODE sind derzeit 'telnet' und 'local' erlaubt. 'local' erfordert keine weiteren Angaben und kann auch ganz weggelassen werden.
  4130. <br>
  4131. <br>
  4132. <b>Readings:</b>
  4133. <br><br>
  4134. <ul>
  4135. <li>cpu_core_count<br>
  4136. Anzahl der CPU Kerne
  4137. </li>
  4138. <li>cpu_model_name<br>
  4139. CPU Modellname
  4140. </li>
  4141. <li>cpu_bogomips<br>
  4142. CPU Speed: BogoMIPS
  4143. </li>
  4144. <li>cpu_freq (auf den DualCore-Systemen wie Cubietruck auch cpu1_freq)<br>
  4145. CPU-Frequenz
  4146. </li>
  4147. <br>
  4148. <li>cpu_temp<br>
  4149. CPU-Temperatur
  4150. </li>
  4151. <br>
  4152. <li>cpu_temp_avg<br>
  4153. Durchschnitt der CPU-Temperatur, gebildet &uuml;ber die letzten 4 Werte.
  4154. </li>
  4155. <br>
  4156. <li>fhemuptime<br>
  4157. Zeit (in Sekunden) seit dem Start des FHEM-Servers.
  4158. </li>
  4159. <br>
  4160. <li>fhemuptime_text<br>
  4161. Zeit seit dem Start des FHEM-Servers: Menschenlesbare Ausgabe (texttuelle Darstellung).
  4162. </li>
  4163. <br>
  4164. <li>fhemstarttime<br>
  4165. Startzeit (in Sekunden seit 1.1.1970 1:00:00) des FHEM-Servers.
  4166. </li>
  4167. <br>
  4168. <li>fhemstarttime_text<br>
  4169. Startzeit des FHEM-Servers: Menschenlesbare Ausgabe (texttuelle Darstellung).
  4170. </li>
  4171. <br>
  4172. <li>idletime<br>
  4173. Zeit (in Sekunden und in Prozent), die das System (nicht der FHEM-Server!)
  4174. seit dem Start in dem Idle-Modus verbracht hat. Also die Zeit der Inaktivit&auml;t.
  4175. </li>
  4176. <br>
  4177. <li>idletime_text<br>
  4178. Zeit der Inaktivit&auml;t des Systems seit dem Systemstart in menschenlesbarer Form.
  4179. </li>
  4180. <br>
  4181. <li>loadavg<br>
  4182. Ausgabe der Werte f&uuml;r die Systemauslastung (load average): 1 Minute-, 5 Minuten- und 15 Minuten-Werte.
  4183. </li>
  4184. <br>
  4185. <li>ram<br>
  4186. Ausgabe der Speicherauslastung.
  4187. </li>
  4188. <br>
  4189. <li>swap<br>
  4190. Benutzung und Auslastung der SWAP-Datei (bzw. Partition).
  4191. </li>
  4192. <br>
  4193. <li>uptime<br>
  4194. Zeit (in Sekenden) seit dem Systemstart.
  4195. </li>
  4196. <br>
  4197. <li>uptime_text<br>
  4198. Zeit seit dem Systemstart in menschenlesbarer Form.
  4199. </li>
  4200. <br>
  4201. <li>starttime<br>
  4202. Systemstart (Sekunden seit Thu Jan 1 01:00:00 1970).
  4203. </li>
  4204. <br>
  4205. <li>starttime_text<br>
  4206. Systemstart in menschenlesbarer Form.
  4207. </li>
  4208. <br>
  4209. <li>Netzwerkinformationen<br>
  4210. Informationen zu den &uuml;ber die angegebene Netzwerkschnittstellen &uuml;bertragene Datenmengen
  4211. und der Differenz zu der vorherigen Messung.
  4212. <br>
  4213. Beispiele:<br>
  4214. Menge der &uuml;bertragenen Daten &uuml;ber die Schnittstelle eth0.<br>
  4215. <code>eth0: RX: 940.58 MB, TX: 736.19 MB, Total: 1676.77 MB</code><br>
  4216. &Auml;nderung der &uuml;bertragenen Datenmenge in Bezug auf den vorherigen Aufruf (f&uuml;r eth0).<br>
  4217. <code>eth0_diff: RX: 0.66 MB, TX: 0.06 MB, Total: 0.72 MB</code><br>
  4218. IP and IP v6 Adressen
  4219. <code>eth0_ip 192.168.0.15</code><br>
  4220. <code>eth0_ip6 fe85::49:4ff:fe85:f885/64</code><br>
  4221. </li>
  4222. <br>
  4223. <li>Network Speed (wenn verf&uuml;gbar)<br>
  4224. Geschwindigkeit der aktuellen Netzwerkverbindung.
  4225. <br>
  4226. Beispiel:<br>
  4227. <code>eth0_speed 100</code><br>
  4228. </li>
  4229. <br>
  4230. <li>Dateisysteminformationen<br>
  4231. Informationen zu der Gr&ouml;&szlig;e und der Belegung der gew&uuml;nschten Dateisystemen.<br>
  4232. Seit Version 1.1.0 k&ouml;nnen Dateisysteme auch benannt werden (s.u.). <br>
  4233. In diesem Fall werden f&uuml;r die diese Readings die angegebenen Namen verwendet.<br>
  4234. Dies soll die &Uuml;bersicht verbessern und die Erstellung von Plots erleichten.<br>
  4235. Beispiel:<br>
  4236. <code>fs_root: Total: 7340 MB, Used: 3573 MB, 52 %, Available: 3425 MB at /</code>
  4237. </li>
  4238. <br>
  4239. <li>CPU Auslastung<br>
  4240. Informationen zu der Auslastung der CPU(s).<br>
  4241. Beispiel:<br>
  4242. <code>stat_cpu: 10145283 0 2187286 90586051 542691 69393 400342</code><br>
  4243. <code>stat_cpu_diff: 2151 0 1239 2522 10 3 761</code><br>
  4244. <code>stat_cpu_percent: 4.82 0.00 1.81 93.11 0.05 0.00 0.20</code><br>
  4245. <code>stat_cpu_text: user: 32.17 %, nice: 0.00 %, sys: 18.53 %, idle: 37.72 %, io: 0.15 %, irq: 0.04 %, sirq: 11.38 %</code>
  4246. </li>
  4247. <br>
  4248. <li>Benutzerdefinierte Eintr&auml;ge<br>
  4249. Diese Readings sind Ausgaben der Kommanden, die an das Betriebssystem &uuml;bergeben werden.
  4250. Die entsprechende Angaben werden durch Attributen <code>user-defined</code> und <code>user-fn</code> definiert.
  4251. </li>
  4252. <br>
  4253. <b>FritzBox-spezifische Readings</b>
  4254. <li>wlan_state<br>
  4255. WLAN-Status: on/off
  4256. </li>
  4257. <br>
  4258. <li>wlan_guest_state<br>
  4259. Gast-WLAN-Status: on/off
  4260. </li>
  4261. <br>
  4262. <li>internet_ip<br>
  4263. aktuelle IP-Adresse
  4264. </li>
  4265. <br>
  4266. <li>internet_state<br>
  4267. Status der Internetverbindung: connected/disconnected
  4268. </li>
  4269. <br>
  4270. <li>night_time_ctrl<br>
  4271. Status der Klingelsperre on/off
  4272. </li>
  4273. <br>
  4274. <li>num_new_messages<br>
  4275. Anzahl der neuen Anrufbeantworter-Meldungen
  4276. </li>
  4277. <br>
  4278. <li>fw_version_info<br>
  4279. Angaben zu der installierten Firmware-Version: &lt;VersionNr&gt; &lt;Erstelldatum&gt; &lt;Zeit&gt;
  4280. </li>
  4281. <br>
  4282. <b>DSL Informationen (FritzBox)</b>
  4283. <li>dsl_rate<br>
  4284. Down/Up Verbindungsgeschwindigkeit
  4285. </li>
  4286. <br>
  4287. <li>dsl_synctime<br>
  4288. Sync-Zeit mit Vermittlungsstelle
  4289. </li>
  4290. <br>
  4291. <li>dsl_crc_15<br>
  4292. Nicht behebbare &Uuml;bertragungsfehler in den letzten 15 Minuten
  4293. </li>
  4294. <br>
  4295. <li>dsl_fec_15<br>
  4296. Behebbare &Uuml;bertragungsfehler in den letzten 15 Minuten
  4297. </li>
  4298. <br>
  4299. <b>Readings zur Stromversorgung</b>
  4300. <li>power_ac_stat<br>
  4301. Statusinformation f&uuml;r die AC-Buchse: online (0|1), present (0|1), voltage, current<br>
  4302. Beispiel:<br>
  4303. <code>power_ac_stat: 1 1 4.807 264</code><br>
  4304. </li>
  4305. <br>
  4306. <li>power_ac_text<br>
  4307. Statusinformation f&uuml;r die AC-Buchse in menschenlesbarer Form<br>
  4308. Beispiel:<br>
  4309. <code>power_ac_text ac: present / online, Voltage: 4.807 V, Current: 264 mA</code><br>
  4310. </li>
  4311. <br>
  4312. <li>power_usb_stat<br>
  4313. Statusinformation f&uuml;r die USB-Buchse
  4314. </li>
  4315. <br>
  4316. <li>power_usb_text<br>
  4317. Statusinformation f&uuml;r die USB-Buchse in menschenlesbarer Form
  4318. </li>
  4319. <br>
  4320. <li>power_battery_stat<br>
  4321. Statusinformation f&uuml;r die Batterie (wenn vorhanden): online (0|1), present (0|1), voltage, current, actual capacity<br>
  4322. Beispiel:<br>
  4323. <code>power_battery_stat: 1 1 4.807 264 100</code><br>
  4324. </li>
  4325. <br>
  4326. <li>power_battery_text<br>
  4327. Statusinformation f&uuml;r die Batterie (wenn vorhanden) in menschenlesbarer Form
  4328. </li>
  4329. <br>
  4330. <li>power_battery_info<br>
  4331. Menschenlesbare Zusatzinformationen f&uuml;r die Batterie (wenn vorhanden): Technologie, Kapazit&auml;t, Status, Zustand, Gesamtkapazit&auml;t<br>
  4332. Beispiel:<br>
  4333. <code>power_battery_info: battery info: Li-Ion , capacity: 100 %, status: Full , health: Good , total capacity: 2100 mAh</code><br>
  4334. Die Kapazit&auml;t soll in script.bin (z.B. ct-hdmi.bin) eingestellt werden (Parameter pmu_battery_cap). Mit bin2fex konvertieren (bin2fex -> script.fex -> edit -> fex2bin -> script.bin)<br>
  4335. </li>
  4336. <br>
  4337. <li>cpuX_freq_stat<br>
  4338. Frequenz-Statistik f&uuml;r die CPU X: Minimum, Maximum und Durchschnittswert<br>
  4339. Beispiel:<br>
  4340. <code>cpu0_freq_stat: 100 1000 900</code><br>
  4341. </li>
  4342. <br>
  4343. <li>cpuX_idle_stat<br>
  4344. Leerlaufzeit-Statistik f&uuml;r die CPU X: Minimum, Maximum und Durchschnittswert<br>
  4345. Beispiel:<br>
  4346. <code>cpu0_freq_stat: 23.76 94.74 90.75</code><br>
  4347. </li>
  4348. <br>
  4349. <li>cpu[X]_temp_stat<br>
  4350. Temperatur-Statistik f&uuml;r CPU: Minimum, Maximum und Durchschnittswert<br>
  4351. Beispiel:<br>
  4352. <code>cpu_temp_stat: 41.00 42.50 42.00</code><br>
  4353. </li>
  4354. <br>
  4355. <li>ram_used_stat<br>
  4356. Statistik der RAM-Nutzung: Minimum, Maximum und Durchschnittswert<br>
  4357. Example:<br>
  4358. <code>ram_used_stat: 267.55 1267.75 855.00</code><br>
  4359. </li>
  4360. <br>
  4361. <li>swap_used_stat<br>
  4362. Statistik der SWAP-Nutzung: Minimum, Maximum und Durchschnittswert<br>
  4363. Example:<br>
  4364. <code>swap_used_stat: 0 1024.00 250.00</code><br>
  4365. </li>
  4366. <br>
  4367. <br>
  4368. </ul>
  4369. <br>
  4370. <b>Get:</b><br><br>
  4371. <ul>
  4372. <li>interval<br>
  4373. Listet die bei der Definition angegebene Polling-Intervalle auf.
  4374. </li>
  4375. <br>
  4376. <li>interval_multipliers<br>
  4377. Listet die definierten Multipliers.
  4378. </li>
  4379. <br>
  4380. <li>list<br>
  4381. Gibt alle Readings aus.
  4382. </li>
  4383. <br>
  4384. <li>update<br>
  4385. Aktualisiert alle Readings. Alle Werte werden neu abgefragt.
  4386. </li>
  4387. <br>
  4388. <li>version<br>
  4389. Zeigt die Version des SYSMON-Moduls.
  4390. </li>
  4391. <br>
  4392. <br>
  4393. <li>list_lan_devices<br>
  4394. Listet bekannte Ger&auml;te im LAN (nur FritzBox).
  4395. </li>
  4396. </ul>
  4397. <br>
  4398. <b>Set:</b><br><br>
  4399. <ul>
  4400. <li>interval_multipliers<br>
  4401. Definiert Multipliers (wie bei der Definition des Ger&auml;tes).
  4402. </li>
  4403. <br>
  4404. <li>clean<br>
  4405. L&ouml;scht benutzerdefinierbare Readings. Nach einem Update (oder nach der automatischen Aktualisierung) werden neue Readings generiert.<br>
  4406. </li>
  4407. <br>
  4408. <li>clear &lt;reading name&gt;<br>
  4409. L&ouml;scht den Reading-Eintrag mit dem gegebenen Namen. Nach einem Update (oder nach der automatischen Aktualisierung)
  4410. wird dieser Eintrag ggf. neu erstellt (falls noch definiert). Dieses Mechanismus erlaubt das gezielte L&ouml;schen nicht mehr ben&ouml;tigter
  4411. benutzerdefinierten Eintr&auml;ge.<br>
  4412. </li>
  4413. <br>
  4414. <li>password &lt;Passwort&gt;<br>
  4415. Definiert das Passwort f&uuml;r den Remote-Zugriff (i.d.R. nur einmalig notwendig).
  4416. </li>
  4417. <br>
  4418. </ul>
  4419. <br>
  4420. <b>Attributes:</b><br><br>
  4421. <ul>
  4422. <li>filesystems &lt;reading name&gt;[:&lt;mountpoint&gt;[:&lt;comment&gt;]],...<br>
  4423. Gibt die zu &uuml;berwachende Dateisysteme an. Es wird eine kommaseparierte Liste erwartet.<br>
  4424. Reading-Name wird bei der Anzeige und Logging verwendet, Mount-Point ist die Grundlage der Auswertung,
  4425. Kommentar ist relevant f&uuml;r die HTML-Anzeige (s. SYSMON_ShowValuesHTML)<br>
  4426. Beispiel: <code>/boot,/,/media/usb1</code><br>
  4427. oder: <code>fs_boot:/boot,fs_root:/:Root,fs_usb1:/media/usb1:USB-Stick</code><br>
  4428. Im Sinne der besseren &Uuml;bersicht sollten zumindest Name und MountPoint angegeben werden.
  4429. </li>
  4430. <br>
  4431. <li>network-interfaces &lt;name&gt;[:&lt;interface&gt;[:&lt;comment&gt;]],...<br>
  4432. Kommaseparierte Liste der Netzwerk-Interfaces, die &uuml;berwacht werden sollen.
  4433. Jeder Eintrag besteht aus dem Reading-Namen, dem Namen
  4434. des Netwerk-Adapters und einem Kommentar f&uuml;r die HTML-Anzeige (s. SYSMON_ShowValuesHTML). Wird kein Doppelpunkt verwendet,
  4435. wird der Wert gleichzeitig als Reading-Name und Interface-Name verwendet.<br>
  4436. Beispiel <code>ethernet:eth0:Ethernet,wlan:wlan0:WiFi</code><br>
  4437. </li>
  4438. <br>
  4439. <li>user-defined &lt;readingsName&gt;:&lt;Interval_Minutes&gt;:&lt;Comment&gt;:&lt;Cmd&gt;,...<br>
  4440. Diese kommaseparierte Liste definiert Eintr&auml;ge mit jeweils folgenden Daten:
  4441. Reading-Name, Aktualisierungsintervall in Minuten, Kommentar und Betriebssystem-Commando.
  4442. <br>Die BS-Befehle werden entsprechend des angegebenen Intervalls ausgef&uuml;hrt und als Readings mit den angegebenen Namen vermerkt.
  4443. Kommentare werden f&uuml;r die HTML-Ausgaben (s. SYSMON_ShowValuesHTML) ben&ouml;tigt.
  4444. <br>Alle Parameter sind nicht optional!
  4445. <br>Es ist wichtig, dass die angegebenen Befehle schnell ausgef&uuml;hrt werden, denn in dieser Zeit wird der gesamte FHEM-Server blockiert!
  4446. <br>Werden Ergebnisse der lang laufenden Operationen ben&ouml;tigt, sollten diese z.B als CRON-Job eingerichtet werden
  4447. und in FHEM nur die davor gespeicherten Ausgaben visualisiert.<br><br>
  4448. Beispiel: Anzeige der vorliegenden Paket-Aktualisierungen f&uuml;r das Betriebssystem:<br>
  4449. In einem cron-Job wird folgendes t&auml;glich ausgef&uuml;hrt: <br>
  4450. <code> sudo apt-get update 2>/dev/null >/dev/null</code>
  4451. <code> apt-get upgrade --dry-run| perl -ne '/(\d*)\s[upgraded|aktualisiert]\D*(\d*)\D*install|^ \S+.*/ and print "$1 aktualisierte, $2 neue Pakete"' 2>/dev/null &gt; /opt/fhem/data/updatestatus.txt</code>
  4452. <br>
  4453. Das Attribute <code>uder-defined</code> wird auf <br><code>sys_updates:1440:System Aktualisierungen:cat /opt/fhem/data/updatestatus.txt</code><br> gesetzt.
  4454. Danach wird die Anzahl der verf&uuml;gbaren Aktualisierungen t&auml;glich als Reading 'sys_updates' protokolliert.
  4455. </li>
  4456. <br>
  4457. <li>user-fn &lt;fn_name&gt;:&lt;Interval_Minutes&gt;:&lt;reading_name1&gt;:&lt;reading_name2&gt;...[:&lt;reading_nameX&gt;],...<br>
  4458. Liste der benutzerdefinierten Perlfunktionen.<br>
  4459. Als &lt;fn_name&gt; k&ouml;nnen entweder Name einer Perlfunktion oder ein Perlausdruck verwendet werden.
  4460. Die Perlfunktion bekommt den Device-Hash als &Uuml;bergabeparameter und muss ein Array mit Werte liefern.
  4461. Diese Werte werden entsprechend den Parameter &lt;reading_nameX&gt; in Readings &uuml;bernommen.<br>
  4462. Ein Perlausdruck muss in geschweifte Klammer eingeschlossen werden und kann folgende Paramter verwenden: $HASH (Device-Hash) und $NAME (Device-Name).
  4463. R&uuml;ckgabe wird analog einer Perlfunktion erwartet.<br>
  4464. Wichtig! Die Trennung zwischen mehreren Benutzerfunktionen muss mit einem Komma UND einem Leerzeichen erfolgen! Innerhalb der Funktiondefinition d&uuml;rfen Kommas nicht durch Leerzeichen gefolgt werden.
  4465. </li>
  4466. <br>
  4467. <li>disable<br>
  4468. M&ouml;gliche Werte: <code>0,1</code>. Bei <code>1</code> wird die Aktualisierung gestoppt.
  4469. </li>
  4470. <br>
  4471. <li>telnet-prompt-regx, telnet-login-prompt-regx<br>
  4472. RegExp zur Erkennung von Login- und Kommandozeile-Prompt. (Nur f&uuml;r Zugriffe &uuml;ber Telnet relevant.)
  4473. </li>
  4474. <br>
  4475. <li>exclude<br>
  4476. Erlaubt das Abfragen bestimmten Informationen zu unterbinden. <br>
  4477. Mögliche Werte: user-defined (s. user-defined und user-fn), cpucount, uptime, fhemuptime,
  4478. loadavg, cputemp, cpufreq, cpuinfo, diskstat, cpustat, ramswap, filesystem, network,
  4479. fbwlan, fbnightctrl, fbnewmessages, fbdecttemp, fbversion, fbdsl, powerinfo
  4480. </li>
  4481. <br>
  4482. </ul>
  4483. <br>
  4484. <b>Plots:</b><br><br>
  4485. <ul>
  4486. F&uuml;r dieses Modul sind bereits einige gplot-Dateien vordefiniert:<br>
  4487. <ul>
  4488. FileLog-Versionen:<br>
  4489. <code>
  4490. SM_RAM.gplot<br>
  4491. SM_CPUTemp.gplot<br>
  4492. SM_FS_root.gplot<br>
  4493. SM_FS_usb1.gplot<br>
  4494. SM_Load.gplot<br>
  4495. SM_Network_eth0.gplot<br>
  4496. SM_Network_eth0t.gplot<br>
  4497. SM_Network_wlan0.gplot<br>
  4498. SM_CPUStat.gplot<br>
  4499. SM_CPUStatSum.gplot<br>
  4500. SM_CPUStatTotal.gplot<br>
  4501. SM_power_ac.gplot<br>
  4502. SM_power_usb.gplot<br>
  4503. SM_power_battery.gplot<br>
  4504. </code>
  4505. DbLog-Versionen:<br>
  4506. <code>
  4507. SM_DB_all.gplot<br>
  4508. SM_DB_CPUFreq.gplot<br>
  4509. SM_DB_CPUTemp.gplot<br>
  4510. SM_DB_Load.gplot<br>
  4511. SM_DB_Network_eth0.gplot<br>
  4512. SM_DB_RAM.gplot<br>
  4513. </code>
  4514. </ul>
  4515. </ul>
  4516. <br>
  4517. <b>HTML-Ausgabe-Methode (f&uuml;r ein Weblink): SYSMON_ShowValuesHTML(&lt;SYSMON-Instanz&gt;[,&lt;Liste&gt;])</b><br><br>
  4518. <ul>
  4519. Das Modul definiert eine Funktion, die ausgew&auml;hlte Readings in HTML-Format ausgibt. <br>
  4520. Als Parameter wird der Name des definierten SYSMON-Ger&auml;ts erwartet.<br>
  4521. Es kann auch ReadingsGroup, CloneDummy oder andere Module genutzt werden, dann werden einfach deren Readings verwendet.<br>
  4522. Der zweite Parameter ist optional und gibt eine Liste der anzuzeigende Readings
  4523. im Format <code>&lt;ReadingName&gt;[:&lt;Comment&gt;[:&lt;Postfix&gt;[:&lt;FormatString&gt;]]]</code> an.<br>
  4524. Dabei gibt <code>ReadingName</code> den anzuzeigenden Reading an, der Wert aus <code>Comment</code> wird als der Anzeigename verwendet
  4525. und <code>Postfix</code> wird nach dem eihentlichen Wert angezeigt (so k&ouml;nnen z.B. Einheiten wie MHz angezeigt werden).
  4526. Mit Hilfe von FormatString kann die Ausgabe beeinflusst werden (s. sprintf in PerlDoku).<br>
  4527. Falls kein <code>Comment</code> angegeben ist, wird eine intern vordefinierte Beschreibung angegeben.
  4528. Bei benutzerdefinierbaren Readings wird ggf. <code>Comment</code> aus der Definition verwendet.<br>
  4529. Wird keine Liste angegeben, wird eine vordefinierte Auswahl verwendet (alle Werte).<br><br>
  4530. <code>define sysv1 weblink htmlCode {SYSMON_ShowValuesHTML('sysmon')}</code><br>
  4531. <code>define sysv2 weblink htmlCode {SYSMON_ShowValuesHTML('sysmon', ('date:Datum', 'cpu_temp:CPU Temperatur: &deg;C', 'cpu_freq:CPU Frequenz: MHz'))}</code>
  4532. </ul>
  4533. <br>
  4534. <b>HTML-Ausgabe-Methode (f&uuml;r ein Weblink): SYSMON_ShowValuesHTMLTitled(&lt;SYSMON-Instance&gt;[,&lt;Title&gt;,&lt;Liste&gt;])</b><br><br>
  4535. <ul>
  4536. Wie SYSMON_ShowValuesHTML, aber mit einer &Uuml;berschrift dar&uuml;ber. Wird keine &Uuml;berschrift angegeben, wird alias des Moduls genutzt (falls definiert).<br>
  4537. </ul>
  4538. <br>
  4539. <b>Text-Ausgabe-Methode (see Weblink): SYSMON_ShowValuesText(&lt;SYSMON-Instance&gt;[,&lt;Liste&gt;])</b><br><br>
  4540. <ul>
  4541. Analog SYSMON_ShowValuesHTML, jedoch formatiert als reines Text.<br>
  4542. </ul>
  4543. <br>
  4544. <b>HTML-Ausgabe-Methode (f&uuml;r ein Weblink): SYSMON_ShowValuesTextTitled(&lt;SYSMON-Instance&gt;[,&lt;Title&gt;,&lt;Liste&gt;])</b><br><br>
  4545. <ul>
  4546. Wie SYSMON_ShowValuesText, aber mit einer &Uuml;berschrift dar&uuml;ber.<br>
  4547. </ul>
  4548. <br>
  4549. <b>Readings-Werte mit Perl lesen: SYSMON_getValues(&lt;name&gt;[, &lt;Liste der gew&uuml;nschten Schl&uuml;ssel&gt;])</b><br><br>
  4550. <ul>
  4551. Liefert ein Hash-Ref mit den gew&uuml;nschten Werten. Wenn keine Liste (array) &uuml;bergeben wird, werden alle Werte geliefert.<br>
  4552. {(SYSMON_getValues("sysmon"))->{'cpu_temp'}}<br>
  4553. {(SYSMON_getValues("sysmon",("cpu_freq","cpu_temp")))->{"cpu_temp"}}<br>
  4554. {join(" ", values (SYSMON_getValues("sysmon")))}<br>
  4555. {join(" ", values (SYSMON_getValues("sysmon",("cpu_freq","cpu_temp"))))}<br>
  4556. </ul>
  4557. <br>
  4558. <b>Beispiele:</b><br><br>
  4559. <ul>
  4560. <code>
  4561. # Modul-Definition<br>
  4562. define sysmon SYSMON 1 1 1 10<br>
  4563. #attr sysmon event-on-update-reading cpu_temp,cpu_temp_avg,cpu_freq,eth0_diff,loadavg,ram,^~ /.*usb.*,~ /$<br>
  4564. attr sysmon event-on-update-reading cpu_temp,cpu_temp_avg,cpu_freq,eth0_diff,loadavg,ram,fs_.*,stat_cpu_percent<br>
  4565. attr sysmon filesystems fs_boot:/boot,fs_root:/:Root,fs_usb1:/media/usb1:USB-Stick<br>
  4566. attr sysmon network-interfaces eth0:eth0:Ethernet,wlan0:wlan0:WiFi<br>
  4567. attr sysmon group RPi<br>
  4568. attr sysmon room 9.03_Tech<br>
  4569. <br>
  4570. # Log<br>
  4571. define FileLog_sysmon FileLog ./log/sysmon-%Y-%m.log sysmon<br>
  4572. attr FileLog_sysmon group RPi<br>
  4573. attr FileLog_sysmon logtype SM_CPUTemp:Plot,text<br>
  4574. attr FileLog_sysmon room 9.03_Tech<br>
  4575. <br>
  4576. # Visualisierung: CPU-Temperatur<br>
  4577. define wl_sysmon_temp SVG FileLog_sysmon:SM_CPUTemp:CURRENT<br>
  4578. attr wl_sysmon_temp group RPi<br>
  4579. attr wl_sysmon_temp label "CPU Temperatur: Min $data{min2}, Max $data{max2}, Last $data{currval2}"<br>
  4580. attr wl_sysmon_temp room 9.03_Tech<br>
  4581. <br>
  4582. # Visualisierung: Netzwerk-Daten&uuml;bertragung f&uuml;r eth0<br>
  4583. define wl_sysmon_eth0 SVG FileLog_sysmon:SM_Network_eth0:CURRENT<br>
  4584. attr wl_sysmon_eth0 group RPi<br>
  4585. attr wl_sysmon_eth0 label "Netzwerk-Traffic eth0: $data{min1}, Max: $data{max1}, Aktuell: $data{currval1}"<br>
  4586. attr wl_sysmon_eth0 room 9.03_Tech<br>
  4587. <br>
  4588. # Visualisierung: Netzwerk-Daten&uuml;bertragung f&uuml;r wlan0<br>
  4589. define wl_sysmon_wlan0 SVG FileLog_sysmon:SM_Network_wlan0:CURRENT<br>
  4590. attr wl_sysmon_wlan0 group RPi<br>
  4591. attr wl_sysmon_wlan0 label "Netzwerk-Traffic wlan0: $data{min1}, Max: $data{max1}, Aktuell: $data{currval1}"<br>
  4592. attr wl_sysmon_wlan0 room 9.03_Tech<br>
  4593. <br>
  4594. # Visualisierung: CPU-Auslastung (load average)<br>
  4595. define wl_sysmon_load SVG FileLog_sysmon:SM_Load:CURRENT<br>
  4596. attr wl_sysmon_load group RPi<br>
  4597. attr wl_sysmon_load label "Load Min: $data{min1}, Max: $data{max1}, Aktuell: $data{currval1}"<br>
  4598. attr wl_sysmon_load room 9.03_Tech<br>
  4599. <br>
  4600. # Visualisierung: RAM-Nutzung<br>
  4601. define wl_sysmon_ram SVG FileLog_sysmon:SM_RAM:CURRENT<br>
  4602. attr wl_sysmon_ram group RPi<br>
  4603. attr wl_sysmon_ram label "RAM-Nutzung Total: $data{max1}, Min: $data{min2}, Max: $data{max2}, Aktuell: $data{currval2}"<br>
  4604. attr wl_sysmon_ram room 9.03_Tech<br>
  4605. <br>
  4606. # Visualisierung: Dateisystem: Root-Partition<br>
  4607. define wl_sysmon_fs_root SVG FileLog_sysmon:SM_FS_root:CURRENT<br>
  4608. attr wl_sysmon_fs_root group RPi<br>
  4609. attr wl_sysmon_fs_root label "Root Partition Total: $data{max1}, Min: $data{min2}, Max: $data{max2}, Aktuell: $data{currval2}"<br>
  4610. attr wl_sysmon_fs_root room 9.03_Tech<br>
  4611. <br>
  4612. # Visualisierung: Dateisystem: USB-Stick<br>
  4613. define wl_sysmon_fs_usb1 SVG FileLog_sysmon:SM_FS_usb1:CURRENT<br>
  4614. attr wl_sysmon_fs_usb1 group RPi<br>
  4615. attr wl_sysmon_fs_usb1 label "USB1 Total: $data{max1}, Min: $data{min2}, Max: $data{max2}, Aktuell: $data{currval2}"<br>
  4616. attr wl_sysmon_fs_usb1 room 9.03_Tech<br>
  4617. <br>
  4618. # Anzeige der Readings zum Einbinden in ein 'Raum'.<br>
  4619. define SysValues weblink htmlCode {SYSMON_ShowValuesHTML('sysmon')}<br>
  4620. attr SysValues group RPi<br>
  4621. attr SysValues room 9.03_Tech<br>
  4622. <br>
  4623. # Anzeige CPU Auslasung<br>
  4624. define wl_sysmon_cpustat SVG FileLog_sysmon:SM_CPUStat:CURRENT<br>
  4625. attr wl_sysmon_cpustat label "CPU(min/max): user:$data{min1}/$data{max1} nice:$data{min2}/$data{max2} sys:$data{min3}/$data{max3} idle:$data{min4}/$data{max4} io:$data{min5}/$data{max5} irq:$data{min6}/$data{max6} sirq:$data{min7}/$data{max7}"<br>
  4626. attr wl_sysmon_cpustat group RPi<br>
  4627. attr wl_sysmon_cpustat room 9.99_Test<br>
  4628. attr wl_sysmon_cpustat plotsize 840,420<br>
  4629. define wl_sysmon_cpustat_s SVG FileLog_sysmon:SM_CPUStatSum:CURRENT<br>
  4630. attr wl_sysmon_cpustat_s label "CPU(min/max): user:$data{min1}/$data{max1} nice:$data{min2}/$data{max2} sys:$data{min3}/$data{max3} idle:$data{min4}/$data{max4} io:$data{min5}/$data{max5} irq:$data{min6}/$data{max6} sirq:$data{min7}/$data{max7}"<br>
  4631. attr wl_sysmon_cpustat_s group RPi<br>
  4632. attr wl_sysmon_cpustat_s room 9.99_Test<br>
  4633. attr wl_sysmon_cpustat_s plotsize 840,420<br>
  4634. define wl_sysmon_cpustatT SVG FileLog_sysmon:SM_CPUStatTotal:CURRENT<br>
  4635. attr wl_sysmon_cpustatT label "CPU-Auslastung"<br>
  4636. attr wl_sysmon_cpustatT group RPi<br>
  4637. attr wl_sysmon_cpustatT plotsize 840,420<br>
  4638. attr wl_sysmon_cpustatT room 9.99_Test<br>
  4639. <br>
  4640. # Anzeige Stromversorgung AC<br>
  4641. define wl_sysmon_power_ac SVG FileLog_sysmon:SM_power_ac:CURRENT<br>
  4642. attr wl_sysmon_power_ac label "Stromversorgung (ac) Spannung: $data{min1} - $data{max1} V, Strom: $data{min2} - $data{max2} mA"<br>
  4643. attr wl_sysmon_power_ac room Technik<br>
  4644. attr wl_sysmon_power_ac group system<br>
  4645. # Anzeige Stromversorgung Battery<br>
  4646. define wl_sysmon_power_bat SVG FileLog_sysmon:SM_power_battery:CURRENT<br>
  4647. attr wl_sysmon_power_bat label "Stromversorgung (bat) Spannung: $data{min1} - $data{max1} V, Strom: $data{min2} - $data{max2} mA"<br>
  4648. attr wl_sysmon_power_bat room Technik<br>
  4649. attr wl_sysmon_power_bat group system<br>
  4650. </code>
  4651. </ul>
  4652. </ul>
  4653. =end html_DE
  4654. =cut