10_RESIDENTS.pm 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328
  1. # $Id: 10_RESIDENTS.pm 12317 2016-10-10 23:12:02Z loredo $
  2. ##############################################################################
  3. #
  4. # 10_RESIDENTS.pm
  5. # An FHEM Perl module to ease resident administration.
  6. #
  7. # Copyright by Julian Pawlowski
  8. # e-mail: julian.pawlowski at gmail.com
  9. #
  10. # This file is part of fhem.
  11. #
  12. # Fhem is free software: you can redistribute it and/or modify
  13. # it under the terms of the GNU General Public License as published by
  14. # the Free Software Foundation, either version 2 of the License, or
  15. # (at your option) any later version.
  16. #
  17. # Fhem 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. # You should have received a copy of the GNU General Public License
  23. # along with fhem. If not, see <http://www.gnu.org/licenses/>.
  24. #
  25. ##############################################################################
  26. package main;
  27. use strict;
  28. use warnings;
  29. use Time::Local;
  30. use Data::Dumper;
  31. require RESIDENTStk;
  32. no if $] >= 5.017011, warnings => 'experimental';
  33. sub RESIDENTS_Set($@);
  34. sub RESIDENTS_Define($$);
  35. sub RESIDENTS_Notify($$);
  36. sub RESIDENTS_Undefine($$);
  37. ###################################
  38. sub RESIDENTS_Initialize($) {
  39. my ($hash) = @_;
  40. Log3 $hash, 5, "RESIDENTS_Initialize: Entering";
  41. $hash->{SetFn} = "RESIDENTS_Set";
  42. $hash->{DefFn} = "RESIDENTS_Define";
  43. $hash->{NotifyFn} = "RESIDENTS_Notify";
  44. $hash->{UndefFn} = "RESIDENTS_Undefine";
  45. $hash->{AttrList} =
  46. "rgr_showAllStates:0,1 rgr_states:multiple-strict,home,gotosleep,asleep,awoken,absent,gone rgr_wakeupDevice "
  47. . $readingFnAttributes;
  48. }
  49. ###################################
  50. sub RESIDENTS_Define($$) {
  51. my ( $hash, $def ) = @_;
  52. my $name = $hash->{NAME};
  53. my $name_attr;
  54. Log3 $name, 5, "RESIDENTS $name: called function RESIDENTS_Define()";
  55. $hash->{TYPE} = "RESIDENTS";
  56. # set default settings on first define
  57. if ( $init_done && !defined( $hash->{OLDDEF} ) ) {
  58. $attr{$name}{alias} = "Residents";
  59. $attr{$name}{devStateIcon} =
  60. '.*home:status_available:absent .*absent:status_away_1:home .*gone:status_standby:home .*none:control_building_empty .*gotosleep:status_night:asleep .*asleep:status_night:awoken .*awoken:status_available:home .*:user_unknown:home';
  61. $attr{$name}{group} = "Home State";
  62. $attr{$name}{icon} = "control_building_filled";
  63. $attr{$name}{room} = "Residents";
  64. $attr{$name}{webCmd} = "state";
  65. }
  66. # Injecting AttrFn for use with RESIDENTS Toolkit
  67. if ( !defined( $modules{dummy}{AttrFn} ) ) {
  68. $modules{dummy}{AttrFn} = "RESIDENTStk_AttrFnDummy";
  69. }
  70. elsif ( $modules{dummy}{AttrFn} ne "RESIDENTStk_AttrFnDummy" ) {
  71. Log3 $name, 5,
  72. "RESIDENTStk $name: concurrent AttrFn already defined for dummy module. Some attribute based functions like auto-creations will not be available.";
  73. }
  74. return undef;
  75. }
  76. ###################################
  77. sub RESIDENTS_Undefine($$) {
  78. my ( $hash, $name ) = @_;
  79. # delete child roommates
  80. if ( defined( $hash->{ROOMMATES} )
  81. && $hash->{ROOMMATES} ne "" )
  82. {
  83. my @registeredRoommates =
  84. split( /,/, $hash->{ROOMMATES} );
  85. foreach my $child (@registeredRoommates) {
  86. fhem( "delete " . $child );
  87. Log3 $name, 3, "RESIDENTS $name: deleted device $child";
  88. }
  89. }
  90. # delete child guests
  91. if ( defined( $hash->{GUESTS} )
  92. && $hash->{GUESTS} ne "" )
  93. {
  94. my @registeredGuests =
  95. split( /,/, $hash->{GUESTS} );
  96. foreach my $child (@registeredGuests) {
  97. fhem( "delete " . $child );
  98. Log3 $name, 3, "RESIDENTS $name: deleted device $child";
  99. }
  100. }
  101. return undef;
  102. }
  103. ###################################
  104. sub RESIDENTS_Notify($$) {
  105. my ( $hash, $dev ) = @_;
  106. my $devName = $dev->{NAME};
  107. my $hashName = $hash->{NAME};
  108. # process child notifies
  109. if ( $devName ne $hashName ) {
  110. my @registeredRoommates =
  111. split( /,/, $hash->{ROOMMATES} )
  112. if ( defined( $hash->{ROOMMATES} )
  113. && $hash->{ROOMMATES} ne "" );
  114. my @registeredGuests =
  115. split( /,/, $hash->{GUESTS} )
  116. if ( defined( $hash->{GUESTS} )
  117. && $hash->{GUESTS} ne "" );
  118. my @registeredWakeupdevs =
  119. split( /,/, $attr{$hashName}{rgr_wakeupDevice} )
  120. if ( defined( $attr{$hashName}{rgr_wakeupDevice} )
  121. && $attr{$hashName}{rgr_wakeupDevice} ne "" );
  122. # process only registered ROOMMATE or GUEST devices
  123. if ( ( @registeredRoommates && $devName ~~ @registeredRoommates )
  124. || ( @registeredGuests && $devName ~~ @registeredGuests ) )
  125. {
  126. return
  127. if ( !$dev->{CHANGED} ); # Some previous notify deleted the array.
  128. readingsBeginUpdate($hash);
  129. foreach my $change ( @{ $dev->{CHANGED} } ) {
  130. Log3 $hash, 5,
  131. "RESIDENTS " . $hashName . ": processing change $change";
  132. # state changed
  133. if ( $change !~ /:/
  134. || $change =~ /wayhome:/
  135. || $change =~ /wakeup:/ )
  136. {
  137. Log3 $hash, 4,
  138. "RESIDENTS "
  139. . $hashName . ": "
  140. . $devName
  141. . ": notify about change to $change";
  142. RESIDENTS_UpdateReadings($hash);
  143. }
  144. # activity
  145. if ( $change !~ /:/ ) {
  146. # get user realname
  147. my $realnamesrc;
  148. if ( $dev->{TYPE} eq "GUEST" ) {
  149. $realnamesrc = (
  150. defined( $attr{$devName}{rg_realname} )
  151. && $attr{$devName}{rg_realname} ne ""
  152. ? $attr{$devName}{rg_realname}
  153. : "alias"
  154. );
  155. }
  156. else {
  157. $realnamesrc = (
  158. defined( $attr{$devName}{rr_realname} )
  159. && $attr{$devName}{rr_realname} ne ""
  160. ? $attr{$devName}{rr_realname}
  161. : "group"
  162. );
  163. }
  164. my $realname = (
  165. defined( $attr{$devName}{$realnamesrc} )
  166. && $attr{$devName}{$realnamesrc} ne ""
  167. ? $attr{$devName}{$realnamesrc}
  168. : $devName
  169. );
  170. # update statistics
  171. readingsBulkUpdate( $hash, "lastActivity",
  172. ReadingsVal( $devName, "state", $change ) );
  173. readingsBulkUpdate( $hash, "lastActivityBy", $realname );
  174. readingsBulkUpdate( $hash, "lastActivityByDev", $devName );
  175. }
  176. }
  177. readingsEndUpdate( $hash, 1 );
  178. return;
  179. }
  180. # if we have registered wakeup devices
  181. if (@registeredWakeupdevs) {
  182. # if this is a notification of a registered wakeup device
  183. if ( $devName ~~ @registeredWakeupdevs ) {
  184. # Some previous notify deleted the array.
  185. return
  186. if ( !$dev->{CHANGED} );
  187. foreach my $change ( @{ $dev->{CHANGED} } ) {
  188. RESIDENTStk_wakeupSet( $devName, $change );
  189. }
  190. return;
  191. }
  192. # process sub-child notifies: *_wakeupDevice
  193. foreach my $wakeupDev (@registeredWakeupdevs) {
  194. # if this is a notification of a registered sub dummy device
  195. # of one of our wakeup devices
  196. if ( defined( $attr{$wakeupDev}{wakeupResetSwitcher} )
  197. && $attr{$wakeupDev}{wakeupResetSwitcher} eq $devName
  198. && $defs{$devName}{TYPE} eq "dummy" )
  199. {
  200. # Some previous notify deleted the array.
  201. return
  202. if ( !$dev->{CHANGED} );
  203. foreach my $change ( @{ $dev->{CHANGED} } ) {
  204. RESIDENTStk_wakeupSet( $wakeupDev, $change )
  205. if ( $change ne "off" );
  206. }
  207. last;
  208. }
  209. }
  210. }
  211. }
  212. return;
  213. }
  214. ###################################
  215. sub RESIDENTS_Set($@) {
  216. my ( $hash, @a ) = @_;
  217. my $name = $hash->{NAME};
  218. my $state = ReadingsVal( $name, "state", "initialized" );
  219. my $roommates = ( $hash->{ROOMMATES} ? $hash->{ROOMMATES} : "" );
  220. my $guests = ( $hash->{GUESTS} ? $hash->{GUESTS} : "" );
  221. Log3 $name, 5, "RESIDENTS $name: called function RESIDENTS_Set()";
  222. return "No Argument given" if ( !defined( $a[1] ) );
  223. # depending on current FHEMWEB instance's allowedCommands,
  224. # restrict set commands if there is "set-user" in it
  225. my $adminMode = 1;
  226. my $FWallowedCommands = 0;
  227. $FWallowedCommands = AttrVal( $FW_wname, "allowedCommands", 0 )
  228. if ( defined($FW_wname) );
  229. if ( $FWallowedCommands && $FWallowedCommands =~ m/\bset-user\b/ ) {
  230. $adminMode = 0;
  231. return "Forbidden command: set " . $a[1]
  232. if ( lc( $a[1] ) eq "addroommate"
  233. || lc( $a[1] ) eq "addguest"
  234. || lc( $a[1] ) eq "removeroommate"
  235. || lc( $a[1] ) eq "removeguest"
  236. || lc( $a[1] ) eq "create" );
  237. }
  238. # states
  239. my $states = (
  240. defined( $attr{$name}{rgr_states} ) ? $attr{$name}{rgr_states}
  241. : (
  242. defined( $attr{$name}{rgr_showAllStates} )
  243. && $attr{$name}{rgr_showAllStates} == 1
  244. ? "home,gotosleep,asleep,awoken,absent,gone"
  245. : "home,gotosleep,absent,gone"
  246. )
  247. );
  248. $states = $state . "," . $states
  249. if ( $state ne "initialized" && $states !~ /$state/ );
  250. my $usage = "Unknown argument " . $a[1] . ", choose one of state:$states";
  251. if ($adminMode) {
  252. $usage .= " addRoommate addGuest";
  253. $usage .= " removeRoommate:" . $roommates if ( $roommates ne "" );
  254. $usage .= " removeGuest:" . $guests if ( $guests ne "" );
  255. $usage .= " create:wakeuptimer";
  256. }
  257. # states
  258. if ( $a[1] eq "state"
  259. || $a[1] eq "home"
  260. || $a[1] eq "gotosleep"
  261. || $a[1] eq "asleep"
  262. || $a[1] eq "awoken"
  263. || $a[1] eq "absent"
  264. || $a[1] eq "gone" )
  265. {
  266. my $newstate;
  267. my $presence = "absent";
  268. # if not direct
  269. if (
  270. $a[1] eq "state"
  271. && defined( $a[2] )
  272. && ( $a[2] eq "home"
  273. || $a[2] eq "gotosleep"
  274. || $a[2] eq "asleep"
  275. || $a[2] eq "awoken"
  276. || $a[2] eq "absent"
  277. || $a[2] eq "gone" )
  278. )
  279. {
  280. $newstate = $a[2];
  281. }
  282. elsif ( defined( $a[2] ) ) {
  283. return
  284. "Invalid 2nd argument, choose one of home gotosleep asleep awoken absent gone ";
  285. }
  286. else {
  287. $newstate = $a[1];
  288. }
  289. Log3 $name, 2, "RESIDENTS set $name " . $newstate;
  290. # loop through every roommate
  291. if ( defined( $hash->{ROOMMATES} )
  292. && $hash->{ROOMMATES} ne "" )
  293. {
  294. my @registeredRoommates =
  295. split( /,/, $hash->{ROOMMATES} );
  296. foreach my $roommate (@registeredRoommates) {
  297. fhem "set $roommate silentSet state $newstate"
  298. if ( ReadingsVal( $roommate, "state", "initialized" ) ne
  299. $newstate );
  300. }
  301. }
  302. # loop through every guest
  303. if ( defined( $hash->{GUESTS} )
  304. && $hash->{GUESTS} ne "" )
  305. {
  306. $newstate = "none" if ( $newstate eq "gone" );
  307. my @registeredGuests =
  308. split( /,/, $hash->{GUESTS} );
  309. foreach my $guest (@registeredGuests) {
  310. fhem "set $guest silentSet state $newstate"
  311. if ( ReadingsVal( $guest, "state", "initialized" ) ne
  312. $newstate );
  313. }
  314. }
  315. }
  316. # addRoommate
  317. elsif ( $a[1] eq "addRoommate" ) {
  318. Log3 $name, 2, "RESIDENTS set $name " . $a[1] . " " . $a[2]
  319. if ( defined( $a[2] ) );
  320. my $rr_name;
  321. my $rr_name_attr;
  322. if ( $a[2] ne "" ) {
  323. $rr_name = "rr_" . $a[2];
  324. # define roommate
  325. if ( !defined( $defs{$rr_name} ) ) {
  326. fhem( "define " . $rr_name . " ROOMMATE " . $name );
  327. if ( defined( $defs{$rr_name} ) ) {
  328. fhem "set $rr_name silentSet state home";
  329. Log3 $name, 3,
  330. "RESIDENTS $name: created new device $rr_name";
  331. }
  332. }
  333. else {
  334. return "Can't create, device $rr_name already existing.";
  335. }
  336. }
  337. else {
  338. return "No Argument given, choose one of name ";
  339. }
  340. }
  341. # removeRoommate
  342. elsif ( $a[1] eq "removeRoommate" ) {
  343. Log3 $name, 2, "RESIDENTS set $name " . $a[1] . " " . $a[2]
  344. if ( defined( $a[2] ) );
  345. if ( $a[2] ne "" ) {
  346. my $rr_name = $a[2];
  347. # delete roommate
  348. if ( defined( $defs{$rr_name} ) ) {
  349. Log3 $name, 3, "RESIDENTS $name: deleted device $rr_name"
  350. if fhem( "delete " . $rr_name );
  351. }
  352. }
  353. else {
  354. return "No Argument given, choose one of name ";
  355. }
  356. }
  357. # addGuest
  358. elsif ( $a[1] eq "addGuest" ) {
  359. Log3 $name, 2, "RESIDENTS set $name " . $a[1] . " " . $a[2]
  360. if ( defined( $a[2] ) );
  361. my $rg_name;
  362. my $rg_name_attr;
  363. if ( $a[2] ne "" ) {
  364. $rg_name = "rg_" . $a[2];
  365. # define guest
  366. if ( !defined( $defs{$rg_name} ) ) {
  367. fhem( "define " . $rg_name . " GUEST " . $name );
  368. if ( defined( $defs{$rg_name} ) ) {
  369. fhem "set $rg_name silentSet state none";
  370. Log3 $name, 3,
  371. "RESIDENTS $name: created new device $rg_name";
  372. }
  373. }
  374. else {
  375. return "Can't create, device $rg_name already existing.";
  376. }
  377. }
  378. else {
  379. return "No Argument given, choose one of name ";
  380. }
  381. }
  382. # removeGuest
  383. elsif ( $a[1] eq "removeGuest" ) {
  384. Log3 $name, 2, "RESIDENTS set $name " . $a[1] . " " . $a[2]
  385. if ( defined( $a[2] ) );
  386. if ( $a[2] ne "" ) {
  387. my $rg_name = $a[2];
  388. # delete guest
  389. if ( defined( $defs{$rg_name} ) ) {
  390. Log3 $name, 3, "RESIDENTS $name: deleted device $rg_name"
  391. if fhem( "delete " . $rg_name );
  392. }
  393. }
  394. else {
  395. return "No Argument given, choose one of name ";
  396. }
  397. }
  398. # register
  399. elsif ( $a[1] eq "register" ) {
  400. if ( defined( $a[2] ) && $a[2] ne "" ) {
  401. return "No such device " . $a[2]
  402. if ( !defined( $defs{ $a[2] } ) );
  403. # ROOMMATE
  404. if ( $defs{ $a[2] }{TYPE} eq "ROOMMATE" ) {
  405. Log3 $name, 4, "RESIDENTS $name: " . $a[2] . " registered";
  406. # update readings
  407. $roommates .= ( $roommates eq "" ? $a[2] : "," . $a[2] )
  408. if ( $roommates !~ /$a[2]/ );
  409. $hash->{ROOMMATES} = $roommates;
  410. }
  411. # GUEST
  412. elsif ( $defs{ $a[2] }{TYPE} eq "GUEST" ) {
  413. Log3 $name, 4, "RESIDENTS $name: " . $a[2] . " registered";
  414. # update readings
  415. $guests .= ( $guests eq "" ? $a[2] : "," . $a[2] )
  416. if ( $guests !~ /$a[2]/ );
  417. $hash->{GUESTS} = $guests;
  418. }
  419. # unsupported
  420. else {
  421. return "Device type is not supported.";
  422. }
  423. }
  424. else {
  425. return "No Argument given, choose one of ROOMMATE GUEST ";
  426. }
  427. }
  428. # unregister
  429. elsif ( $a[1] eq "unregister" ) {
  430. if ( defined( $a[2] ) && $a[2] ne "" ) {
  431. return "No such device " . $a[2]
  432. if ( !defined( $defs{ $a[2] } ) );
  433. # ROOMMATE
  434. if ( $defs{ $a[2] }{TYPE} eq "ROOMMATE" ) {
  435. Log3 $name, 4, "RESIDENTS $name: " . $a[2] . " unregistered";
  436. # update readings
  437. my $replace = "," . $a[2];
  438. $roommates =~ s/$replace//g;
  439. $replace = $a[2] . ",";
  440. $roommates =~ s/^$replace//g;
  441. $roommates =~ s/^$a[2]//g;
  442. $hash->{ROOMMATES} = $roommates;
  443. }
  444. # GUEST
  445. elsif ( $defs{ $a[2] }{TYPE} eq "GUEST" ) {
  446. Log3 $name, 4, "RESIDENTS $name: " . $a[2] . " unregistered";
  447. # update readings
  448. my $replace = "," . $a[2];
  449. $guests =~ s/$replace//g;
  450. $replace = $a[2] . ",";
  451. $guests =~ s/^$replace//g;
  452. $guests =~ s/^$a[2]//g;
  453. $hash->{GUESTS} = $guests;
  454. }
  455. # unsupported
  456. else {
  457. return "Device type is not supported.";
  458. }
  459. }
  460. else {
  461. return "No Argument given, choose one of ROOMMATE GUEST ";
  462. }
  463. readingsBeginUpdate($hash);
  464. RESIDENTS_UpdateReadings($hash);
  465. readingsEndUpdate( $hash, 1 );
  466. }
  467. # create
  468. elsif ( $a[1] eq "create" ) {
  469. if ( defined( $a[2] ) && $a[2] eq "wakeuptimer" ) {
  470. my $i = "1";
  471. my $wakeuptimerName = $name . "_wakeuptimer" . $i;
  472. my $created = 0;
  473. until ($created) {
  474. if ( defined( $defs{$wakeuptimerName} ) ) {
  475. $i++;
  476. $wakeuptimerName = $name . "_wakeuptimer" . $i;
  477. }
  478. else {
  479. my $sortby = AttrVal( $name, "sortby", -1 );
  480. $sortby++;
  481. # create new dummy device
  482. fhem "define $wakeuptimerName dummy";
  483. fhem "attr $wakeuptimerName alias Wake-up Timer $i";
  484. fhem
  485. "attr $wakeuptimerName comment Auto-created by RESIDENTS module for use with RESIDENTS Toolkit";
  486. fhem
  487. "attr $wakeuptimerName devStateIcon OFF:general_aus\@red:reset running:general_an\@green:stop .*:general_an\@orange:nextRun%20OFF";
  488. fhem "attr $wakeuptimerName group " . $attr{$name}{group}
  489. if ( defined( $attr{$name}{group} ) );
  490. fhem "attr $wakeuptimerName icon time_timer";
  491. fhem "attr $wakeuptimerName room " . $attr{$name}{room}
  492. if ( defined( $attr{$name}{room} ) );
  493. fhem
  494. "attr $wakeuptimerName setList nextRun:OFF,00:00,00:15,00:30,00:45,01:00,01:15,01:30,01:45,02:00,02:15,02:30,02:45,03:00,03:15,03:30,03:45,04:00,04:15,04:30,04:45,05:00,05:15,05:30,05:45,06:00,06:15,06:30,06:45,07:00,07:15,07:30,07:45,08:00,08:15,08:30,08:45,09:00,09:15,09:30,09:45,10:00,10:15,10:30,10:45,11:00,11:15,11:30,11:45,12:00,12:15,12:30,12:45,13:00,13:15,13:30,13:45,14:00,14:15,14:30,14:45,15:00,15:15,15:30,15:45,16:00,16:15,16:30,16:45,17:00,17:15,17:30,17:45,18:00,18:15,18:30,18:45,19:00,19:15,19:30,19:45,20:00,20:15,20:30,20:45,21:00,21:15,21:30,21:45,22:00,22:15,22:30,22:45,23:00,23:15,23:30,23:45 reset:noArg trigger:noArg start:noArg stop:noArg end:noArg";
  495. fhem "attr $wakeuptimerName userattr wakeupUserdevice";
  496. fhem "attr $wakeuptimerName sortby " . $sortby
  497. if ($sortby);
  498. fhem "attr $wakeuptimerName wakeupUserdevice $name";
  499. fhem "attr $wakeuptimerName webCmd nextRun";
  500. # register slave device
  501. my $wakeupDevice = AttrVal( $name, "rgr_wakeupDevice", 0 );
  502. if ( !$wakeupDevice ) {
  503. fhem "attr $name rgr_wakeupDevice $wakeuptimerName";
  504. }
  505. elsif ( $wakeupDevice !~ /(.*,?)($wakeuptimerName)(.*,?)/ )
  506. {
  507. fhem "attr $name rgr_wakeupDevice "
  508. . $wakeupDevice
  509. . ",$wakeuptimerName";
  510. }
  511. # trigger first update
  512. fhem "set $wakeuptimerName nextRun OFF";
  513. $created = 1;
  514. }
  515. }
  516. return
  517. "Dummy $wakeuptimerName and other pending devices created and pre-configured.\nYou may edit Macro_$wakeuptimerName to define your wake-up actions\nand at_$wakeuptimerName for optional at-device adjustments.";
  518. }
  519. else {
  520. return "Invalid 2nd argument, choose one of wakeuptimer ";
  521. }
  522. }
  523. # return usage hint
  524. else {
  525. return $usage;
  526. }
  527. return undef;
  528. }
  529. ############################################################################################################
  530. #
  531. # Begin of helper functions
  532. #
  533. ############################################################################################################
  534. sub RESIDENTS_UpdateReadings (@) {
  535. my ($hash) = @_;
  536. my $name = $hash->{NAME};
  537. my $state = ReadingsVal( $name, "state", "none" );
  538. my $presence = ReadingsVal( $name, "presence", "absent" );
  539. my $state_home = 0;
  540. my $state_gotosleep = 0;
  541. my $state_asleep = 0;
  542. my $state_awoken = 0;
  543. my $state_absent = 0;
  544. my $state_gone = 0;
  545. my $state_total = 0;
  546. my $state_totalPresent = 0;
  547. my $state_totalAbsent = 0;
  548. my $state_totalGuests = 0;
  549. my $state_totalGuestsPresent = 0;
  550. my $state_totalGuestsAbsent = 0;
  551. my $state_totalRoommates = 0;
  552. my $state_totalRoommatesPresent = 0;
  553. my $state_totalRoommatesAbsent = 0;
  554. my $state_guestDev = 0;
  555. my $residentsDevs_home = "-";
  556. my $residentsDevs_absent = "-";
  557. my $residentsDevs_asleep = "-";
  558. my $residentsDevs_awoken = "-";
  559. my $residentsDevs_gone = "-";
  560. my $residentsDevs_gotosleep = "-";
  561. my $residentsDevs_wakeup = "-";
  562. my $residentsDevs_wayhome = "-";
  563. my $residentsDevs_wayhomeDelayed = "-";
  564. my $residentsDevs_totalAbsent = "-";
  565. my $residentsDevs_totalPresent = "-";
  566. my $residentsDevs_totalAbsentGuest = "-";
  567. my $residentsDevs_totalPresentGuest = "-";
  568. my $residentsDevs_totalAbsentRoommates = "-";
  569. my $residentsDevs_totalPresentRoommates = "-";
  570. my $residents_home = "-";
  571. my $residents_absent = "-";
  572. my $residents_asleep = "-";
  573. my $residents_awoken = "-";
  574. my $residents_gone = "-";
  575. my $residents_gotosleep = "-";
  576. my $residents_wakeup = "-";
  577. my $residents_wayhome = "-";
  578. my $residents_wayhomeDelayed = "-";
  579. my $residents_totalAbsent = "-";
  580. my $residents_totalPresent = "-";
  581. my $residents_totalAbsentGuest = "-";
  582. my $residents_totalPresentGuest = "-";
  583. my $residents_totalAbsentRoommates = "-";
  584. my $residents_totalPresentRoommates = "-";
  585. my $wayhome = 0;
  586. my $wayhomeDelayed = 0;
  587. my $wakeup = 0;
  588. my $newstate;
  589. my @registeredRoommates =
  590. split( /,/, $hash->{ROOMMATES} )
  591. if ( defined( $hash->{ROOMMATES} )
  592. && $hash->{ROOMMATES} ne "" );
  593. my @registeredGuests =
  594. split( /,/, $hash->{GUESTS} )
  595. if ( defined( $hash->{GUESTS} )
  596. && $hash->{GUESTS} ne "" );
  597. # count child states for ROOMMATE devices
  598. foreach my $roommate (@registeredRoommates) {
  599. $state_total++;
  600. $state_totalRoommates++;
  601. my $roommateName =
  602. AttrVal( $roommate,
  603. AttrVal( $roommate, "rr_realname", "alias" ), "" );
  604. Log3 $name, 5,
  605. "RESIDENTS $name: considering $roommate for state change";
  606. if ( ReadingsVal( $roommate, "state", "initialized" ) eq "home" ) {
  607. $state_home++;
  608. $residentsDevs_home .= "," . $roommate
  609. if ( $residentsDevs_home ne "-" );
  610. $residentsDevs_home = $roommate
  611. if ( $residentsDevs_home eq "-" );
  612. $residents_home .= ", " . $roommateName
  613. if ( $roommateName ne "" && $residents_home ne "-" );
  614. $residents_home = $roommateName
  615. if ( $roommateName ne "" && $residents_home eq "-" );
  616. $state_totalPresent++;
  617. $state_totalRoommatesPresent++;
  618. $residentsDevs_totalPresent .= "," . $roommate
  619. if ( $residentsDevs_totalPresent ne "-" );
  620. $residentsDevs_totalPresent = $roommate
  621. if ( $residentsDevs_totalPresent eq "-" );
  622. $residentsDevs_totalPresentRoommates .= "," . $roommate
  623. if ( $residentsDevs_totalPresentRoommates ne "-" );
  624. $residentsDevs_totalPresentRoommates = $roommate
  625. if ( $residentsDevs_totalPresentRoommates eq "-" );
  626. $residents_totalPresent .= ", " . $roommateName
  627. if ( $roommateName ne "" && $residents_totalPresent ne "-" );
  628. $residents_totalPresent = $roommateName
  629. if ( $roommateName ne "" && $residents_totalPresent eq "-" );
  630. $residents_totalPresentRoommates .= ", " . $roommateName
  631. if ( $roommateName ne ""
  632. && $residents_totalPresentRoommates ne "-" );
  633. $residents_totalPresentRoommates = $roommateName
  634. if ( $roommateName ne ""
  635. && $residents_totalPresentRoommates eq "-" );
  636. }
  637. elsif (
  638. ReadingsVal( $roommate, "state", "initialized" ) eq "gotosleep" )
  639. {
  640. $state_gotosleep++;
  641. $residentsDevs_gotosleep .= "," . $roommate
  642. if ( $residentsDevs_gotosleep ne "-" );
  643. $residentsDevs_gotosleep = $roommate
  644. if ( $residentsDevs_gotosleep eq "-" );
  645. $residents_gotosleep .= ", " . $roommateName
  646. if ( $roommateName ne "" && $residents_gotosleep ne "-" );
  647. $residents_gotosleep = $roommateName
  648. if ( $roommateName ne "" && $residents_gotosleep eq "-" );
  649. $state_totalPresent++;
  650. $state_totalRoommatesPresent++;
  651. $residentsDevs_totalPresent .= "," . $roommate
  652. if ( $residentsDevs_totalPresent ne "-" );
  653. $residentsDevs_totalPresent = $roommate
  654. if ( $residentsDevs_totalPresent eq "-" );
  655. $residentsDevs_totalPresentRoommates .= "," . $roommate
  656. if ( $residentsDevs_totalPresentRoommates ne "-" );
  657. $residentsDevs_totalPresentRoommates = $roommate
  658. if ( $residentsDevs_totalPresentRoommates eq "-" );
  659. $residents_totalPresent .= ", " . $roommateName
  660. if ( $roommateName ne "" && $residents_totalPresent ne "-" );
  661. $residents_totalPresent = $roommateName
  662. if ( $roommateName ne "" && $residents_totalPresent eq "-" );
  663. $residents_totalPresentRoommates .= ", " . $roommateName
  664. if ( $roommateName ne ""
  665. && $residents_totalPresentRoommates ne "-" );
  666. $residents_totalPresentRoommates = $roommateName
  667. if ( $roommateName ne ""
  668. && $residents_totalPresentRoommates eq "-" );
  669. }
  670. elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "asleep" ) {
  671. $state_asleep++;
  672. $residentsDevs_asleep .= "," . $roommate
  673. if ( $residentsDevs_asleep ne "-" );
  674. $residentsDevs_asleep = $roommate
  675. if ( $residentsDevs_asleep eq "-" );
  676. $residents_asleep .= ", " . $roommateName
  677. if ( $roommateName ne "" && $residents_asleep ne "-" );
  678. $residents_asleep = $roommateName
  679. if ( $roommateName ne "" && $residents_asleep eq "-" );
  680. $state_totalPresent++;
  681. $state_totalRoommatesPresent++;
  682. $residentsDevs_totalPresent .= "," . $roommate
  683. if ( $residentsDevs_totalPresent ne "-" );
  684. $residentsDevs_totalPresent = $roommate
  685. if ( $residentsDevs_totalPresent eq "-" );
  686. $residentsDevs_totalPresentRoommates .= "," . $roommate
  687. if ( $residentsDevs_totalPresentRoommates ne "-" );
  688. $residentsDevs_totalPresentRoommates = $roommate
  689. if ( $residentsDevs_totalPresentRoommates eq "-" );
  690. $residents_totalPresent .= ", " . $roommateName
  691. if ( $roommateName ne "" && $residents_totalPresent ne "-" );
  692. $residents_totalPresent = $roommateName
  693. if ( $roommateName ne "" && $residents_totalPresent eq "-" );
  694. $residents_totalPresentRoommates .= ", " . $roommateName
  695. if ( $roommateName ne ""
  696. && $residents_totalPresentRoommates ne "-" );
  697. $residents_totalPresentRoommates = $roommateName
  698. if ( $roommateName ne ""
  699. && $residents_totalPresentRoommates eq "-" );
  700. }
  701. elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "awoken" ) {
  702. $state_awoken++;
  703. $residentsDevs_awoken .= "," . $roommate
  704. if ( $residentsDevs_awoken ne "-" );
  705. $residentsDevs_awoken = $roommate
  706. if ( $residentsDevs_awoken eq "-" );
  707. $residents_awoken .= ", " . $roommateName
  708. if ( $roommateName ne "" && $residents_awoken ne "-" );
  709. $residents_awoken = $roommateName
  710. if ( $roommateName ne "" && $residents_awoken eq "-" );
  711. $state_totalPresent++;
  712. $state_totalRoommatesPresent++;
  713. $residentsDevs_totalPresent .= "," . $roommate
  714. if ( $residentsDevs_totalPresent ne "-" );
  715. $residentsDevs_totalPresent = $roommate
  716. if ( $residentsDevs_totalPresent eq "-" );
  717. $residentsDevs_totalPresentRoommates .= "," . $roommate
  718. if ( $residentsDevs_totalPresentRoommates ne "-" );
  719. $residentsDevs_totalPresentRoommates = $roommate
  720. if ( $residentsDevs_totalPresentRoommates eq "-" );
  721. $residents_totalPresent .= ", " . $roommateName
  722. if ( $roommateName ne "" && $residents_totalPresent ne "-" );
  723. $residents_totalPresent = $roommateName
  724. if ( $roommateName ne "" && $residents_totalPresent eq "-" );
  725. $residents_totalPresentRoommates .= ", " . $roommateName
  726. if ( $roommateName ne ""
  727. && $residents_totalPresentRoommates ne "-" );
  728. $residents_totalPresentRoommates = $roommateName
  729. if ( $roommateName ne ""
  730. && $residents_totalPresentRoommates eq "-" );
  731. }
  732. elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "absent" ) {
  733. $state_absent++;
  734. $residentsDevs_absent .= "," . $roommate
  735. if ( $residentsDevs_absent ne "-" );
  736. $residentsDevs_absent = $roommate
  737. if ( $residentsDevs_absent eq "-" );
  738. $residents_absent .= ", " . $roommateName
  739. if ( $roommateName ne "" && $residents_absent ne "-" );
  740. $residents_absent = $roommateName
  741. if ( $roommateName ne "" && $residents_absent eq "-" );
  742. $state_totalAbsent++;
  743. $state_totalRoommatesAbsent++;
  744. $residentsDevs_totalAbsent .= "," . $roommate
  745. if ( $residentsDevs_totalAbsent ne "-" );
  746. $residentsDevs_totalAbsent = $roommate
  747. if ( $residentsDevs_totalAbsent eq "-" );
  748. $residentsDevs_totalAbsentRoommates .= "," . $roommate
  749. if ( $residentsDevs_totalAbsentRoommates ne "-" );
  750. $residentsDevs_totalAbsentRoommates = $roommate
  751. if ( $residentsDevs_totalAbsentRoommates eq "-" );
  752. $residents_totalAbsent .= ", " . $roommateName
  753. if ( $roommateName ne "" && $residents_totalAbsent ne "-" );
  754. $residents_totalAbsent = $roommateName
  755. if ( $roommateName ne "" && $residents_totalAbsent eq "-" );
  756. $residents_totalAbsentRoommates .= ", " . $roommateName
  757. if ( $roommateName ne ""
  758. && $residents_totalAbsentRoommates ne "-" );
  759. $residents_totalAbsentRoommates = $roommateName
  760. if ( $roommateName ne ""
  761. && $residents_totalAbsentRoommates eq "-" );
  762. }
  763. elsif ( ReadingsVal( $roommate, "state", "initialized" ) eq "gone" ) {
  764. $state_gone++;
  765. $residentsDevs_gone .= "," . $roommate
  766. if ( $residentsDevs_gone ne "-" );
  767. $residentsDevs_gone = $roommate
  768. if ( $residentsDevs_gone eq "-" );
  769. $residents_gone .= ", " . $roommateName
  770. if ( $roommateName ne "" && $residents_gone ne "-" );
  771. $residents_gone = $roommateName
  772. if ( $roommateName ne "" && $residents_gone eq "-" );
  773. $state_totalAbsent++;
  774. $state_totalRoommatesAbsent++;
  775. $residentsDevs_totalAbsent .= "," . $roommate
  776. if ( $residentsDevs_totalAbsent ne "-" );
  777. $residentsDevs_totalAbsent = $roommate
  778. if ( $residentsDevs_totalAbsent eq "-" );
  779. $residentsDevs_totalAbsentRoommates .= "," . $roommate
  780. if ( $residentsDevs_totalAbsentRoommates ne "-" );
  781. $residentsDevs_totalAbsentRoommates = $roommate
  782. if ( $residentsDevs_totalAbsentRoommates eq "-" );
  783. $residents_totalAbsent .= ", " . $roommateName
  784. if ( $roommateName ne "" && $residents_totalAbsent ne "-" );
  785. $residents_totalAbsent = $roommateName
  786. if ( $roommateName ne "" && $residents_totalAbsent eq "-" );
  787. $residents_totalAbsentRoommates .= ", " . $roommateName
  788. if ( $roommateName ne ""
  789. && $residents_totalAbsentRoommates ne "-" );
  790. $residents_totalAbsentRoommates = $roommateName
  791. if ( $roommateName ne ""
  792. && $residents_totalAbsentRoommates eq "-" );
  793. }
  794. if ( ReadingsVal( $roommate, "wakeup", "0" ) > 0 ) {
  795. $wakeup++;
  796. $residentsDevs_wakeup .= "," . $roommate
  797. if ( $residentsDevs_wakeup ne "-" );
  798. $residentsDevs_wakeup = $roommate
  799. if ( $residentsDevs_wakeup eq "-" );
  800. $residents_wakeup .= ", " . $roommateName
  801. if ( $roommateName ne "" && $residents_wakeup ne "-" );
  802. $residents_wakeup = $roommateName
  803. if ( $roommateName ne "" && $residents_wakeup eq "-" );
  804. }
  805. if ( ReadingsVal( $roommate, "wayhome", "0" ) > 0 ) {
  806. $wayhome++;
  807. $residentsDevs_wayhome .= "," . $roommate
  808. if ( $residentsDevs_wayhome ne "-" );
  809. $residentsDevs_wayhome = $roommate
  810. if ( $residentsDevs_wayhome eq "-" );
  811. $residents_wayhome .= ", " . $roommateName
  812. if ( $roommateName ne "" && $residents_wayhome ne "-" );
  813. $residents_wayhome = $roommateName
  814. if ( $roommateName ne "" && $residents_wayhome eq "-" );
  815. if ( ReadingsVal( $roommate, "wayhome", "0" ) == 2 ) {
  816. $wayhomeDelayed++;
  817. $residentsDevs_wayhomeDelayed .= "," . $roommate
  818. if ( $residentsDevs_wayhomeDelayed ne "-" );
  819. $residentsDevs_wayhomeDelayed = $roommate
  820. if ( $residentsDevs_wayhomeDelayed eq "-" );
  821. $residents_wayhomeDelayed .= ", " . $roommateName
  822. if ( $roommateName ne ""
  823. && $residents_wayhomeDelayed ne "-" );
  824. $residents_wayhomeDelayed = $roommateName
  825. if ( $roommateName ne ""
  826. && $residents_wayhomeDelayed eq "-" );
  827. }
  828. }
  829. }
  830. # count child states for GUEST devices
  831. foreach my $guest (@registeredGuests) {
  832. $state_guestDev++;
  833. my $guestName =
  834. AttrVal( $guest, AttrVal( $guest, "rg_realname", "alias" ), "" );
  835. Log3 $name, 5, "RESIDENTS $name: considering $guest for state change";
  836. if ( ReadingsVal( $guest, "state", "initialized" ) eq "home" ) {
  837. $state_home++;
  838. $state_totalPresent++;
  839. $state_totalGuestsPresent++;
  840. $state_totalGuests++;
  841. $state_total++;
  842. $residentsDevs_totalPresentGuest .= "," . $guest
  843. if ( $residentsDevs_totalPresentGuest ne "-" );
  844. $residentsDevs_totalPresentGuest = $guest
  845. if ( $residentsDevs_totalPresentGuest eq "-" );
  846. $residents_totalPresentGuest .= ", " . $guestName
  847. if ( $guestName ne ""
  848. && $residents_totalPresentGuest ne "-" );
  849. $residents_totalPresentGuest = $guestName
  850. if ( $guestName ne ""
  851. && $residents_totalPresentGuest eq "-" );
  852. $residentsDevs_totalPresent .= "," . $guest
  853. if ( $residentsDevs_totalPresent ne "-" );
  854. $residentsDevs_totalPresent = $guest
  855. if ( $residentsDevs_totalPresent eq "-" );
  856. $residents_totalPresent .= ", " . $guestName
  857. if ( $guestName ne ""
  858. && $residents_totalPresent ne "-" );
  859. $residents_totalPresent = $guestName
  860. if ( $guestName ne ""
  861. && $residents_totalPresent eq "-" );
  862. }
  863. elsif ( ReadingsVal( $guest, "state", "initialized" ) eq "gotosleep" ) {
  864. $state_gotosleep++;
  865. $state_totalPresent++;
  866. $state_totalGuestsPresent++;
  867. $state_totalGuests++;
  868. $state_total++;
  869. $residentsDevs_totalPresentGuest .= "," . $guest
  870. if ( $residentsDevs_totalPresentGuest ne "-" );
  871. $residentsDevs_totalPresentGuest = $guest
  872. if ( $residentsDevs_totalPresentGuest eq "-" );
  873. $residents_totalPresentGuest .= ", " . $guestName
  874. if ( $guestName ne ""
  875. && $residents_totalPresentGuest ne "-" );
  876. $residents_totalPresentGuest = $guestName
  877. if ( $guestName ne ""
  878. && $residents_totalPresentGuest eq "-" );
  879. $residentsDevs_totalPresent .= "," . $guest
  880. if ( $residentsDevs_totalPresent ne "-" );
  881. $residentsDevs_totalPresent = $guest
  882. if ( $residentsDevs_totalPresent eq "-" );
  883. $residents_totalPresent .= ", " . $guestName
  884. if ( $guestName ne ""
  885. && $residents_totalPresent ne "-" );
  886. $residents_totalPresent = $guestName
  887. if ( $guestName ne ""
  888. && $residents_totalPresent eq "-" );
  889. }
  890. elsif ( ReadingsVal( $guest, "state", "initialized" ) eq "asleep" ) {
  891. $state_asleep++;
  892. $state_totalPresent++;
  893. $state_totalGuestsPresent++;
  894. $state_totalGuests++;
  895. $state_total++;
  896. $residentsDevs_totalPresentGuest .= "," . $guest
  897. if ( $residentsDevs_totalPresentGuest ne "-" );
  898. $residentsDevs_totalPresentGuest = $guest
  899. if ( $residentsDevs_totalPresentGuest eq "-" );
  900. $residents_totalPresentGuest .= ", " . $guestName
  901. if ( $guestName ne ""
  902. && $residents_totalPresentGuest ne "-" );
  903. $residents_totalPresentGuest = $guestName
  904. if ( $guestName ne ""
  905. && $residents_totalPresentGuest eq "-" );
  906. $residentsDevs_totalPresent .= "," . $guest
  907. if ( $residentsDevs_totalPresent ne "-" );
  908. $residentsDevs_totalPresent = $guest
  909. if ( $residentsDevs_totalPresent eq "-" );
  910. $residents_totalPresent .= ", " . $guestName
  911. if ( $guestName ne ""
  912. && $residents_totalPresent ne "-" );
  913. $residents_totalPresent = $guestName
  914. if ( $guestName ne ""
  915. && $residents_totalPresent eq "-" );
  916. }
  917. elsif ( ReadingsVal( $guest, "state", "initialized" ) eq "awoken" ) {
  918. $state_awoken++;
  919. $state_totalPresent++;
  920. $state_totalGuestsPresent++;
  921. $state_totalGuests++;
  922. $state_total++;
  923. $residentsDevs_totalPresentGuest .= "," . $guest
  924. if ( $residentsDevs_totalPresentGuest ne "-" );
  925. $residentsDevs_totalPresentGuest = $guest
  926. if ( $residentsDevs_totalPresentGuest eq "-" );
  927. $residents_totalPresentGuest .= ", " . $guestName
  928. if ( $guestName ne ""
  929. && $residents_totalPresentGuest ne "-" );
  930. $residents_totalPresentGuest = $guestName
  931. if ( $guestName ne ""
  932. && $residents_totalPresentGuest eq "-" );
  933. $residentsDevs_totalPresent .= "," . $guest
  934. if ( $residentsDevs_totalPresent ne "-" );
  935. $residentsDevs_totalPresent = $guest
  936. if ( $residentsDevs_totalPresent eq "-" );
  937. $residents_totalPresent .= ", " . $guestName
  938. if ( $guestName ne ""
  939. && $residents_totalPresent ne "-" );
  940. $residents_totalPresent = $guestName
  941. if ( $guestName ne ""
  942. && $residents_totalPresent eq "-" );
  943. }
  944. elsif ( ReadingsVal( $guest, "state", "initialized" ) eq "absent" ) {
  945. $state_absent++;
  946. $state_totalAbsent++;
  947. $state_totalGuestsAbsent++;
  948. $state_totalGuests++;
  949. $state_total++;
  950. $residentsDevs_totalAbsentGuest .= "," . $guest
  951. if ( $residentsDevs_totalAbsentGuest ne "-" );
  952. $residentsDevs_totalAbsentGuest = $guest
  953. if ( $residentsDevs_totalAbsentGuest eq "-" );
  954. $residents_totalAbsentGuest .= ", " . $guestName
  955. if ( $guestName ne ""
  956. && $residents_totalAbsentGuest ne "-" );
  957. $residents_totalAbsentGuest = $guestName
  958. if ( $guestName ne ""
  959. && $residents_totalAbsentGuest eq "-" );
  960. $residentsDevs_totalAbsent .= "," . $guest
  961. if ( $residentsDevs_totalAbsent ne "-" );
  962. $residentsDevs_totalAbsent = $guest
  963. if ( $residentsDevs_totalAbsent eq "-" );
  964. $residents_totalAbsent .= ", " . $guestName
  965. if ( $guestName ne ""
  966. && $residents_totalAbsent ne "-" );
  967. $residents_totalAbsent = $guestName
  968. if ( $guestName ne ""
  969. && $residents_totalAbsent eq "-" );
  970. }
  971. if ( ReadingsVal( $guest, "wakeup", "0" ) > 0 ) {
  972. $wakeup++;
  973. $residentsDevs_wakeup .= "," . $guest
  974. if ( $residentsDevs_wakeup ne "-" );
  975. $residentsDevs_wakeup = $guest
  976. if ( $residentsDevs_wakeup eq "-" );
  977. $residents_wakeup .= ", " . $guestName
  978. if ( $guestName ne "" && $residents_wakeup ne "-" );
  979. $residents_wakeup = $guestName
  980. if ( $guestName ne "" && $residents_wakeup eq "-" );
  981. }
  982. if ( ReadingsVal( $guest, "wayhome", "0" ) > 0 ) {
  983. $wayhome++;
  984. $residents_wayhome .= "," . $guest
  985. if ( $residents_wayhome ne "-" );
  986. $residents_wayhome = $guest if ( $residents_wayhome eq "-" );
  987. $residents_wayhome .= ", " . $guestName
  988. if ( $guestName ne "" && $residents_wayhome ne "-" );
  989. $residents_wayhome = $guestName
  990. if ( $guestName ne "" && $residents_wayhome eq "-" );
  991. if ( ReadingsVal( $guest, "wayhome", "0" ) == 2 ) {
  992. $wayhomeDelayed++;
  993. $residentsDevs_wayhomeDelayed .= "," . $guest
  994. if ( $residentsDevs_wayhomeDelayed ne "-" );
  995. $residentsDevs_wayhomeDelayed = $guest
  996. if ( $residentsDevs_wayhomeDelayed eq "-" );
  997. $residents_wayhomeDelayed .= ", " . $guestName
  998. if ( $guestName ne ""
  999. && $residents_wayhomeDelayed ne "-" );
  1000. $residents_wayhomeDelayed = $guestName
  1001. if ( $guestName ne ""
  1002. && $residents_wayhomeDelayed eq "-" );
  1003. }
  1004. }
  1005. }
  1006. # update counter
  1007. readingsBulkUpdate( $hash, "residentsTotal", $state_total )
  1008. if ( ReadingsVal( $name, "residentsTotal", "" ) ne $state_total );
  1009. readingsBulkUpdate( $hash, "residentsTotalGuests", $state_totalGuests )
  1010. if ( ReadingsVal( $name, "residentsTotalGuests", "" ) ne
  1011. $state_totalGuests );
  1012. readingsBulkUpdate( $hash, "residentsTotalGuestsPresent",
  1013. $state_totalGuestsPresent )
  1014. if ( ReadingsVal( $name, "residentsTotalGuestsPresent", "" ) ne
  1015. $state_totalGuestsPresent );
  1016. readingsBulkUpdate(
  1017. $hash,
  1018. "residentsTotalGuestsPresentDevs",
  1019. $residentsDevs_totalPresentGuest
  1020. )
  1021. if ( ReadingsVal( $name, "residentsTotalGuestsPresentDevs", "" ) ne
  1022. $residentsDevs_totalPresentGuest );
  1023. readingsBulkUpdate( $hash, "residentsTotalGuestsPresentNames",
  1024. $residents_totalPresentGuest )
  1025. if ( ReadingsVal( $name, "residentsTotalGuestsPresentNames", "" ) ne
  1026. $residents_totalPresentGuest );
  1027. readingsBulkUpdate( $hash, "residentsTotalGuestsAbsent",
  1028. $state_totalGuestsAbsent )
  1029. if ( ReadingsVal( $name, "residentsTotalGuestsAbsent", "" ) ne
  1030. $state_totalGuestsAbsent );
  1031. readingsBulkUpdate(
  1032. $hash,
  1033. "residentsTotalGuestsAbsentDevs",
  1034. $residentsDevs_totalAbsentGuest
  1035. )
  1036. if ( ReadingsVal( $name, "residentsTotalGuestsAbsentDevs", "" ) ne
  1037. $residentsDevs_totalAbsentGuest );
  1038. readingsBulkUpdate( $hash, "residentsTotalGuestsAbsentNames",
  1039. $residents_totalAbsentGuest )
  1040. if ( ReadingsVal( $name, "residentsTotalGuestsAbsentNames", "" ) ne
  1041. $residents_totalAbsentGuest );
  1042. readingsBulkUpdate( $hash, "residentsTotalRoommates",
  1043. $state_totalRoommates )
  1044. if ( ReadingsVal( $name, "residentsTotalRoommates", "" ) ne
  1045. $state_totalRoommates );
  1046. readingsBulkUpdate( $hash, "residentsTotalRoommatesPresent",
  1047. $state_totalRoommatesPresent )
  1048. if ( ReadingsVal( $name, "residentsTotalRoommatesPresent", "" ) ne
  1049. $state_totalRoommatesPresent );
  1050. readingsBulkUpdate(
  1051. $hash,
  1052. "residentsTotalRoommatesPresentDevs",
  1053. $residentsDevs_totalPresentRoommates
  1054. )
  1055. if ( ReadingsVal( $name, "residentsTotalRoommatesPresentDevs", "" ) ne
  1056. $residentsDevs_totalPresentRoommates );
  1057. readingsBulkUpdate(
  1058. $hash,
  1059. "residentsTotalRoommatesPresentNames",
  1060. $residents_totalPresentRoommates
  1061. )
  1062. if ( ReadingsVal( $name, "residentsTotalRoommatesPresentNames", "" ) ne
  1063. $residents_totalPresentRoommates );
  1064. readingsBulkUpdate( $hash, "residentsTotalRoommatesAbsent",
  1065. $state_totalRoommatesAbsent )
  1066. if ( ReadingsVal( $name, "residentsTotalRoommatesAbsent", "" ) ne
  1067. $state_totalRoommatesAbsent );
  1068. readingsBulkUpdate(
  1069. $hash,
  1070. "residentsTotalRoommatesAbsentDevs",
  1071. $residentsDevs_totalAbsentRoommates
  1072. )
  1073. if ( ReadingsVal( $name, "residentsTotalRoommatesAbsentDevs", "" ) ne
  1074. $residentsDevs_totalAbsentRoommates );
  1075. readingsBulkUpdate(
  1076. $hash,
  1077. "residentsTotalRoommatesAbsentNames",
  1078. $residents_totalAbsentRoommates
  1079. )
  1080. if ( ReadingsVal( $name, "residentsTotalRoommatesAbsentNames", "" ) ne
  1081. $residents_totalAbsentRoommates );
  1082. readingsBulkUpdate( $hash, "residentsTotalPresent", $state_totalPresent )
  1083. if ( ReadingsVal( $name, "residentsTotalPresent", "" ) ne
  1084. $state_totalPresent );
  1085. readingsBulkUpdate( $hash, "residentsTotalPresentDevs",
  1086. $residentsDevs_totalPresent )
  1087. if ( ReadingsVal( $name, "residentsTotalPresentDevs", "" ) ne
  1088. $residentsDevs_totalPresent );
  1089. readingsBulkUpdate( $hash, "residentsTotalPresentNames",
  1090. $residents_totalPresent )
  1091. if ( ReadingsVal( $name, "residentsTotalPresentNames", "" ) ne
  1092. $residents_totalPresent );
  1093. readingsBulkUpdate( $hash, "residentsTotalAbsent", $state_totalAbsent )
  1094. if ( ReadingsVal( $name, "residentsTotalAbsent", "" ) ne
  1095. $state_totalAbsent );
  1096. readingsBulkUpdate( $hash, "residentsTotalAbsentDevs",
  1097. $residentsDevs_totalAbsent )
  1098. if ( ReadingsVal( $name, "residentsTotalAbsentDevs", "" ) ne
  1099. $residentsDevs_totalAbsent );
  1100. readingsBulkUpdate( $hash, "residentsTotalAbsentNames",
  1101. $residents_totalAbsent )
  1102. if ( ReadingsVal( $name, "residentsTotalAbsentNames", "" ) ne
  1103. $residents_totalAbsent );
  1104. readingsBulkUpdate( $hash, "residentsHome", $state_home )
  1105. if ( ReadingsVal( $name, "residentsHome", "" ) ne $state_home );
  1106. readingsBulkUpdate( $hash, "residentsHomeDevs", $residentsDevs_home )
  1107. if (
  1108. ReadingsVal( $name, "residentsHomeDevs", "" ) ne $residentsDevs_home );
  1109. readingsBulkUpdate( $hash, "residentsHomeNames", $residents_home )
  1110. if ( ReadingsVal( $name, "residentsHomeNames", "" ) ne $residents_home );
  1111. readingsBulkUpdate( $hash, "residentsGotosleep", $state_gotosleep )
  1112. if ( ReadingsVal( $name, "residentsGotosleep", "" ) ne $state_gotosleep );
  1113. readingsBulkUpdate( $hash, "residentsGotosleepDevs",
  1114. $residentsDevs_gotosleep )
  1115. if ( ReadingsVal( $name, "residentsGotosleepDevs", "" ) ne
  1116. $residentsDevs_gotosleep );
  1117. readingsBulkUpdate( $hash, "residentsGotosleepNames", $residents_gotosleep )
  1118. if ( ReadingsVal( $name, "residentsGotosleepNames", "" ) ne
  1119. $residents_gotosleep );
  1120. readingsBulkUpdate( $hash, "residentsAsleep", $state_asleep )
  1121. if ( ReadingsVal( $name, "residentsAsleep", "" ) ne $state_asleep );
  1122. readingsBulkUpdate( $hash, "residentsAsleepDevs", $residentsDevs_asleep )
  1123. if ( ReadingsVal( $name, "residentsAsleepDevs", "" ) ne
  1124. $residentsDevs_asleep );
  1125. readingsBulkUpdate( $hash, "residentsAsleepNames", $residents_asleep )
  1126. if (
  1127. ReadingsVal( $name, "residentsAsleepNames", "" ) ne $residents_asleep );
  1128. readingsBulkUpdate( $hash, "residentsAwoken", $state_awoken )
  1129. if ( ReadingsVal( $name, "residentsAwoken", "" ) ne $state_awoken );
  1130. readingsBulkUpdate( $hash, "residentsAwokenDevs", $residentsDevs_awoken )
  1131. if ( ReadingsVal( $name, "residentsAwokenDevs", "" ) ne
  1132. $residentsDevs_awoken );
  1133. readingsBulkUpdate( $hash, "residentsAwokenNames", $residents_awoken )
  1134. if (
  1135. ReadingsVal( $name, "residentsAwokenNames", "" ) ne $residents_awoken );
  1136. readingsBulkUpdate( $hash, "residentsAbsent", $state_absent )
  1137. if ( ReadingsVal( $name, "residentsAbsent", "" ) ne $state_absent );
  1138. readingsBulkUpdate( $hash, "residentsAbsentDevs", $residentsDevs_absent )
  1139. if ( ReadingsVal( $name, "residentsAbsentDevs", "" ) ne
  1140. $residentsDevs_absent );
  1141. readingsBulkUpdate( $hash, "residentsAbsentNames", $residents_absent )
  1142. if (
  1143. ReadingsVal( $name, "residentsAbsentNames", "" ) ne $residents_absent );
  1144. readingsBulkUpdate( $hash, "residentsGone", $state_gone )
  1145. if ( ReadingsVal( $name, "residentsGone", "" ) ne $state_gone );
  1146. readingsBulkUpdate( $hash, "residentsGoneDevs", $residentsDevs_gone )
  1147. if (
  1148. ReadingsVal( $name, "residentsGoneDevs", "" ) ne $residentsDevs_gone );
  1149. readingsBulkUpdate( $hash, "residentsGoneNames", $residents_gone )
  1150. if ( ReadingsVal( $name, "residentsGoneNames", "" ) ne $residents_gone );
  1151. readingsBulkUpdate( $hash, "residentsTotalWakeup", $wakeup )
  1152. if ( ReadingsVal( $name, "residentsTotalWakeup", "" ) ne $wakeup );
  1153. readingsBulkUpdate( $hash, "residentsTotalWakeupDevs",
  1154. $residentsDevs_wakeup )
  1155. if ( ReadingsVal( $name, "residentsTotalWakeupDevs", "" ) ne
  1156. $residentsDevs_wakeup );
  1157. readingsBulkUpdate( $hash, "residentsTotalWakeupNames", $residents_wakeup )
  1158. if ( ReadingsVal( $name, "residentsTotalWakeupNames", "" ) ne
  1159. $residents_wakeup );
  1160. readingsBulkUpdate( $hash, "residentsTotalWayhome", $wayhome )
  1161. if ( ReadingsVal( $name, "residentsTotalWayhome", "" ) ne $wayhome );
  1162. readingsBulkUpdate( $hash, "residentsTotalWayhomeDevs",
  1163. $residentsDevs_wayhome )
  1164. if ( ReadingsVal( $name, "residentsTotalWayhomeDevs", "" ) ne
  1165. $residentsDevs_wayhome );
  1166. readingsBulkUpdate( $hash, "residentsTotalWayhomeNames",
  1167. $residents_wayhome )
  1168. if ( ReadingsVal( $name, "residentsTotalWayhomeNames", "" ) ne
  1169. $residents_wayhome );
  1170. readingsBulkUpdate( $hash, "residentsTotalWayhomeDelayed", $wayhomeDelayed )
  1171. if ( ReadingsVal( $name, "residentsTotalWayhomeDelayed", "" ) ne
  1172. $wayhomeDelayed );
  1173. readingsBulkUpdate( $hash, "residentsTotalWayhomeDelayedDevs",
  1174. $residentsDevs_wayhomeDelayed )
  1175. if ( ReadingsVal( $name, "residentsTotalWayhomeDelayedDevs", "" ) ne
  1176. $residentsDevs_wayhomeDelayed );
  1177. readingsBulkUpdate( $hash, "residentsTotalWayhomeDelayedNames",
  1178. $residents_wayhomeDelayed )
  1179. if ( ReadingsVal( $name, "residentsTotalWayhomeDelayedNames", "" ) ne
  1180. $residents_wayhomeDelayed );
  1181. #
  1182. # state calculation
  1183. #
  1184. # gotosleep
  1185. if ( $state_home == 0
  1186. && $state_gotosleep > 0
  1187. && $state_asleep >= 0
  1188. && $state_awoken == 0 )
  1189. {
  1190. $newstate = "gotosleep";
  1191. }
  1192. # asleep
  1193. elsif ($state_home == 0
  1194. && $state_gotosleep == 0
  1195. && $state_asleep > 0
  1196. && $state_awoken == 0 )
  1197. {
  1198. $newstate = "asleep";
  1199. }
  1200. # awoken
  1201. elsif ($state_home == 0
  1202. && $state_gotosleep >= 0
  1203. && $state_asleep >= 0
  1204. && $state_awoken > 0 )
  1205. {
  1206. $newstate = "awoken";
  1207. }
  1208. # general presence
  1209. elsif ($state_home > 0
  1210. || $state_gotosleep > 0
  1211. || $state_asleep > 0
  1212. || $state_awoken > 0 )
  1213. {
  1214. $newstate = "home";
  1215. }
  1216. # absent
  1217. elsif ($state_absent > 0
  1218. && $state_home == 0
  1219. && $state_gotosleep == 0
  1220. && $state_asleep == 0
  1221. && $state_awoken == 0 )
  1222. {
  1223. $newstate = "absent";
  1224. }
  1225. # gone
  1226. elsif ($state_gone > 0
  1227. && $state_absent == 0
  1228. && $state_home == 0
  1229. && $state_gotosleep == 0
  1230. && $state_asleep == 0
  1231. && $state_awoken == 0 )
  1232. {
  1233. $newstate = "gone";
  1234. }
  1235. # none
  1236. elsif ($state_totalGuests == 0
  1237. && $state_totalRoommates == 0
  1238. && $state_gone == 0
  1239. && $state_absent == 0
  1240. && $state_home == 0
  1241. && $state_gotosleep == 0
  1242. && $state_asleep == 0
  1243. && $state_awoken == 0 )
  1244. {
  1245. $newstate = "none";
  1246. }
  1247. # unspecified; this should not happen
  1248. else {
  1249. $newstate = "unspecified";
  1250. }
  1251. # calculate presence state
  1252. my $newpresence =
  1253. ( $newstate ne "none" && $newstate ne "gone" && $newstate ne "absent" )
  1254. ? "present"
  1255. : "absent";
  1256. Log3 $name, 4,
  1257. "RESIDENTS $name: calculation result - residentsTotal:$state_total residentsTotalRoommates:$state_totalRoommates residentsTotalRoommatesPresent:$state_totalRoommatesPresent residentsTotalRoommatesAbsent:$state_totalRoommatesAbsent residentsTotalGuests:$state_totalGuests residentsTotalGuestsPresent:$state_totalGuestsPresent residentsTotalGuestsAbsent:$state_totalGuestsAbsent residentsTotalPresent:$state_totalPresent residentsTotalAbsent:$state_totalAbsent residentsHome:$state_home residentsGotosleep:$state_gotosleep residentsAsleep:$state_asleep residentsAwoken:$state_awoken residentsAbsent:$state_absent residentsGone:$state_gone presence:$newpresence state:$newstate";
  1258. # safe current time
  1259. my $datetime = FmtDateTime(time);
  1260. # if state changed
  1261. if ( $state ne $newstate ) {
  1262. # stop any running wakeup-timers in case state changed
  1263. my $wakeupState = AttrVal( $name, "wakeup", 0 );
  1264. if ($wakeupState) {
  1265. my $wakeupDeviceList = AttrVal( $name, "rgr_wakeupDevice", 0 );
  1266. for my $wakeupDevice ( split /,/, $wakeupDeviceList ) {
  1267. next if !$wakeupDevice;
  1268. if ( defined( $defs{$wakeupDevice} )
  1269. && $defs{$wakeupDevice}{TYPE} eq "dummy" )
  1270. {
  1271. # forced-stop only if resident is not present anymore
  1272. if ( $newpresence eq "present" ) {
  1273. fhem "set $wakeupDevice:FILTER=running!=0 end";
  1274. }
  1275. else {
  1276. fhem "set $wakeupDevice:FILTER=running!=0 stop";
  1277. }
  1278. }
  1279. }
  1280. }
  1281. # if newstate is asleep, start sleep timer
  1282. readingsBulkUpdate( $hash, "lastSleep", $datetime )
  1283. if ( $newstate eq "asleep" );
  1284. # if prior state was asleep, update sleep statistics
  1285. if ( $state eq "asleep"
  1286. && ReadingsVal( $name, "lastSleep", "" ) ne "" )
  1287. {
  1288. readingsBulkUpdate( $hash, "lastAwake", $datetime );
  1289. readingsBulkUpdate(
  1290. $hash,
  1291. "lastDurSleep",
  1292. RESIDENTStk_TimeDiff(
  1293. $datetime, ReadingsVal( $name, "lastSleep", "" )
  1294. )
  1295. );
  1296. readingsBulkUpdate(
  1297. $hash,
  1298. "lastDurSleep_cr",
  1299. RESIDENTStk_TimeDiff(
  1300. $datetime, ReadingsVal( $name, "lastSleep", "" ), "min"
  1301. )
  1302. );
  1303. }
  1304. readingsBulkUpdate( $hash, "lastState",
  1305. ReadingsVal( $name, "state", "initialized" ) );
  1306. readingsBulkUpdate( $hash, "state", $newstate );
  1307. }
  1308. # if presence changed
  1309. if ( $newpresence ne $presence ) {
  1310. readingsBulkUpdate( $hash, "presence", $newpresence );
  1311. # update statistics
  1312. if ( $newpresence eq "present" ) {
  1313. readingsBulkUpdate( $hash, "lastArrival", $datetime );
  1314. # absence duration
  1315. if ( ReadingsVal( $name, "lastDeparture", "-" ) ne "-" ) {
  1316. readingsBulkUpdate(
  1317. $hash,
  1318. "lastDurAbsence",
  1319. RESIDENTStk_TimeDiff(
  1320. $datetime, ReadingsVal( $name, "lastDeparture", "-" )
  1321. )
  1322. );
  1323. readingsBulkUpdate(
  1324. $hash,
  1325. "lastDurAbsence_cr",
  1326. RESIDENTStk_TimeDiff(
  1327. $datetime, ReadingsVal( $name, "lastDeparture", "-" ),
  1328. "min"
  1329. )
  1330. );
  1331. }
  1332. }
  1333. else {
  1334. readingsBulkUpdate( $hash, "lastDeparture", $datetime );
  1335. # presence duration
  1336. if ( ReadingsVal( $name, "lastArrival", "-" ) ne "-" ) {
  1337. readingsBulkUpdate(
  1338. $hash,
  1339. "lastDurPresence",
  1340. RESIDENTStk_TimeDiff(
  1341. $datetime, ReadingsVal( $name, "lastArrival", "-" )
  1342. )
  1343. );
  1344. readingsBulkUpdate(
  1345. $hash,
  1346. "lastDurPresence_cr",
  1347. RESIDENTStk_TimeDiff(
  1348. $datetime, ReadingsVal( $name, "lastArrival", "-" ),
  1349. "min"
  1350. )
  1351. );
  1352. }
  1353. }
  1354. }
  1355. }
  1356. 1;
  1357. =pod
  1358. =item helper
  1359. =item summary combines ROOMMATE and GUEST devices to a residential community
  1360. =item summary_de fasst ROOMMATE und GUEST Ger&auml;te zu einer Wohngemeinschaft zusammen
  1361. =begin html
  1362. <p>
  1363. <a name="RESIDENTS" id="RESIDENTS"></a>
  1364. </p>
  1365. <h3>
  1366. RESIDENTS
  1367. </h3>
  1368. <ul>
  1369. <a name="RESIDENTSdefine" id="RESIDENTSdefine"></a> <b>Define</b>
  1370. <ul>
  1371. <code>define &lt;rgr_ResidentsName&gt; RESIDENTS</code><br>
  1372. <br>
  1373. Provides a special virtual device to represent a group of individuals living at your home.<br>
  1374. It locically combines individual states of <a href="#ROOMMATE">ROOMMATE</a> and <a href="#GUEST">GUEST</a> devices and allows state changes for all members.<br>
  1375. Based on the current state and other readings, you may trigger other actions within FHEM.<br>
  1376. <br>
  1377. Example:<br>
  1378. <ul>
  1379. <code># Standalone<br>
  1380. define rgr_Residents RESIDENTS</code>
  1381. </ul>
  1382. </ul><br>
  1383. <br>
  1384. <a name="RESIDENTSset" id="RESIDENTSset"></a> <b>Set</b>
  1385. <ul>
  1386. <code>set &lt;rgr_ResidentsName&gt; &lt;command&gt; [&lt;parameter&gt;]</code><br>
  1387. <br>
  1388. Currently, the following commands are defined.<br>
  1389. <ul>
  1390. <li>
  1391. <b>addGuest</b> &nbsp;&nbsp;-&nbsp;&nbsp; creates a new GUEST device and adds it to the current RESIDENTS group. Just enter the dummy name and there you go.
  1392. </li>
  1393. <li>
  1394. <b>addRoommate</b> &nbsp;&nbsp;-&nbsp;&nbsp; creates a new ROOMMATE device and adds it to the current RESIDENTS group. Just enter the first name and there you go.
  1395. </li>
  1396. <li>
  1397. <b>removeGuest</b> &nbsp;&nbsp;-&nbsp;&nbsp; shows all GUEST members and allows to delete their dummy devices easily.
  1398. </li>
  1399. <li>
  1400. <b>removeRoommate</b> &nbsp;&nbsp;-&nbsp;&nbsp; shows all ROOMMATE members and allows to delete their dummy devices easily.
  1401. </li>
  1402. <li>
  1403. <b>state</b> &nbsp;&nbsp;home,gotosleep,asleep,awoken,absent,gone&nbsp;&nbsp; switch between states for all group members at once; see attribute rgr_states to adjust list shown in FHEMWEB
  1404. </li>
  1405. <li>
  1406. <b>create</b> &nbsp;&nbsp;wakeuptimer&nbsp;&nbsp; add several pre-configurations provided by RESIDENTS Toolkit. See separate section for details.
  1407. </li>
  1408. </ul>
  1409. <ul>
  1410. <u>Note:</u> If you would like to restrict access to admin set-commands (-> addGuest, addRoommate, removeGuest, create) you may set your FHEMWEB instance's attribute allowedCommands like 'set,set-user'.
  1411. The string 'set-user' will ensure only non-admin set-commands can be executed when accessing FHEM using this FHEMWEB instance.
  1412. </ul>
  1413. </ul><br>
  1414. <br>
  1415. <ul>
  1416. <u>Possible states and their meaning</u><br>
  1417. <br>
  1418. <ul>
  1419. This module differs between 7 states:<br>
  1420. <br>
  1421. <ul>
  1422. <li>
  1423. <b>home</b> - residents are present at home and at least one of them is not asleep
  1424. </li>
  1425. <li>
  1426. <b>gotosleep</b> - present residents are on their way to bed (if they are not asleep already)
  1427. </li>
  1428. <li>
  1429. <b>asleep</b> - all present residents are currently sleeping
  1430. </li>
  1431. <li>
  1432. <b>awoken</b> - at least one resident just woke up from sleep
  1433. </li>
  1434. <li>
  1435. <b>absent</b> - no resident is currently at home but at least one will be back shortly
  1436. </li>
  1437. <li>
  1438. <b>gone</b> - all residents left home for longer period
  1439. </li>
  1440. <li>
  1441. <b>none</b> - no active member
  1442. </li>
  1443. </ul><br>
  1444. <br>
  1445. Note: State 'none' cannot explicitly be set. Setting state to 'gone' will be handled as 'none' for GUEST member devices.
  1446. </ul>
  1447. </ul><br>
  1448. <br>
  1449. <a name="RESIDENTSattr" id="RESIDENTSattr"></a> <b>Attributes</b><br>
  1450. <ul>
  1451. <ul>
  1452. <li>
  1453. <b>rgr_showAllStates</b> - states 'asleep' and 'awoken' are hidden by default to allow simple gotosleep process via devStateIcon; defaults to 0
  1454. </li>
  1455. <li>
  1456. <b>rgr_states</b> - list of states to be shown in FHEMWEB; separate entries by comma only and do NOT use spaces; unsupported states will lead to errors though
  1457. </li>
  1458. <li>
  1459. <b>rgr_wakeupDevice</b> - reference to enslaved DUMMY devices used as a wake-up timer (part of RESIDENTS Toolkit's wakeuptimer)
  1460. </li>
  1461. </ul>
  1462. </ul><br>
  1463. <br>
  1464. <br>
  1465. <b>Generated Readings/Events:</b><br>
  1466. <ul>
  1467. <ul>
  1468. <li>
  1469. <b>lastActivity</b> - the last state change of one of the group members
  1470. </li>
  1471. <li>
  1472. <b>lastActivityBy</b> - the realname of the last group member with changed state
  1473. </li>
  1474. <li>
  1475. <b>lastArrival</b> - timestamp of last arrival at home
  1476. </li>
  1477. <li>
  1478. <b>lastAwake</b> - timestamp of last sleep cycle end
  1479. </li>
  1480. <li>
  1481. <b>lastDeparture</b> - timestamp of last departure from home
  1482. </li>
  1483. <li>
  1484. <b>lastDurAbsence</b> - duration of last absence from home in human readable format (hours:minutes:seconds)
  1485. </li>
  1486. <li>
  1487. <b>lastDurAbsence_cr</b> - duration of last absence from home in computer readable format (minutes)
  1488. </li>
  1489. <li>
  1490. <b>lastDurPresence</b> - duration of last presence at home in human readable format (hours:minutes:seconds)
  1491. </li>
  1492. <li>
  1493. <b>lastDurPresence_cr</b> - duration of last presence at home in computer readable format (minutes)
  1494. </li>
  1495. <li>
  1496. <b>lastDurSleep</b> - duration of last sleep in human readable format (hours:minutes:seconds)
  1497. </li>
  1498. <li>
  1499. <b>lastDurSleep_cr</b> - duration of last sleep in computer readable format (minutes)
  1500. </li>
  1501. <li>
  1502. <b>lastSleep</b> - timestamp of last sleep cycle begin
  1503. </li>
  1504. <li>
  1505. <b>lastState</b> - the prior state
  1506. </li>
  1507. <li>
  1508. <b>lastWakeup</b> - time of last wake-up timer run
  1509. </li>
  1510. <li>
  1511. <b>lastWakeupDev</b> - device name of last wake-up timer
  1512. </li>
  1513. <li>
  1514. <b>nextWakeup</b> - time of next wake-up program run
  1515. </li>
  1516. <li>
  1517. <b>nextWakeupDev</b> - device name for next wake-up program run
  1518. </li>
  1519. <li>
  1520. <b>presence</b> - reflects the home presence state, depending on value of reading 'state' (can be 'present' or 'absent')
  1521. </li>
  1522. <li>
  1523. <b>residentsAbsent</b> - number of residents with state 'absent'
  1524. </li>
  1525. <li>
  1526. <b>residentsAbsentDevs</b> - device name of residents with state 'absent'
  1527. </li>
  1528. <li>
  1529. <b>residentsAbsentNames</b> - device alias of residents with state 'absent'
  1530. </li>
  1531. <li>
  1532. <b>residentsAsleep</b> - number of residents with state 'asleep'
  1533. </li>
  1534. <li>
  1535. <b>residentsAsleepDevs</b> - device name of residents with state 'asleep'
  1536. </li>
  1537. <li>
  1538. <b>residentsAsleepNames</b> - device alias of residents with state 'asleep'
  1539. </li>
  1540. <li>
  1541. <b>residentsAwoken</b> - number of residents with state 'awoken'
  1542. </li>
  1543. <li>
  1544. <b>residentsAwokenDevs</b> - device name of residents with state 'awoken'
  1545. </li>
  1546. <li>
  1547. <b>residentsAwokenNames</b> - device alias of residents with state 'awoken'
  1548. </li>
  1549. <li>
  1550. <b>residentsGone</b> - number of residents with state 'gone'
  1551. </li>
  1552. <li>
  1553. <b>residentsGoneDevs</b> - device name of residents with state 'gone'
  1554. </li>
  1555. <li>
  1556. <b>residentsGoneNames</b> - device alias of residents with state 'gone'
  1557. </li>
  1558. <li>
  1559. <b>residentsGotosleep</b> - number of residents with state 'gotosleep'
  1560. </li>
  1561. <li>
  1562. <b>residentsGotosleepDevs</b> - device name of residents with state 'gotosleep'
  1563. </li>
  1564. <li>
  1565. <b>residentsGotosleepNames</b> - device alias of residents with state 'gotosleep'
  1566. </li>
  1567. <li>
  1568. <b>residentsHome</b> - number of residents with state 'home'
  1569. </li>
  1570. <li>
  1571. <b>residentsHomeDevs</b> - device name of residents with state 'home'
  1572. </li>
  1573. <li>
  1574. <b>residentsHomeNames</b> - device alias of residents with state 'home'
  1575. </li>
  1576. <li>
  1577. <b>residentsTotal</b> - total number of all active residents despite their current state
  1578. </li>
  1579. <li>
  1580. <b>residentsTotalAbsent</b> - number of all residents who are currently underway
  1581. </li>
  1582. <li>
  1583. <b>residentsTotalAbsentDevs</b> - device name of all residents who are currently underway
  1584. </li>
  1585. <li>
  1586. <b>residentsTotalAbsentNames</b> - device alias of all residents who are currently underway
  1587. </li>
  1588. <li>
  1589. <b>residentsTotalGuests</b> - number of active guests who are currently treated as part of the residents scope
  1590. </li>
  1591. <li>
  1592. <b>residentsTotalGuestsAbsent</b> - number of all active guests who are currently underway
  1593. </li>
  1594. <li>
  1595. <b>residentsTotalGuestsAbsentDevs</b> - device name of all active guests who are currently underway
  1596. </li>
  1597. <li>
  1598. <b>residentsTotalGuestsAbsentNames</b> - device alias of all active guests who are currently underway
  1599. </li>
  1600. <li>
  1601. <b>residentsTotalGuestsPresent</b> - number of all active guests who are currently at home
  1602. </li>
  1603. <li>
  1604. <b>residentsTotalGuestsPresentDevs</b> - device name of all active guests who are currently at home
  1605. </li>
  1606. <li>
  1607. <b>residentsTotalGuestsPresentNames</b> - device alias of all active guests who are currently at home
  1608. </li>
  1609. <li>
  1610. <b>residentsTotalRoommates</b> - number of residents treated as being a permanent resident
  1611. </li>
  1612. <li>
  1613. <b>residentsTotalRoommatesAbsent</b> - number of all roommates who are currently underway
  1614. </li>
  1615. <li>
  1616. <b>residentsTotalRoommatesAbsentDevs</b> - device name of all roommates who are currently underway
  1617. </li>
  1618. <li>
  1619. <b>residentsTotalRoommatesAbsentNames</b> - device alias of all roommates who are currently underway
  1620. </li>
  1621. <li>
  1622. <b>residentsTotalRoommatesPresent</b> - number of all roommates who are currently at home
  1623. </li>
  1624. <li>
  1625. <b>residentsTotalRoommatesPresentDevs</b> - device name of all roommates who are currently at home
  1626. </li>
  1627. <li>
  1628. <b>residentsTotalRoommatesPresentNames</b> - device alias of all roommates who are currently at home
  1629. </li>
  1630. <li>
  1631. <b>residentsTotalPresent</b> - number of all residents who are currently at home
  1632. </li>
  1633. <li>
  1634. <b>residentsTotalPresentDevs</b> - device name of all residents who are currently at home
  1635. </li>
  1636. <li>
  1637. <b>residentsTotalPresentNames</b> - device alias of all residents who are currently at home
  1638. </li>
  1639. <li>
  1640. <b>residentsTotalWakeup</b> - number of all residents which currently have a wake-up program being executed
  1641. </li>
  1642. <li>
  1643. <b>residentsTotalWakeupDevs</b> - device name of all residents which currently have a wake-up program being executed
  1644. </li>
  1645. <li>
  1646. <b>residentsTotalWakeupNames</b> - device alias of all residents which currently have a wake-up program being executed
  1647. </li>
  1648. <li>
  1649. <b>residentsTotalWayhome</b> - number of all active residents who are currently on their way back home
  1650. </li>
  1651. <li>
  1652. <b>residentsTotalWayhomeDevs</b> - device name of all active residents who are currently on their way back home
  1653. </li>
  1654. <li>
  1655. <b>residentsTotalWayhomeNames</b> - device alias of all active residents who are currently on their way back home
  1656. </li>
  1657. <li>
  1658. <b>residentsTotalWayhomeDelayed</b> - number of all residents who are delayed on their way back home
  1659. </li>
  1660. <li>
  1661. <b>residentsTotalWayhomeDelayedDevs</b> - device name of all delayed residents who are currently on their way back home
  1662. </li>
  1663. <li>
  1664. <b>residentsTotalWayhomeDelayedNames</b> - device alias of all delayed residents who are currently on their way back home
  1665. </li>
  1666. <li>
  1667. <b>state</b> - reflects the current state
  1668. </li>
  1669. <li>
  1670. <b>wakeup</b> - becomes '1' while a wake-up program of this resident group is being executed
  1671. </li>
  1672. </ul>
  1673. </ul>
  1674. <br>
  1675. <br>
  1676. <b>RESIDENTS Toolkit</b><br>
  1677. <ul>
  1678. <ul>
  1679. Using set-command <code>create</code> you may add pre-configured configurations to your RESIDENTS, <a href="#ROOMMATE">ROOMMATE</a> or <a href="#GUEST">GUEST</a> devices for your convenience.<br>
  1680. The following commands are currently available:<br>
  1681. <br>
  1682. <li>
  1683. <b>wakeuptimer</b> &nbsp;&nbsp;-&nbsp;&nbsp; adds a wake-up timer dummy device with enhanced functions to start with wake-up automations
  1684. <ul>
  1685. A notify device is created to be used as a Macro to carry out your actual automations. The macro is triggered by a normal at device you may customize as well. However, a special RESIDENTS Toolkit function is handling the wake-up trigger event for you.<br>
  1686. The time of activated wake-up timers may be relatively increased or decreased by using +<MINUTES> or -<MINUTES> respectively. +HH:MM can be used as well.<br>
  1687. <br>
  1688. The wake-up behaviour may be influenced by the following device attributes:<br>
  1689. <li>
  1690. <i>wakeupAtdevice</i> - backlink the at device (mandatory)
  1691. </li>
  1692. <li>
  1693. <i>wakeupDays</i> - only trigger macro at these days. Mon=1,Tue=2,Wed=3,Thu=4,Fri=5,Sat=6,Sun=0 (optional)
  1694. </li>
  1695. <li>
  1696. <i>wakeupDefaultTime</i> - after triggering macro reset the wake-up time to this default value (optional)
  1697. </li>
  1698. <li>
  1699. <i>wakeupEnforced</i> - Enforce wake-up (optional; 0=no, 1=yes, 2=if wake-up time is not wakeupDefaultTime)
  1700. </li>
  1701. <li>
  1702. <i>wakeupHolidays</i> - May trigger macro on holidays or non-holidays (optional; andHoliday=on holidays also considering wakeupDays, orHoliday=on holidays independently of wakeupDays, andNoHoliday=on non-holidays also considering wakeupDays, orNoHoliday=on non-holidays independently of wakeupDays)
  1703. </li>
  1704. <li>
  1705. <i>wakeupMacro</i> - name of the notify macro device (mandatory)
  1706. </li>
  1707. <li>
  1708. <i>wakeupOffset</i> - value in minutes to trigger your macro earlier than the user requested to be woken up, e.g. if you have a complex wake-up program over 30 minutes (defaults to 0)
  1709. </li>
  1710. <li>
  1711. <i>wakeupResetSwitcher</i> - DUMMY device to quickly turn on/off reset function (optional, device will be auto-created)
  1712. </li>
  1713. <li>
  1714. <i>wakeupResetdays</i> - if wakeupDefaultTime is set you may restrict timer reset to specific days only. Mon=1,Tue=2,Wed=3,Thu=4,Fri=5,Sat=6,Sun=0 (optional)
  1715. </li>
  1716. <li>
  1717. <i>wakeupUserdevice</i> - backlink to RESIDENTS, ROOMMATE or GUEST device to check it's status (mandatory)
  1718. </li>
  1719. <li>
  1720. <i>wakeupWaitPeriod</i> - waiting period threshold in minutes until wake-up program may be triggered again, e.g. if you manually set an earlier wake-up time than normal while using wakeupDefaultTime. Does not apply in case wake-up time was changed during this period; defaults to 360 minutes / 6h (optional)
  1721. </li>
  1722. </ul>
  1723. </li>
  1724. </ul>
  1725. </ul>
  1726. </ul>
  1727. =end html
  1728. =begin html_DE
  1729. <p>
  1730. <a name="RESIDENTS" id="RESIDENTS"></a>
  1731. </p>
  1732. <h3>
  1733. RESIDENTS
  1734. </h3>
  1735. <ul>
  1736. <a name="RESIDENTSdefine" id="RESIDENTSdefine"></a> <b>Define</b>
  1737. <ul>
  1738. <code>define &lt;rgr_ResidentsName&gt; RESIDENTS</code><br>
  1739. <br>
  1740. Stellt ein spezielles virtuelles Device bereit, um eine Gruppe von Personen zu repr&auml;sentieren, die zusammen wohnen.<br>
  1741. Es kombiniert dabei logisch die individuellen Status von <a href="#ROOMMATE">ROOMMATE</a> und <a href="#GUEST">GUEST</a> Devices und erlaubt den Status f&uuml;r alle Mitglieder zeitgleich zu &auml;ndern. Basierend auf dem aktuellen Status und anderen Readings k&ouml;nnen andere Aktionen innerhalb von FHEM angestoßen werden.<br>
  1742. <br>
  1743. Beispiele:<br>
  1744. <ul>
  1745. <code># Einzeln<br>
  1746. define rgr_Residents RESIDENTS</code>
  1747. </ul>
  1748. </ul><br>
  1749. <br>
  1750. <a name="RESIDENTSset" id="RESIDENTSset"></a> <b>Set</b>
  1751. <ul>
  1752. <code>set &lt;rgr_ResidentsName&gt; &lt;command&gt; [&lt;parameter&gt;]</code><br>
  1753. <br>
  1754. Momentan sind die folgenden Kommandos definiert.<br>
  1755. <ul>
  1756. <li>
  1757. <b>addGuest</b> &nbsp;&nbsp;-&nbsp;&nbsp; erstellt ein neues GUEST Device und f&uuml;gt es der aktuellen RESIDENTS Gruppe hinzu. Einfach den Platzhalternamen eingeben und das wars.
  1758. </li>
  1759. <li>
  1760. <b>addRoommate</b> &nbsp;&nbsp;-&nbsp;&nbsp; erstellt ein neues ROOMMATE Device und f&uuml;gt es der aktuellen RESIDENTS Gruppe hinzu. Einfach den Vornamen eingeben und das wars.
  1761. </li>
  1762. <li>
  1763. <b>removeGuest</b> &nbsp;&nbsp;-&nbsp;&nbsp; zeigt alle Mitglieder vom Typ GUEST an und erm&ouml;glicht ein einfaches l&ouml;schen des dazugeh&ouml;rigen Dummy Devices.
  1764. </li>
  1765. <li>
  1766. <b>removeRoommate</b> &nbsp;&nbsp;-&nbsp;&nbsp; zeigt alle Mitglieder vom Typ ROOMMATE an und erm&ouml;glicht ein einfaches l&ouml;schen des dazugeh&ouml;rigen Dummy Devices.
  1767. </li>
  1768. <li>
  1769. <b>state</b> &nbsp;&nbsp;home,gotosleep,asleep,awoken,absent,gone&nbsp;&nbsp; wechselt den Status f&uuml;r alle Gruppenmitglieder gleichzeitig; siehe Attribut rgr_states, um die angezeigte Liste in FHEMWEB abzu&auml;ndern
  1770. </li>
  1771. <li>
  1772. <b>create</b> &nbsp;&nbsp;wakeuptimer&nbsp;&nbsp; f&uuml;gt diverse Vorkonfigurationen auf Basis von RESIDENTS Toolkit hinzu. Siehe separate Sektion.
  1773. </li>
  1774. </ul>
  1775. <ul>
  1776. <u>Hinweis:</u> Sofern der Zugriff auf administrative set-Kommandos (-> addGuest, addRoommate, removeGuest, create) eingeschr&auml;nkt werden soll, kann in einer FHEMWEB Instanz das Attribut allowedCommands &auml;hnlich wie 'set,set-user' erweitert werden.
  1777. Die Zeichenfolge 'set-user' stellt dabei sicher, dass beim Zugriff auf FHEM &uuml;ber diese FHEMWEB Instanz nur nicht-administrative set-Kommandos ausgef&uuml;hrt werden k&ouml;nnen.
  1778. </ul>
  1779. </ul><br>
  1780. <br>
  1781. <ul>
  1782. <u>M&ouml;gliche Status und ihre Bedeutung</u><br>
  1783. <br>
  1784. <ul>
  1785. Dieses Modul unterscheidet 7 verschiedene Status:<br>
  1786. <br>
  1787. <ul>
  1788. <li>
  1789. <b>home</b> - Bewohner sind zu Hause und mindestens einer schl&auml;ft nicht
  1790. </li>
  1791. <li>
  1792. <b>gotosleep</b> - alle anwesenden Bewohner sind auf dem Weg ins Bett (wenn sie nicht schon schlafen)
  1793. </li>
  1794. <li>
  1795. <b>asleep</b> - alle anwesenden Bewohner schlafen
  1796. </li>
  1797. <li>
  1798. <b>awoken</b> - mindestens einer der anwesenden Bewohner ist gerade aufgewacht
  1799. </li>
  1800. <li>
  1801. <b>absent</b> - keiner der Bewohner ist momentan zu Hause; mindestens einer ist aber in K&uuml;rze zur&uuml;ck
  1802. </li>
  1803. <li>
  1804. <b>gone</b> - alle Bewohner sind f&uuml;r l&auml;ngere Zeit verreist
  1805. </li>
  1806. <li>
  1807. <b>none</b> - kein Mitglied aktiv
  1808. </li>
  1809. </ul><br>
  1810. <br>
  1811. Hinweis: Der Status 'none' kann nicht explizit gesetzt werden. Das setzen von 'gone' wird bei Mitgliedern vom Typ GUEST als 'none' behandelt.
  1812. </ul>
  1813. </ul><br>
  1814. <br>
  1815. <a name="RESIDENTSattr" id="RESIDENTSattr"></a> <b>Attribute</b><br>
  1816. <ul>
  1817. <ul>
  1818. <li>
  1819. <b>rgr_showAllStates</b> - die Status 'asleep' und 'awoken' sind normalerweise nicht immer sichtbar, um einen einfachen Zubettgeh-Prozess &uuml;ber das devStateIcon Attribut zu erm&ouml;glichen; Standard ist 0
  1820. </li>
  1821. <li>
  1822. <b>rgr_states</b> - Liste aller in FHEMWEB angezeigter Status; Eintrage nur mit Komma trennen und KEINE Leerzeichen benutzen; nicht unterst&uuml;tzte Status f&uuml;hren zu Fehlern
  1823. </li>
  1824. <li>
  1825. <b>rgr_wakeupDevice</b> - Referenz zu versklavten DUMMY Ger&auml;ten, welche als Wecker benutzt werden (Teil von RESIDENTS Toolkit's wakeuptimer)
  1826. </li>
  1827. </ul>
  1828. </ul><br>
  1829. <br>
  1830. <br>
  1831. <b>Generierte Readings/Events:</b><br>
  1832. <ul>
  1833. <ul>
  1834. <li>
  1835. <b>lastActivity</b> - der letzte Status Wechsel eines Gruppenmitglieds
  1836. </li>
  1837. <li>
  1838. <b>lastActivityBy</b> - der Name des Gruppenmitglieds, dessen Status zuletzt ge&auml;ndert wurde
  1839. </li>
  1840. <li>
  1841. <b>lastArrival</b> - Zeitstempel der letzten Ankunft zu Hause
  1842. </li>
  1843. <li>
  1844. <b>lastAwake</b> - Zeitstempel des Endes des letzten Schlafzyklus
  1845. </li>
  1846. <li>
  1847. <b>lastDeparture</b> - Zeitstempel des letzten Verlassens des Zuhauses
  1848. </li>
  1849. <li>
  1850. <b>lastDurAbsence</b> - Dauer der letzten Abwesenheit in normal lesbarem Format (Stunden:Minuten:Sekunden)
  1851. </li>
  1852. <li>
  1853. <b>lastDurAbsence_cr</b> - Dauer der letzten Abwesenheit in Computer lesbarem Format (Minuten)
  1854. </li>
  1855. <li>
  1856. <b>lastDurPresence</b> - Dauer der letzten Anwesenheit in normal lesbarem Format (Stunden:Minuten:Sekunden)
  1857. </li>
  1858. <li>
  1859. <b>lastDurPresence_cr</b> - Dauer der letzten Anwesenheit in Computer lesbarem Format (Minuten)
  1860. </li>
  1861. <li>
  1862. <b>lastDurSleep</b> - Dauer des letzten Schlafzyklus in normal lesbarem Format (Stunden:Minuten:Sekunden)
  1863. </li>
  1864. <li>
  1865. <b>lastDurSleep_cr</b> - Dauer des letzten Schlafzyklus in Computer lesbarem Format (Minuten)
  1866. </li>
  1867. <li>
  1868. <b>lastSleep</b> - Zeitstempel des Beginns des letzten Schlafzyklus
  1869. </li>
  1870. <li>
  1871. <b>lastState</b> - der vorherige Status
  1872. </li>
  1873. <li>
  1874. <b>lastWakeup</b> - Zeit der letzten Wake-up Timer Ausf&uuml;hring
  1875. </li>
  1876. <li>
  1877. <b>lastWakeupDev</b> - Device Name des zuletzt verwendeten Wake-up Timers
  1878. </li>
  1879. <li>
  1880. <b>nextWakeup</b> - Zeit der n&auml;chsten Wake-up Timer Ausf&uuml;hrung
  1881. </li>
  1882. <li>
  1883. <b>nextWakeupDev</b> - Device Name des als n&auml;chstes ausgef&auml;hrten Wake-up Timer
  1884. </li>
  1885. <li>
  1886. <b>presence</b> - gibt den zu Hause Status in Abh&auml;ngigkeit des Readings 'state' wieder (kann 'present' oder 'absent' sein)
  1887. </li>
  1888. <li>
  1889. <b>residentsAbsent</b> - Anzahl der Bewohner mit Status 'absent'
  1890. </li>
  1891. <li>
  1892. <b>residentsAbsentDevs</b> - Ger&auml;tename der Bewohner mit Status 'absent'
  1893. </li>
  1894. <li>
  1895. <b>residentsAbsentNames</b> - Ger&auml;tealias der Bewohner mit Status 'absent'
  1896. </li>
  1897. <li>
  1898. <b>residentsAsleep</b> - Anzahl der Bewohner mit Status 'asleep'
  1899. </li>
  1900. <li>
  1901. <b>residentsAsleepDevs</b> - Ger&auml;tename der Bewohner mit Status 'asleep'
  1902. </li>
  1903. <li>
  1904. <b>residentsAsleepNames</b> - Ger&auml;tealias der Bewohner mit Status 'asleep'
  1905. </li>
  1906. <li>
  1907. <b>residentsAwoken</b> - Anzahl der Bewohner mit Status 'awoken'
  1908. </li>
  1909. <li>
  1910. <b>residentsAwokenDevs</b> - Ger&auml;tename der Bewohner mit Status 'awoken'
  1911. </li>
  1912. <li>
  1913. <b>residentsAwokenNames</b> - Ger&auml;tealias der Bewohner mit Status 'awoken'
  1914. </li>
  1915. <li>
  1916. <b>residentsGone</b> - Anzahl der Bewohner mit Status 'gone'
  1917. </li>
  1918. <li>
  1919. <b>residentsGoneDevs</b> - Ger&auml;tename der Bewohner mit Status 'gone'
  1920. </li>
  1921. <li>
  1922. <b>residentsGoneNames</b> - Ger&auml;tealias der Bewohner mit Status 'gone'
  1923. </li>
  1924. <li>
  1925. <b>residentsGotosleep</b> - Anzahl der Bewohner mit Status 'gotosleep'
  1926. </li>
  1927. <li>
  1928. <b>residentsGotosleepDevs</b> - Ger&auml;tename der Bewohner mit Status 'gotosleep'
  1929. </li>
  1930. <li>
  1931. <b>residentsGotosleepNames</b> - Ger&auml;tealias der Bewohner mit Status 'gotosleep'
  1932. </li>
  1933. <li>
  1934. <b>residentsHome</b> - Anzahl der Bewohner mit Status 'home'
  1935. </li>
  1936. <li>
  1937. <b>residentsHomeDevs</b> - Ger&auml;tename der Bewohner mit Status 'home'
  1938. </li>
  1939. <li>
  1940. <b>residentsHomeNames</b> - Ger&auml;tealias der Bewohner mit Status 'home'
  1941. </li>
  1942. <li>
  1943. <b>residentsTotal</b> - Summe aller aktiven Bewohner unabh&auml;ngig von ihrem aktuellen Status
  1944. </li>
  1945. <li>
  1946. <b>residentsTotalAbsent</b> - Summe aller aktiven Bewohner, die unterwegs sind
  1947. </li>
  1948. <li>
  1949. <b>residentsTotalAbsentDevs</b> - Ger&auml;tename aller aktiven Bewohner, die unterwegs sind
  1950. </li>
  1951. <li>
  1952. <b>residentsTotalAbsentNames</b> - Ger&auml;tealias aller aktiven Bewohner, die unterwegs sind
  1953. </li>
  1954. <li>
  1955. <b>residentsTotalGuests</b> - Anzahl der aktiven G&auml;ste, welche momentan du den Bewohnern dazugez&auml;hlt werden
  1956. </li>
  1957. <li>
  1958. <b>residentsTotalGuestsAbsent</b> - Anzahl der aktiven G&auml;ste, die momentan unterwegs sind
  1959. </li>
  1960. <li>
  1961. <b>residentsTotalGuestsAbsentDevs</b> - Ger&auml;tename der aktiven G&auml;ste, die momentan unterwegs sind
  1962. </li>
  1963. <li>
  1964. <b>residentsTotalGuestsAbsentNames</b> - Ger&auml;tealias der aktiven G&auml;ste, die momentan unterwegs sind
  1965. </li>
  1966. <li>
  1967. <b>residentsTotalGuestsPresent</b> - Anzahl der aktiven G&auml;ste, die momentan zu Hause sind
  1968. </li>
  1969. <li>
  1970. <b>residentsTotalGuestsPresentDevs</b> - Ger&auml;tename der aktiven G&auml;ste, die momentan zu Hause sind
  1971. </li>
  1972. <li>
  1973. <b>residentsTotalGuestsPresentNames</b> - Ger&auml;tealias der aktiven G&auml;ste, die momentan zu Hause sind
  1974. </li>
  1975. <li>
  1976. <b>residentsTotalRoommates</b> - Anzahl der Bewohner, die als permanente Bewohner behandelt werden
  1977. </li>
  1978. <li>
  1979. <b>residentsTotalRoommatesAbsent</b> - Anzahl der Besitzer, die momentan unterwegs sind
  1980. </li>
  1981. <li>
  1982. <b>residentsTotalRoommatesAbsentDevs</b> - Ger&auml;tename der Besitzer, die momentan unterwegs sind
  1983. </li>
  1984. <li>
  1985. <b>residentsTotalRoommatesAbsentNames</b> - Ger&auml;tealias der Besitzer, die momentan unterwegs sind
  1986. </li>
  1987. <li>
  1988. <b>residentsTotalRoommatesPresent</b> - Anzahl der Besitzer, die momentan zu Hause sind
  1989. </li>
  1990. <li>
  1991. <b>residentsTotalRoommatesPresentDevs</b> - Ger&auml;tename der Besitzer, die momentan zu Hause sind
  1992. </li>
  1993. <li>
  1994. <b>residentsTotalRoommatesPresentNames</b> - Ger&auml;tealias der Besitzer, die momentan zu Hause sind
  1995. </li>
  1996. <li>
  1997. <b>residentsTotalPresent</b> - Summe aller aktiven Bewohner, die momentan zu Hause sind
  1998. </li>
  1999. <li>
  2000. <b>residentsTotalPresentDevs</b> - Ger&auml;tename aller aktiven Bewohner, die momentan zu Hause sind
  2001. </li>
  2002. <li>
  2003. <b>residentsTotalPresentNames</b> - Ger&auml;tealias aller aktiven Bewohner, die momentan zu Hause sind
  2004. </li>
  2005. <li>
  2006. <b>residentsTotalWakeup</b> - Summe aller Bewohner, bei denen aktuell ein Weckprogramm ausgef&uuml;hrt wird
  2007. </li>
  2008. <li>
  2009. <b>residentsTotalWakeupDevs</b> - Ger&auml;tename aller Bewohner, bei denen aktuell ein Weckprogramm ausgef&uuml;hrt wird
  2010. </li>
  2011. <li>
  2012. <b>residentsTotalWakeupNames</b> - Ger&auml;tealias aller Bewohner, bei denen aktuell ein Weckprogramm ausgef&uuml;hrt wird
  2013. </li>
  2014. <li>
  2015. <b>residentsTotalWayhome</b> - Summe aller aktiven Bewohner, die momentan auf dem Weg zur&uuml;ck nach Hause sind
  2016. </li>
  2017. <li>
  2018. <b>residentsTotalWayhomeDevs</b> - Ger&auml;tename aller aktiven Bewohner, die momentan auf dem Weg zur&uuml;ck nach Hause sind
  2019. </li>
  2020. <li>
  2021. <b>residentsTotalWayhomeNames</b> - Ger&auml;tealias aller aktiven Bewohner, die momentan auf dem Weg zur&uuml;ck nach Hause sind
  2022. </li>
  2023. <li>
  2024. <b>residentsTotalWayhomeDelayed</b> - Summe aller Bewohner, die momentan mit Versp&auml;tung auf dem Weg zur&uuml;ck nach Hause sind
  2025. </li>
  2026. <li>
  2027. <b>residentsTotalWayhomeDelayedDevs</b> - Ger&auml;tename aller Bewohner, die momentan versp&auml;tet auf dem Weg zur&uuml;ck nach Hause sind
  2028. </li>
  2029. <li>
  2030. <b>residentsTotalWayhomeDelayedNames</b> - Ger&auml;tealias aller Bewohner, die momentan versp&auml;tet auf dem Weg zur&uuml;ck nach Hause sind
  2031. </li>
  2032. <li>
  2033. <b>state</b> - gibt den aktuellen Status wieder
  2034. </li>
  2035. <li>
  2036. <b>wakeup</b> - hat den Wert '1' w&auml;hrend ein Weckprogramm dieser Bewohner-Gruppe ausgef&uuml;hrt wird
  2037. </li>
  2038. </ul>
  2039. </ul>
  2040. <br>
  2041. <br>
  2042. <b>RESIDENTS Toolkit</b><br>
  2043. <ul>
  2044. <ul>
  2045. Mit dem set-Kommando <code>create</code> k&ouml;nnen zur Vereinfachung vorkonfigurierte Konfigurationen zu RESIDENTS, <a href="#ROOMMATE">ROOMMATE</a> oder <a href="#GUEST">GUEST</a> Ger&auml;ten hinzugef&uuml;gt werden.<br>
  2046. Die folgenden Kommandos sind momentan verf&uuml;gbar:<br>
  2047. <br>
  2048. <li>
  2049. <b>wakeuptimer</b> &nbsp;&nbsp;-&nbsp;&nbsp; f&uuml;gt ein Dummy Ger&auml;t mit erweiterten Funktionen als Wecker hinzu, um darauf Weck-Automationen aufzubauen.
  2050. <ul>
  2051. Ein notify Ger&auml;t wird als Makro erstellt, um die eigentliche Automation auszuf&uuml;hren. Das Makro wird durch ein normales at-Ger&auml;t ausgel&ouml;st und kann ebenfalls angepasst werden. Die Hauptfunktion wird dabei trotzdem von einer speziellen RESIDENTS Toolkit funktion gehandhabt.<br>
  2052. Die Zeit aktiver Wecker kann mittels +<MINUTEN> oder -<MINUTEN> relativ erh&ouml;ht bzw. verringert werden. Die Angabe als +HH:MM ist auch m&ouml;glich.<br>
  2053. <br>
  2054. Die Weckfunktion kann wie folgt &uuml;ber Attribute beinflusst werden:<br>
  2055. <li>
  2056. <i>wakeupAtdevice</i> - Backlink zum at Ger&auml;t (notwendig)
  2057. </li>
  2058. <li>
  2059. <i>wakeupDays</i> - Makro nur an bestimmten Tagen ausl&ouml;sen. Mon=1,Di=2,Mi=3,Do=4,Fr=5,Sa=6,So=0 (optional)
  2060. </li>
  2061. <li>
  2062. <i>wakeupDefaultTime</i> - Stellt die Weckzeit nach dem ausl&ouml;sen zur&uuml;ck auf diesen Standardwert (optional)
  2063. </li>
  2064. <li>
  2065. <i>wakeupEnforced</i> - Forciertes wecken (optional; 0=nein, 1=ja, 2=wenn Weckzeit ungleich wakeupDefaultTime)
  2066. </li>
  2067. <li>
  2068. <i>wakeupHolidays</i> - Makro u.U. an Feiertagen oder Nicht-Feiertagen ausf&uuml;hren (optional; andHoliday=an Feiertagen ggf. zusammen mit wakeupDays, orHoliday=an Feiertagen unabh&auml;ngig von wakeupDays, andNoHoliday=an Nicht-Feiertagen ggf. zusammen mit wakeupDays, orNoHoliday=an Nicht-Feiertagen unabh&auml;ngig von wakeupDays)
  2069. </li>
  2070. <li>
  2071. <i>wakeupMacro</i> - Name des notify Makro Ger&auml;tes (notwendig)
  2072. </li>
  2073. <li>
  2074. <i>wakeupOffset</i> - Wert in Minuten, die das Makro fr&uuml;her ausgel&ouml;st werden soll, z.B. bei komplexen Weckprogrammen &uuml;ber einen Zeitraum von 30 Minuten (Standard ist 0)
  2075. </li>
  2076. <li>
  2077. <i>wakeupResetSwitcher</i> - das DUMMY Device, welches zum schnellen ein/aus schalten der Resetfunktion verwendet wird (optional, Device wird automatisch angelegt)
  2078. </li>
  2079. <li>
  2080. <i>wakeupResetdays</i> - sofern wakeupDefaultTime gesetzt ist, kann der Reset hier auf betimmte Tage begrenzt werden. Mon=1,Di=2,Mi=3,Do=4,Fr=5,Sa=6,So=0 (optional)
  2081. </li>
  2082. <li>
  2083. <i>wakeupUserdevice</i> - Backlink zum RESIDENTS, ROOMMATE oder GUEST Ger&auml;t, um dessen Status zu pr&uuml;fen (notwendig)
  2084. </li>
  2085. <li>
  2086. <i>wakeupWaitPeriod</i> - Schwelle der Wartezeit in Minuten bis das Weckprogramm erneut ausgef&uuml;hrt werden kann, z.B. wenn manuell eine fr&uuml;here Weckzeit gesetzt wurde als normal w&auml;hrend wakeupDefaultTime verwendet wird. Greift nicht, wenn die Weckzeit w&auml;hrend dieser Zeit ge&auml;ndert wurde; Standard ist 360 Minuten / 6h (optional)
  2087. </li>
  2088. </ul>
  2089. </li>
  2090. </ul>
  2091. </ul>
  2092. </ul>
  2093. =end html_DE
  2094. =cut