42_SYSMON.pm 190 KB

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