98_monitoring.pm 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  1. # Id ##########################################################################
  2. # $Id: 98_monitoring.pm 17223 2018-08-28 15:51:43Z igami $
  3. # copyright ###################################################################
  4. #
  5. # 98_monitoring.pm
  6. #
  7. # Copyright by igami
  8. #
  9. # This file is part of FHEM.
  10. #
  11. # FHEM is free software: you can redistribute it and/or modify it under the
  12. # terms of the GNU General Public License as published by the Free Software
  13. # Foundation, either version 2 of the License, or (at your option) any later
  14. # version.
  15. #
  16. # FHEM is distributed in the hope that it will be useful, but WITHOUT ANY
  17. # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  18. # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License along with
  21. # FHEM. If not, see <http://www.gnu.org/licenses/>.
  22. # packages ####################################################################
  23. package main;
  24. use strict;
  25. use warnings;
  26. # forward declarations ########################################################
  27. sub monitoring_Initialize($);
  28. sub monitoring_Define($$);
  29. sub monitoring_Undefine($$);
  30. sub monitoring_Set($@);
  31. sub monitoring_Get($@);
  32. sub archetype_Attr(@);
  33. sub monitoring_Notify($$);
  34. sub monitoring_modify($);
  35. sub monitoring_RemoveInternalTimer($);
  36. sub monitoring_return($$);
  37. sub monitoring_setActive($);
  38. # initialize ##################################################################
  39. sub monitoring_Initialize($) {
  40. my ($hash) = @_;
  41. my $TYPE = "monitoring";
  42. $hash->{DefFn} = $TYPE."_Define";
  43. $hash->{UndefFn} = $TYPE."_Undefine";
  44. $hash->{SetFn} = $TYPE."_Set";
  45. $hash->{GetFn} = $TYPE."_Get";
  46. $hash->{AttrFn} = $TYPE."_Attr";
  47. $hash->{NotifyFn} = $TYPE."_Notify";
  48. $hash->{AttrList} =
  49. "addStateEvent:1,0 ".
  50. "blacklist:textField-long ".
  51. "disable:1,0 ".
  52. "disabledForIntervals ".
  53. "errorFuncAdd:textField-long ".
  54. "errorFuncRemove:textField-long ".
  55. "errorWait ".
  56. "errorReturn:textField-long ".
  57. "getDefault:all,error,warning ".
  58. "setActiveFunc:textField-long ".
  59. "warningFuncAdd:textField-long ".
  60. "warningFuncRemove:textField-long ".
  61. "warningWait ".
  62. "warningReturn:textField-long ".
  63. "whitelist:textField-long ".
  64. $readingFnAttributes
  65. ;
  66. }
  67. # regular Fn ##################################################################
  68. sub monitoring_Define($$) {
  69. my ($hash, $def) = @_;
  70. my ($SELF, $TYPE, @re) = split(/[\s]+/, $def, 5);
  71. return("Usage: define <name> $TYPE <add-event> [<remove-event>]")
  72. if(int(@re) < 1 || int(@re) > 2);
  73. monitoring_NOTIFYDEV($hash);
  74. monitoring_setActive($hash) if($init_done);
  75. return;
  76. }
  77. sub monitoring_Undefine($$) {
  78. my ($hash, $arg) = @_;
  79. monitoring_RemoveInternalTimer($hash);
  80. return;
  81. }
  82. sub monitoring_Set($@) {
  83. my ($hash, @a) = @_;
  84. my $TYPE = $hash->{TYPE};
  85. return("\"set $TYPE\" needs at least one argument") if(@a < 2);
  86. my $SELF = shift @a;
  87. my $argument = shift @a;
  88. my $value = join(" ", @a) if (@a);
  89. my %monitoring_sets = (
  90. "active" => "active:noArg",
  91. "clear" => "clear:all,error,warning",
  92. "errorAdd" => "errorAdd:textField",
  93. "errorRemove" => "errorRemove:".
  94. join(",", ReadingsVal($SELF, "error", "")),
  95. "inactive" => "inactive:noArg",
  96. "warningAdd" => "warningAdd:textField",
  97. "warningRemove" => "warningRemove:".
  98. join(",", ReadingsVal($SELF, "warning", ""))
  99. );
  100. return(
  101. "Unknown argument $argument, choose one of ".
  102. join(" ", sort(values %monitoring_sets))
  103. ) unless(exists($monitoring_sets{$argument}));
  104. if($argument eq "active"){
  105. monitoring_setActive($hash);
  106. }
  107. elsif($argument eq "inactive"){
  108. readingsSingleUpdate($hash, "state", $argument, 0);
  109. Log3($SELF, 3, "$SELF ($TYPE) set $SELF inactive");
  110. monitoring_RemoveInternalTimer($hash);
  111. }
  112. elsif($argument eq "clear"){
  113. readingsBeginUpdate($hash);
  114. if($value =~ m/^(warning|all)$/){
  115. readingsBulkUpdate($hash, "warning", "", 0);
  116. readingsBulkUpdate($hash, "warningCount", 0, 0);
  117. foreach my $r (keys %{$hash->{READINGS}}){
  118. if($r =~ m/(warning)Add_(.+)/){
  119. RemoveInternalTimer("$SELF|$1|add|$2");
  120. delete $hash->{READINGS}{$r};
  121. }
  122. }
  123. }
  124. if($value =~ m/^(error|all)$/){
  125. readingsBulkUpdate($hash, "error", "", 0);
  126. readingsBulkUpdate($hash, "errorCount", 0, 0);
  127. foreach my $r (keys %{$hash->{READINGS}}){
  128. if($r =~ m/(error)Add_(.+)/){
  129. RemoveInternalTimer("$SELF|$1|add|$2");
  130. delete $hash->{READINGS}{$r};
  131. }
  132. }
  133. }
  134. readingsBulkUpdate($hash, "state", "$argument $value", 0)
  135. unless(IsDisabled($SELF));
  136. readingsEndUpdate($hash, 0);
  137. Log3($SELF, 2, "$TYPE ($SELF) set $SELF $argument $value");
  138. }
  139. elsif($argument =~ /^(error|warning)(Add|Remove)$/){
  140. monitoring_modify("$SELF|$1|".lc($2)."|$value");
  141. }
  142. return;
  143. }
  144. sub monitoring_Get($@) {
  145. my ($hash, @a) = @_;
  146. my $TYPE = $hash->{TYPE};
  147. my $SELF = shift @a;
  148. return if(IsDisabled($SELF));
  149. return("\"get $TYPE\" needs at least one argument") if(@a < 1);
  150. my $argument = shift @a;
  151. my $value = join(" ", @a) if (@a);
  152. my $default = AttrVal($SELF, "getDefault", "all");
  153. my %monitoring_gets = (
  154. "all" => "all:noArg",
  155. "default" => "default:noArg",
  156. "error" => "error:noArg",
  157. "warning" => "warning:noArg"
  158. );
  159. my @ret;
  160. return(
  161. "Unknown argument $argument, choose one of ".
  162. join(" ", sort(values %monitoring_gets))
  163. ) unless(exists($monitoring_gets{$argument}));
  164. if($argument eq "all" || ($argument eq "default" && $default eq "all")){
  165. push(@ret, monitoring_return($hash, "error"));
  166. push(@ret, monitoring_return($hash, "warning"));
  167. }
  168. elsif($argument eq "default"){
  169. push(@ret, monitoring_return($hash, $default));
  170. }
  171. elsif($argument eq "error"){
  172. push(@ret, monitoring_return($hash, "error"));
  173. }
  174. elsif($argument eq "warning"){
  175. push(@ret, monitoring_return($hash, "warning"));
  176. }
  177. return(join("\n\n", @ret)."\n") if(@ret);
  178. return;
  179. }
  180. sub monitoring_Attr(@) {
  181. my ($cmd, $SELF, $attribute, $value) = @_;
  182. my ($hash) = $defs{$SELF};
  183. if($attribute =~ "blacklist" && $value){
  184. my @blacklist;
  185. push(@blacklist, devspec2array($_)) foreach (split(/[\s]+/, $value));
  186. my %blacklist = map{$_, 1} @blacklist;
  187. foreach my $name (sort(keys %blacklist)){
  188. monitoring_modify("$SELF|warning|remove|$name");
  189. monitoring_modify("$SELF|error|remove|$name");
  190. }
  191. }
  192. elsif($attribute eq "whitelist"){
  193. monitoring_NOTIFYDEV($hash);
  194. if($value){
  195. my @whitelist;
  196. push(@whitelist, devspec2array($_)) foreach (split(/[\s]+/, $value));
  197. foreach my $list ("warning", "error"){
  198. foreach my $name (split(",", ReadingsVal($SELF, $list, ""))){
  199. monitoring_modify("$SELF|$list|remove|$name")
  200. unless(grep(/$name/, @whitelist));
  201. }
  202. }
  203. }
  204. }
  205. elsif($attribute eq "disable"){
  206. if($cmd eq "set" and $value == 1){
  207. monitoring_setActive($hash);
  208. }
  209. else{
  210. readingsSingleUpdate($hash, "state", "disabled", 0);
  211. Log3($SELF, 3, "$hash->{TYPE} ($SELF) attr $SELF disabled");
  212. }
  213. }
  214. return;
  215. }
  216. sub monitoring_Notify($$) {
  217. my ($hash, $dev_hash) = @_;
  218. my $SELF = $hash->{NAME};
  219. my $name = $dev_hash->{NAME};
  220. my $TYPE = $hash->{TYPE};
  221. return if(
  222. !$init_done ||
  223. IsDisabled($SELF) ||
  224. IsDisabled($name) ||
  225. $SELF eq $name # do not process own events
  226. );
  227. my $events = deviceEvents($dev_hash, AttrVal($SELF, "addStateEvent", 0));
  228. return unless($events);
  229. if($name eq "global" && "INITIALIZED" =~ m/\Q@{$events}\E/){
  230. monitoring_setActive($hash);
  231. return;
  232. }
  233. my ($addRegex, $removeRegex) = split(/[\s]+/, InternalVal($SELF, "DEF", ""));
  234. return unless(
  235. $addRegex =~ m/^$name:/ ||
  236. $removeRegex && $removeRegex =~ m/^$name:/ ||
  237. $events
  238. );
  239. my @blacklist;
  240. push(@blacklist, devspec2array($_))
  241. foreach (split(/[\s]+/, AttrVal($SELF, "blacklist", "")));
  242. return if(@blacklist && grep(/$name/, @blacklist));
  243. my @whitelist;
  244. push(@whitelist, devspec2array($_))
  245. foreach (split(/[\s]+/, AttrVal($SELF, "whitelist", "")));
  246. return if(@whitelist && !(grep(/$name/, @whitelist)));
  247. foreach my $event (@{$events}){
  248. next unless($event);
  249. my $addMatch = "$name:$event" =~ m/^$addRegex$/;
  250. my $removeMatch = $removeRegex ? "$name:$event" =~ m/^$removeRegex$/ : 0;
  251. next unless(defined($event) && ($addMatch || $removeMatch));
  252. Log3($SELF, 4 , "$TYPE ($SELF) triggered by \"$name $event\"");
  253. foreach my $list ("error", "warning"){
  254. my $listFuncAdd = AttrVal($SELF, $list."FuncAdd", "preset");
  255. my $listFuncRemove = AttrVal($SELF, $list."FuncRemove", "preset");
  256. my $listWait = eval(AttrVal($SELF, $list."Wait", 0));
  257. $listWait = 0 unless(looks_like_number($listWait));
  258. if($listFuncAdd eq "preset" && $listFuncRemove eq "preset"){
  259. Log3(
  260. $SELF, 5, "$TYPE ($SELF) ".
  261. $list."FuncAdd and $list"."FuncRemove are preset"
  262. );
  263. if(!$removeRegex){
  264. if($listWait == 0){
  265. Log3(
  266. $SELF, 2, "$TYPE ($SELF) ".
  267. "set \"$list"."Wait\" while \"$list".
  268. "FuncAdd\" and \"$list"."FuncRemove\" are same"
  269. ) if($list eq "error");
  270. next;
  271. }
  272. Log3($SELF, 5, "$TYPE ($SELF) only addRegex is defined");
  273. monitoring_modify("$SELF|$list|remove|$name");
  274. monitoring_modify("$SELF|$list|add|$name|$listWait");
  275. next;
  276. }
  277. else{
  278. next unless($list eq "error" || AttrVal($SELF, "errorWait", undef));
  279. Log3(
  280. $SELF, 5, "$TYPE ($SELF) ".
  281. "addRegex ($addRegex) and removeRegex ($removeRegex) are defined"
  282. );
  283. monitoring_modify("$SELF|$list|remove|$name") if($removeMatch);
  284. monitoring_modify("$SELF|$list|add|$name|$listWait") if($addMatch);
  285. next;
  286. }
  287. }
  288. $listFuncAdd = 1 if($listFuncAdd eq "preset" && $addMatch);
  289. if(!$removeRegex){
  290. Log3($SELF, 5, "$TYPE ($SELF) only addRegex is defined");
  291. if($listFuncRemove eq "preset"){
  292. if($listWait == 0){
  293. Log3(
  294. $SELF, 2, "$TYPE ($SELF) ".
  295. "set \"$list"."Wait\" while \"$list".
  296. "FuncAdd\" and \"$list"."FuncRemove\" are same"
  297. ) if($list eq "error");
  298. next;
  299. }
  300. $listFuncRemove = $listFuncAdd;
  301. }
  302. }
  303. else{
  304. Log3(
  305. $SELF, 5, "$TYPE ($SELF) ".
  306. "addRegex ($addRegex) and removeRegex ($removeRegex) are defined"
  307. );
  308. $listFuncRemove = 1 if($listFuncRemove eq "preset" && $removeMatch);
  309. }
  310. $listFuncAdd = eval($listFuncAdd) if($listFuncAdd =~ /^\{.*\}$/s);
  311. $listFuncRemove = eval($listFuncRemove)
  312. if($listFuncRemove =~ /^\{.*\}$/s);
  313. monitoring_modify("$SELF|$list|remove|$name")
  314. if($listFuncRemove && $listFuncRemove eq "1");
  315. monitoring_modify("$SELF|$list|add|$name|$listWait")
  316. if($listFuncAdd && $listFuncAdd eq "1");
  317. next;
  318. }
  319. }
  320. return;
  321. }
  322. # module Fn ###################################################################
  323. sub monitoring_modify($) {
  324. my ($SELF, $list, $operation, $value, $wait) = split("\\|", shift);
  325. my ($hash) = $defs{$SELF};
  326. return unless(defined($hash));
  327. return if(IsDisabled($SELF));
  328. my $at = eval($wait + gettimeofday()) if($wait && $wait ne "quiet");
  329. my $TYPE = $hash->{TYPE};
  330. my (@change, %readings);
  331. %readings = map{$_, 1} split(",", ReadingsVal($SELF, $list, ""));
  332. my $arg = "$SELF|$list|$operation|$value";
  333. my $reading = $list."Add_".$value;
  334. Log3(
  335. $SELF, 5 , "$TYPE ($SELF)".
  336. "\n entering monitoring_modify".
  337. "\n reading: $list".
  338. "\n operation: $operation".
  339. "\n value: $value".
  340. "\n at: ".($at ? FmtDateTime($at) : "now")
  341. );
  342. if($operation eq "add"){
  343. return if(
  344. $readings{$value} ||
  345. ReadingsVal($SELF, "error", "") =~ m/(?:^|,)$value(?:,|$)/
  346. );
  347. if($at){
  348. return if($hash->{READINGS}{$reading});
  349. readingsSingleUpdate($hash, $reading, FmtDateTime($at), 0);
  350. InternalTimer($at, "monitoring_modify", $arg);
  351. return;
  352. }
  353. else{
  354. monitoring_modify("$SELF|warning|remove|$value|quiet")
  355. if($list eq "error");
  356. $readings{$value} = 1;
  357. delete $hash->{READINGS}{$reading};
  358. }
  359. }
  360. elsif($operation eq "remove"){
  361. push(@change, 1) if(delete $readings{$value});
  362. delete $hash->{READINGS}{"$reading"};
  363. }
  364. RemoveInternalTimer("$SELF|$list|add|$value");
  365. return unless(@change || $operation eq "add");
  366. my $allCount =
  367. int(keys %readings) +
  368. ReadingsNum($SELF, ($list eq "warning" ? "error" : "warning")."Count", 0)
  369. ;
  370. readingsBeginUpdate($hash);
  371. readingsBulkUpdate($hash, "state", "$list $operation: $value");
  372. readingsBulkUpdate($hash, $list, join(",", sort(keys %readings)));
  373. readingsBulkUpdate($hash, $list."Count", int(keys %readings));
  374. readingsBulkUpdate($hash, "allCount", $allCount)
  375. unless($wait &&$wait eq "quiet");
  376. readingsEndUpdate($hash, 1);
  377. return;
  378. }
  379. sub monitoring_NOTIFYDEV($) {
  380. my ($hash) = @_;
  381. my $SELF = $hash->{NAME};
  382. my $NOTIFYDEV =
  383. AttrVal($SELF, "whitelist", undef) ||
  384. join(",", (InternalVal($SELF, "DEF", undef) =~ m/(?:^|\s)([^:\s]+):/g))
  385. ;
  386. $NOTIFYDEV =~ s/\s/,/g;
  387. notifyRegexpChanged($hash, $NOTIFYDEV);
  388. }
  389. sub monitoring_RemoveInternalTimer($) {
  390. my ($hash) = @_;
  391. my $SELF = $hash->{NAME};
  392. foreach my $reading (sort(keys %{$hash->{READINGS}})){
  393. RemoveInternalTimer("$SELF|$1|add|$2")
  394. if($reading =~ m/(error|warning)Add_(.+)/);
  395. }
  396. return;
  397. }
  398. sub monitoring_return($$) {
  399. my ($hash, $list) = @_;
  400. my $SELF = $hash->{NAME};
  401. my @errors = split(",", ReadingsVal($SELF, "error", ""));
  402. my @warnings = split(",", ReadingsVal($SELF, "warning", ""));
  403. my $value = ReadingsVal($SELF, $list, undef);
  404. my $ret = AttrVal($SELF, $list."Return", undef);
  405. $ret = '"$list: $value"' if(!$ret && $value);
  406. return unless($ret);
  407. return eval($ret);
  408. }
  409. sub monitoring_setActive($) {
  410. my ($hash) = @_;
  411. my $SELF = $hash->{NAME};
  412. my $TYPE = $hash->{TYPE};
  413. readingsSingleUpdate($hash, "state", "active", 0);
  414. Log3($SELF, 3, "$TYPE ($SELF) set $SELF active");
  415. foreach my $reading (reverse sort(keys %{$hash->{READINGS}})){
  416. if($reading =~ m/(error|warning)Add_(.+)/){
  417. my $wait = time_str2num(ReadingsVal($SELF, $reading, ""));
  418. next unless(looks_like_number($wait));
  419. $wait -= gettimeofday();
  420. if($wait > 0){
  421. Log3($SELF, 4 , "$TYPE ($SELF) restore Timer \"$SELF|$1|add|$2\"");
  422. monitoring_modify("$SELF|$1|add|$2|$wait");
  423. }
  424. else{
  425. monitoring_modify("$SELF|$1|add|$2");
  426. }
  427. }
  428. }
  429. AnalyzeCommandChain(undef, AttrVal($SELF, "setActiveFunc", "preset"));
  430. return;
  431. }
  432. 1;
  433. # commandref ##################################################################
  434. =pod
  435. =item helper
  436. =item summary monitors devices towards events and stores them in two lists
  437. =item summary_DE überwacht Geräte auf Events und speichert diese in zwei Listen
  438. =begin html
  439. <a name="monitoring"></a>
  440. <h3>monitoring</h3>
  441. ( en | <a href="commandref_DE.html#monitoring"><u>de</u></a> )
  442. <div>
  443. <ul>
  444. Each monitoring has a warning and an error list, which are stored
  445. as readings. <br>
  446. When a defined add-event occurs, the device is set to the warning
  447. list after a predefined time.<br>
  448. After a further predefined time, the device is deleted from the
  449. warning list and set to the error list.<br>
  450. If a defined remove-event occurs, the device is deleted from both
  451. lists and still running timers are canceled.<br>
  452. This makes it easy to create group messages and send them
  453. formatted by two attributes.<br>
  454. <br>
  455. The following applications are possible and are described
  456. <a href="#monitoringexamples"><u>below</u></a>:<br>
  457. <ul>
  458. <li>opened windows</li>
  459. <li>battery warnings</li>
  460. <li>activity monitor</li>
  461. <li>
  462. regular maintenance (for example changing the table water
  463. filter or cleaning rooms)
  464. </li>
  465. <li>
  466. operating hours dependent maintenance (for example clean the
  467. Beamer filter)
  468. </li>
  469. </ul>
  470. <br>
  471. The monitor does not send a message by itself, a notify or DOIF is
  472. necessary, which responds to the event "&lt;monitoring-name&gt; error
  473. add: &lt;name&gt;" and then sends the return value of "get
  474. &lt;monitoring-name&gt; default".
  475. <br>
  476. <br>
  477. <a name="monitoringdefine"></a>
  478. <b>Define</b>
  479. <ul>
  480. <code>
  481. define &lt;name&gt; monitoring &lt;add-event&gt; [&lt;remove-event&gt;]
  482. </code>
  483. <br>
  484. The syntax for &lt;add-event&gt; and &lt;remove-event&gt; is the
  485. same as the pattern for <a href="#notify">notify</a>
  486. (device-name or device-name:event).<br>
  487. If only an &lt;add-event&gt; is defined, the device is deleted from
  488. both lists as it occurs and the timers for warning and error are
  489. started.<br>
  490. </ul>
  491. <br>
  492. <a name="monitoringset"></a>
  493. <b>Set</b>
  494. <ul>
  495. <li>
  496. <code>active</code><br>
  497. Two things will happen:<br>
  498. 1. Restores pending timers, or sets the devices immediately to the
  499. corresponding list if the time is in the past.<br>
  500. 2. Executes the commands specified under the "setActiveFunc" attribute.
  501. </li>
  502. <li>
  503. <code>clear (warning|error|all)</code><br>
  504. Removes all devices from the specified list and aborts timers for this
  505. list. With "all", all devices are removed from both lists and all
  506. running timers are aborted.
  507. </li>
  508. <li>
  509. <code>errorAdd &lt;name&gt;</code><br>
  510. Add &lt;name&gt; to the error list.
  511. </li>
  512. <li>
  513. <code>errorRemove &lt;name&gt;</code><br>
  514. Removes &lt;name&gt; from the error list.
  515. </li>
  516. <li>
  517. <code>inactive</code><br>
  518. Inactivates the current device. Note the slight difference to the
  519. disable attribute: using set inactive the state is automatically saved
  520. to the statefile on shutdown, there is no explicit save necesary.
  521. </li>
  522. <li>
  523. <code>warningAdd &lt;name&gt;</code><br>
  524. Add &lt;name&gt; to the warning list.
  525. </li>
  526. <li>
  527. <code>warningRemove &lt;name&gt;</code><br>
  528. Removes &lt;name&gt; from the warning list.
  529. </li>
  530. </ul>
  531. <br>
  532. <a name="monitoringget"></a>
  533. <b>Get</b>
  534. <ul>
  535. <li>
  536. <code>all</code><br>
  537. Returns the error and warning list, separated by a blank line.<br>
  538. The formatting can be set with the attributes "errorReturn" and
  539. "warningReturn".
  540. </li>
  541. <li>
  542. <code>default</code><br>
  543. The "default" value can be set in the attribute "getDefault" and is
  544. intended to leave the configuration for the return value in the
  545. monitoring device. If nothing is specified "all" is used.
  546. </li>
  547. <li>
  548. <code>error</code><br>
  549. Returns the error list.<br>
  550. The formatting can be set with the attribute "errorReturn".
  551. </li>
  552. <li>
  553. <code>warning</code><br>
  554. Returns the warning list.<br>
  555. The formatting can be set with the attribute "warningReturn".
  556. </li>
  557. </ul>
  558. <br>
  559. <a name="monitoringreadings"></a>
  560. <b>Readings</b><br>
  561. <ul>
  562. <li>
  563. <code>allCount</code><br>
  564. Displays the amount of devices on the warning and error list..
  565. </li>
  566. <li>
  567. <code>error</code><br>
  568. Comma-separated list of devices.
  569. </li>
  570. <li>
  571. <code>errorAdd_&lt;name&gt;</code><br>
  572. Displays the time when the device will be set to the error list.
  573. </li>
  574. <li>
  575. <code>errorCount</code><br>
  576. Displays the amount of devices on the error list.
  577. </li>
  578. <li>
  579. <code>state</code><br>
  580. Displays the status (active, inactive, or disabled). In "active" it
  581. displays which device added to which list or was removed from which
  582. list.
  583. </li>
  584. <li>
  585. <code>warning</code><br>
  586. Comma-separated list of devices.
  587. </li>
  588. <li>
  589. <code>warningAdd_&lt;name&gt;</code><br>
  590. Displays the time when the device will be set to the warning list.
  591. </li>
  592. <li>
  593. <code>warningCount</code><br>
  594. Displays the amount of devices on the warning list.
  595. </li>
  596. </ul>
  597. <br>
  598. <a name="monitoringattr"></a>
  599. <b>Attribute</b>
  600. <ul>
  601. <li>
  602. <a href="#addStateEvent">
  603. <u><code>addStateEvent</code></u>
  604. </a>
  605. </li>
  606. <li>
  607. <code>blacklist</code><br>
  608. Space-separated list of devspecs which will be ignored.<br>
  609. If the attribute is set all devices which are specified by the devspecs
  610. are removed from both lists.
  611. </li>
  612. <li>
  613. <code>disable (1|0)</code><br>
  614. 1: Disables the monitoring.<br>
  615.         0: see "set active"
  616. </li>
  617. <li>
  618. <a href="#disabledForIntervals">
  619. <u><code>disabledForIntervals HH:MM-HH:MM HH:MM-HH-MM ...</code></u>
  620. </a>
  621. </li>
  622. <li>
  623. <code>errorFuncAdd {&lt;perl code&gt;}</code><br>
  624. The following variables are available in this function:
  625. <br>
  626. <ul>
  627. <li>
  628. <code>$name</code><br>
  629. Name of the event triggering device
  630. </li>
  631. <li>
  632. <code>$event</code><br>
  633. Includes the complete event, e.g.
  634. <code>measured-temp: 21.7 (Celsius)</code>
  635. </li>
  636. <li>
  637. <code>$addMatch</code><br>
  638. Has the value 1 if the add-event is true
  639. </li>
  640. <li>
  641. <code>$removeMatch</code><br>
  642. Has the value 1 if the remove-event is true
  643. </li>
  644. <li>
  645. <code>$SELF</code><br>
  646. Name of the monitoring
  647. </li>
  648. </ul>
  649. If the function returns a 1, the device is set to the error list after
  650. the wait time.<br>
  651. If the attribute is not set, it will be checked for
  652. <code>$addMatch</code>.
  653. </li>
  654. <li>
  655. <code>errorFuncRemove {&lt;perl code&gt;}</code><br>
  656. This function provides the same variables as for "errorFuncAdd".<br>
  657. If the function returns a 1, the device is removed from the error list
  658. and still running timers are canceled.<br>
  659. If the attribute is not set, it will be checked for
  660. <code>$removeMatch</code> if there is a
  661. <code>&lt;remove-event&gt;</code> in the DEF, otherwise it will be
  662. checked for <code>errorFuncAdd</code>.
  663. </li>
  664. <li>
  665. <code>errorWait &lt;perl code&gt;</code><br>
  666. Wait until the device is set to the error list.
  667. </li>
  668. <li>
  669. <code>errorReturn {&lt;perl code&gt;}</code><br>
  670. The following variables are available in this attribute:
  671. <ul>
  672. <li>
  673. <code>@errors</code><br>
  674. Array with all devices on the error list.
  675. </li>
  676. <li>
  677. <code>@warnings</code><br>
  678. Array with all devices on the warning list.
  679. </li>
  680. <li>
  681. <code>$SELF</code><br>
  682. Name of the monitoring
  683. </li>
  684. </ul>
  685. With this attribute the output created with "get &lt;name&gt; error"
  686. can be formatted.
  687. </li>
  688. <li>
  689. <code>getDefault (all|error|warning)</code><br>
  690. This attribute can be used to specify which list(s) are / are returned
  691. by "get &lt;name&gt; default". If the attribute is not set, "all" will
  692. be used.
  693. </li>
  694. <li>
  695. <code>setActiveFunc &lt;Anweisung&gt;</code><br>
  696. The statement is one of the FHEM command types and is executed when you
  697. define the monitoring or "set active".<br>
  698. For a battery message <code>"trigger battery=low battery: low"</code>
  699. can be useful.
  700. </li>
  701. <li>
  702. <code>warningFuncAdd {&lt;perl code&gt;}</code><br>
  703. Like errorFuncAdd, just for the warning list.
  704. </li>
  705. <li>
  706. <code>warningFuncRemove {&lt;perl code&gt;}</code><br>
  707. Like errorFuncRemove, just for the warning list.
  708. </li>
  709. <li>
  710. <code>warningWait &lt;perl code&gt;</code><br>
  711. Like errorWait, just for the warning list.
  712. </li>
  713. <li>
  714. <code>warningReturn {&lt;perl code&gt;}</code><br>
  715. Like errorReturn, just for the warning list.
  716. </li>
  717. <li>
  718. <code>whitelist {&lt;perl code&gt;}</code><br>
  719. Space-separated list of devspecs which are allowed.<br>
  720. If the attribute is set all devices which are not specified by the
  721. devspecs are removed from both lists.
  722. </li>
  723. <li>
  724. <a href="#readingFnAttributes">
  725. <u><code>readingFnAttributes</code></u>
  726. </a>
  727. </li>
  728. </ul>
  729. <br>
  730. <a name="monitoringexamples"></a>
  731. <b>Examples</b>
  732. <ul>
  733. <a href="https://wiki.fhem.de/wiki/Import_von_Code_Snippets">
  734. <u>The following sample codes can be imported via "Raw definition".</u>
  735. </a>
  736. <br><br>
  737. <li>
  738. <b>
  739. Global, flexible opened windows/doors message
  740. <a href="https://forum.fhem.de/index.php/topic,36504">
  741. <u>(similar to those described in the forum)</u>
  742. </a>
  743. </b>
  744. <br>
  745. <pre>defmod Fenster_monitoring monitoring .*:(open|tilted) .*:closed
  746. attr Fenster_monitoring errorReturn {return unless(@errors);;\
  747. $_ = AttrVal($_, "alias", $_) foreach(@errors);;\
  748. return("Das Fenster \"$errors[0]\" ist schon l&auml;nger ge&ouml;ffnet.") if(int(@errors) == 1);;\
  749. @errors = sort {lc($a) cmp lc($b)} @errors;;\
  750. return(join("\n - ", "Die folgenden ".@errors." Fenster sind schon l&auml;nger ge&ouml;ffnet:", @errors))\
  751. }
  752. attr Fenster_monitoring errorWait {AttrVal($name, "winOpenTimer", 60*10)}
  753. attr Fenster_monitoring warningReturn {return unless(@warnings);;\
  754. $_ = AttrVal($_, "alias", $_) foreach(@warnings);;\
  755. return("Das Fenster \"$warnings[0]\" ist seit kurzem ge&ouml;ffnet.") if(int(@warnings) == 1);;\
  756. @warnings = sort {lc($a) cmp lc($b)} @warnings;;\
  757. return(join("\n - ", "Die folgenden ".@warnings." Fenster sind seit kurzem ge&ouml;ffnet:", @warnings))\
  758. }</pre>
  759. As soon as a device triggers an "open" or "tilded" event, the device is
  760. set to the warning list and a timer is started after which the device
  761. is moved from the warning to the error list. The waiting time can be
  762. set for each device via userattr "winOpenTimer". The default value is
  763. 10 minutes.<br>
  764. As soon as a device triggers a "closed" event, the device is deleted
  765. from both lists and still running timers are stopped.
  766. </li>
  767. <br>
  768. <li>
  769. <b>Battery monitoring</b><br>
  770. <pre>defmod Batterie_monitoring monitoring .*:battery:.low .*:battery:.ok
  771. attr Batterie_monitoring errorReturn {return unless(@errors);;\
  772. $_ = AttrVal($_, "alias", $_) foreach(@errors);;\
  773. return("Bei dem Ger&auml;t \"$errors[0]\" muss die Batterie gewechselt werden.") if(int(@errors) == 1);;\
  774. @errors = sort {lc($a) cmp lc($b)} @errors;;\
  775. return(join("\n - ", "Die folgenden ".@errors." Ger&auml;ten muss die Batterie gewechselt werden:", @errors))\
  776. }
  777. attr Batterie_monitoring errorWait 60*60*24*14
  778. attr Batterie_monitoring warningReturn {return unless(@warnings);;\
  779. $_ = AttrVal($_, "alias", $_) foreach(@warnings);;\
  780. return("Bei dem Ger&auml;t \"$warnings[0]\" muss die Batterie demn&auml;chst gewechselt werden.") if(int(@warnings) == 1);;\
  781. @warnings = sort {lc($a) cmp lc($b)} @warnings;;\
  782. return(join("\n - ", "Die folgenden ".@warnings." Ger&auml;ten muss die Batterie demn&auml;chst gewechselt werden:", @warnings))\
  783. }</pre>
  784. As soon as a device triggers a "battery: low" event, the device is set
  785. to the warning list and a timer is started after which the device is
  786. moved from the warning to the error list. The waiting time is set to 14
  787. days.<br>
  788. As soon as a device triggers a "battery: ok" event, the device is
  789. deleted from both lists and still running timers are stopped.
  790. </li>
  791. <br>
  792. <li>
  793. <b>Activity Monitor</b><br>
  794. <pre>defmod Activity_monitoring monitoring .*:.*
  795. attr Activity_monitoring errorReturn {return unless(@errors);;\
  796. $_ = AttrVal($_, "alias", $_) foreach(@errors);;\
  797. return("Das Ger&auml;t \"$errors[0]\" hat sich seit mehr als 24 Stunden nicht mehr gemeldet.") if(int(@errors) == 1);;\
  798. @errors = sort {lc($a) cmp lc($b)} @errors;;\
  799. return(join("\n - ", "Die folgenden ".@errors." Ger&auml;ten haben sich seit mehr als 24 Stunden nicht mehr gemeldet:", @errors))\
  800. }
  801. attr Activity_monitoring errorWait 60*60*24
  802. attr Activity_monitoring warningReturn {return unless(@warnings);;\
  803. $_ = AttrVal($_, "alias", $_) foreach(@warnings);;\
  804. return("Das Ger&auml;t \"$warnings[0]\" hat sich seit mehr als 12 Stunden nicht mehr gemeldet.") if(int(@warnings) == 1);;\
  805. @warnings = sort {lc($a) cmp lc($b)} @warnings;;\
  806. return(join("\n - ", "Die folgenden ".@warnings." Ger&auml;ten haben sich seit mehr als 12 Stunden nicht mehr gemeldet:", @warnings))\
  807. }
  808. attr Activity_monitoring warningWait 60*60*12</pre>
  809. Devices are not monitored until they have triggered at least one event.
  810. If the device does not trigger another event in 12 hours, it will be
  811. set to the warning list. If the device does not trigger another event
  812. within 24 hours, it will be moved from the warning list to the error
  813. list.<br>
  814. <br>
  815. Note: It is recommended to use the whitelist attribute.
  816. </li>
  817. <br>
  818. <li>
  819. <b>Regular maintenance (for example changing the table water filter)</b>
  820. <br>
  821. <pre>defmod Wasserfilter_monitoring monitoring Wasserfilter_DashButton:.*:.short
  822. attr Wasserfilter_monitoring errorReturn {return unless(@errors);;\
  823. return "Der Wasserfilter muss gewechselt werden.";;\
  824. }
  825. attr Wasserfilter_monitoring errorWait 60*60*24*30
  826. attr Wasserfilter_monitoring warningReturn {return unless(@warnings);;\
  827. return "Der Wasserfilter muss demn&auml;chst gewechselt werden.";;\
  828. }
  829. attr Wasserfilter_monitoring warningWait 60*60*24*25</pre>
  830. A <a href="#dash_dhcp"><u>DashButton</u></a> is used to tell FHEM that
  831. the water filter has been changed.<br>
  832. After 30 days, the DashButton is set to the error list.
  833. </li>
  834. <br>
  835. <li>
  836. <b>Regular maintenance (for example cleaning rooms)</b>
  837. <br>
  838. <pre>defmod putzen_DashButton dash_dhcp
  839. attr putzen_DashButton allowed AC:63:BE:2E:19:AF,AC:63:BE:49:23:48,AC:63:BE:49:5E:FD,50:F5:DA:93:2B:EE,AC:63:BE:B2:07:78
  840. attr putzen_DashButton devAlias ac-63-be-2e-19-af:Badezimmer\
  841. ac-63-be-49-23-48:Küche\
  842. ac-63-be-49-5e-fd:Schlafzimmer\
  843. 50-f5-da-93-2b-ee:Arbeitszimmer\
  844. ac-63-be-b2-07-78:Wohnzimmer
  845. attr putzen_DashButton event-min-interval .*:5
  846. attr putzen_DashButton port 6767
  847. attr putzen_DashButton userReadings state {return (split(":", @{$hash->{CHANGED}}[0]))[0];;}
  848. attr putzen_DashButton widgetOverride allowed:textField-long devAlias:textField-long
  849. defmod putzen_monitoring monitoring putzen_DashButton:.*:.short
  850. attr putzen_monitoring errorFuncAdd {$event =~ m/^(.+):/;;\
  851. $name = $1;;\
  852. return 1;;\
  853. }
  854. attr putzen_monitoring errorReturn {return unless(@errors);;\
  855. return("Der Raum \"$errors[0]\" muss wieder geputzt werden.") if(int(@errors) == 1);;\
  856. return(join("\n - ", "Die folgenden Räume müssen wieder geputzt werden:", @errors))\
  857. }
  858. attr putzen_monitoring errorWait 60*60*24*7</pre>
  859. Several <a href="#dash_dhcp"><u>DashButton</u></a> are used to inform
  860. FHEM that the rooms have been cleaned.<br>
  861. After 7 days, the room is set to the error list.<br>
  862. However, the room name is not the device name but the readings name and
  863. is changed in the <code>errorFuncAdd</code> attribute.
  864. </li>
  865. <br>
  866. <li>
  867. <b>
  868. Operating hours dependent maintenance
  869. (for example, clean the Beamer filter)
  870. </b>
  871. <br>
  872. <pre>defmod BeamerFilter_monitoring monitoring Beamer_HourCounter:pulseTimeOverall BeamerFilter_DashButton:.*:.short
  873. attr BeamerFilter_monitoring userattr errorInterval
  874. attr BeamerFilter_monitoring errorFuncAdd {return 1\
  875. if(ReadingsVal($name, "pulseTimeOverall", 0) >= \
  876. ReadingsVal($name, "pulseTimeService", 0)\
  877. + (AttrVal($SELF, "errorInterval", 0))\
  878. && $addMatch\
  879. );;\
  880. return;;\
  881. }
  882. attr BeamerFilter_monitoring errorFuncRemove {return unless($removeMatch);;\
  883. $name = "Beamer_HourCounter";;\
  884. fhem(\
  885. "setreading $name pulseTimeService "\
  886. .ReadingsVal($name, "pulseTimeOverall", 0)\
  887. );;\
  888. return 1;;\
  889. }
  890. attr BeamerFilter_monitoring errorInterval 60*60*200
  891. attr BeamerFilter_monitoring errorReturn {return unless(@errors);;\
  892. return "Der Filter vom Beamer muss gereinigt werden.";;\
  893. }
  894. attr BeamerFilter_monitoring warningFuncAdd {return}
  895. attr BeamerFilter_monitoring warningFuncRemove {return}</pre>
  896. An <a href="#HourCounter"><u>HourCounter</u></a> is used to record the
  897. operating hours of a beamer and a
  898. <a href="#dash_dhcp"><u>DashButton</u></a> to tell FHEM that the filter
  899. has been cleaned.<br>
  900. If the filter has not been cleaned for more than 200 hours, the device
  901. is set to the error list.<br>
  902. If cleaning is acknowledged with the DashButton, the device is removed
  903. from the error list and the current operating hours are stored in the
  904. HourCounter device.
  905. </li>
  906. </ul>
  907. </ul>
  908. </div>
  909. =end html
  910. =begin html_DE
  911. <a name="monitoring"></a>
  912. <h3>monitoring</h3>
  913. ( <a href="commandref.html#monitoring"><u>en</u></a> | de )
  914. <div>
  915. <ul>
  916. Jedes monitoring verf&uuml;gt &uuml;ber eine warning- und eine error-Liste,
  917. welche als Readings gespeichert werden.<br>
  918. Beim auftreten eines definierten add-events wird das Ger&auml;t nach einer
  919. vorgegeben Zeit auf die warning-Liste gesetzt.<br>
  920. Nach einer weiteren vorgegeben Zeit wird das Ger&auml;t von der
  921. warning-Liste gel&ouml;scht und auf die error-Liste gesetzt.<br>
  922. Beim auftreten eines definierten remove-events wird das Ger&auml;t von
  923. beiden Listen gel&ouml;scht und noch laufende Timer abgebrochen.<br>
  924. Hiermit lassen sich auf einfache Weise Sammelmeldungen erstellen und durch
  925. zwei Attribute formatiert ausgeben.<br>
  926. <br>
  927. Folgende Anwendungen sind m&ouml;glich und werden
  928. <a href="#monitoringexamples"><u>unten</u></a> beschrieben:<br>
  929. <ul>
  930. <li>ge&ouml;ffnete Fenster</li>
  931. <li>Batterie Warnungen</li>
  932. <li>Activity Monitor</li>
  933. <li>
  934. regelm&auml;&szlig;ige Wartungsarbeiten
  935. (z.B. Tischwasserfilter wechseln oder Räume putzen)
  936. </li>
  937. <li>
  938. Betriebsstunden abh&auml;ngige Wartungsarbeiten
  939. (z.B. Beamer Filter reinigen)
  940. </li>
  941. </ul>
  942. <br>
  943. Das monitor sendet selbst keine Benachrichtung, hierf&uuml;r ist ein notify
  944. oder DOIF notwendig, welches auf das Event "&lt;monitoring-name&gt; error
  945. add: &lt;name&gt;" reagiert und dann den R&uuml;ckgabewert von
  946. "get &lt;monitoring-name&gt; default" versendet.
  947. <br>
  948. <br>
  949. <a name="monitoringdefine"></a>
  950. <b>Define</b>
  951. <ul>
  952. <code>
  953. define &lt;name&gt; mointoring &lt;add-event&gt; [&lt;remove-event&gt;]
  954. </code>
  955. <br>
  956. Die Syntax f&uuml;r &lt;add-event&gt; und &lt;remove-event&gt; ist die
  957. gleiche wie f&uuml;r das Suchmuster von
  958. <a href="commandref_DE.html#notify"><u>notify</u></a> (Ger&auml;tename
  959. oder Ger&auml;tename:Event).<br>
  960. Ist nur ein &lt;add-event&gt; definiert wird beim auftreten das
  961. Ger&auml;t von beiden Listen gel&ouml;scht und die Timer f&uuml;r warning
  962. und error werden gestartet.<br>
  963. </ul>
  964. <br>
  965. <a name="monitoringset"></a>
  966. <b>Set</b>
  967. <ul>
  968. <li>
  969. <code>active</code><br>
  970. Es passieren zwei Dinge:<br>
  971. 1. Stellt noch ausstehende Timer wieder her, bzw. setzt die Ger&auml;te
  972. sofort auf die entsprechende Liste, falls der Zeitpunkt in der
  973. Vergangenheit liegt.<br>
  974. 2. F&uuml;hrt die unter dem Attribut "setActiveFunc" angegeben Befehle
  975. aus.
  976. </li>
  977. <li>
  978. <code>clear (warning|error|all)</code><br>
  979. Entfernt alle Ger&auml;te von der angegeben Liste und bricht f&uuml;r
  980. diese Liste laufende Timer ab. Bei "all" werden alle Ger&auml;te von
  981. beiden Listen entfernt und alle laufenden Timer abgebrochen.
  982. </li>
  983. <li>
  984. <code>errorAdd &lt;name&gt;</code><br>
  985. F&uuml;gt &lt;name&gt; zu der error-Liste hinzu.
  986. </li>
  987. <li>
  988. <code>errorRemove &lt;name&gt;</code><br>
  989. Entfernt &lt;name&gt; von der error-Liste.
  990. </li>
  991. <li>
  992. <code>inactive</code><br>
  993. Deaktiviert das monitoring. Beachte den leichten semantischen
  994. Unterschied zum disable Attribut: "set inactive" wird bei einem
  995. shutdown automatisch in fhem.state gespeichert, es ist kein save
  996. notwendig.
  997. </li>
  998. <li>
  999. <code>warningAdd &lt;name&gt;</code><br>
  1000. F&uuml;gt &lt;name&gt; zu der warning-Liste hinzu.
  1001. </li>
  1002. <li>
  1003. <code>warningRemove &lt;name&gt;</code><br>
  1004. Entfernt &lt;name&gt; von der warning-Liste.
  1005. </li>
  1006. </ul>
  1007. <br>
  1008. <a name="monitoringget"></a>
  1009. <b>Get</b>
  1010. <ul>
  1011. <li>
  1012. <code>all</code><br>
  1013. Gibt, durch eine Leerzeile getrennt, die error- und warning-Liste
  1014. zur&uuml;ck.<br>
  1015. Die Formatierung kann dabei mit den Attributen "errorReturn" und
  1016. "warningReturn" eingestellt werden.
  1017. </li>
  1018. <li>
  1019. <code>default</code><br>
  1020. Der "default" Wert kann in dem Attribut "getDefault" festgelegt werden
  1021. und ist dazu gedacht um die Konfiguration f&uuml;r den
  1022. R&uuml;ckgabewert im monitoring Ger&auml;t zu belassen. Wird nichts
  1023. angegeben wird "all" verwendent.
  1024. </li>
  1025. <li>
  1026. <code>error</code><br>
  1027. Gibt die error-Liste zur&uuml;ck.<br>
  1028. Die Formatierung kann dabei mit dem Attribut "errorReturn" eingestellt
  1029. werden.
  1030. </li>
  1031. <li>
  1032. <code>warning</code><br>
  1033. Gibt die warning-Liste zur&uuml;ck.<br>
  1034. Die Formatierung kann dabei mit dem Attribut "warningReturn"
  1035. eingestellt werden.
  1036. </li>
  1037. </ul>
  1038. <br>
  1039. <a name="monitoringreadings"></a>
  1040. <b>Readings</b><br>
  1041. <ul>
  1042. <li>
  1043. <code>allCount</code><br>
  1044. Zeigt die Anzahl der Geräte in der warning- und error-Liste an.
  1045. </li>
  1046. <li>
  1047. <code>error</code><br>
  1048. Durch Komma getrennte Liste von Ger&auml;ten.
  1049. </li>
  1050. <li>
  1051. <code>errorAdd_&lt;name&gt;</code><br>
  1052. Zeigt den Zeitpunkt an wann das Ger&auml;t auf die error-Liste gesetzt
  1053. wird.
  1054. </li>
  1055. <li>
  1056. <code>errorCount</code><br>
  1057. Zeigt die Anzahl der Geräte in der error-Liste an.
  1058. </li>
  1059. <li>
  1060. <code>state</code><br>
  1061. Zeigt den Status (active, inactive oder disabled) an. Bei "active" wird
  1062. angezeigt welches Gerät zu welcher Liste hinzugefügt bzw. von welcher
  1063. Liste entfernt wurde.
  1064. </li>
  1065. <li>
  1066. <code>warning</code><br>
  1067. Durch Komma getrennte Liste von Ger&auml;ten.
  1068. </li>
  1069. <li>
  1070. <code>warningAdd_&lt;name&gt;</code><br>
  1071. Zeigt den Zeitpunkt an wann das Ger&auml;t auf die warning-Liste
  1072. gesetzt wird.
  1073. </li>
  1074. <li>
  1075. <code>warningCount</code><br>
  1076. Zeigt die Anzahl der Geräte in der warning-Liste an.
  1077. </li>
  1078. </ul>
  1079. <br>
  1080. <a name="monitoringattr"></a>
  1081. <b>Attribute</b>
  1082. <ul>
  1083. <li>
  1084. <a href="#addStateEvent">
  1085. <u><code>addStateEvent</code></u>
  1086. </a>
  1087. </li>
  1088. <li>
  1089. <code>blacklist</code><br>
  1090. Durch Leerzeichen getrennte Liste von devspecs die ignoriert werden.<br>
  1091. Wenn das Attribut gesetzt wird werden alle Geräte die durch die
  1092. devspecs definiert sind von beiden Listen gelöscht.
  1093. </li>
  1094. <li>
  1095. <code>disable (1|0)</code><br>
  1096. 1: Deaktiviert das monitoring.<br>
  1097. 0: siehe "set active"
  1098. </li>
  1099. <li>
  1100. <a href="#disabledForIntervals">
  1101. <u><code>disabledForIntervals HH:MM-HH:MM HH:MM-HH-MM ...</code></u>
  1102. </a>
  1103. </li>
  1104. <li>
  1105. <code>errorFuncAdd {&lt;perl code&gt;}</code><br>
  1106. In dieser Funktion stehen die folgende Variablen zur Verf&uuml;gung:
  1107. <br>
  1108. <ul>
  1109. <li>
  1110. <code>$name</code><br>
  1111. Name des Event ausl&ouml;senden Ger&auml;tes
  1112. </li>
  1113. <li>
  1114. <code>$event</code><br>
  1115. Beinhaltet das komplette Event, z.B.
  1116. <code>measured-temp: 21.7 (Celsius)</code>
  1117. </li>
  1118. <li>
  1119. <code>$addMatch</code><br>
  1120. Hat den Wert 1, falls das add-event zutrifft
  1121. </li>
  1122. <li>
  1123. <code>$removeMatch</code><br>
  1124. Hat den Wert 1, falls das remove-event zutrifft
  1125. </li>
  1126. <li>
  1127. <code>$SELF</code><br>
  1128. Eigenname des monitoring
  1129. </li>
  1130. </ul>
  1131. Gibt die Funktion eine 1 zur&uuml;ck, wird das Ger&auml;t, nach der
  1132. Wartezeit, auf die error-Liste gesetzt.<br>
  1133. Wenn das Attribut nicht gesetzt ist wird auf <code>$addMatch</code>
  1134. gepr&uuml;ft.
  1135. </li>
  1136. <li>
  1137. <code>errorFuncRemove {&lt;perl code&gt;}</code><br>
  1138. In dieser Funktion stehen die selben Variablen wie bei "errorFuncAdd"
  1139. zur Verf&uuml;gung.<br>
  1140. Gibt die Funktion eine 1 zur&uuml;ck, wird das Ger&auml;t von der
  1141. error-Liste entfernt und noch laufende Timer werden abgebrochen.<br>
  1142. Wenn das Attribut nicht gesetzt ist wird bei einer DEF mit
  1143. <code>&lt;remove-event&gt;</code> auf <code>$removeMatch</code>
  1144. gepr&uuml;ft und bei einer DEF ohne <code>&lt;remove-event&gt;</code>
  1145. auf <code>errorFuncAdd</code>.
  1146. </li>
  1147. <li>
  1148. <code>errorWait &lt;perl code&gt;</code><br>
  1149. Wartezeit bis das Ger&auml;t auf die error-Liste gesetzt wird.
  1150. </li>
  1151. <li>
  1152. <code>errorReturn {&lt;perl code&gt;}</code><br>
  1153. In diesem Attribut stehen folgende Variablen zur Verf&uuml;gung:
  1154. <ul>
  1155. <li>
  1156. <code>@errors</code><br>
  1157. Array mit allen Ger&auml;ten auf der error-Liste.
  1158. </li>
  1159. <li>
  1160. <code>@warnings</code><br>
  1161. Array mit allen Ger&auml;ten auf der warning-Liste.
  1162. </li>
  1163. <li>
  1164. <code>$SELF</code><br>
  1165. Eigenname des monitoring
  1166. </li>
  1167. </ul>
  1168. Mit diesem Attribut kann die Ausgabe die mit "get &lt;name&gt; error"
  1169. erzeugt wird angepasst werden.
  1170. </li>
  1171. <li>
  1172. <code>getDefault (all|error|warning)</code><br>
  1173. Mit diesem Attribut kann festgelegt werden welche Liste/n mit "get
  1174. &lt;name&gt; default" zur&uuml;ck gegeben wird/werden. Wenn das
  1175. Attribut nicht gesetzt ist wird "all" verwendet.
  1176. </li>
  1177. <li>
  1178. <code>setActiveFunc &lt;Anweisung&gt;</code><br>
  1179. Die Anweisung ist einer der FHEM
  1180. <a href="#command"><u>Befehlstypen</u></a> und wird beim definieren des
  1181. monitoring oder bei "set active" ausgef&uuml;hrt.<br>
  1182. F&uuml;r eine Batterie Meldung kann <code>"trigger battery=low
  1183. battery:low"</code> sinnvoll sein.
  1184. </li>
  1185. <li>
  1186. <code>warningFuncAdd {&lt;perl code&gt;}</code><br>
  1187. Wie errorFuncAdd, nur f&uuml;r die warning-Liste.
  1188. </li>
  1189. <li>
  1190. <code>warningFuncRemove {&lt;perl code&gt;}</code><br>
  1191. Wie errorFuncRemove, nur f&uuml;r die warning-Liste.
  1192. </li>
  1193. <li>
  1194. <code>warningWait &lt;perl code&gt;</code><br>
  1195. Wie errorWait, nur f&uuml;r die warning-Liste.
  1196. </li>
  1197. <li>
  1198. <code>warningReturn {&lt;perl code&gt;}</code><br>
  1199. Wie errorReturn, nur f&uuml;r die warning-Liste.
  1200. </li>
  1201. <li>
  1202. <code>whitelist {&lt;perl code&gt;}</code><br>
  1203. Durch Leerzeichen getrennte Liste von devspecs die erlaubt sind
  1204. werden.<br>
  1205. Wenn das Attribut gesetzt wird werden alle Geräte die nicht durch die
  1206. devspecs definiert sind von beiden Listen gelöscht.
  1207. </li>
  1208. <li>
  1209. <a href="#readingFnAttributes">
  1210. <u><code>readingFnAttributes</code></u>
  1211. </a>
  1212. </li>
  1213. </ul>
  1214. <br>
  1215. <a name="monitoringexamples"></a>
  1216. <b>Beispiele</b>
  1217. <ul>
  1218. <a href="https://wiki.fhem.de/wiki/Import_von_Code_Snippets">
  1219. <u>
  1220. Die folgenden beispiel Codes k&ouml;nnen per "Raw defnition"
  1221. importiert werden.
  1222. </u>
  1223. </a>
  1224. <br><br>
  1225. <li>
  1226. <b>
  1227. Globale, flexible Fenster-/T&uuml;r-Offen-Meldungen
  1228. <a href="https://forum.fhem.de/index.php/topic,36504">
  1229. <u>(&auml;hnlich wie im Forum beschrieben)</u>
  1230. </a>
  1231. </b>
  1232. <br>
  1233. <pre>defmod Fenster_monitoring monitoring .*:(open|tilted) .*:closed
  1234. attr Fenster_monitoring errorReturn {return unless(@errors);;\
  1235. $_ = AttrVal($_, "alias", $_) foreach(@errors);;\
  1236. return("Das Fenster \"$errors[0]\" ist schon l&auml;nger ge&ouml;ffnet.") if(int(@errors) == 1);;\
  1237. @errors = sort {lc($a) cmp lc($b)} @errors;;\
  1238. return(join("\n - ", "Die folgenden ".@errors." Fenster sind schon l&auml;nger ge&ouml;ffnet:", @errors))\
  1239. }
  1240. attr Fenster_monitoring errorWait {AttrVal($name, "winOpenTimer", 60*10)}
  1241. attr Fenster_monitoring warningReturn {return unless(@warnings);;\
  1242. $_ = AttrVal($_, "alias", $_) foreach(@warnings);;\
  1243. return("Das Fenster \"$warnings[0]\" ist seit kurzem ge&ouml;ffnet.") if(int(@warnings) == 1);;\
  1244. @warnings = sort {lc($a) cmp lc($b)} @warnings;;\
  1245. return(join("\n - ", "Die folgenden ".@warnings." Fenster sind seit kurzem ge&ouml;ffnet:", @warnings))\
  1246. }</pre>
  1247. Sobald ein Ger&auml;t ein "open" oder "tilded" Event ausl&ouml;st wird
  1248. das Ger&auml;t auf die warning-Liste gesetzt und es wird ein Timer
  1249. gestartet nach dessen Ablauf das Ger&auml;t von der warning- auf die
  1250. error-Liste verschoben wird. Die Wartezeit kann f&uuml;r jedes
  1251. Ger&auml;t per userattr "winOpenTimer" festgelegt werden. Der
  1252. Vorgabewert sind 10 Minuten.<br>
  1253. Sobald ein Ger&auml;t ein "closed" Event ausl&ouml;st wird das
  1254. Ger&auml;t von beiden Listen gel&ouml;scht und noch laufende Timer
  1255. werden gestoppt.
  1256. </li>
  1257. <br>
  1258. <li>
  1259. <b>Batterie&uuml;berwachung</b><br>
  1260. <pre>defmod Batterie_monitoring monitoring .*:battery:.low .*:battery:.ok
  1261. attr Batterie_monitoring errorReturn {return unless(@errors);;\
  1262. $_ = AttrVal($_, "alias", $_) foreach(@errors);;\
  1263. return("Bei dem Ger&auml;t \"$errors[0]\" muss die Batterie gewechselt werden.") if(int(@errors) == 1);;\
  1264. @errors = sort {lc($a) cmp lc($b)} @errors;;\
  1265. return(join("\n - ", "Die folgenden ".@errors." Ger&auml;ten muss die Batterie gewechselt werden:", @errors))\
  1266. }
  1267. attr Batterie_monitoring errorWait 60*60*24*14
  1268. attr Batterie_monitoring warningReturn {return unless(@warnings);;\
  1269. $_ = AttrVal($_, "alias", $_) foreach(@warnings);;\
  1270. return("Bei dem Ger&auml;t \"$warnings[0]\" muss die Batterie demn&auml;chst gewechselt werden.") if(int(@warnings) == 1);;\
  1271. @warnings = sort {lc($a) cmp lc($b)} @warnings;;\
  1272. return(join("\n - ", "Die folgenden ".@warnings." Ger&auml;ten muss die Batterie demn&auml;chst gewechselt werden:", @warnings))\
  1273. }</pre>
  1274. Sobald ein Ger&auml;t ein "battery: low" Event ausl&ouml;st wird das
  1275. Ger&auml;t auf die warning-Liste gesetzt und es wird ein Timer
  1276. gestartet nach dessen Ablauf das Ger&auml;t von der warning- auf die
  1277. error-Liste verschoben wird. Die Wartezeit ist auf 14 Tage
  1278. eingestellt.<br>
  1279. Sobald ein Ger&auml;t ein "battery: ok" Event ausl&ouml;st wird das
  1280. Ger&auml;t von beiden Listen gel&ouml;scht und noch laufende Timer
  1281. werden gestoppt.
  1282. </li>
  1283. <br>
  1284. <li>
  1285. <b>Activity Monitor</b><br>
  1286. <pre>defmod Activity_monitoring monitoring .*:.*
  1287. attr Activity_monitoring errorReturn {return unless(@errors);;\
  1288. $_ = AttrVal($_, "alias", $_) foreach(@errors);;\
  1289. return("Das Ger&auml;t \"$errors[0]\" hat sich seit mehr als 24 Stunden nicht mehr gemeldet.") if(int(@errors) == 1);;\
  1290. @errors = sort {lc($a) cmp lc($b)} @errors;;\
  1291. return(join("\n - ", "Die folgenden ".@errors." Ger&auml;ten haben sich seit mehr als 24 Stunden nicht mehr gemeldet:", @errors))\
  1292. }
  1293. attr Activity_monitoring errorWait 60*60*24
  1294. attr Activity_monitoring warningReturn {return unless(@warnings);;\
  1295. $_ = AttrVal($_, "alias", $_) foreach(@warnings);;\
  1296. return("Das Ger&auml;t \"$warnings[0]\" hat sich seit mehr als 12 Stunden nicht mehr gemeldet.") if(int(@warnings) == 1);;\
  1297. @warnings = sort {lc($a) cmp lc($b)} @warnings;;\
  1298. return(join("\n - ", "Die folgenden ".@warnings." Ger&auml;ten haben sich seit mehr als 12 Stunden nicht mehr gemeldet:", @warnings))\
  1299. }
  1300. attr Activity_monitoring warningWait 60*60*12</pre>
  1301. Ger&auml;te werden erst &uuml;berwacht, wenn sie mindestens ein Event
  1302. ausgel&ouml;st haben. Sollte das Ger&auml;t in 12 Stunden kein weiterer
  1303. Event ausl&ouml;sen, wird es auf die warning-Liste gesetzt. Sollte das
  1304. Ger&auml;t in 24 Stunden kein weiteres Event ausl&ouml;sen, wird es von
  1305. der warning- auf die error-Liste verschoben.<br>
  1306. <br>
  1307. Hinweis: Es ist empfehlenswert das whitelist Attribut zu verwenden.
  1308. </li>
  1309. <br>
  1310. <li>
  1311. <b>
  1312. regelm&auml;&szlig;ige Wartungsarbeiten
  1313. (z.B. Tischwasserfilter wechseln)
  1314. </b>
  1315. <br>
  1316. <pre>defmod Wasserfilter_monitoring monitoring Wasserfilter_DashButton:.*:.short
  1317. attr Wasserfilter_monitoring errorReturn {return unless(@errors);;\
  1318. return "Der Wasserfilter muss gewechselt werden.";;\
  1319. }
  1320. attr Wasserfilter_monitoring errorWait 60*60*24*30
  1321. attr Wasserfilter_monitoring warningReturn {return unless(@warnings);;\
  1322. return "Der Wasserfilter muss demn&auml;chst gewechselt werden.";;\
  1323. }
  1324. attr Wasserfilter_monitoring warningWait 60*60*24*25</pre>
  1325. Hierbei wird ein <a href="#dash_dhcp"><u>DashButton</u></a> genutzt um
  1326. FHEM mitzuteilen, dass der Wasserfilter gewechselt wurde.<br>
  1327. Nach 30 Tagen wird der DashButton auf die error-Liste gesetzt.
  1328. </li>
  1329. <br>
  1330. <li>
  1331. <b>
  1332. regelm&auml;&szlig;ige Wartungsarbeiten
  1333. (z.B. Räume putzen)
  1334. </b>
  1335. <br>
  1336. <pre>defmod putzen_DashButton dash_dhcp
  1337. attr putzen_DashButton allowed AC:63:BE:2E:19:AF,AC:63:BE:49:23:48,AC:63:BE:49:5E:FD,50:F5:DA:93:2B:EE,AC:63:BE:B2:07:78
  1338. attr putzen_DashButton devAlias ac-63-be-2e-19-af:Badezimmer\
  1339. ac-63-be-49-23-48:Küche\
  1340. ac-63-be-49-5e-fd:Schlafzimmer\
  1341. 50-f5-da-93-2b-ee:Arbeitszimmer\
  1342. ac-63-be-b2-07-78:Wohnzimmer
  1343. attr putzen_DashButton event-min-interval .*:5
  1344. attr putzen_DashButton port 6767
  1345. attr putzen_DashButton userReadings state {return (split(":", @{$hash->{CHANGED}}[0]))[0];;}
  1346. attr putzen_DashButton widgetOverride allowed:textField-long devAlias:textField-long
  1347. defmod putzen_monitoring monitoring putzen_DashButton:.*:.short
  1348. attr putzen_monitoring errorFuncAdd {$event =~ m/^(.+):/;;\
  1349. $name = $1;;\
  1350. return 1;;\
  1351. }
  1352. attr putzen_monitoring errorReturn {return unless(@errors);;\
  1353. return("Der Raum \"$errors[0]\" muss wieder geputzt werden.") if(int(@errors) == 1);;\
  1354. return(join("\n - ", "Die folgenden Räume müssen wieder geputzt werden:", @errors))\
  1355. }
  1356. attr putzen_monitoring errorWait 60*60*24*7</pre>
  1357. Hierbei werden mehrere <a href="#dash_dhcp"><u>DashButton</u></a>
  1358. genutzt um FHEM mitzuteilen, dass die Räume geputzt wurden.<br>
  1359. Nach 7 Tagen wird der Raum auf die error-Liste gesetzt.<br>
  1360. Der Raum Name ist hierbei jedoch nicht der Geräte-Name, sondern der
  1361. Readings-Name und wird in dem <code>errorFuncAdd</code>-Attribut
  1362. geändert.
  1363. </li>
  1364. <br>
  1365. <li>
  1366. <b>
  1367. Betriebsstunden abh&auml;ngige Wartungsarbeiten
  1368. (z.B. Beamer Filter reinigen)
  1369. </b>
  1370. <br>
  1371. <pre>defmod BeamerFilter_monitoring monitoring Beamer_HourCounter:pulseTimeOverall BeamerFilter_DashButton:.*:.short
  1372. attr BeamerFilter_monitoring userattr errorInterval
  1373. attr BeamerFilter_monitoring errorFuncAdd {return 1\
  1374. if(ReadingsVal($name, "pulseTimeOverall", 0) >= \
  1375. ReadingsVal($name, "pulseTimeService", 0)\
  1376. + (AttrVal($SELF, "errorInterval", 0))\
  1377. && $addMatch\
  1378. );;\
  1379. return;;\
  1380. }
  1381. attr BeamerFilter_monitoring errorFuncRemove {return unless($removeMatch);;\
  1382. $name = "Beamer_HourCounter";;\
  1383. fhem(\
  1384. "setreading $name pulseTimeService "\
  1385. .ReadingsVal($name, "pulseTimeOverall", 0)\
  1386. );;\
  1387. return 1;;\
  1388. }
  1389. attr BeamerFilter_monitoring errorInterval 60*60*200
  1390. attr BeamerFilter_monitoring errorReturn {return unless(@errors);;\
  1391. return "Der Filter vom Beamer muss gereinigt werden.";;\
  1392. }
  1393. attr BeamerFilter_monitoring warningFuncAdd {return}
  1394. attr BeamerFilter_monitoring warningFuncRemove {return}</pre>
  1395. Hierbei wird ein <a href="#HourCounter"><u>HourCounter</u></a> genutzt
  1396. um die Betriebsstunden eine Beamer zu erfassen und ein
  1397. <a href="#dash_dhcp"><u>DashButton</u></a> um FHEM mitzuteilen, dass der
  1398. Filter gereinigt wurde.<br>
  1399. Wurde der Filter l&auml;nger als 200 Betriebsstunden nicht gereinigt
  1400. wird das Ger&auml;t auf die error-Liste gesetzt.<br>
  1401. Wurde die Reinigung mit dem DashButton quittiert wird das Ger&auml;t
  1402. von der error-Liste entfernt und der aktuelle Betriebsstunden-Stand in
  1403. dem HourCounter Ger&auml;t gespeichert.
  1404. </li>
  1405. </ul>
  1406. </ul>
  1407. </div>
  1408. =end html_DE
  1409. =cut