22_HOMEMODE.pm 174 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466
  1. #####################################################################################
  2. # $Id: 22_HOMEMODE.pm 15329 2017-10-27 18:12:35Z DeeSPe $
  3. #
  4. # Usage
  5. #
  6. # define <name> HOMEMODE [RESIDENTS-MASTER-DEVICE]
  7. #
  8. #####################################################################################
  9. package main;
  10. use strict;
  11. use warnings;
  12. use POSIX;
  13. use Time::HiRes qw(gettimeofday);
  14. use HttpUtils;
  15. use vars qw{%attr %defs %modules $FW_CSRF};
  16. my $HOMEMODE_version = "1.1.11";
  17. my $HOMEMODE_Daytimes = "05:00|morning 10:00|day 14:00|afternoon 18:00|evening 23:00|night";
  18. my $HOMEMODE_Seasons = "03.01|spring 06.01|summer 09.01|autumn 12.01|winter";
  19. my $HOMEMODE_UserModes = "gotosleep,awoken,asleep";
  20. my $HOMEMODE_UserModesAll = "$HOMEMODE_UserModes,home,absent,gone";
  21. my $HOMEMODE_AlarmModes = "disarm,armhome,armnight,armaway";
  22. my $HOMEMODE_Locations = "arrival,home,bed,underway,wayhome";
  23. my $HOMEMODE_de;
  24. sub HOMEMODE_Initialize($)
  25. {
  26. my ($hash) = @_;
  27. $hash->{AttrFn} = "HOMEMODE_Attr";
  28. $hash->{DefFn} = "HOMEMODE_Define";
  29. $hash->{NotifyFn} = "HOMEMODE_Notify";
  30. $hash->{GetFn} = "HOMEMODE_Get";
  31. $hash->{SetFn} = "HOMEMODE_Set";
  32. $hash->{UndefFn} = "HOMEMODE_Undef";
  33. $hash->{FW_detailFn} = "HOMEMODE_Details";
  34. $hash->{AttrList} = HOMEMODE_Attributes($hash);
  35. $hash->{NotifyOrderPrefix} = "51-";
  36. $hash->{FW_deviceOverview} = 1;
  37. $hash->{FW_addDetailToSummary} = 1;
  38. }
  39. sub HOMEMODE_Define($$)
  40. {
  41. my ($hash,$def) = @_;
  42. my @args = split " ",$def;
  43. my ($name,$type,$resdev) = @args;
  44. $HOMEMODE_de = (AttrVal("global","language","EN") eq "DE" || AttrVal($name,"HomeLanguage","EN") eq "DE") ? 1 : 0;
  45. my $trans;
  46. if (@args < 2 || @args > 3)
  47. {
  48. $trans = $HOMEMODE_de?
  49. "Benutzung: define <name> HOMEMODE [RESIDENTS-MASTER-GERAET]":
  50. "Usage: define <name> HOMEMODE [RESIDENTS-MASTER-DEVICE]";
  51. return $trans;
  52. }
  53. RemoveInternalTimer($hash);
  54. if (!$resdev)
  55. {
  56. my @resdevs;
  57. foreach (devspec2array("TYPE=RESIDENTS:FILTER=disable!=1"))
  58. {
  59. push @resdevs,$_;
  60. }
  61. if (@resdevs == 1)
  62. {
  63. $trans = $HOMEMODE_de?
  64. "$resdevs[0] existiert nicht":
  65. "$resdevs[0] doesn't exists";
  66. return $trans if (!IsDevice($resdevs[0]));
  67. $hash->{DEF} = $resdevs[0];
  68. }
  69. elsif (@resdevs > 1)
  70. {
  71. $trans = $HOMEMODE_de?
  72. "Es gibt zu viele RESIDENTS Geräte! Bitte das Master RESIDENTS Gerät angeben! Verfügbare RESIDENTS Geräte:":
  73. "Found too many available RESIDENTS devives! Please specify the RESIDENTS master device! Available RESIDENTS devices:";
  74. return "$trans ".join(",",@resdevs);
  75. }
  76. else
  77. {
  78. $trans = $HOMEMODE_de?
  79. "Kein RESIDENTS Gerät gefunden! Bitte erst ein RESIDENTS Gerät anlegen und ein paar ROOMMATE/GUEST und ihre korrespondierenden PRESENCE Geräte hinzufügen um Spaß mit diesem Modul zu haben!":
  80. "No RESIDENTS device found! Please define a RESIDENTS device first and add some ROOMMATE/GUEST and their PRESENCE device(s) to have fun with this module!";
  81. return $trans;
  82. }
  83. }
  84. $hash->{NOTIFYDEV} = "global";
  85. if ($init_done && !defined $hash->{OLDDEF})
  86. {
  87. $attr{$name}{devStateIcon} = "absent:user_away:dnd+on\n".
  88. "gone:user_ext_away:dnd+on\n".
  89. "dnd:audio_volume_mute:dnd+off\n".
  90. "gotosleep:scene_sleeping:dnd+on\n".
  91. "asleep:scene_sleeping_alternat:dnd+on\n".
  92. "awoken:weather_sunrise:dnd+on\n".
  93. "home:status_available:dnd+on\n".
  94. "morning:weather_sunrise:dnd+on\n".
  95. "day:weather_sun:dnd+on\n".
  96. "afternoon:weather_summer:dnd+on\n".
  97. "evening:weather_sunset:dnd+on\n".
  98. "night:weather_moon_phases_2:dnd+on";
  99. $attr{$name}{icon} = "floor";
  100. $attr{$name}{room} = "HOMEMODE";
  101. $attr{$name}{webCmd} = "modeAlarm";
  102. readingsBeginUpdate($hash);
  103. readingsBulkUpdate($hash,"dnd","off") if (!defined ReadingsVal($name,"dnd",undef));
  104. readingsBulkUpdate($hash,"anyoneElseAtHome","off") if (!defined ReadingsVal($name,"anyoneElseAtHome",undef));
  105. readingsEndUpdate($hash,0);
  106. HOMEMODE_updateInternals($hash);
  107. }
  108. return;
  109. }
  110. sub HOMEMODE_Undef($$)
  111. {
  112. my ($hash,$arg) = @_;
  113. RemoveInternalTimer($hash);
  114. my $name = $hash->{NAME};
  115. if (devspec2array("TYPE=HOMEMODE:FILTER=disable!=1") == 1)
  116. {
  117. HOMEMODE_cleanUserattr($hash,AttrVal($name,"HomeSensorsContact","")) if (AttrVal($name,"HomeSensorsContact",undef));
  118. HOMEMODE_cleanUserattr($hash,AttrVal($name,"HomeSensorsMotion","")) if (AttrVal($name,"HomeSensorsMotion",undef));
  119. }
  120. return;
  121. }
  122. sub HOMEMODE_Notify($$)
  123. {
  124. my ($hash,$dev) = @_;
  125. my $name = $hash->{NAME};
  126. return if (IsDisabled($name));
  127. my $devname = $dev->{NAME};
  128. my $devtype = $dev->{TYPE};
  129. my $events = deviceEvents($dev,1);
  130. return if (!$events);
  131. my $prestype = AttrVal($name,"HomePresenceDeviceType","PRESENCE");
  132. if ($devname eq "global")
  133. {
  134. if (grep /^INITIALIZED$/,@{$events})
  135. {
  136. HOMEMODE_updateInternals($hash);
  137. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,(AttrVal($name,"HomeCMDfhemINITIALIZED","")))) if (AttrVal($name,"HomeCMDfhemINITIALIZED",undef));
  138. }
  139. elsif (grep /^(REREADCFG|MODIFIED\s$name)$/,@{$events})
  140. {
  141. HOMEMODE_updateInternals($hash,1);
  142. }
  143. }
  144. return if ($devname eq "global");
  145. Log3 $name,5,"$name: Events from monitored device $devname: ". join " --- ",@{$events};
  146. my @commands;
  147. if ($devtype =~ /^(RESIDENTS|ROOMMATE|GUEST)$/)
  148. {
  149. $devtype eq "RESIDENTS" ? HOMEMODE_RESIDENTS($hash) : HOMEMODE_RESIDENTS($hash,$devname);
  150. }
  151. if ($hash->{SENSORSCONTACT} && grep(/^$devname$/,split /,/,$hash->{SENSORSCONTACT}))
  152. {
  153. my ($oread,$tread) = split " ",AttrVal($devname,"HomeReadings",AttrVal($name,"HomeSensorsContactReadings","state sabotageError"));
  154. HOMEMODE_TriggerState($hash,undef,undef,$devname) if (grep /^($oread|$tread):\s.*$/,@{$events});
  155. }
  156. if ($hash->{SENSORSMOTION} && grep(/^$devname$/,split /,/,$hash->{SENSORSMOTION}))
  157. {
  158. my ($oread,$tread) = split " ",AttrVal($devname,"HomeReadings",AttrVal($name,"HomeSensorsMotionReadings","state sabotageError"));
  159. HOMEMODE_TriggerState($hash,undef,undef,$devname) if (grep /^($oread|$tread):\s.*$/,@{$events});
  160. }
  161. if ($hash->{SENSORSLUMINANCE} && grep(/^$devname$/,split /,/,$hash->{SENSORSLUMINANCE}))
  162. {
  163. my $read = AttrVal($name,"HomeSensorsLuminanceReading","luminance");
  164. if (grep /^$read:\s.*$/,@{$events})
  165. {
  166. foreach my $evt (@{$events})
  167. {
  168. next unless ($evt =~ /^$read:\s(.*)$/);
  169. HOMEMODE_Luminance($hash,$devname,(split " ",$1)[0]);
  170. }
  171. }
  172. }
  173. if (AttrVal($name,"HomeYahooWeatherDevice",undef) && grep(/^$devname$/,split /,/,AttrVal($name,"HomeYahooWeatherDevice","")))
  174. {
  175. HOMEMODE_Weather($hash,$devname);
  176. }
  177. if (AttrVal($name,"HomeTwilightDevice",undef) && grep(/^$devname$/,split /,/,AttrVal($name,"HomeTwilightDevice","")))
  178. {
  179. HOMEMODE_Twilight($hash,$devname);
  180. }
  181. if (AttrVal($name,"HomeSensorTemperatureOutside",undef) && $devname eq AttrVal($name,"HomeSensorTemperatureOutside","") && grep /^(temperature|humidity):\s/,@{$events})
  182. {
  183. my $temp;
  184. my $humi;
  185. foreach my $evt (@{$events})
  186. {
  187. next unless ($evt =~ /^(humidity|temperature):\s(.*)$/);
  188. $temp = (split " ",$2)[0] if ($1 eq "temperature");
  189. $humi = (split " ",$2)[0] if ($1 eq "humidity");
  190. }
  191. readingsBeginUpdate($hash);
  192. readingsBulkUpdate($hash,"temperature",$temp);
  193. if (defined $humi && !AttrVal($name,"HomeSensorHumidityOutside",undef))
  194. {
  195. readingsBulkUpdate($hash,"humidity",$humi);
  196. $hash->{helper}{externalHumidity} = 1;
  197. }
  198. elsif (!AttrVal($name,"HomeSensorHumidityOutside",undef))
  199. {
  200. delete $hash->{helper}{externalHumidity};
  201. }
  202. readingsEndUpdate($hash,1);
  203. HOMEMODE_ReadingTrend($hash,"humidity",$humi) if (defined $humi);
  204. HOMEMODE_ReadingTrend($hash,"temperature",$temp);
  205. HOMEMODE_Icewarning($hash);
  206. }
  207. if (AttrVal($name,"HomeSensorHumidityOutside",undef) && $devname eq AttrVal($name,"HomeSensorHumidityOutside","") && grep /^humidity:\s/,@{$events})
  208. {
  209. $hash->{helper}{externalHumidity} = 1;
  210. foreach my $evt (@{$events})
  211. {
  212. next unless ($evt =~ /^humidity:\s(.*)$/);
  213. my $val = (split " ",$1)[0];
  214. readingsSingleUpdate($hash,"humidity",$val,1);
  215. HOMEMODE_ReadingTrend($hash,"humidity",$val);
  216. }
  217. }
  218. if (AttrVal($name,"HomeSensorWindspeed",undef) && $devname eq (split /:/,AttrVal($name,"HomeSensorWindspeed",""))[0])
  219. {
  220. my $read = (split /:/,AttrVal($name,"HomeSensorWindspeed",""))[1];
  221. if (grep /^$read:\s(.*)$/,@{$events})
  222. {
  223. foreach my $evt (@{$events})
  224. {
  225. next unless ($evt =~ /^$read:\s(.*)$/);
  226. my $val = (split " ",$1)[0];
  227. readingsSingleUpdate($hash,"wind",$val,1);
  228. HOMEMODE_ReadingTrend($hash,"wind",$val);
  229. }
  230. }
  231. }
  232. if (AttrVal($name,"HomeSensorAirpressure",undef) && $devname eq (split /:/,AttrVal($name,"HomeSensorAirpressure",""))[0])
  233. {
  234. my $read = (split /:/,AttrVal($name,"HomeSensorAirpressure",""))[1];
  235. if (grep /^$read:\s(.*)$/,@{$events})
  236. {
  237. foreach my $evt (@{$events})
  238. {
  239. next unless ($evt =~ /^$read:\s(.*)$/);
  240. my $val = (split " ",$1)[0];
  241. readingsSingleUpdate($hash,"pressure",$val,1);
  242. HOMEMODE_ReadingTrend($hash,"pressure",$val);
  243. }
  244. }
  245. }
  246. if ($hash->{SENSORSENERGY} && grep(/^$devname$/,split /,/,$hash->{SENSORSENERGY}))
  247. {
  248. my $read = AttrVal($name,"HomeSensorsPowerEnergyReadings","power energy");
  249. $read =~ s/ /\|/g;
  250. foreach my $evt (@{$events})
  251. {
  252. next unless ($evt =~ /^($read):\s(.*)$/);
  253. HOMEMODE_PowerEnergy($hash,$devname,$1,(split " ",$2)[0]);
  254. }
  255. }
  256. if (AttrVal($name,"HomeEventsHolidayDevices",undef) && grep(/^$devname$/,devspec2array(AttrVal($name,"HomeEventsHolidayDevices","").":FILTER=disable!=1")) && grep /^state:\s/,@{$events})
  257. {
  258. foreach my $evt (@{$events})
  259. {
  260. next unless ($evt =~ /^state:\s(.*)$/);
  261. HOMEMODE_EventCommands($hash,$devname,$1);
  262. }
  263. }
  264. if (AttrVal($name,"HomeUWZ",undef) && $devname eq AttrVal($name,"HomeUWZ","") && grep /^WarnCount:\s/,@{$events})
  265. {
  266. HOMEMODE_UWZCommands($hash,$events);
  267. }
  268. if ($hash->{SENSORSBATTERY} && grep(/^$devname$/,split /,/,$hash->{SENSORSBATTERY}))
  269. {
  270. my $read = AttrVal($name,"HomeSensorsBatteryReading","battery");
  271. if (grep /^$read:\s/,@{$events})
  272. {
  273. my @lowOld = split /,/,ReadingsVal($name,"batteryLow","");
  274. my @low;
  275. @low = @lowOld if (@lowOld);
  276. foreach my $evt (@{$events})
  277. {
  278. next unless ($evt =~ /^$read:\s(.*)$/);
  279. my $val = $1;
  280. if (($val =~ /^(\d{1,3})(%|\s%)?$/ && $1 <= AttrNum($name,"HomeSensorsBatteryLowPercentage",50)) || $val =~ /^(nok|low)$/)
  281. {
  282. push @low,$devname if (!grep /^$devname$/,@low);
  283. }
  284. elsif (grep /^$devname$/,@low)
  285. {
  286. my @lown;
  287. foreach (@low)
  288. {
  289. push @lown,$_ if ($_ ne $devname);
  290. }
  291. @low = @lown;
  292. }
  293. }
  294. readingsBeginUpdate($hash);
  295. if (@low)
  296. {
  297. readingsBulkUpdateIfChanged($hash,"batteryLow",join(",",@low));
  298. readingsBulkUpdateIfChanged($hash,"batteryLow_ct",scalar @low);
  299. readingsBulkUpdateIfChanged($hash,"batteryLow_hr",HOMEMODE_makeHR($hash,1,@low));
  300. readingsBulkUpdateIfChanged($hash,"lastBatteryLow",$devname) if (grep(/^$devname$/,@low) && !grep(/^$devname$/,@lowOld));
  301. push @commands,AttrVal($name,"HomeCMDbatteryLow","") if (AttrVal($name,"HomeCMDbatteryLow",undef) && grep(/^$devname$/,@low) && !grep(/^$devname$/,@lowOld));
  302. }
  303. else
  304. {
  305. readingsBulkUpdateIfChanged($hash,"batteryLow","");
  306. readingsBulkUpdateIfChanged($hash,"batteryLow_ct",scalar @low);
  307. readingsBulkUpdateIfChanged($hash,"batteryLow_hr","");
  308. }
  309. readingsEndUpdate($hash,1);
  310. }
  311. }
  312. if ($devtype =~ /^($prestype)$/ && grep(/^presence:\s(absent|present|appeared|disappeared)$/,@{$events}) && AttrNum($name,"HomeAutoPresence",0))
  313. {
  314. my $resident;
  315. my $residentregex;
  316. foreach (split /,/,$hash->{RESIDENTS})
  317. {
  318. my $regex = lc($_);
  319. $regex =~ s/^(rr_|rg_)//;
  320. next if (lc($devname) !~ /$regex/);
  321. $resident = $_;
  322. $residentregex = $regex;
  323. }
  324. return if (!$resident);
  325. $hash->{helper}{lar} = $resident;
  326. if (ReadingsVal($devname,"presence","") !~ /^maybe/)
  327. {
  328. my @presentdevicespresent;
  329. foreach my $device (devspec2array("TYPE=$prestype:FILTER=disable!=1:FILTER=presence=^(maybe.)?(absent|present|appeared|disappeared)"))
  330. {
  331. next if (lc($device) !~ /$residentregex/);
  332. push @presentdevicespresent,$device if (ReadingsVal($device,"presence","") =~ /^(present|appeared|maybe.absent)$/);
  333. }
  334. if (grep /^.*:\s(present|appeared)$/,@{$events})
  335. {
  336. readingsBeginUpdate($hash);
  337. readingsBulkUpdate($hash,"lastActivityByPresenceDevice",$devname);
  338. readingsBulkUpdate($hash,"lastPresentByPresenceDevice",$devname);
  339. readingsEndUpdate($hash,1);
  340. push @commands,AttrVal($name,"HomeCMDpresence-present-device","") if (AttrVal($name,"HomeCMDpresence-present-device",undef));
  341. push @commands,AttrVal($name,"HomeCMDpresence-present-$resident-device","") if (AttrVal($name,"HomeCMDpresence-present-$resident-device",undef));
  342. push @commands,AttrVal($name,"HomeCMDpresence-present-$resident-$devname","") if (AttrVal($name,"HomeCMDpresence-present-$resident-$devname",undef));
  343. if (@presentdevicespresent >= AttrNum($name,"HomePresenceDevicePresentCount-$resident",1)
  344. && ReadingsVal($resident,"state","") =~ /^(absent|[gn]one)$/)
  345. {
  346. CommandSet(undef,"$resident:FILTER=state!=home state home");
  347. }
  348. }
  349. elsif (grep /^.*:\s(absent|disappeared)$/,@{$events})
  350. {
  351. readingsBeginUpdate($hash);
  352. readingsBulkUpdate($hash,"lastActivityByPresenceDevice",$devname);
  353. readingsBulkUpdate($hash,"lastAbsentByPresenceDevice",$devname);
  354. readingsEndUpdate($hash,1);
  355. push @commands,AttrVal($name,"HomeCMDpresence-absent-device","") if (AttrVal($name,"HomeCMDpresence-absent-device",undef));
  356. push @commands,AttrVal($name,"HomeCMDpresence-absent-$resident-device","") if (AttrVal($name,"HomeCMDpresence-absent-$resident-device",undef));
  357. push @commands,AttrVal($name,"HomeCMDpresence-absent-$resident-$devname","") if (AttrVal($name,"HomeCMDpresence-absent-$resident-$devname",undef));
  358. my $devcount = 1;
  359. $devcount = @{$hash->{helper}{presdevs}{$resident}} if ($hash->{helper}{presdevs}{$resident});
  360. my $presdevsabsent = $devcount - scalar @presentdevicespresent;
  361. if ($presdevsabsent >= AttrNum($name,"HomePresenceDeviceAbsentCount-$resident",1)
  362. && ReadingsVal($resident,"state","absent") !~ /^(absent|gone|none)$/)
  363. {
  364. CommandSet(undef,"$resident:FILTER=state!=absent state absent");
  365. }
  366. }
  367. }
  368. }
  369. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  370. HOMEMODE_GetUpdate($hash) if (!$hash->{".TRIGGERTIME_NEXT"} || $hash->{".TRIGGERTIME_NEXT"} + 1 < gettimeofday());
  371. return;
  372. }
  373. sub HOMEMODE_updateInternals($;$)
  374. {
  375. my ($hash,$force) = @_;
  376. my $name = $hash->{NAME};
  377. my $resdev = $hash->{DEF};
  378. my $trans;
  379. if (!IsDevice($resdev))
  380. {
  381. $trans = $HOMEMODE_de?
  382. "$resdev ist nicht definiert!":
  383. "$resdev is not defined!";
  384. readingsSingleUpdate($hash,"state",$trans,0);
  385. }
  386. elsif (!IsDevice($resdev,"RESIDENTS"))
  387. {
  388. $trans = $HOMEMODE_de?
  389. "$resdev ist kein gültiges RESIDENTS Gerät!":
  390. "$resdev is not a valid RESIDENTS device!";
  391. readingsSingleUpdate($hash,"state",$trans,0);
  392. }
  393. else
  394. {
  395. my @oldMonitoredDevices = split /,/,$hash->{NOTIFYDEV};
  396. delete $hash->{helper}{presdevs};
  397. delete $hash->{RESIDENTS};
  398. delete $hash->{SENSORSCONTACT};
  399. delete $hash->{SENSORSMOTION};
  400. delete $hash->{SENSORSENERGY};
  401. delete $hash->{SENSORSLUMINANCE};
  402. delete $hash->{SENSORSBATTERY};
  403. $hash->{VERSION} = $HOMEMODE_version;
  404. my @residents;
  405. push @residents,$defs{$resdev}->{ROOMMATES} if ($defs{$resdev}->{ROOMMATES});
  406. push @residents,$defs{$resdev}->{GUESTS} if ($defs{$resdev}->{GUESTS});
  407. if (@residents < 1)
  408. {
  409. $trans = $HOMEMODE_de?
  410. "Keine verfügbaren ROOMMATE/GUEST im RESIDENTS Gerät $resdev":
  411. "No available ROOMMATE/GUEST in RESIDENTS device $resdev";
  412. Log3 $name,2,$trans;
  413. readingsSingleUpdate($hash,"HomeInfo",$trans,1);
  414. return;
  415. }
  416. else
  417. {
  418. $hash->{RESIDENTS} = join(",",@residents);
  419. }
  420. my @allMonitoredDevices;
  421. push @allMonitoredDevices,"global";
  422. push @allMonitoredDevices,$resdev;
  423. my $autopresence = HOMEMODE_AttrCheck($hash,"HomeAutoPresence",0);
  424. my $presencetype = HOMEMODE_AttrCheck($hash,"HomePresenceDeviceType","PRESENCE");
  425. my @presdevs = devspec2array("TYPE=$presencetype:FILTER=disable!=1:FILTER=presence=^(maybe.)?(absent|present|appeared|disappeared)");
  426. my @residentsshort;
  427. my @logtexte;
  428. foreach my $resident (split /,/,$hash->{RESIDENTS})
  429. {
  430. push @allMonitoredDevices,$resident;
  431. my $short = lc($resident);
  432. $short =~ s/^(rr_|rg_)//;
  433. push @residentsshort,$short;
  434. if ($autopresence)
  435. {
  436. my @residentspresdevs;
  437. foreach my $p (@presdevs)
  438. {
  439. next if (lc($p) !~ /($short)/);
  440. push @residentspresdevs,$p;
  441. push @allMonitoredDevices,$p if (!grep /^($p)$/,@allMonitoredDevices);
  442. }
  443. my $c = scalar @residentspresdevs;
  444. if ($c)
  445. {
  446. my $devlist = join(",",@residentspresdevs);
  447. $trans = $HOMEMODE_de?
  448. "Gefunden wurden $c übereinstimmende(s) Anwesenheits Gerät(e) vom Devspec \"TYPE=$presencetype\" für Bewohner \"$resident\"! Übereinstimmende Geräte: \"$devlist\"":
  449. "Found $c matching presence devices of devspec \"TYPE=$presencetype\" for resident \"$resident\"! Matching devices: \"$devlist\"";
  450. push @logtexte,$trans;
  451. $attr{$name}{"HomePresenceDeviceAbsentCount-$resident"} = $c if ($init_done && ((!defined AttrNum($name,"HomePresenceDeviceAbsentCount-$resident",undef) && $c > 1) || (defined AttrNum($name,"HomePresenceDeviceAbsentCount-$resident",undef) && $c < AttrNum($name,"HomePresenceDeviceAbsentCount-$resident",1))));
  452. }
  453. else
  454. {
  455. $trans = $HOMEMODE_de?
  456. "Keine Geräte mit presence Reading gefunden vom Devspec \"TYPE=$presencetype\" für Bewohner \"$resident\"!":
  457. "No devices with presence reading found of devspec \"TYPE=$presencetype\" for resident \"$resident\"!";
  458. push @logtexte,$trans;
  459. }
  460. $hash->{helper}{presdevs}{$resident} = \@residentspresdevs if (@residentspresdevs > 1);
  461. }
  462. }
  463. if (@logtexte && $force)
  464. {
  465. $trans = $HOMEMODE_de?
  466. "Falls ein oder mehr Anweseheits Geräte falsch zugeordnet wurden, so benenne diese bitte so um dass die Bewohner Namen (".join(",",@residentsshort).") nicht Bestandteil des Namen sind.\nNach dem Umbenennen führe einfach \"set $name updateInternalsForce\" aus um diese Überprüfung zu wiederholen.":
  467. "If any recognized presence device is wrong, please rename this device so that it will NOT match the residents names (".join(",",@residentsshort).") somewhere in the device name.\nAfter renaming simply execute \"set $name updateInternalsForce\" to redo this check.";
  468. push @logtexte,"\n$trans";
  469. my $log = join("\n",@logtexte);
  470. Log3 $name,3,"$name: $log";
  471. $log =~ s/\n/<br>/gm;
  472. readingsSingleUpdate($hash,"HomeInfo","<html>$log</html>",1);
  473. }
  474. my $contacts = HOMEMODE_AttrCheck($hash,"HomeSensorsContact");
  475. if ($contacts)
  476. {
  477. my @sensors;
  478. foreach my $s (devspec2array("$contacts:FILTER=disable!=1"))
  479. {
  480. push @sensors,$s;
  481. push @allMonitoredDevices,$s if (!grep /^$s$/,@allMonitoredDevices);
  482. }
  483. $hash->{SENSORSCONTACT} = join(",",sort @sensors) if (@sensors);
  484. }
  485. my $motion = HOMEMODE_AttrCheck($hash,"HomeSensorsMotion");
  486. if ($motion)
  487. {
  488. my @sensors;
  489. foreach my $s (devspec2array("$motion:FILTER=disable!=1"))
  490. {
  491. push @sensors,$s;
  492. push @allMonitoredDevices,$s if (!grep /^$s$/,@allMonitoredDevices);
  493. }
  494. $hash->{SENSORSMOTION} = join(",",sort @sensors) if (@sensors);
  495. }
  496. my $power = HOMEMODE_AttrCheck($hash,"HomeSensorsPowerEnergy");
  497. if ($power)
  498. {
  499. my @sensors;
  500. my ($p,$e) = split " ",AttrVal($name,"HomeSensorsPowerEnergyReadings","power energy");
  501. foreach my $s (devspec2array("$power:FILTER=disable!=1"))
  502. {
  503. next unless (defined ReadingsVal($s,$p,undef) && defined ReadingsVal($s,$e,undef));
  504. push @sensors,$s;
  505. push @allMonitoredDevices,$s if (!grep /^$s$/,@allMonitoredDevices);
  506. }
  507. $hash->{SENSORSENERGY} = join(",",sort @sensors) if (@sensors);
  508. }
  509. my $battery = HOMEMODE_AttrCheck($hash,"HomeSensorsBattery");
  510. if ($battery)
  511. {
  512. my @sensors;
  513. foreach my $s (devspec2array("$battery:FILTER=disable!=1"))
  514. {
  515. my $read = AttrVal($name,"HomeSensorsBatteryReading","battery");
  516. my $val = ReadingsVal($s,$read,undef);
  517. next unless (defined $val && $val =~ /^(ok|low|nok|\d{1,3})(%|\s%)?$/);
  518. push @sensors,$s;
  519. push @allMonitoredDevices,$s if (!grep /^$s$/,@allMonitoredDevices);
  520. }
  521. $hash->{SENSORSBATTERY} = join(",",sort @sensors) if (@sensors);
  522. }
  523. my $weather = HOMEMODE_AttrCheck($hash,"HomeYahooWeatherDevice");
  524. push @allMonitoredDevices,$weather if ($weather && !grep /^$weather$/,@allMonitoredDevices);
  525. my $twilight = HOMEMODE_AttrCheck($hash,"HomeTwilightDevice");
  526. push @allMonitoredDevices,$twilight if ($twilight && !grep /^$twilight$/,@allMonitoredDevices);
  527. my $temperature = HOMEMODE_AttrCheck($hash,"HomeSensorTemperatureOutside");
  528. push @allMonitoredDevices,$temperature if ($temperature && !grep /^$temperature$/,@allMonitoredDevices);
  529. my $humidity = HOMEMODE_AttrCheck($hash,"HomeSensorHumidityOutside");
  530. if ($humidity && $temperature ne $humidity)
  531. {
  532. push @allMonitoredDevices,$humidity if (!grep /^$humidity$/,@allMonitoredDevices);
  533. }
  534. my $holiday = HOMEMODE_AttrCheck($hash,"HomeEventsHolidayDevices");
  535. if ($holiday)
  536. {
  537. foreach my $c (devspec2array("$holiday:FILTER=disable!=1"))
  538. {
  539. push @allMonitoredDevices,$c if (!grep /^$c$/,@allMonitoredDevices);
  540. }
  541. }
  542. my $uwz = HOMEMODE_AttrCheck($hash,"HomeUWZ","");
  543. push @allMonitoredDevices,$uwz if ($uwz && !grep /^$uwz$/,@allMonitoredDevices);
  544. my $luminance = HOMEMODE_AttrCheck($hash,"HomeSensorsLuminance");
  545. if ($luminance)
  546. {
  547. my $read = AttrVal($name,"HomeSensorsLuminanceReading","luminance");
  548. my @sensors;
  549. foreach my $s (devspec2array("$luminance:FILTER=disable!=1"))
  550. {
  551. if (defined ReadingsVal($s,AttrVal($name,"HomeSensorsLuminanceReading","luminance"),undef))
  552. {
  553. push @sensors,$s;
  554. push @allMonitoredDevices,$s if (!grep /^$s$/,@allMonitoredDevices);
  555. }
  556. }
  557. $hash->{SENSORSLUMINANCE} = join(",",sort @sensors) if (@sensors);
  558. }
  559. push @allMonitoredDevices,(split /:/,HOMEMODE_AttrCheck($hash,"HomeSensorAirpressure"))[0] if (HOMEMODE_AttrCheck($hash,"HomeSensorAirpressure"));
  560. push @allMonitoredDevices,(split /:/,HOMEMODE_AttrCheck($hash,"HomeSensorWindspeed"))[0] if (HOMEMODE_AttrCheck($hash,"HomeSensorWindspeed"));
  561. Log3 $name,5,"$name: new monitored device count: ".@allMonitoredDevices;
  562. Log3 $name,5,"$name: old monitored device count: ".@oldMonitoredDevices;
  563. @allMonitoredDevices = sort @allMonitoredDevices;
  564. $hash->{NOTIFYDEV} = join(",",@allMonitoredDevices);
  565. HOMEMODE_GetUpdate($hash);
  566. return if (!@allMonitoredDevices);
  567. HOMEMODE_RESIDENTS($hash);
  568. HOMEMODE_userattr($hash);
  569. HOMEMODE_TriggerState($hash) if ($hash->{SENSORSCONTACT} || $hash->{SENSORSMOTION});
  570. HOMEMODE_Luminance($hash) if ($hash->{SENSORSLUMINANCE});
  571. HOMEMODE_PowerEnergy($hash) if ($hash->{SENSORSENERGY});
  572. HOMEMODE_Weather($hash,$weather) if ($weather);
  573. HOMEMODE_Twilight($hash,$twilight,1) if ($twilight);
  574. }
  575. return;
  576. }
  577. sub HOMEMODE_GetUpdate(@)
  578. {
  579. my ($hash) = @_;
  580. my $name = $hash->{NAME};
  581. RemoveInternalTimer($hash,"HOMEMODE_GetUpdate");
  582. return if (AttrNum($name,"disable",0));
  583. my $mode = HOMEMODE_DayTime($hash);
  584. HOMEMODE_SetDaytime($hash);
  585. HOMEMODE_SetSeason($hash);
  586. CommandSet(undef,"$name:FILTER=mode!=$mode mode $mode") if (ReadingsVal($hash->{DEF},"state","") eq "home" && AttrNum($name,"HomeAutoDaytime",1));
  587. HOMEMODE_checkIP($hash) if ((AttrNum($name,"HomePublicIpCheckInterval",0) && !$hash->{".IP_TRIGGERTIME_NEXT"}) || (AttrNum($name,"HomePublicIpCheckInterval",0) && $hash->{".IP_TRIGGERTIME_NEXT"} && $hash->{".IP_TRIGGERTIME_NEXT"} < gettimeofday()));
  588. my $timer = gettimeofday() + 5;
  589. $hash->{".TRIGGERTIME_NEXT"} = $timer;
  590. InternalTimer($timer,"HOMEMODE_GetUpdate",$hash);
  591. return;
  592. }
  593. sub HOMEMODE_Get($@)
  594. {
  595. my ($hash,$name,@aa) = @_;
  596. my ($cmd,@args) = @aa;
  597. my $params;
  598. $params .= "contactsOpen:all,doorsinside,doorsoutside,doorsmain,outside,windows" if ($hash->{SENSORSCONTACT});
  599. $params .= " " if ($params);
  600. $params .= "sensorsTampered:noArg" if ($hash->{SENSORSCONTACT} || $hash->{SENSORSMOTION});
  601. $params .= " " if ($params);
  602. $params .= "publicIP:noArg";
  603. my $trans;
  604. if (AttrVal($name,"HomeYahooWeatherDevice",undef))
  605. {
  606. $params .= " " if ($params);
  607. $params .= "weather:" if (AttrVal($name,"HomeTextWeatherLong",undef) || AttrVal($name,"HomeTextWeatherShort",undef));
  608. $params .= "long" if (AttrVal($name,"HomeTextWeatherLong",undef));
  609. if (AttrVal($name,"HomeTextWeatherShort",undef))
  610. {
  611. $params .= ",";
  612. $params .= "short";
  613. }
  614. $params .= " " if ($params);
  615. $params .= "weatherForecast";
  616. }
  617. return if (!$params);
  618. my $value = $args[0];
  619. if ($cmd =~ /^contactsOpen$/)
  620. {
  621. $trans = $HOMEMODE_de?
  622. "$cmd benötigt ein Argument":
  623. "$cmd needs one argument!";
  624. return $trans if (!$value);
  625. HOMEMODE_TriggerState($hash,$cmd,$value);
  626. }
  627. elsif ($cmd =~ /^sensorsTampered$/)
  628. {
  629. $trans = $HOMEMODE_de?
  630. "$cmd benötigt kein Argument":
  631. "$cmd needs no argument!";
  632. return $trans if ($value);
  633. HOMEMODE_TriggerState($hash,$cmd);
  634. }
  635. elsif ($cmd eq "weather")
  636. {
  637. $trans = $HOMEMODE_de?
  638. "$cmd benötigt ein Argument, entweder long oder short!":
  639. "$cmd needs one argument of long or short!";
  640. return $trans if (!$value || $value !~ /^(long|short)$/);
  641. my $m = "Long";
  642. $m = "Short" if ($value eq "short");
  643. HOMEMODE_WeatherTXT($hash,AttrVal($name,"HomeTextWeather$m",""));
  644. }
  645. elsif ($cmd eq "weatherForecast")
  646. {
  647. $trans = $HOMEMODE_de?
  648. "Der Wert für $cmd muss zwischen 1 und 10 sein. Falls der Wert weggelassen wird, so wird 2 (für morgen) benutzt.":
  649. "Value for $cmd must be from 1 to 10. If omitted the value will be 2 for tomorrow.";
  650. return $trans if ($value && $value !~ /^[1-9]0?$/ && ($value < 1 || $value > 10));
  651. HOMEMODE_ForecastTXT($hash,$value);
  652. }
  653. elsif ($cmd eq "publicIP")
  654. {
  655. return HOMEMODE_checkIP($hash,1);
  656. }
  657. else
  658. {
  659. return "Unknown argument $cmd for $name, choose one of $params";
  660. }
  661. }
  662. sub HOMEMODE_Set($@)
  663. {
  664. my ($hash,$name,@aa) = @_;
  665. $HOMEMODE_de = (AttrVal("global","language","EN") eq "DE" || AttrVal($name,"HomeLanguage","EN") eq "DE") ? 1 : 0;
  666. my ($cmd,@args) = @aa;
  667. my $trans = $HOMEMODE_de?
  668. "\"set $name\" benötigt mindestens ein und maximal drei Argumente":
  669. "\"set $name\" needs at least one argument and maximum three arguments";
  670. return $trans if (@aa > 3);
  671. my $option = defined $args[0] ? $args[0] : undef;
  672. my $value = defined $args[1] ? $args[1] : undef;
  673. my $mode = ReadingsVal($name,"mode","");
  674. my $amode = ReadingsVal($name,"modeAlarm","");
  675. my $plocation = ReadingsVal($name,"location","");
  676. my $presence = ReadingsVal($name,"presence","");
  677. my @locations = split /,/,$HOMEMODE_Locations;
  678. my $slocations = HOMEMODE_AttrCheck($hash,"HomeSpecialLocations");
  679. if ($slocations)
  680. {
  681. foreach (split /,/,$slocations)
  682. {
  683. push @locations,$_;
  684. }
  685. }
  686. my @modeparams = split /,/,$HOMEMODE_UserModesAll;
  687. my $smodes = HOMEMODE_AttrCheck($hash,"HomeSpecialModes");
  688. if ($smodes)
  689. {
  690. foreach (split /,/,$smodes)
  691. {
  692. push @modeparams,$_;
  693. }
  694. }
  695. my $para;
  696. $para .= "mode:".join(",",sort @modeparams)." " if (!AttrNum($name,"HomeAutoDaytime",1));
  697. $para .= "modeAlarm:$HOMEMODE_AlarmModes";
  698. $para .= " modeAlarm-for-minutes";
  699. $para .= " dnd:on,off";
  700. $para .= " dnd-for-minutes";
  701. $para .= " anyoneElseAtHome:off,on";
  702. $para .= " location:".join(",", sort @locations);
  703. $para .= " updateInternalsForce:noArg";
  704. $para .= " updateHomebridgeMapping:noArg";
  705. return "$cmd is not a valid command for $name, please choose one of $para" if (!$cmd || $cmd eq "?");
  706. my @commands;
  707. if ($cmd eq "mode")
  708. {
  709. my $namode = "disarm";
  710. my $present = "absent";
  711. my $location = "underway";
  712. $option = HOMEMODE_DayTime($hash) if ($option && $option eq "home" && AttrNum($name,"HomeAutoDaytime",1));
  713. if ($option !~ /^(absent|gone)$/)
  714. {
  715. push @commands,AttrVal($name,"HomeCMDpresence-present","") if (AttrVal($name,"HomeCMDpresence-present",undef) && $mode =~ /^(absent|gone)$/);
  716. $present = "present";
  717. $location = grep(/^$plocation$/,split /,/,$slocations) ? $plocation : "home";
  718. if ($presence eq "absent")
  719. {
  720. if (AttrNum($name,"HomeAutoArrival",0))
  721. {
  722. my $hour = HOMEMODE_hourMaker(AttrNum($name,"HomeAutoArrival",0));
  723. CommandDelete(undef,"atTmp_set_home_$name") if (IsDevice("atTmp_set_home_$name"));
  724. CommandDefine(undef,"atTmp_set_home_$name at +$hour set $name:FILTER=location=arrival location home");
  725. $location = "arrival";
  726. }
  727. }
  728. if ($option eq "asleep")
  729. {
  730. $namode = "armnight";
  731. $location = "bed";
  732. }
  733. }
  734. elsif ($option =~ /^(absent|gone)$/)
  735. {
  736. push @commands,AttrVal($name,"HomeCMDpresence-absent","") if (AttrVal($name,"HomeCMDpresence-absent",undef) && $mode !~ /^(absent|gone)$/);
  737. $namode = ReadingsVal($name,"anyoneElseAtHome","off") eq "off" ? "armaway" : "armhome";
  738. if (AttrNum($name,"HomeModeAbsentBelatedTime",0) && AttrVal($name,"HomeCMDmode-absent-belated",undef))
  739. {
  740. my $hour = HOMEMODE_hourMaker(AttrNum($name,"HomeModeAbsentBelatedTime",0));
  741. CommandDelete(undef,"atTmp_absent_belated_$name") if (IsDevice("atTmp_absent_belated_$name"));
  742. CommandDefine(undef,"atTmp_absent_belated_$name at +$hour {HOMEMODE_execCMDs_belated(\"$name\",\"HomeCMDmode-absent-belated\",\"$option\")}");
  743. }
  744. }
  745. HOMEMODE_ContactOpenCheckAfterModeChange($hash,$option,$mode) if ($hash->{SENSORSCONTACT} && $option && $mode ne $option);
  746. push @commands,AttrVal($name,"HomeCMDmode","") if ($mode && AttrVal($name,"HomeCMDmode",undef));
  747. push @commands,AttrVal($name,"HomeCMDmode-$option","") if (AttrVal($name,"HomeCMDmode-$option",undef));
  748. CommandSetReading(undef,"$name:FILTER=presence!=$present presence $present");
  749. CommandSet(undef,"$name:FILTER=location!=$location location $location");
  750. if (AttrNum($name,"HomeAutoAlarmModes",1))
  751. {
  752. CommandDelete(undef,"atTmp_modeAlarm_delayed_arm_$name") if (IsDevice("atTmp_modeAlarm_delayed_arm_$name"));
  753. CommandSet(undef,"$name:FILTER=modeAlarm!=$namode modeAlarm $namode");
  754. }
  755. readingsBeginUpdate($hash);
  756. readingsBulkUpdate($hash,$cmd,$option);
  757. readingsBulkUpdate($hash,"prevMode",$mode);
  758. readingsBulkUpdate($hash,"state",$option);
  759. readingsEndUpdate($hash,1);
  760. }
  761. elsif ($cmd eq "modeAlarm-for-minutes")
  762. {
  763. $trans = $HOMEMODE_de?
  764. "$cmd benötigt zwei Parameter: einen modeAlarm und die Minuten":
  765. "$cmd needs two paramters: a modeAlarm and minutes";
  766. return $trans if (!$option || !$value);
  767. my $timer = $name."_alarmMode_for_timer_$option";
  768. my $time = HOMEMODE_hourMaker($value);
  769. CommandDelete(undef,$timer) if (IsDevice($timer));
  770. CommandDefine(undef,"$timer at +$time set $name:FILTER=modeAlarm!=$amode modeAlarm $amode");
  771. CommandSet(undef,"$name:FILTER=modeAlarm!=$option modeAlarm $option");
  772. }
  773. elsif ($cmd eq "dnd-for-minutes")
  774. {
  775. $trans = $HOMEMODE_de?
  776. "$cmd benötigt einen Paramter: Minuten":
  777. "$cmd needs one paramter: minutes";
  778. return $trans if (!$option);
  779. $trans = $HOMEMODE_de?
  780. "$name darf nicht im dnd Modus sein um diesen Modus für bestimmte Minuten zu setzen! Bitte deaktiviere den dnd Modus zuerst!":
  781. "$name can't be in dnd mode to turn dnd on for minutes! Please disable dnd mode first!";
  782. return $trans if (ReadingsVal($name,"dnd","off") eq "on");
  783. my $timer = $name."_dnd_for_timer";
  784. my $time = HOMEMODE_hourMaker($option);
  785. CommandDelete(undef,$timer) if (IsDevice($timer));
  786. CommandDefine(undef,"$timer at +$time set $name:FILTER=dnd!=off dnd off");
  787. CommandSet(undef,"$name:FILTER=dnd!=on dnd on");
  788. }
  789. elsif ($cmd eq "dnd")
  790. {
  791. push @commands,AttrVal($name,"HomeCMDdnd-$option","") if (AttrVal($name,"HomeCMDdnd-$option",undef));
  792. readingsBeginUpdate($hash);
  793. readingsBulkUpdate($hash,$cmd,$option);
  794. readingsBulkUpdate($hash,"state","dnd") if ($option eq "on");
  795. readingsBulkUpdate($hash,"state",$mode) if ($option ne "on");
  796. readingsEndUpdate($hash,1);
  797. }
  798. elsif ($cmd eq "location")
  799. {
  800. push @commands,AttrVal($name,"HomeCMDlocation","") if (AttrVal($name,"HomeCMDlocation",undef));
  801. push @commands,AttrVal($name,"HomeCMDlocation-$option","") if (AttrVal($name,"HomeCMDlocation-$option",undef));
  802. readingsBeginUpdate($hash);
  803. readingsBulkUpdate($hash,"prevLocation",$plocation);
  804. readingsBulkUpdate($hash,$cmd,$option);
  805. readingsEndUpdate($hash,1);
  806. }
  807. elsif ($cmd eq "modeAlarm")
  808. {
  809. CommandDelete(undef,"atTmp_modeAlarm_delayed_arm_$name") if (IsDevice("atTmp_modeAlarm_delayed_arm_$name"));
  810. my $delay;
  811. if ($option =~ /^arm/ && AttrVal($name,"HomeModeAlarmArmDelay",0))
  812. {
  813. my @delays = split " ",AttrVal($name,"HomeModeAlarmArmDelay",0);
  814. if (defined $delays[1])
  815. {
  816. $delay = $delays[0] if ($option eq "armaway");
  817. $delay = $delays[1] if ($option eq "armnight");
  818. $delay = $delays[2] if ($option eq "armhome");
  819. }
  820. else
  821. {
  822. $delay = $delays[0];
  823. }
  824. }
  825. if ($delay)
  826. {
  827. my $hours = HOMEMODE_hourMaker(sprintf("%.2f",$delay / 60));
  828. CommandDefine(undef,"atTmp_modeAlarm_delayed_arm_$name at +$hours {HOMEMODE_set_modeAlarm(\"$name\",\"$option\",\"$amode\")}");
  829. }
  830. else
  831. {
  832. HOMEMODE_set_modeAlarm($name,$option,$amode);
  833. }
  834. }
  835. elsif ($cmd eq "anyoneElseAtHome")
  836. {
  837. $trans = $HOMEMODE_de?
  838. "Zulässige Werte für $cmd sind nur on oder off!":
  839. "Values for $cmd can only be on or off!";
  840. return $trans if ($option !~ /^(on|off)$/);
  841. push @commands,AttrVal($name,"HomeCMDanyoneElseAtHome-$option","") if (AttrVal($name,"HomeCMDanyoneElseAtHome-$option",undef));
  842. if (AttrNum($name,"HomeAutoAlarmModes",1))
  843. {
  844. CommandSet(undef,"$name:FILTER=modeAlarm=armaway modeAlarm armhome") if ($option eq "on");
  845. CommandSet(undef,"$name:FILTER=modeAlarm=armhome modeAlarm armaway") if ($option eq "off");
  846. }
  847. readingsSingleUpdate($hash,"anyoneElseAtHome",$option,1);
  848. }
  849. elsif ($cmd eq "updateInternalsForce")
  850. {
  851. HOMEMODE_updateInternals($hash,1);
  852. }
  853. elsif ($cmd eq "updateHomebridgeMapping")
  854. {
  855. HOMEMODE_HomebridgeMapping($hash);
  856. }
  857. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  858. return;
  859. }
  860. sub HOMEMODE_set_modeAlarm($$$)
  861. {
  862. my ($name,$option,$amode) = @_;
  863. my $hash = $defs{$name};
  864. my $resident = $hash->{helper}{lar} ? $hash->{helper}{lar} : ReadingsVal($name,"lastActivityByResident","");
  865. delete $hash->{helper}{lar} if ($hash->{helper}{lar});
  866. my @commands;
  867. push @commands,AttrVal($name,"HomeCMDmodeAlarm","") if (AttrVal($name,"HomeCMDmodeAlarm",undef));
  868. push @commands,AttrVal($name,"HomeCMDmodeAlarm-$option","") if (AttrVal($name,"HomeCMDmodeAlarm-$option",undef));
  869. readingsBeginUpdate($hash);
  870. readingsBulkUpdate($hash,"prevModeAlarm",$amode);
  871. readingsBulkUpdate($hash,"modeAlarm",$option);
  872. readingsBulkUpdateIfChanged($hash,"alarmState",$option);
  873. readingsEndUpdate($hash,1);
  874. HOMEMODE_TriggerState($hash) if ($hash->{SENSORSCONTACT} || $hash->{SENSORSMOTION});
  875. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands),$resident) if (@commands);
  876. }
  877. sub HOMEMODE_execCMDs_belated($$$)
  878. {
  879. my ($name,$attrib,$option) = @_;
  880. return if (!AttrVal($name,$attrib,undef) || ReadingsVal($name,"mode","") ne $option);
  881. my $hash = $defs{$name};
  882. my @commands;
  883. push @commands,AttrVal($name,$attrib,"");
  884. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  885. }
  886. sub HOMEMODE_alarmTriggered($@)
  887. {
  888. my ($hash,@triggers) = @_;
  889. my $name = $hash->{NAME};
  890. my @commands;
  891. my $text = HOMEMODE_makeHR($hash,0,@triggers);
  892. readingsBeginUpdate($hash);
  893. readingsBulkUpdateIfChanged($hash,"alarmTriggered_ct",scalar @triggers);
  894. if ($text)
  895. {
  896. push @commands,AttrVal($name,"HomeCMDalarmTriggered-on","") if (AttrVal($name,"HomeCMDalarmTriggered-on",undef));
  897. readingsBulkUpdateIfChanged($hash,"alarmTriggered",join ",",@triggers);
  898. readingsBulkUpdateIfChanged($hash,"alarmTriggered_hr",$text);
  899. readingsBulkUpdateIfChanged($hash,"alarmState","alarm");
  900. }
  901. else
  902. {
  903. push @commands,AttrVal($name,"HomeCMDalarmTriggered-off","") if (AttrVal($name,"HomeCMDalarmTriggered-off",undef) && ReadingsVal($name,"alarmTriggered",""));
  904. readingsBulkUpdateIfChanged($hash,"alarmTriggered","");
  905. readingsBulkUpdateIfChanged($hash,"alarmTriggered_hr","");
  906. readingsBulkUpdateIfChanged($hash,"alarmState",ReadingsVal($name,"modeAlarm","disarm"));
  907. }
  908. readingsEndUpdate($hash,1);
  909. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands && ReadingsAge($name,"modeAlarm","") > 5);
  910. }
  911. sub HOMEMODE_makeHR($$@)
  912. {
  913. my ($hash,$noart,@names) = @_;
  914. my $name = $hash->{NAME};
  915. my @aliases;
  916. my $and = (split /\|/,AttrVal($name,"HomeTextAndAreIs","and|are|is"))[0];
  917. my $text;
  918. foreach (@names)
  919. {
  920. my $alias = $noart ? HOMEMODE_name2alias($_) : HOMEMODE_name2alias($_,1);
  921. push @aliases,$alias;
  922. }
  923. if (@aliases > 0)
  924. {
  925. my $alias = $aliases[0];
  926. $alias =~ s/^d/D/;
  927. $text = $alias;
  928. if (@aliases > 1)
  929. {
  930. for (my $i = 1; $i < @aliases; $i++)
  931. {
  932. $text .= " $and " if ($i == @aliases - 1);
  933. $text .= ", " if ($i < @aliases - 1);
  934. $text .= $aliases[$i];
  935. }
  936. }
  937. }
  938. $text = $text ? $text : "";
  939. return $text;
  940. }
  941. sub HOMEMODE_alarmTampered($@)
  942. {
  943. my ($hash,@triggers) = @_;
  944. my $name = $hash->{NAME};
  945. my @commands;
  946. my $text = HOMEMODE_makeHR($hash,0,@triggers);
  947. if ($text)
  948. {
  949. push @commands,AttrVal($name,"HomeCMDalarmTampered-on","") if (AttrVal($name,"HomeCMDalarmTampered-on",undef));
  950. }
  951. else
  952. {
  953. push @commands,AttrVal($name,"HomeCMDalarmTampered-off","") if (AttrVal($name,"HomeCMDalarmTampered-off",undef));
  954. }
  955. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  956. }
  957. sub HOMEMODE_RESIDENTS($;$)
  958. {
  959. my ($hash,$dev) = @_;
  960. $dev = $hash->{DEF} if (!$dev);
  961. my $name = $hash->{NAME};
  962. my $events = deviceEvents($defs{$dev},1);
  963. my $devtype = $defs{$dev}->{TYPE};
  964. my $alias = AttrVal($dev,"alias",$dev);
  965. my $lad = ReadingsVal($name,"lastActivityByResident","");
  966. my $mode;
  967. my @commands;
  968. foreach (split /,/,"$HOMEMODE_UserModesAll,home")
  969. {
  970. next if (!grep /^$_$/,@{$events});
  971. $mode = $_;
  972. }
  973. if ($devtype eq "RESIDENTS")
  974. {
  975. $mode = ReadingsVal($dev,"state","");
  976. $mode = $mode eq "home" && AttrNum($name,"HomeAutoDaytime",1) ? HOMEMODE_DayTime($hash) : $mode;
  977. CommandSet(undef,"$name:FILTER=mode!=$mode mode $mode");
  978. return;
  979. }
  980. if ($devtype =~ /^(ROOMMATE|GUEST)$/)
  981. {
  982. my $usermode;
  983. my $HOMEMODE_UserModesAll_Regex = $HOMEMODE_UserModesAll;
  984. $HOMEMODE_UserModesAll_Regex =~ s/,/|/g;
  985. if (grep /^state:\s($HOMEMODE_UserModesAll_Regex)$/,@{$events})
  986. {
  987. foreach my $evt (@{$events})
  988. {
  989. my $um = $evt;
  990. $um =~ s/.*:\s//;
  991. next if (!grep /^$um$/,split /,/,$HOMEMODE_UserModesAll);
  992. $usermode = $um;
  993. }
  994. }
  995. if ($usermode)
  996. {
  997. if ($usermode =~ /^(home|awoken)$/ && AttrNum($name,"HomeAutoAwoken",0))
  998. {
  999. if ($usermode eq "home" && ReadingsVal($dev,"lastState","") eq "asleep")
  1000. {
  1001. AnalyzeCommandChain(undef,"sleep 0.1; set $dev:FILTER=state!=awoken state awoken");
  1002. return;
  1003. }
  1004. elsif ($usermode eq "awoken")
  1005. {
  1006. my $hours = HOMEMODE_hourMaker(AttrNum($name,"HomeAutoAwoken",0));
  1007. CommandDelete(undef,"atTmp_awoken_".$dev."_$name") if (IsDevice("atTmp_awoken_".$dev."_$name"));
  1008. CommandDefine(undef,"atTmp_awoken_".$dev."_$name at +$hours set $dev:FILTER=state=awoken state home");
  1009. }
  1010. }
  1011. if ($usermode eq "home" && ReadingsVal($dev,"lastState","") =~ /^(absent|[gn]one)$/ && AttrNum($name,"HomeAutoArrival",0))
  1012. {
  1013. my $hours = HOMEMODE_hourMaker(AttrNum($name,"HomeAutoArrival",0));
  1014. AnalyzeCommandChain(undef,"sleep 0.1; set $dev:FILTER=location!=arrival location arrival");
  1015. CommandDelete(undef,"atTmp_location_home_".$dev."_$name") if (IsDevice("atTmp_location_home_".$dev."_$name"));
  1016. CommandDefine(undef,"atTmp_location_home_".$dev."_$name at +$hours set $dev:FILTER=location=arrival location home")
  1017. }
  1018. if ($usermode eq "gotosleep" && AttrNum($name,"HomeAutoAsleep",0))
  1019. {
  1020. my $hours = HOMEMODE_hourMaker(AttrNum($name,"HomeAutoAsleep",0));
  1021. CommandDelete(undef,"atTmp_asleep_".$dev."_$name") if (IsDevice("atTmp_asleep_".$dev."_$name"));
  1022. CommandDefine(undef,"atTmp_asleep_".$dev."_$name at +$hours set $dev:FILTER=state=gotosleep state asleep");
  1023. }
  1024. readingsBeginUpdate($hash);
  1025. if (grep /^presence:\sabsent$/,@{$events})
  1026. {
  1027. push @commands,AttrVal($name,"HomeCMDpresence-absent-resident","") if (AttrVal($name,"HomeCMDpresence-absent-resident",undef));
  1028. push @commands,AttrVal($name,"HomeCMDpresence-absent-$dev","") if (AttrVal($name,"HomeCMDpresence-absent-$dev",undef));
  1029. readingsBulkUpdate($hash,"lastAbsentByResident",$dev);
  1030. }
  1031. elsif (grep /^presence:\spresent$/,@{$events})
  1032. {
  1033. push @commands,AttrVal($name,"HomeCMDpresence-present-resident","") if (AttrVal($name,"HomeCMDpresence-present-resident",undef));
  1034. push @commands,AttrVal($name,"HomeCMDpresence-present-$dev","") if (AttrVal($name,"HomeCMDpresence-present-$dev",undef));
  1035. readingsBulkUpdate($hash,"lastPresentByResident",$dev);
  1036. }
  1037. push @commands,AttrVal($name,"HomeCMDmode-$usermode-resident","") if (AttrVal($name,"HomeCMDmode-$usermode-resident",undef));
  1038. push @commands,AttrVal($name,"HomeCMDmode-$usermode-$dev","") if (AttrVal($name,"HomeCMDmode-$usermode-$dev",undef));
  1039. readingsBulkUpdate($hash,"lastActivityByResident",$dev);
  1040. readingsBulkUpdate($hash,"lastAsleepByResident",$dev) if ($usermode eq "asleep");
  1041. readingsBulkUpdate($hash,"lastAwokenByResident",$dev) if ($usermode eq "awoken");
  1042. readingsBulkUpdate($hash,"lastGoneByResident",$dev) if ($usermode =~ /^(gone|none)$/);
  1043. readingsBulkUpdate($hash,"lastGotosleepByResident",$dev) if ($usermode eq "gotosleep");
  1044. readingsBulkUpdate($hash,"prevActivityByResident",$lad);
  1045. readingsEndUpdate($hash,1);
  1046. }
  1047. HOMEMODE_ContactOpenCheckAfterModeChange($hash,undef,undef,$dev);
  1048. }
  1049. if (@commands)
  1050. {
  1051. if ($devtype eq "RESIDENTS")
  1052. {
  1053. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands));
  1054. }
  1055. else
  1056. {
  1057. my $delay = AttrNum($name,"HomeResidentCmdDelay",1);
  1058. my $cmd = encode_base64(HOMEMODE_serializeCMD($hash,@commands),"");
  1059. InternalTimer(gettimeofday() + $delay,"HOMEMODE_execUserCMDs","$name|$cmd|$dev");
  1060. }
  1061. }
  1062. return;
  1063. }
  1064. sub HOMEMODE_Attributes($)
  1065. {
  1066. my ($hash) = @_;
  1067. my $name = $hash->{NAME};
  1068. my @attribs;
  1069. push @attribs,"disable:1,0";
  1070. push @attribs,"disabledForIntervals";
  1071. push @attribs,"HomeAdvancedDetails:none,detail,both,room";
  1072. push @attribs,"HomeAdvancedUserAttr:1,0";
  1073. push @attribs,"HomeAutoAlarmModes:0,1";
  1074. push @attribs,"HomeAutoArrival";
  1075. push @attribs,"HomeAutoAsleep";
  1076. push @attribs,"HomeAutoAwoken";
  1077. push @attribs,"HomeAutoDaytime:0,1";
  1078. push @attribs,"HomeAutoPresence:1,0";
  1079. push @attribs,"HomeCMDalarmTriggered-off:textField-long";
  1080. push @attribs,"HomeCMDalarmTriggered-on:textField-long";
  1081. push @attribs,"HomeCMDalarmTampered-off:textField-long";
  1082. push @attribs,"HomeCMDalarmTampered-on:textField-long";
  1083. push @attribs,"HomeCMDanyoneElseAtHome-on:textField-long";
  1084. push @attribs,"HomeCMDanyoneElseAtHome-off:textField-long";
  1085. push @attribs,"HomeCMDbatteryLow:textField-long";
  1086. push @attribs,"HomeCMDcontact:textField-long";
  1087. push @attribs,"HomeCMDcontactClosed:textField-long";
  1088. push @attribs,"HomeCMDcontactOpen:textField-long";
  1089. push @attribs,"HomeCMDcontactDoormain:textField-long";
  1090. push @attribs,"HomeCMDcontactDoormainClosed:textField-long";
  1091. push @attribs,"HomeCMDcontactDoormainOpen:textField-long";
  1092. push @attribs,"HomeCMDcontactOpenWarning1:textField-long";
  1093. push @attribs,"HomeCMDcontactOpenWarning2:textField-long";
  1094. push @attribs,"HomeCMDcontactOpenWarningLast:textField-long";
  1095. push @attribs,"HomeCMDdaytime:textField-long";
  1096. push @attribs,"HomeCMDdnd-off:textField-long";
  1097. push @attribs,"HomeCMDdnd-on:textField-long";
  1098. push @attribs,"HomeCMDevent:textField-long";
  1099. push @attribs,"HomeCMDfhemINITIALIZED:textField-long";
  1100. push @attribs,"HomeCMDicewarning-on:textField-long";
  1101. push @attribs,"HomeCMDicewarning-off:textField-long";
  1102. push @attribs,"HomeCMDlocation:textField-long";
  1103. foreach (split /,/,$HOMEMODE_Locations)
  1104. {
  1105. push @attribs,"HomeCMDlocation-$_:textField-long";
  1106. }
  1107. push @attribs,"HomeCMDmode:textField-long";
  1108. push @attribs,"HomeCMDmode-absent-belated:textField-long";
  1109. foreach (split /,/,$HOMEMODE_UserModesAll)
  1110. {
  1111. push @attribs,"HomeCMDmode-$_:textField-long";
  1112. push @attribs,"HomeCMDmode-$_-resident:textField-long";
  1113. }
  1114. push @attribs,"HomeCMDmodeAlarm:textField-long";
  1115. foreach (split /,/,$HOMEMODE_AlarmModes)
  1116. {
  1117. push @attribs,"HomeCMDmodeAlarm-$_:textField-long";
  1118. }
  1119. push @attribs,"HomeCMDmotion:textField-long";
  1120. push @attribs,"HomeCMDmotion-on:textField-long";
  1121. push @attribs,"HomeCMDmotion-off:textField-long";
  1122. push @attribs,"HomeCMDpresence-absent:textField-long";
  1123. push @attribs,"HomeCMDpresence-present:textField-long";
  1124. push @attribs,"HomeCMDpresence-absent-device:textField-long";
  1125. push @attribs,"HomeCMDpresence-present-device:textField-long";
  1126. push @attribs,"HomeCMDpresence-absent-resident:textField-long";
  1127. push @attribs,"HomeCMDpresence-present-resident:textField-long";
  1128. push @attribs,"HomeCMDpublic-ip-change:textField-long";
  1129. push @attribs,"HomeCMDseason:textField-long";
  1130. push @attribs,"HomeCMDtwilight:textField-long";
  1131. push @attribs,"HomeCMDtwilight-sr:textField-long";
  1132. push @attribs,"HomeCMDtwilight-sr_astro:textField-long";
  1133. push @attribs,"HomeCMDtwilight-sr_civil:textField-long";
  1134. push @attribs,"HomeCMDtwilight-sr_indoor:textField-long";
  1135. push @attribs,"HomeCMDtwilight-sr_weather:textField-long";
  1136. push @attribs,"HomeCMDtwilight-ss:textField-long";
  1137. push @attribs,"HomeCMDtwilight-ss_astro:textField-long";
  1138. push @attribs,"HomeCMDtwilight-ss_civil:textField-long";
  1139. push @attribs,"HomeCMDtwilight-ss_indoor:textField-long";
  1140. push @attribs,"HomeCMDtwilight-ss_weather:textField-long";
  1141. push @attribs,"HomeCMDuwz-warn-begin:textField-long";
  1142. push @attribs,"HomeCMDuwz-warn-end:textField-long";
  1143. push @attribs,"HomeDaytimes:textField-long";
  1144. push @attribs,"HomeEventsHolidayDevices";
  1145. push @attribs,"HomeIcewarningOnOffTemps";
  1146. push @attribs,"HomeLanguage:DE,EN";
  1147. push @attribs,"HomeModeAlarmArmDelay";
  1148. push @attribs,"HomeModeAbsentBelatedTime";
  1149. push @attribs,"HomePresenceDeviceType";
  1150. push @attribs,"HomePublicIpCheckInterval";
  1151. push @attribs,"HomeResidentCmdDelay";
  1152. push @attribs,"HomeSeasons:textField-long";
  1153. push @attribs,"HomeSensorAirpressure";
  1154. push @attribs,"HomeSensorWindspeed";
  1155. push @attribs,"HomeSensorsBattery";
  1156. push @attribs,"HomeSensorsBatteryLowPercentage";
  1157. push @attribs,"HomeSensorsBatteryReading";
  1158. push @attribs,"HomeSensorsContact";
  1159. push @attribs,"HomeSensorsContactReadings";
  1160. push @attribs,"HomeSensorsContactValues";
  1161. push @attribs,"HomeSensorsContactOpenTimeDividers";
  1162. push @attribs,"HomeSensorsContactOpenTimeMin";
  1163. push @attribs,"HomeSensorsContactOpenTimes";
  1164. push @attribs,"HomeSensorsLuminance";
  1165. push @attribs,"HomeSensorsLuminanceReading";
  1166. push @attribs,"HomeSensorsMotion";
  1167. push @attribs,"HomeSensorsMotionReadings";
  1168. push @attribs,"HomeSensorsMotionValues";
  1169. push @attribs,"HomeSensorsPowerEnergy";
  1170. push @attribs,"HomeSensorsPowerEnergyReadings";
  1171. push @attribs,"HomeSensorHumidityOutside";
  1172. push @attribs,"HomeSensorTemperatureOutside";
  1173. push @attribs,"HomeSpecialLocations";
  1174. push @attribs,"HomeSpecialModes";
  1175. push @attribs,"HomeTextAndAreIs";
  1176. push @attribs,"HomeTextClosedOpen";
  1177. push @attribs,"HomeTextRisingConstantFalling";
  1178. push @attribs,"HomeTextTodayTomorrowAfterTomorrow";
  1179. push @attribs,"HomeTextWeatherForecastToday:textField-long";
  1180. push @attribs,"HomeTextWeatherForecastTomorrow:textField-long";
  1181. push @attribs,"HomeTextWeatherForecastInSpecDays:textField-long";
  1182. push @attribs,"HomeTextWeatherNoForecast:textField-long";
  1183. push @attribs,"HomeTextWeatherLong:textField-long";
  1184. push @attribs,"HomeTextWeatherShort:textField-long";
  1185. push @attribs,"HomeTrendCalcAge:900,1800,2700,3600";
  1186. push @attribs,"HomeTwilightDevice";
  1187. push @attribs,"HomeUWZ";
  1188. push @attribs,"HomeYahooWeatherDevice";
  1189. push @attribs,$readingFnAttributes;
  1190. return join(" ",@attribs);
  1191. }
  1192. sub HOMEMODE_userattr($)
  1193. {
  1194. my ($hash) = @_;
  1195. my $name = $hash->{NAME};
  1196. my $adv = HOMEMODE_AttrCheck($hash,"HomeAdvancedUserAttr",0);
  1197. my @userattrAll;
  1198. my @userattrPrev = split " ",AttrVal($name,"userattr","") if (AttrVal($name,"userattr",undef));
  1199. HOMEMODE_cleanUserattr($hash,$name,$name) if (@userattrPrev);
  1200. my $specialevents = HOMEMODE_AttrCheck($hash,"HomeEventsHolidayDevices");
  1201. my $specialmodes = HOMEMODE_AttrCheck($hash,"HomeSpecialModes");
  1202. my $speciallocations = HOMEMODE_AttrCheck($hash,"HomeSpecialLocations");
  1203. my $daytimes = HOMEMODE_AttrCheck($hash,"HomeDaytimes",$HOMEMODE_Daytimes);
  1204. my $seasons = HOMEMODE_AttrCheck($hash,"HomeSeasons",$HOMEMODE_Seasons);
  1205. foreach (split /,/,$specialmodes)
  1206. {
  1207. push @userattrAll,"HomeCMDmode-$_";
  1208. }
  1209. foreach (split /,/,$speciallocations)
  1210. {
  1211. push @userattrAll,"HomeCMDlocation-$_";
  1212. }
  1213. foreach my $cal (devspec2array("$specialevents:FILTER=disable!=1"))
  1214. {
  1215. my $events = HOMEMODE_HolidayEvents($cal);
  1216. push @userattrAll,"HomeCMDevent-$cal-each";
  1217. if ($adv)
  1218. {
  1219. foreach my $evt (@{$events})
  1220. {
  1221. push @userattrAll,"HomeCMDevent-$cal-$evt-begin";
  1222. push @userattrAll,"HomeCMDevent-$cal-$evt-end";
  1223. }
  1224. }
  1225. }
  1226. foreach my $resident (split /,/,$hash->{RESIDENTS})
  1227. {
  1228. my $devtype = IsDevice($resident) ? $defs{$resident}->{TYPE} : "";
  1229. next if (!$devtype);
  1230. if ($adv)
  1231. {
  1232. my $states = "absent";
  1233. $states .= ",$HOMEMODE_UserModesAll" if ($devtype eq "ROOMMATE");
  1234. $states .= ",home,$HOMEMODE_UserModes" if ($devtype eq "GUEST");
  1235. foreach (split /,/,$states)
  1236. {
  1237. push @userattrAll,"HomeCMDmode-$_-$resident";
  1238. }
  1239. push @userattrAll,"HomeCMDpresence-absent-$resident";
  1240. push @userattrAll,"HomeCMDpresence-present-$resident";
  1241. }
  1242. my @presdevs = @{$hash->{helper}{presdevs}{$resident}} if ($hash->{helper}{presdevs}{$resident});
  1243. if (@presdevs)
  1244. {
  1245. my $count;
  1246. my $numbers;
  1247. foreach (@presdevs)
  1248. {
  1249. $count++;
  1250. $numbers .= "," if ($numbers);
  1251. $numbers .= $count;
  1252. }
  1253. push @userattrAll,"HomePresenceDeviceAbsentCount-$resident:$numbers";
  1254. push @userattrAll,"HomePresenceDevicePresentCount-$resident:$numbers";
  1255. if ($adv)
  1256. {
  1257. foreach (@presdevs)
  1258. {
  1259. push @userattrAll,"HomeCMDpresence-absent-$resident-device";
  1260. push @userattrAll,"HomeCMDpresence-present-$resident-device";
  1261. push @userattrAll,"HomeCMDpresence-absent-$resident-$_";
  1262. push @userattrAll,"HomeCMDpresence-present-$resident-$_";
  1263. }
  1264. }
  1265. }
  1266. }
  1267. foreach (split " ",$daytimes)
  1268. {
  1269. my $text = (split /\|/)[1];
  1270. my $d = "HomeCMDdaytime-$text";
  1271. my $m = "HomeCMDmode-$text";
  1272. push @userattrAll,$d if (!grep /^$d$/,@userattrAll);
  1273. push @userattrAll,$m if (!grep /^$m$/,@userattrAll);
  1274. }
  1275. foreach (split " ",$seasons)
  1276. {
  1277. my $text = (split /\|/)[1];
  1278. my $s = "HomeCMDseason-$text";
  1279. push @userattrAll,$s if (!grep /^$s$/,@userattrAll);
  1280. }
  1281. my $userattrPrevList = join(" ",@userattrPrev) if (\@userattrPrev);
  1282. my $userattrNewList = join(" ",@userattrAll);
  1283. return if ($userattrNewList eq $userattrPrevList);
  1284. foreach my $attrib (@userattrAll)
  1285. {
  1286. $attrib = $attrib =~ /^.*:.*$/ ? $attrib : "$attrib:textField-long";
  1287. addToDevAttrList($name,$attrib);
  1288. }
  1289. }
  1290. sub HOMEMODE_cleanUserattr($$;$)
  1291. {
  1292. my ($hash,$devs,$newdevs) = @_;
  1293. my @devspec = devspec2array($devs);
  1294. return if (!@devspec);
  1295. my @newdevspec = devspec2array($newdevs) if ($newdevs);
  1296. foreach my $dev (@devspec)
  1297. {
  1298. if (AttrVal($dev,"userattr",undef))
  1299. {
  1300. my @stayattr;
  1301. foreach (split " ",AttrVal($dev,"userattr",""))
  1302. {
  1303. if ($_ =~ /^Home/)
  1304. {
  1305. $_ =~ s/:.*//;
  1306. delete $attr{$dev}{$_} if ((defined AttrVal($dev,$_,undef) && !@newdevspec) || (defined AttrVal($dev,$_,undef) && @newdevspec && !grep /^$dev$/,@newdevspec));
  1307. next;
  1308. }
  1309. push @stayattr,$_;
  1310. }
  1311. if (@stayattr)
  1312. {
  1313. $attr{$dev}{userattr} = join(" ",@stayattr);
  1314. }
  1315. else
  1316. {
  1317. delete $attr{$dev}{userattr};
  1318. }
  1319. }
  1320. }
  1321. }
  1322. sub HOMEMODE_Attr(@)
  1323. {
  1324. my ($cmd,$name,$attr_name,$attr_value) = @_;
  1325. my $hash = $defs{$name};
  1326. delete $hash->{helper}{lastChangedAttr};
  1327. delete $hash->{helper}{lastChangedAttrValue};
  1328. my $attr_value_old = AttrVal($name,$attr_name,"");
  1329. $hash->{helper}{lastChangedAttr} = $attr_name;
  1330. my $trans;
  1331. if ($cmd eq "set")
  1332. {
  1333. $hash->{helper}{lastChangedAttrValue} = $attr_value;
  1334. if ($attr_name =~ /^(HomeAutoAwoken|HomeAutoAsleep|HomeAutoArrival|HomeModeAbsentBelatedTime)$/)
  1335. {
  1336. $trans = $HOMEMODE_de?
  1337. "Ungültiger Wert $attr_value für Attribut $attr_name. Muss eine Zahl von 0 bis 5999.99 sein.":
  1338. "Invalid value $attr_value for attribute $attr_name. Must be a number from 0 to 5999.99.";
  1339. return $trans if ($attr_value !~ /^(\d{1,4})(\.\d{1,2})?$/ || $1 >= 6000 || $1 < 0);
  1340. }
  1341. elsif ($attr_name eq "HomeLanguage")
  1342. {
  1343. $trans = $HOMEMODE_de?
  1344. "Ungültiger Wert $attr_value für Attribut $attr_name. Kann nur \"EN\" oder \"DE\" sein, Vorgabewert ist Sprache aus global.":
  1345. "Invalid value $attr_value for attribute $attr_name. Must be \"EN\" or \"DE\", default is language from global.";
  1346. return $trans if ($attr_value !~ /^(DE|EN)$/);
  1347. $HOMEMODE_de = 1 if ($attr_value eq "DE");
  1348. $HOMEMODE_de = undef if ($attr_value eq "EN");
  1349. }
  1350. elsif ($attr_name eq "HomeAdvancedDetails")
  1351. {
  1352. $trans = $HOMEMODE_de?
  1353. "Ungültiger Wert $attr_value für Attribut $attr_name. Kann nur \"none\", \"detail\", \"both\" oder \"room\" sein, Vorgabewert ist \"none\".":
  1354. "Invalid value $attr_value for attribute $attr_name. Must be \"none\", \"detail\", \"both\" or \"room\", default is \"none\".";
  1355. return $trans if ($attr_value !~ /^(none|detail|both|room)$/);
  1356. if ($attr_value eq "detail")
  1357. {
  1358. $modules{HOMEMODE}->{FW_deviceOverview} = 1;
  1359. $modules{HOMEMODE}->{FW_addDetailToSummary} = 0;
  1360. }
  1361. else
  1362. {
  1363. $modules{HOMEMODE}->{FW_deviceOverview} = 1;
  1364. $modules{HOMEMODE}->{FW_addDetailToSummary} = 1;
  1365. }
  1366. }
  1367. elsif ($attr_name =~ /^(disable|HomeAdvancedUserAttr|HomeAutoDaytime|HomeAutoAlarmModes|HomeAutoPresence)$/)
  1368. {
  1369. $trans = $HOMEMODE_de?
  1370. "Ungültiger Wert $attr_value für Attribut $attr_name. Kann nur 1 oder 0 sein, Vorgabewert ist 0.":
  1371. "Invalid value $attr_value for attribute $attr_name. Must be 1 or 0, default is 0.";
  1372. return $trans if ($attr_value !~ /^[01]$/);
  1373. RemoveInternalTimer($hash) if ($attr_name eq "disable" && $attr_value == 1);
  1374. HOMEMODE_GetUpdate($hash) if ($attr_name eq "disable" && !$attr_value);
  1375. HOMEMODE_updateInternals($hash,1) if ($attr_name =~ /^(HomeAdvancedUserAttr|HomeAutoPresence)$/ && $init_done);
  1376. }
  1377. elsif ($attr_name =~ /^HomeCMD/ && $init_done)
  1378. {
  1379. if ($attr_value_old ne $attr_value)
  1380. {
  1381. my $err = perlSyntaxCheck(HOMEMODE_replacePlaceholders($hash,$attr_value));
  1382. return $err if ($err);
  1383. }
  1384. }
  1385. elsif ($attr_name eq "HomeEventsHolidayDevices" && $init_done)
  1386. {
  1387. my $wd = HOMEMODE_CheckHolidayDevices($attr_value);
  1388. if ($wd)
  1389. {
  1390. $trans = $HOMEMODE_de?
  1391. "Ungültige holiday Geräte gefunden: ":
  1392. "Invalid holiday device(s) found: ";
  1393. return $trans.join(",",@{$wd});
  1394. }
  1395. else
  1396. {
  1397. HOMEMODE_updateInternals($hash);
  1398. }
  1399. }
  1400. elsif ($attr_name =~ /^(HomePresenceDeviceType)$/ && $init_done)
  1401. {
  1402. $trans = $HOMEMODE_de?
  1403. "$attr_value muss ein gültiger TYPE sein":
  1404. "$attr_value must be a valid TYPE";
  1405. return $trans if (!HOMEMODE_CheckIfIsValidDevspec("TYPE=$attr_value","presence"));
  1406. HOMEMODE_updateInternals($hash,1);
  1407. }
  1408. elsif ($attr_name =~ /^(HomeSensorsContactReadings|HomeSensorsMotionReadings)$/)
  1409. {
  1410. $trans = $HOMEMODE_de?
  1411. "Ungültiger Wert $attr_value für Attribut $attr_name. Es werden wenigstens 2 Leerzeichen separierte Readings benötigt! z.B. state sabotageError":
  1412. "Invalid value $attr_value for attribute $attr_name. You have to provide at least 2 space separated readings, e.g. state sabotageError";
  1413. return $trans if ($attr_value !~ /^[\w\-\.]+\s[\w\-\.]+$/);
  1414. }
  1415. elsif ($attr_name =~ /^(HomeSensorsContactValues|HomeSensorsMotionValues)$/)
  1416. {
  1417. $trans = $HOMEMODE_de?
  1418. "Ungültiger Wert $attr_value für Attribut $attr_name. Es wird wenigstens ein Wert oder mehrere Pipe separierte Readings benötigt! z.B. open|tilted|on":
  1419. "Invalid value $attr_value for attribute $attr_name. You have to provide at least one value or more values pipe separated, e.g. open|tilted|on";
  1420. return $trans if ($attr_value !~ /^[\w\-äöüß\.]+(\|[\w\-äöüß\.]+){0,}?$/i);
  1421. }
  1422. elsif ($attr_name eq "HomeIcewarningOnOffTemps")
  1423. {
  1424. $trans = $HOMEMODE_de?
  1425. "Ungültiger Wert $attr_value für Attribut $attr_name. Es werden wenigstens 2 Leerzeichen separierte Temperaturen benötigt, z.B. -0.1 2.5":
  1426. "Invalid value $attr_value for attribute $attr_name. You have to provide 2 space separated temperatures, e.g. -0.1 2.5";
  1427. return $trans if ($attr_value !~ /^-?\d{1,2}(\.\d)?\s-?\d{1,2}(\.\d)?$/);
  1428. }
  1429. elsif ($attr_name eq "HomeSensorsContactOpenTimeDividers")
  1430. {
  1431. $trans = $HOMEMODE_de?
  1432. "Ungültiger Wert $attr_value für Attribut $attr_name. Es werden Leerzeichen separierte Zahlen für jede Jahreszeit (aus Attribut HomeSeasons) benötigt, z.B. 2 1 2 3.333":
  1433. "Invalid value $attr_value for attribute $attr_name. You have to provide space separated numbers for each season in order of the seasons provided in attribute HomeSeasons, e.g. 2 1 2 3.333";
  1434. return $trans if ($attr_value !~ /^\d{1,2}(\.\d{1,3})?(\s\d{1,2}(\.\d{1,3})?){0,}$/);
  1435. my @times = split " ",$attr_value;
  1436. my $s = scalar split " ",AttrVal($name,"HomeSeasons",$HOMEMODE_Seasons);
  1437. my $t = scalar @times;
  1438. $trans = $HOMEMODE_de?
  1439. "Anzahl von $attr_name Werten ($t) ungleich zu den verfügbaren Jahreszeiten ($s) im Attribut HomeSeasons!":
  1440. "Number of $attr_name values ($t) not matching the number of available seasons ($s) in attribute HomeSeasons!";
  1441. return $trans if ($s != $t);
  1442. foreach (@times)
  1443. {
  1444. $trans = $HOMEMODE_de?
  1445. "Teiler dürfen nicht 0 sein, denn Division durch 0 ist nicht definiert!":
  1446. "Dividers can't be zero, because division by zero is not defined!";
  1447. return $trans if ($_ == 0);
  1448. }
  1449. }
  1450. elsif ($attr_name eq "HomeSensorsContactOpenTimeMin")
  1451. {
  1452. $trans = $HOMEMODE_de?
  1453. "Ungültiger Wert $attr_value für Attribut $attr_name. Zahlen von 1 bis 9.9 sind nur erlaubt!":
  1454. "Invalid value $attr_value for attribute $attr_name. Numbers from 1 to 9.9 are allowed only!";
  1455. return $trans if ($attr_value !~ /^[1-9](\.\d)?$/);
  1456. }
  1457. elsif ($attr_name eq "HomeSensorsContactOpenTimes")
  1458. {
  1459. $trans = $HOMEMODE_de?
  1460. "Ungültiger Wert $attr_value für Attribut $attr_name. Es werden Leerzeichen separierte Zahlen benötigt, z.B. 5 10 15 17.5":
  1461. "Invalid value $attr_value for attribute $attr_name. You have to provide space separated numbers, e.g. 5 10 15 17.5";
  1462. return $trans if ($attr_value !~ /^\d{1,4}(\.\d)?((\s\d{1,4}(\.\d)?)?){0,}$/);
  1463. foreach (split " ",$attr_value)
  1464. {
  1465. $trans = $HOMEMODE_de?
  1466. "Teiler dürfen nicht 0 sein, denn Division durch 0 ist nicht definiert!":
  1467. "Dividers can't be zero, because division by zero is not defined!";
  1468. return $trans if ($_ == 0);
  1469. }
  1470. }
  1471. elsif ($attr_name eq "HomeResidentCmdDelay")
  1472. {
  1473. $trans = $HOMEMODE_de?
  1474. "Ungültiger Wert $attr_value für Attribut $attr_name. Zahlen von 0 bis 9999 sind nur erlaubt!":
  1475. "Invalid value $attr_value for attribute $attr_name. Numbers from 0 to 9999 are allowed only!";
  1476. return $trans if ($attr_value !~ /^\d{1,4}$/);
  1477. }
  1478. elsif ($attr_name =~ /^(HomeSpecialModes|HomeSpecialLocations)$/ && $init_done)
  1479. {
  1480. $trans = $HOMEMODE_de?
  1481. "Ungültiger Wert $attr_value für Attribut $attr_name. Muss eine Komma separierte Liste von Wörtern sein!":
  1482. "Invalid value $attr_value for attribute $attr_name. Must be a comma separated list of words!";
  1483. return $trans if ($attr_value !~ /^[\w\-äöüß\.]+(,[\w\-äöüß\.]+){0,}$/i);
  1484. HOMEMODE_userattr($hash);
  1485. }
  1486. elsif ($attr_name eq "HomePublicIpCheckInterval")
  1487. {
  1488. $trans = $HOMEMODE_de?
  1489. "Ungültiger Wert $attr_value für Attribut $attr_name. Muss eine Zahl von 1 bis 99999 für das Interval in Minuten sein!":
  1490. "Invalid value $attr_value for attribute $attr_name. Must be a number from 1 to 99999 for interval in minutes!";
  1491. return $trans if ($attr_value !~ /^\d{1,5}$/);
  1492. }
  1493. elsif ($attr_name =~ /^(HomeSensorsContact|HomeSensorsMotion)$/ && $init_done)
  1494. {
  1495. $trans = $HOMEMODE_de?
  1496. "$attr_value muss ein gültiger Devspec sein!":
  1497. "$attr_value must be a valid devspec!";
  1498. return $trans if (!HOMEMODE_CheckIfIsValidDevspec($attr_value));
  1499. my $od = "";
  1500. $od = $hash->{SENSORSCONTACT} if ($hash->{SENSORSCONTACT} && $attr_name eq "HomeSensorsContact");
  1501. $od = $hash->{SENSORSMOTION} if ($hash->{SENSORSMOTION} && $attr_name eq "HomeSensorsMotion");
  1502. HOMEMODE_updateInternals($hash);
  1503. HOMEMODE_addSensorsuserattr($hash,$attr_value,$od);
  1504. }
  1505. elsif ($attr_name eq "HomeSensorsPowerEnergy" && $init_done)
  1506. {
  1507. my ($p,$e) = split " ",AttrVal($name,"HomeSensorsPowerEnergyReadings","power energy");
  1508. $trans = $HOMEMODE_de?
  1509. "$attr_value muss ein gültiger Devspec mit $p und $e Readings sein!":
  1510. "$attr_value must be a valid devspec with $p and $e readings!";
  1511. return $trans if (!HOMEMODE_CheckIfIsValidDevspec($attr_value,$p) || !HOMEMODE_CheckIfIsValidDevspec($attr_value,$e));
  1512. HOMEMODE_updateInternals($hash);
  1513. }
  1514. elsif ($attr_name eq "HomeTwilightDevice" && $init_done)
  1515. {
  1516. $trans = $HOMEMODE_de?
  1517. "$attr_value muss ein gültiges Gerät vom TYPE Twilight sein!":
  1518. "$attr_value must be a valid device of TYPE Twilight!";
  1519. return $trans if (!HOMEMODE_CheckIfIsValidDevspec("$attr_value:FILTER=TYPE=Twilight"));
  1520. if ($attr_value_old ne $attr_value)
  1521. {
  1522. CommandDeleteReading(undef,"$name light|twilight|twilightEvent");
  1523. HOMEMODE_updateInternals($hash);
  1524. }
  1525. }
  1526. elsif ($attr_name eq "HomeYahooWeatherDevice" && $init_done)
  1527. {
  1528. $trans = $HOMEMODE_de?
  1529. "$attr_value muss ein gültiges Gerät vom TYPE Weather sein!":
  1530. "$attr_value must be a valid device of TYPE Weather!";
  1531. return $trans if (!HOMEMODE_CheckIfIsValidDevspec("$attr_value:FILTER=TYPE=Weather"));
  1532. if ($attr_value_old ne $attr_value)
  1533. {
  1534. CommandDeleteReading(undef,"$name pressure|condition|wind|wind_chill");
  1535. CommandDeleteReading(undef,"$name temperature") if (!AttrVal($name,"HomeSensorTemperatureOutside",undef));
  1536. CommandDeleteReading(undef,"$name humidity") if (!AttrVal($name,"HomeSensorHumidityOutside",undef));
  1537. HOMEMODE_updateInternals($hash);
  1538. }
  1539. }
  1540. elsif ($attr_name eq "HomeSensorTemperatureOutside" && $init_done)
  1541. {
  1542. $trans = $HOMEMODE_de?
  1543. "$attr_value muss ein gültiger Devspec mit temperature Reading sein!":
  1544. "$attr_value must be a valid device with temperature reading!";
  1545. return $trans if (!HOMEMODE_CheckIfIsValidDevspec($attr_value,"temperature"));
  1546. delete $attr{$name}{HomeSensorHumidityOutside} if (AttrVal($name,"HomeSensorHumidityOutside",undef) && $attr_value eq AttrVal($name,"HomeSensorHumidityOutside",undef));
  1547. if ($attr_value_old ne $attr_value)
  1548. {
  1549. CommandDeleteReading(undef,"$name temperature") if (!AttrVal($name,"HomeYahooWeatherDevice",undef));
  1550. HOMEMODE_updateInternals($hash);
  1551. }
  1552. }
  1553. elsif ($attr_name eq "HomeSensorHumidityOutside" && $init_done)
  1554. {
  1555. $trans = $HOMEMODE_de?
  1556. "Dieses Attribut ist wegzulassen wenn es den gleichen Wert haben sollte wie HomeSensorTemperatureOutside!":
  1557. "You have to omit this attribute if it should have the same value like HomeSensorTemperatureOutside!";
  1558. return $trans if ($attr_value eq AttrVal($name,"HomeSensorTemperatureOutside",undef));
  1559. $trans = $HOMEMODE_de?
  1560. "$attr_value muss ein gültiger Devspec mit humidity Reading sein!":
  1561. "$attr_value must be a valid device with humidity reading!";
  1562. return $trans if (!HOMEMODE_CheckIfIsValidDevspec($attr_value,"humidity"));
  1563. if ($attr_value_old ne $attr_value)
  1564. {
  1565. CommandDeleteReading(undef,"$name humidity") if (!AttrVal($name,"HomeYahooWeatherDevice",undef));
  1566. HOMEMODE_updateInternals($hash);
  1567. }
  1568. }
  1569. elsif ($attr_name eq "HomeDaytimes" && $init_done)
  1570. {
  1571. $trans = $HOMEMODE_de?
  1572. "$attr_value für $attr_name muss eine Leerzeichen separierte Liste aus Uhrzeit|Text Paaren sein! z.B. $HOMEMODE_Daytimes":
  1573. "$attr_value for $attr_name must be a space separated list of time|text pairs! e.g. $HOMEMODE_Daytimes";
  1574. return $trans if ($attr_value !~ /^([0-2]\d:[0-5]\d\|[\w\-äöüß\.]+)(\s[0-2]\d:[0-5]\d\|[\w\-äöüß\.]+){0,}$/i);
  1575. if ($attr_value_old ne $attr_value)
  1576. {
  1577. my @ts;
  1578. foreach (split " ",$attr_value)
  1579. {
  1580. my $time = (split /\|/)[0];
  1581. my ($h,$m) = split /:/,$time;
  1582. my $minutes = $h * 60 + $m;
  1583. my $lastminutes = @ts ? $ts[scalar @ts - 1] : -1;
  1584. if ($minutes > $lastminutes)
  1585. {
  1586. push @ts,$minutes;
  1587. }
  1588. else
  1589. {
  1590. $trans = $HOMEMODE_de?
  1591. "Falsche Reihenfolge der Zeiten in $attr_value":
  1592. "Wrong times order in $attr_value";
  1593. return $trans;
  1594. }
  1595. }
  1596. HOMEMODE_userattr($hash);
  1597. }
  1598. }
  1599. elsif ($attr_name eq "HomeSeasons" && $init_done)
  1600. {
  1601. $trans = $HOMEMODE_de?
  1602. "$attr_value für $attr_name muss eine Leerzeichen separierte Liste aus Datum|Text Paaren mit mindestens 4 Werten sein! z.B. $HOMEMODE_Seasons":
  1603. "$attr_value for $attr_name must be a space separated list of date|text pairs with at least 4 values! e.g. $HOMEMODE_Seasons";
  1604. return $trans if (scalar (split " ",$attr_value) < 4 || scalar (split /\|/,$attr_value) < 5);
  1605. if ($attr_value_old ne $attr_value)
  1606. {
  1607. my @ds;
  1608. foreach (split " ",$attr_value)
  1609. {
  1610. my $time = (split /\|/)[0];
  1611. my ($m,$d) = split /\./,$time;
  1612. my $days = $m * 31 + $d;
  1613. my $lastdays = @ds ? $ds[scalar @ds - 1] : -1;
  1614. if ($days > $lastdays)
  1615. {
  1616. push @ds,$days;
  1617. }
  1618. else
  1619. {
  1620. $trans = $HOMEMODE_de?
  1621. "Falsche Reihenfolge der Datumsangaben in $attr_value":
  1622. "Wrong dates order in $attr_value";
  1623. return $trans;
  1624. }
  1625. }
  1626. HOMEMODE_userattr($hash);
  1627. }
  1628. }
  1629. elsif ($attr_name eq "HomeModeAlarmArmDelay")
  1630. {
  1631. $trans = $HOMEMODE_de?
  1632. "$attr_value für $attr_name muss eine einzelne Zahl sein für die Verzögerung in Sekunden oder 3 Leerzeichen separierte Zeiten in Sekunden für jeden modeAlarm individuell (Reihenfolge: armaway armnight armhome), höhster Wert ist 99999":
  1633. "$attr_value for $attr_name must be a single number for delay time in seconds or 3 space separated times in seconds for each modeAlarm individually (order: armaway armnight armhome), max. value is 99999";
  1634. return $trans if ($attr_value !~ /^(\d{1,5})((\s\d{1,5})(\s\d{1,5}))?$/);
  1635. }
  1636. elsif ($attr_name =~ /^(HomeTextAndAreIs|HomeTextTodayTomorrowAfterTomorrow|HomeTextRisingConstantFalling)$/)
  1637. {
  1638. $trans = $HOMEMODE_de?
  1639. "$attr_value für $attr_name muss eine Pipe separierte Liste mit 3 Werten sein!":
  1640. "$attr_value for $attr_name must be a pipe separated list with 3 values!";
  1641. return $trans if (scalar (split /\|/,$attr_value) != 3);
  1642. }
  1643. elsif ($attr_name eq "HomeTextClosedOpen")
  1644. {
  1645. $trans = $HOMEMODE_de?
  1646. "$attr_value für $attr_name muss eine Pipe separierte Liste mit 2 Werten sein!":
  1647. "$attr_value for $attr_name must be a pipe separated list with 2 values!";
  1648. return $trans if (scalar (split /\|/,$attr_value) != 2);
  1649. }
  1650. elsif ($attr_name eq "HomeUWZ" && $init_done)
  1651. {
  1652. $trans = $HOMEMODE_de?
  1653. "$attr_value muss ein gültiges Gerät vom TYPE Weather sein!":
  1654. "$attr_value must be a valid device of TYPE Weather!";
  1655. return "$attr_value must be a valid device of TYPE UWZ!" if (!HOMEMODE_CheckIfIsValidDevspec("$attr_value:FILTER=TYPE=UWZ"));
  1656. HOMEMODE_updateInternals($hash) if ($attr_value_old ne $attr_value);
  1657. }
  1658. elsif ($attr_name eq "HomeSensorsLuminance" && $init_done)
  1659. {
  1660. my $read = AttrVal($name,"HomeSensorsLuminanceReading","luminance");
  1661. $trans = $HOMEMODE_de?
  1662. "$attr_value muss ein gültiges Gerät mit $read Reading sein!":
  1663. "$attr_name must be a valid device with $read reading!";
  1664. return $trans if (!HOMEMODE_CheckIfIsValidDevspec($attr_value,$read));
  1665. HOMEMODE_updateInternals($hash);
  1666. }
  1667. elsif ($attr_name eq "HomeSensorsPowerEnergyReadings" && $init_done)
  1668. {
  1669. $trans = $HOMEMODE_de?
  1670. "$attr_name müssen zwei gültige Readings für power und energy sein!":
  1671. "$attr_name must be two valid readings for power and energy!";
  1672. return $trans if ($attr_value !~ /^([\w\-\.]+)\s([\w\-\.]+)$/);
  1673. HOMEMODE_updateInternals($hash) if ($attr_value_old ne $attr_value);
  1674. }
  1675. elsif ($attr_name =~ /^HomeSensorsLuminanceReading|HomeSensorsBatteryReading$/ && $init_done)
  1676. {
  1677. $trans = $HOMEMODE_de?
  1678. "$attr_name muss ein einzelnes gültiges Reading sein!":
  1679. "$attr_name must be a single valid reading!";
  1680. return $trans if ($attr_value !~ /^([\w\-\.]+)$/);
  1681. HOMEMODE_updateInternals($hash) if ($attr_value_old ne $attr_value);
  1682. }
  1683. elsif ($attr_name =~ /^HomeSensorAirpressure|HomeSensorWindspeed$/ && $init_done)
  1684. {
  1685. $trans = $HOMEMODE_de?
  1686. "$attr_name muss ein einzelnes gültiges Gerät und Reading sein (Sensor:Reading)!":
  1687. "$attr_name must be a single valid device and reading (sensor:reading)!";
  1688. return $trans if ($attr_value !~ /^([\w\.]+):([\w\-\.]+)$/ || !HOMEMODE_CheckIfIsValidDevspec($1,$2));
  1689. HOMEMODE_updateInternals($hash) if ($attr_value_old ne $attr_value);
  1690. }
  1691. elsif ($attr_name eq "HomeSensorsBattery" && $init_done)
  1692. {
  1693. my $read = AttrVal($name,"HomeSensorsBatteryReading","battery");
  1694. $trans = $HOMEMODE_de?
  1695. "$attr_value muss ein gültiges Gerät mit $read Reading sein!":
  1696. "$attr_name must be a valid device with $read reading!";
  1697. return $trans if (!HOMEMODE_CheckIfIsValidDevspec($attr_value,$read));
  1698. HOMEMODE_updateInternals($hash);
  1699. }
  1700. elsif ($attr_name eq "HomeSensorsBatteryLowPercentage")
  1701. {
  1702. $trans = $HOMEMODE_de?
  1703. "$attr_value muss ein Wert zwischen 0 und 99 sein!":
  1704. "$attr_name must be a value from 0 to 99!";
  1705. return $trans if ($attr_value !~ /^\d{1,2}$/);
  1706. }
  1707. }
  1708. else
  1709. {
  1710. $hash->{helper}{lastChangedAttrValue} = "---";
  1711. if ($attr_name eq "disable")
  1712. {
  1713. HOMEMODE_GetUpdate($hash);
  1714. }
  1715. elsif ($attr_name eq "HomeLanguage")
  1716. {
  1717. $HOMEMODE_de = AttrVal("global","language","DE") ? 1 : undef;
  1718. }
  1719. elsif ($attr_name =~ /^(HomeAdvancedUserAttr|HomeAutoPresence|HomePresenceDeviceType|HomeEventsHolidayDevices|HomeSensorAirpressure|HomeSensorWindspeed|HomeSensorsBattery|HomeSensorsBatteryReading)$/)
  1720. {
  1721. HOMEMODE_updateInternals($hash,1);
  1722. }
  1723. elsif ($attr_name =~ /^(HomeSensorsContact|HomeSensorsMotion|HomeSensorsPowerEnergy)$/)
  1724. {
  1725. HOMEMODE_cleanUserattr($hash,$attr_value_old) if ($attr_value_old);
  1726. my $read = "lastContact|prevContact|contacts.*";
  1727. $read = "lastMotion|prevMotion|motions.*" if ($attr_name eq "HomeSensorsMotion");
  1728. $read = "energy|power" if ($attr_name eq "HomeSensorsPowerEnergy");
  1729. CommandDeleteReading(undef,"$name $read");
  1730. HOMEMODE_updateInternals($hash);
  1731. }
  1732. elsif ($attr_name eq "HomePublicIpCheckInterval")
  1733. {
  1734. delete $hash->{".IP_TRIGGERTIME_NEXT"};
  1735. }
  1736. elsif ($attr_name =~ /^(HomeYahooWeatherDevice|HomeTwilightDevice)$/)
  1737. {
  1738. if ($attr_name eq "HomeYahooWeatherDevice")
  1739. {
  1740. CommandDeleteReading(undef,"$name pressure|condition|wind");
  1741. CommandDeleteReading(undef,"$name temperature") if (!AttrVal($name,"HomeSensorTemperatureOutside",undef));
  1742. CommandDeleteReading(undef,"$name humidity") if (!AttrVal($name,"HomeSensorHumidityOutside",undef));
  1743. }
  1744. else
  1745. {
  1746. CommandDeleteReading(undef,"$name twilight|twilightEvent|light");
  1747. }
  1748. HOMEMODE_updateInternals($hash);
  1749. }
  1750. elsif ($attr_name =~ /^(HomeSensorTemperatureOutside|HomeSensorHumidityOutside)$/)
  1751. {
  1752. CommandDeleteReading(undef,"$name .*temperature.*") if (!AttrVal($name,"HomeYahooWeatherDevice",undef) && $attr_name eq "HomeSensorTemperatureOutside");
  1753. CommandDeleteReading(undef,"$name .*humidity.*") if (!AttrVal($name,"HomeYahooWeatherDevice",undef) && $attr_name eq "HomeSensorHumidityOutside");
  1754. HOMEMODE_updateInternals($hash);
  1755. }
  1756. elsif ($attr_name =~ /^(HomeDaytimes|HomeSeasons|HomeSpecialLocations|HomeSpecialModes)$/)
  1757. {
  1758. HOMEMODE_userattr($hash);
  1759. }
  1760. elsif ($attr_name =~ /^(HomeUWZ|HomeSensorsLuminance|HomeSensorsLuminanceReading|HomeSensorsPowerEnergyReadings)$/)
  1761. {
  1762. CommandDeleteReading(undef,"$name uwz.*") if ($attr_name eq "HomeUWZ");
  1763. CommandDeleteReading(undef,"$name .*luminance.*") if ($attr_name eq "HomeSensorsLuminance");
  1764. HOMEMODE_updateInternals($hash);
  1765. }
  1766. }
  1767. return;
  1768. }
  1769. sub HOMEMODE_replacePlaceholders($$;$)
  1770. {
  1771. my ($hash,$cmd,$resident) = @_;
  1772. my $name = $hash->{NAME};
  1773. my $sensor = AttrVal($name,"HomeYahooWeatherDevice","");
  1774. $resident = $resident ? $resident : ReadingsVal($name,"lastActivityByResident","");
  1775. my $alias = AttrVal($resident,"alias","");
  1776. my $audio = AttrVal($resident,"msgContactAudio","");
  1777. $audio = AttrVal("globalMsg","msgContactAudio","no msg audio device available") if (!$audio);
  1778. my $lastabsencedur = ReadingsVal($resident,"lastDurAbsence_cr",0);
  1779. my $lastpresencedur = ReadingsVal($resident,"lastDurPresence_cr",0);
  1780. my $lastsleepdur = ReadingsVal($resident,"lastDurSleep_cr",0);
  1781. my $durabsence = ReadingsVal($resident,"durTimerAbsence_cr",0);
  1782. my $durpresence = ReadingsVal($resident,"durTimerPresence_cr",0);
  1783. my $dursleep = ReadingsVal($resident,"durTimerSleep_cr",0);
  1784. my $condition = ReadingsVal($sensor,"condition","");
  1785. my $conditionart = ReadingsVal($name,".be","");
  1786. my $contactsOpen = ReadingsVal($name,"contactsOutsideOpen_hr","");
  1787. my $contactsOpenCt = ReadingsVal($name,"contactsOutsideOpen_ct",0);
  1788. my $dnd = ReadingsVal($name,"dnd","off") eq "on" ? 1 : 0;
  1789. my $aeah = ReadingsVal($name,"anyoneElseAtHome","off") eq "on" ? 1 : 0;
  1790. my $sensorsTampered = ReadingsVal($name,"sensorsTampered_hr","");
  1791. my $sensorsTamperedCt = ReadingsVal($name,"sensorsTampered_ct","");
  1792. my $ice = ReadingsVal($name,"icewarning",0);
  1793. my $ip = ReadingsVal($name,"publicIP","");
  1794. my $light = ReadingsVal($name,"light",0);
  1795. my $twilight = ReadingsVal($name,"twilight",0);
  1796. my $twilightevent = ReadingsVal($name,"twilightEvent","");
  1797. my $location = ReadingsVal($name,"location","");
  1798. my $rlocation = ReadingsVal($resident,"location","");
  1799. my $alarm = ReadingsVal($name,"alarmTriggered",0);
  1800. my $alarmc = ReadingsVal($name,"alarmTriggered_ct",0);
  1801. my $alarmhr = ReadingsVal($name,"alarmTriggered_hr",0);
  1802. my $daytime = HOMEMODE_DayTime($hash);
  1803. my $mode = ReadingsVal($name,"mode","");
  1804. my $amode = ReadingsVal($name,"modeAlarm","");
  1805. my $pamode = ReadingsVal($name,"prevModeAlarm","");
  1806. my $season = ReadingsVal($name,"season","");
  1807. my $pmode = ReadingsVal($name,"prevMode","");
  1808. my $rpmode = ReadingsVal($resident,"lastState","");
  1809. my $pres = ReadingsVal($name,"presence","") eq "present" ? 1 : 0;
  1810. my $rpres = ReadingsVal($resident,"presence","") eq "present" ? 1 : 0;
  1811. my $pdevice = ReadingsVal($name,"lastActivityByPresenceDevice","");
  1812. my $apdevice = ReadingsVal($name,"lastAbsentByPresenceDevice","");
  1813. my $ppdevice = ReadingsVal($name,"lastPresentByPresenceDevice","");
  1814. my $paddress = InternalVal($pdevice,"ADDRESS","");
  1815. my $pressure = ReadingsVal($name,"pressure","");
  1816. my $pressuretrend = ReadingsVal($sensor,"pressure_trend_txt","");
  1817. my $weatherlong = HOMEMODE_WeatherTXT($hash,AttrVal($name,"HomeTextWeatherLong",""));
  1818. my $weathershort = HOMEMODE_WeatherTXT($hash,AttrVal($name,"HomeTextWeatherShort",""));
  1819. my $forecast = HOMEMODE_ForecastTXT($hash);
  1820. my $forecasttoday = HOMEMODE_ForecastTXT($hash,1);
  1821. my $luminance = ReadingsVal($name,"luminance",0);
  1822. my $luminancetrend = ReadingsVal($name,"luminanceTrend",0);
  1823. my $humi = ReadingsVal($name,"humidity",0);
  1824. my $humitrend = ReadingsVal($name,"humidityTrend",0);
  1825. my $temp = ReadingsVal($name,"temperature",0);
  1826. my $temptrend = ReadingsVal($name,"temperatureTrend","constant");
  1827. my $wind = ReadingsVal($name,"wind",0);
  1828. my $windchill = ReadingsVal($sensor,"wind_chill",0);
  1829. my $motion = ReadingsVal($name,"lastMotion","");
  1830. my $pmotion = ReadingsVal($name,"prevMotion","");
  1831. my $contact = ReadingsVal($name,"lastContact","");
  1832. my $pcontact = ReadingsVal($name,"prevContact","");
  1833. my $uwzc = ReadingsVal($name,"uwz_warnCount",0);
  1834. my $uwzs = HOMEMODE_uwzTXT($hash,$uwzc,undef);
  1835. my $uwzl = HOMEMODE_uwzTXT($hash,$uwzc,1);
  1836. my $lowBat = HOMEMODE_name2alias(ReadingsVal($name,"lastBatteryLow",""));
  1837. my $lowBatAll = ReadingsVal($name,"batteryLow_hr","");
  1838. my $lowBatCount = ReadingsVal($name,"batteryLow_ct",0);
  1839. my $sensorsbattery = $hash->{SENSORSBATTERY};
  1840. my $sensorscontact = $hash->{SENSORSCONTACT};
  1841. my $sensorsenergy = $hash->{SENSORSENERGY};
  1842. my $sensorsmotion = $hash->{SENSORSMOTION};
  1843. my $ure = $hash->{RESIDENTS};
  1844. $ure =~ s/,/\|/g;
  1845. my $arrivers = HOMEMODE_makeHR($hash,0,devspec2array("$ure:FILTER=location=arrival"));
  1846. $cmd =~ s/%ADDRESS%/$paddress/g;
  1847. $cmd =~ s/%ALARM%/$alarm/g;
  1848. $cmd =~ s/%ALARMCT%/$alarmc/g;
  1849. $cmd =~ s/%ALARMHR%/$alarmhr/g;
  1850. $cmd =~ s/%ALIAS%/$alias/g;
  1851. $cmd =~ s/%AMODE%/$amode/g;
  1852. $cmd =~ s/%AEAH%/$aeah/g;
  1853. $cmd =~ s/%ARRIVERS%/$arrivers/g;
  1854. $cmd =~ s/%AUDIO%/$audio/g;
  1855. $cmd =~ s/%BATTERYLOW%/$lowBat/g;
  1856. $cmd =~ s/%BATTERYLOWALL%/$lowBatAll/g;
  1857. $cmd =~ s/%BATTERYLOWCT%/$lowBatCount/g;
  1858. $cmd =~ s/%CONDITION%/$condition/g;
  1859. $cmd =~ s/%CONTACT%/$contact/g;
  1860. $cmd =~ s/%DAYTIME%/$daytime/g;
  1861. $cmd =~ s/%DEVICE%/$pdevice/g;
  1862. $cmd =~ s/%DEVICEA%/$apdevice/g;
  1863. $cmd =~ s/%DEVICEP%/$ppdevice/g;
  1864. $cmd =~ s/%DND%/$dnd/g;
  1865. if (AttrVal($name,"HomeEventsHolidayDevices",undef))
  1866. {
  1867. foreach my $cal (devspec2array(AttrVal($name,"HomeEventsHolidayDevices","")))
  1868. {
  1869. my $state = ReadingsVal($name,"event-$cal","") ne "none" ? ReadingsVal($name,"event-$cal","") : 0;
  1870. $cmd =~ s/%$cal%/$state/g;
  1871. my $events = HOMEMODE_HolidayEvents($cal);
  1872. foreach my $evt (@{$events})
  1873. {
  1874. my $val = $state eq $evt ? 1 : 0;
  1875. $cmd =~ s/%$cal-$evt%/$val/g;
  1876. }
  1877. }
  1878. }
  1879. $cmd =~ s/%DURABSENCE%/$durabsence/g;
  1880. $cmd =~ s/%DURABSENCELAST%/$lastabsencedur/g;
  1881. $cmd =~ s/%DURPRESENCE%/$durpresence/g;
  1882. $cmd =~ s/%DURPRESENCELAST%/$lastpresencedur/g;
  1883. $cmd =~ s/%DURSLEEP%/$dursleep/g;
  1884. $cmd =~ s/%DURSLEEPLAST%/$lastsleepdur/g;
  1885. $cmd =~ s/%FORECAST%/$forecast/g;
  1886. $cmd =~ s/%FORECASTTODAY%/$forecasttoday/g;
  1887. $cmd =~ s/%HUMIDITY%/$humi/g;
  1888. $cmd =~ s/%HUMIDITYTREND%/$humitrend/g;
  1889. $cmd =~ s/%ICE%/$ice/g;
  1890. $cmd =~ s/%IP%/$ip/g;
  1891. $cmd =~ s/%LIGHT%/$light/g;
  1892. $cmd =~ s/%LOCATION%/$location/g;
  1893. $cmd =~ s/%LOCATIONR%/$rlocation/g;
  1894. $cmd =~ s/%LUMINANCE%/$luminance/g;
  1895. $cmd =~ s/%LUMINANCETREND%/$luminancetrend/g;
  1896. $cmd =~ s/%MODE%/$mode/g;
  1897. $cmd =~ s/%MOTION%/$motion/g;
  1898. $cmd =~ s/%OPEN%/$contactsOpen/g;
  1899. $cmd =~ s/%OPENCT%/$contactsOpenCt/g;
  1900. $cmd =~ s/%RESIDENT%/$resident/g;
  1901. $cmd =~ s/%PRESENT%/$pres/g;
  1902. $cmd =~ s/%PRESENTR%/$rpres/g;
  1903. $cmd =~ s/%PRESSURE%/$pressure/g;
  1904. $cmd =~ s/%PRESSURETREND%/$pressuretrend/g;
  1905. $cmd =~ s/%PREVAMODE%/$pamode/g;
  1906. $cmd =~ s/%PREVCONTACT%/$pcontact/g;
  1907. $cmd =~ s/%PREVMODE%/$pmode/g;
  1908. $cmd =~ s/%PREVMODER%/$rpmode/g;
  1909. $cmd =~ s/%PREVMOTION%/$pmotion/g;
  1910. $cmd =~ s/%SEASON%/$season/g;
  1911. $cmd =~ s/%SELF%/$name/g;
  1912. $cmd =~ s/%SENSORSBATTERY%/$sensorsbattery/g;
  1913. $cmd =~ s/%SENSORSCONTACT%/$sensorscontact/g;
  1914. $cmd =~ s/%SENSORSENERGY%/$sensorsenergy/g;
  1915. $cmd =~ s/%SENSORSMOTION%/$sensorsmotion/g;
  1916. $cmd =~ s/%TAMPERED%/$sensorsTampered/g;
  1917. $cmd =~ s/%TEMPERATURE%/$temp/g;
  1918. $cmd =~ s/%TEMPERATURETREND%/$temptrend/g;
  1919. $cmd =~ s/%TOBE%/$conditionart/g;
  1920. $cmd =~ s/%TWILIGHT%/$twilight/g;
  1921. $cmd =~ s/%TWILIGHTEVENT%/$twilightevent/g;
  1922. $cmd =~ s/%UWZ%/$uwzc/g;
  1923. $cmd =~ s/%UWZLONG%/$uwzl/g;
  1924. $cmd =~ s/%UWZSHORT%/$uwzs/g;
  1925. $cmd =~ s/%WEATHER%/$weathershort/g;
  1926. $cmd =~ s/%WEATHERLONG%/$weatherlong/g;
  1927. $cmd =~ s/%WIND%/$wind/g;
  1928. $cmd =~ s/%WINDCHILL%/$windchill/g;
  1929. return $cmd;
  1930. }
  1931. sub HOMEMODE_serializeCMD($@)
  1932. {
  1933. my ($hash,@cmds) = @_;
  1934. my $name = $hash->{NAME};
  1935. my @newcmds;
  1936. foreach my $cmd (@cmds)
  1937. {
  1938. $cmd =~ s/\r\n/\n/gm;
  1939. my @newcmd;
  1940. foreach (split /\n+/,$cmd)
  1941. {
  1942. next if ($_ =~ /^\s*(#|$)/);
  1943. $_ =~ s/\s{2,}/ /g;
  1944. push @newcmd,$_;
  1945. }
  1946. $cmd = join(" ",@newcmd);
  1947. Log3 $name,5,"$name: cmdnew: $cmd";
  1948. push @newcmds,SemicolonEscape($cmd);
  1949. }
  1950. my $cmd = join(";",@newcmds);
  1951. $cmd =~ s/\}\s{0,1};\s{0,1}\{/\};;\{/g;
  1952. return $cmd;
  1953. }
  1954. sub HOMEMODE_ReadingTrend($$;$)
  1955. {
  1956. my ($hash,$read,$val) = @_;
  1957. my $name = $hash->{NAME};
  1958. $val = ReadingsNum($name,$read,5) if (!$val);
  1959. my $time = AttrNum($name,"HomeTrendCalcAge",900);
  1960. my $pval = ReadingsNum($name,".$read",undef);
  1961. if (defined $pval && ReadingsAge($name,".$read",0) >= $time)
  1962. {
  1963. my ($rising,$constant,$falling) = split /\|/,AttrVal($name,"HomeTextRisingConstantFalling","rising|constant|falling");
  1964. my $trend = $constant;
  1965. $trend = $rising if ($val > $pval);
  1966. $trend = $falling if ($val < $pval);
  1967. readingsBeginUpdate($hash);
  1968. readingsBulkUpdate($hash,".$read",$val);
  1969. readingsBulkUpdate($hash,$read."Trend",$trend);
  1970. readingsEndUpdate($hash,1);
  1971. }
  1972. elsif (!defined $pval)
  1973. {
  1974. readingsSingleUpdate($hash,".$read",$val,0);
  1975. }
  1976. }
  1977. sub HOMEMODE_WeatherTXT($$)
  1978. {
  1979. my ($hash,$text) = @_;
  1980. my $name = $hash->{NAME};
  1981. my $weather = AttrVal($name,"HomeYahooWeatherDevice","");
  1982. my $condition = ReadingsVal($weather,"condition","");
  1983. my $conditionart = ReadingsVal($name,".be","");
  1984. my $pressure = ReadingsVal($name,"pressure","");
  1985. my $pressuretrend = ReadingsVal($weather,"pressure_trend_txt","");
  1986. my $humi = ReadingsVal($name,"humidity",0);
  1987. my $temp = ReadingsVal($name,"temperature",0);
  1988. my $windchill = ReadingsVal($weather,"wind_chill",0);
  1989. my $wind = ReadingsVal($name,"wind",0);
  1990. $text =~ s/%CONDITION%/$condition/gm;
  1991. $text =~ s/%TOBE%/$conditionart/gm;
  1992. $text =~ s/%HUMIDITY%/$humi/gm;
  1993. $text =~ s/%PRESSURE%/$pressure/gm;
  1994. $text =~ s/%PRESSURETREND%/$pressuretrend/gm;
  1995. $text =~ s/%TEMPERATURE%/$temp/gm;
  1996. $text =~ s/%WINDCHILL%/$windchill/gm;
  1997. $text =~ s/%WIND%/$wind/gm;
  1998. return $text;
  1999. }
  2000. sub HOMEMODE_ForecastTXT($;$)
  2001. {
  2002. my ($hash,$day) = @_;
  2003. $day = 2 if (!$day);
  2004. my $name = $hash->{NAME};
  2005. my $weather = AttrVal($name,"HomeYahooWeatherDevice","");
  2006. my $cond = ReadingsVal($weather,"fc".$day."_condition","");
  2007. my $low = ReadingsVal($weather,"fc".$day."_low_c","");
  2008. my $high = ReadingsVal($weather,"fc".$day."_high_c","");
  2009. my $temp = ReadingsVal($name,"temperature","");
  2010. my $hum = ReadingsVal($name,"humidity","");
  2011. my $chill = ReadingsVal($weather,"wind_chill","");
  2012. my $wind = ReadingsVal($name,"wind","");
  2013. my $text;
  2014. if (defined $cond && defined $low && defined $high)
  2015. {
  2016. my ($today,$tomorrow,$atomorrow) = split /\|/,AttrVal($name,"HomeTextTodayTomorrowAfterTomorrow","today|tomorrow|day after tomorrow");
  2017. my $d = $today;
  2018. $d = $tomorrow if ($day == 2);
  2019. $d = $atomorrow if ($day == 3);
  2020. $d = $day-1 if ($day > 3);
  2021. $text = AttrVal($name,"HomeTextWeatherForecastToday","");
  2022. $text = AttrVal($name,"HomeTextWeatherForecastTomorrow","") if ($day =~ /^[23]$/);
  2023. $text = AttrVal($name,"HomeTextWeatherForecastInSpecDays","") if ($day > 3);
  2024. $text =~ s/%CONDITION%/$cond/gm;
  2025. $text =~ s/%DAY%/$d/gm;
  2026. $text =~ s/%HIGH%/$high/gm;
  2027. $text =~ s/%LOW%/$low/gm;
  2028. $text = HOMEMODE_WeatherTXT($hash,$text);
  2029. }
  2030. else
  2031. {
  2032. $text = AttrVal($name,"HomeTextWeatherNoForecast","No forecast available");
  2033. }
  2034. return $text;
  2035. }
  2036. sub HOMEMODE_uwzTXT($;$$)
  2037. {
  2038. my ($hash,$count,$sl) = @_;
  2039. my $name = $hash->{NAME};
  2040. $count = defined $count ? $count : ReadingsVal($name,"uwz_warnCount",0);
  2041. $sl = $sl ? "LongText" : "ShortText";
  2042. my $text = "";
  2043. for (my $i = 0; $i < $count; $i++)
  2044. {
  2045. my $read = "Warn_$i";
  2046. my $ii = $i + 1;
  2047. $text .= " " if ($i > 0);
  2048. $text .= "$ii. " if ($count > 1);
  2049. $text .= ReadingsVal(AttrVal($name,"HomeUWZ",""),$read."_$sl","");
  2050. }
  2051. return $text;
  2052. }
  2053. sub HOMEMODE_CheckIfIsValidDevspec($;$)
  2054. {
  2055. my ($spec,$read) = @_;
  2056. my @names;
  2057. foreach (devspec2array($spec))
  2058. {
  2059. next unless (IsDevice($_));
  2060. next if ($read && !defined ReadingsVal($_,$read,undef));
  2061. push @names,$_;
  2062. }
  2063. return if (!@names);
  2064. return \@names;
  2065. }
  2066. sub HOMEMODE_execUserCMDs($)
  2067. {
  2068. my ($string) = @_;
  2069. my ($name,$cmds,$resident) = split /\|/,$string;
  2070. my $hash = $defs{$name};
  2071. $cmds = decode_base64($cmds);
  2072. HOMEMODE_execCMDs($hash,$cmds,$resident);
  2073. return;
  2074. }
  2075. sub HOMEMODE_execCMDs($$;$)
  2076. {
  2077. my ($hash,$cmds,$resident) = @_;
  2078. my $name = $hash->{NAME};
  2079. my $cmd = HOMEMODE_replacePlaceholders($hash,$cmds,$resident);
  2080. my $err = AnalyzeCommandChain(undef,$cmd);
  2081. if ($err && $err !~ /^Deleted.reading/)
  2082. {
  2083. Log3 $name,3,"$name: error: $err";
  2084. Log3 $name,3,"$name: error in command: $cmd";
  2085. readingsSingleUpdate($hash,"lastCMDerror","error: >$err< in CMD: $cmd",1);
  2086. }
  2087. Log3 $name,4,"executed CMDs: $cmd";
  2088. return;
  2089. }
  2090. sub HOMEMODE_AttrCheck($$;$)
  2091. {
  2092. my ($hash,$attribute,$default) = @_;
  2093. $default = "" if (!defined $default);
  2094. my $name = $hash->{NAME};
  2095. my $value;
  2096. if ($hash->{helper}{lastChangedAttr} && $hash->{helper}{lastChangedAttr} eq $attribute)
  2097. {
  2098. $value = defined $hash->{helper}{lastChangedAttrValue} && $hash->{helper}{lastChangedAttrValue} ne "---" ? $hash->{helper}{lastChangedAttrValue} : $default;
  2099. }
  2100. else
  2101. {
  2102. $value = AttrVal($name,$attribute,$default);
  2103. }
  2104. return $value;
  2105. }
  2106. sub HOMEMODE_DayTime($)
  2107. {
  2108. my ($hash) = @_;
  2109. my $name = $hash->{NAME};
  2110. my $daytimes = HOMEMODE_AttrCheck($hash,"HomeDaytimes",$HOMEMODE_Daytimes);
  2111. my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime;
  2112. my $loctime = $hour * 60 + $min;
  2113. my @texts;
  2114. my @times;
  2115. foreach (split " ",$daytimes)
  2116. {
  2117. my ($dt,$text) = split /\|/;
  2118. my ($h,$m) = split /:/,$dt;
  2119. my $minutes = $h * 60 + $m;
  2120. push @times,$minutes;
  2121. push @texts,$text;
  2122. }
  2123. my $daytime = $texts[scalar @texts - 1];
  2124. for (my $x = 0; $x < scalar @times; $x++)
  2125. {
  2126. my $y = $x + 1;
  2127. $y = 0 if ($x == scalar @times - 1);
  2128. $daytime = $texts[$x] if ($y > $x && $loctime >= $times[$x] && $loctime < $times[$y]);
  2129. }
  2130. return $daytime;
  2131. }
  2132. sub HOMEMODE_SetDaytime($)
  2133. {
  2134. my ($hash) = @_;
  2135. my $name = $hash->{NAME};
  2136. my $dt = HOMEMODE_DayTime($hash);
  2137. if (ReadingsVal($name,"daytime","") ne $dt)
  2138. {
  2139. my @commands;
  2140. push @commands,AttrVal($name,"HomeCMDdaytime","") if (AttrVal($name,"HomeCMDdaytime",undef));
  2141. push @commands,AttrVal($name,"HomeCMDdaytime-$dt","") if (AttrVal($name,"HomeCMDdaytime-$dt",undef));
  2142. readingsSingleUpdate($hash,"daytime",$dt,1);
  2143. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  2144. }
  2145. }
  2146. sub HOMEMODE_SetSeason($)
  2147. {
  2148. my ($hash) = @_;
  2149. my $name = $hash->{NAME};
  2150. my $seasons = HOMEMODE_AttrCheck($hash,"HomeSeasons",$HOMEMODE_Seasons);
  2151. my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime;
  2152. my $locdays = ($month + 1) * 31 + $mday;
  2153. my @texts;
  2154. my @dates;
  2155. foreach (split " ",$seasons)
  2156. {
  2157. my ($date,$text) = split /\|/;
  2158. my ($m,$d) = split /\./,$date;
  2159. my $days = $m * 31 + $d;
  2160. push @dates,$days;
  2161. push @texts,$text;
  2162. }
  2163. my $season = $texts[scalar @texts - 1];
  2164. for (my $x = 0; $x < scalar @dates; $x++)
  2165. {
  2166. my $y = $x + 1;
  2167. $y = 0 if ($x == scalar @dates - 1);
  2168. $season = $texts[$x] if ($y > $x && $locdays >= $dates[$x] && $locdays < $dates[$y]);
  2169. }
  2170. if (ReadingsVal($name,"season","") ne $season)
  2171. {
  2172. my @commands;
  2173. push @commands,AttrVal($name,"HomeCMDseason","") if (AttrVal($name,"HomeCMDseason",undef));
  2174. push @commands,AttrVal($name,"HomeCMDseason-$season","") if (AttrVal($name,"HomeCMDseason-$season",undef));
  2175. readingsSingleUpdate($hash,"season",$season,1);
  2176. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  2177. }
  2178. }
  2179. sub HOMEMODE_hourMaker($)
  2180. {
  2181. my ($minutes) = @_;
  2182. my $trans = $HOMEMODE_de?
  2183. "keine gültigen Minuten übergeben":
  2184. "no valid minutes given";
  2185. return $trans if ($minutes !~ /^(\d{1,4})(\.\d{0,2})?$/ || $1 >= 6000 || $minutes < 0.01);
  2186. my $hours = int($minutes / 60);
  2187. $hours = length $hours > 1 ? $hours : "0$hours";
  2188. my $min = $minutes % 60;
  2189. $min = length $min > 1 ? $min : "0$min";
  2190. my $sec = int(($minutes - int($minutes)) * 60);
  2191. $sec = length $sec > 1 ? $sec : "0$sec";
  2192. return "$hours:$min:$sec";
  2193. }
  2194. sub HOMEMODE_addSensorsuserattr($$$)
  2195. {
  2196. my ($hash,$devs,$olddevs) = @_;
  2197. my $name = $hash->{NAME};
  2198. my @devspec = devspec2array($devs);
  2199. return if (!@devspec);
  2200. my @olddevspec = devspec2array($olddevs) if ($olddevs);
  2201. HOMEMODE_cleanUserattr($hash,$olddevs,$devs) if (@olddevspec);
  2202. my @names;
  2203. foreach my $sensor (@devspec)
  2204. {
  2205. my $alias = AttrVal($sensor,"alias","");
  2206. push @names,$sensor;
  2207. addToDevAttrList($sensor,"HomeModeAlarmActive");
  2208. addToDevAttrList($sensor,"HomeReadings");
  2209. addToDevAttrList($sensor,"HomeValues");
  2210. if ($hash->{SENSORSCONTACT} && grep(/^$sensor$/,split /,/,$hash->{SENSORSCONTACT}))
  2211. {
  2212. addToDevAttrList($sensor,"HomeContactType:doorinside,dooroutside,doormain,window");
  2213. addToDevAttrList($sensor,"HomeOpenMaxTrigger");
  2214. addToDevAttrList($sensor,"HomeOpenDontTriggerModes");
  2215. addToDevAttrList($sensor,"HomeOpenDontTriggerModesResidents");
  2216. addToDevAttrList($sensor,"HomeOpenTimeDividers");
  2217. addToDevAttrList($sensor,"HomeOpenTimes");
  2218. if (!AttrVal($sensor,"HomeContactType",undef))
  2219. {
  2220. my $dr = "[Dd]oor|[Tt](ü|ue)r";
  2221. my $wr = "[Ww]indow|[Ff]enster";
  2222. $attr{$sensor}{HomeContactType} = "doorinside" if ($alias =~ /$dr/ || $sensor =~ /$dr/);
  2223. $attr{$sensor}{HomeContactType} = "window" if ($alias =~ /$wr/ || $sensor =~ /$wr/);
  2224. }
  2225. $attr{$sensor}{HomeModeAlarmActive} = "armaway" if (!AttrVal($sensor,"HomeModeAlarmActive",undef));
  2226. }
  2227. if ($hash->{SENSORSMOTION} && grep(/^$sensor$/,split /,/,$hash->{SENSORSMOTION}))
  2228. {
  2229. addToDevAttrList($sensor,"HomeSensorLocation:inside,outside");
  2230. if (!AttrVal($sensor,"HomeSensorLocation",undef))
  2231. {
  2232. my $loc = "inside";
  2233. $loc = "outside" if ($alias =~ /([Aa]u(ss|ß)en)|([Oo]ut)/);
  2234. $attr{$sensor}{HomeSensorLocation} = $loc;
  2235. $attr{$sensor}{HomeModeAlarmActive} = "armaway" if (!AttrVal($sensor,"HomeModeAlarmActive",undef) && $loc eq "inside");
  2236. }
  2237. }
  2238. }
  2239. }
  2240. sub HOMEMODE_Luminance($;$$)
  2241. {
  2242. my ($hash,$dev,$lum) = @_;
  2243. my $name = $hash->{NAME};
  2244. my @sensors = split /,/,$hash->{SENSORSLUMINANCE};
  2245. my $read = AttrVal($name,"HomeSensorsLuminanceReading","luminance");
  2246. $lum = 0 if (!$lum);
  2247. foreach (@sensors)
  2248. {
  2249. my $val = ReadingsNum($_,$read,0);
  2250. next if ($val < 0);
  2251. $lum += $val if (!$dev || $dev ne $_);
  2252. }
  2253. my $lumval = defined $lum ? int ($lum / scalar @sensors) : undef;
  2254. if (defined $lumval && $lumval >= 0)
  2255. {
  2256. readingsSingleUpdate($hash,"luminance",$lumval,1);
  2257. HOMEMODE_ReadingTrend($hash,"luminance",$lumval);
  2258. }
  2259. }
  2260. sub HOMEMODE_TriggerState($;$$$)
  2261. {
  2262. my ($hash,$getter,$type,$trigger) = @_;
  2263. my $exit = 1 if (!$getter && !$type && $trigger);
  2264. $getter = "contactsOpen" if (!$getter);
  2265. $type = "all" if (!$type);
  2266. my $name = $hash->{NAME};
  2267. my $events = deviceEvents($defs{$trigger},1) if ($trigger);
  2268. my $contacts = $hash->{SENSORSCONTACT};
  2269. my $motions = $hash->{SENSORSMOTION};
  2270. my $tampered = ReadingsVal($name,"sensorsTampered","");
  2271. my @contactsOpen;
  2272. my @sensorsTampered;
  2273. my @doorsOOpen;
  2274. my @doorsMOpen;
  2275. my @insideOpen;
  2276. my @outsideOpen;
  2277. my @windowsOpen;
  2278. my @motionsOpen;
  2279. my @motionsInsideOpen;
  2280. my @motionsOutsideOpen;
  2281. my @alarmSensors;
  2282. my @lightSensors;
  2283. my $amode = ReadingsVal($name,"modeAlarm","");
  2284. if ($contacts)
  2285. {
  2286. foreach my $sensor (devspec2array("$contacts:FILTER=disable!=1"))
  2287. {
  2288. my ($oread,$tread) = split " ",AttrVal($sensor,"HomeReadings",AttrVal($name,"HomeSensorsContactReadings","state sabotageError")),2;
  2289. my $otcmd = AttrVal($sensor,"HomeValues",AttrVal($name,"HomeSensorsContactValues","open|tilted|on"));
  2290. my $amodea = AttrVal($sensor,"HomeModeAlarmActive","-");
  2291. my $ostate = ReadingsVal($sensor,$oread,"");
  2292. my $tstate = ReadingsVal($sensor,$tread,"") if ($tread);
  2293. my $kind = AttrVal($sensor,"HomeContactType","window");
  2294. next if (!$ostate && !$tstate);
  2295. if ($ostate =~ /^($otcmd)$/)
  2296. {
  2297. push @contactsOpen,$sensor;
  2298. push @insideOpen,$sensor if ($kind eq "doorinside");
  2299. push @doorsOOpen,$sensor if ($kind && $kind eq "dooroutside");
  2300. push @doorsMOpen,$sensor if ($kind && $kind eq "doormain");
  2301. push @outsideOpen,$sensor if ($kind =~ /^(dooroutside|doormain|window)$/);
  2302. push @windowsOpen,$sensor if ($kind eq "window");
  2303. if (grep /^($amodea)$/,$amode)
  2304. {
  2305. push @alarmSensors,$sensor;
  2306. }
  2307. if (defined $exit && $trigger eq $sensor && grep /^$oread:/,@{$events})
  2308. {
  2309. readingsBeginUpdate($hash);
  2310. readingsBulkUpdate($hash,"prevContact",ReadingsVal($name,"lastContact",""));
  2311. readingsBulkUpdate($hash,"lastContact",$sensor);
  2312. readingsEndUpdate($hash,1);
  2313. HOMEMODE_ContactCommands($hash,$sensor,"open",$kind);
  2314. HOMEMODE_ContactOpenCheck($name,$sensor,"open");
  2315. }
  2316. }
  2317. else
  2318. {
  2319. if (defined $exit && $trigger eq $sensor && grep /^$oread:/,@{$events})
  2320. {
  2321. readingsBeginUpdate($hash);
  2322. readingsBulkUpdate($hash,"prevContactClosed",ReadingsVal($name,"lastContactClosed",""));
  2323. readingsBulkUpdate($hash,"lastContactClosed",$sensor);
  2324. readingsEndUpdate($hash,1);
  2325. HOMEMODE_ContactCommands($hash,$sensor,"closed",$kind);
  2326. my $timer = "atTmp_HomeOpenTimer_".$sensor."_$name";
  2327. CommandDelete(undef,$timer) if (IsDevice($timer));
  2328. }
  2329. }
  2330. if ($tread && $tstate =~ /^($otcmd)$/)
  2331. {
  2332. push @sensorsTampered,$sensor;
  2333. }
  2334. }
  2335. }
  2336. if ($motions)
  2337. {
  2338. foreach my $sensor (devspec2array("$motions:FILTER=disable!=1"))
  2339. {
  2340. my ($oread,$tread) = split " ",AttrVal($sensor,"HomeReadings",AttrVal($name,"HomeSensorsMotionReadings","state sabotageError")),2;
  2341. my $otcmd = AttrVal($sensor,"HomeValues",AttrVal($name,"HomeSensorsMotionValues","open|on"));
  2342. my $amodea = AttrVal($sensor,"HomeModeAlarmActive","-");
  2343. my $ostate = ReadingsVal($sensor,$oread,"");
  2344. my $tstate = ReadingsVal($sensor,$tread,"") if ($tread);
  2345. my $kind = AttrVal($sensor,"HomeSensorLocation","inside");
  2346. next if (!$ostate && !$tstate);
  2347. if ($ostate =~ /^($otcmd)$/)
  2348. {
  2349. push @motionsOpen,$sensor;
  2350. push @motionsInsideOpen,$sensor if ($kind eq "inside");
  2351. push @motionsOutsideOpen,$sensor if ($kind eq "outside");
  2352. if (grep /^($amodea)$/,$amode)
  2353. {
  2354. push @alarmSensors,$sensor;
  2355. }
  2356. if (defined $exit && $trigger eq $sensor && grep /^$oread:/,@{$events})
  2357. {
  2358. readingsBeginUpdate($hash);
  2359. readingsBulkUpdate($hash,"prevMotion",ReadingsVal($name,"lastMotion",""));
  2360. readingsBulkUpdate($hash,"lastMotion",$sensor);
  2361. readingsEndUpdate($hash,1);
  2362. HOMEMODE_MotionCommands($hash,$sensor,"open");
  2363. }
  2364. }
  2365. else
  2366. {
  2367. if (defined $exit && $trigger eq $sensor && grep /^$oread:/,@{$events})
  2368. {
  2369. readingsBeginUpdate($hash);
  2370. readingsBulkUpdate($hash,"prevMotionClosed",ReadingsVal($name,"lastMotionClosed",""));
  2371. readingsBulkUpdate($hash,"lastMotionClosed",$sensor);
  2372. readingsEndUpdate($hash,1);
  2373. HOMEMODE_MotionCommands($hash,$sensor,"closed");
  2374. }
  2375. }
  2376. if ($tread && $tstate =~ /^($otcmd)$/)
  2377. {
  2378. push @sensorsTampered,$sensor;
  2379. }
  2380. }
  2381. }
  2382. HOMEMODE_alarmTriggered($hash,@alarmSensors);
  2383. my $open = @contactsOpen ? join(",",@contactsOpen) : "";
  2384. my $opendo = @doorsOOpen ? join(",",@doorsOOpen) : "";
  2385. my $opendm = @doorsMOpen ? join(",",@doorsMOpen) : "";
  2386. my $openi = @insideOpen ? join(",",@insideOpen) : "";
  2387. my $openm = @motionsOpen ? join(",",@motionsOpen) : "";
  2388. my $openmi = @motionsInsideOpen ? join(",",@motionsInsideOpen) : "";
  2389. my $openmo = @motionsOutsideOpen ? join(",",@motionsOutsideOpen) : "";
  2390. my $openo = @outsideOpen ? join(",",@outsideOpen) : "";
  2391. my $openw = @windowsOpen ? join(",",@windowsOpen) : "";
  2392. my $tamp = @sensorsTampered ? join(",",@sensorsTampered) : "";
  2393. readingsBeginUpdate($hash);
  2394. if ($contacts)
  2395. {
  2396. readingsBulkUpdateIfChanged($hash,"contactsDoorsInsideOpen",$openi);
  2397. readingsBulkUpdateIfChanged($hash,"contactsDoorsInsideOpen_ct",@insideOpen);
  2398. readingsBulkUpdateIfChanged($hash,"contactsDoorsInsideOpen_hr",HOMEMODE_makeHR($hash,0,@insideOpen));
  2399. readingsBulkUpdateIfChanged($hash,"contactsDoorsOutsideOpen",$opendo);
  2400. readingsBulkUpdateIfChanged($hash,"contactsDoorsOutsideOpen_ct",@doorsOOpen);
  2401. readingsBulkUpdateIfChanged($hash,"contactsDoorsOutsideOpen_hr",HOMEMODE_makeHR($hash,0,@doorsOOpen));
  2402. readingsBulkUpdateIfChanged($hash,"contactsDoorsMainOpen",$opendm);
  2403. readingsBulkUpdateIfChanged($hash,"contactsDoorsMainOpen_ct",@doorsMOpen);
  2404. readingsBulkUpdateIfChanged($hash,"contactsDoorsMainOpen_hr",HOMEMODE_makeHR($hash,0,@doorsMOpen));
  2405. readingsBulkUpdateIfChanged($hash,"contactsOpen",$open);
  2406. readingsBulkUpdateIfChanged($hash,"contactsOpen_ct",@contactsOpen);
  2407. readingsBulkUpdateIfChanged($hash,"contactsOpen_hr",HOMEMODE_makeHR($hash,0,@contactsOpen));
  2408. readingsBulkUpdateIfChanged($hash,"contactsOutsideOpen",$openo);
  2409. readingsBulkUpdateIfChanged($hash,"contactsOutsideOpen_ct",@outsideOpen);
  2410. readingsBulkUpdateIfChanged($hash,"contactsOutsideOpen_hr",HOMEMODE_makeHR($hash,0,@outsideOpen));
  2411. readingsBulkUpdateIfChanged($hash,"contactsWindowsOpen",$openw);
  2412. readingsBulkUpdateIfChanged($hash,"contactsWindowsOpen_ct",@windowsOpen);
  2413. readingsBulkUpdateIfChanged($hash,"contactsWindowsOpen_hr",HOMEMODE_makeHR($hash,0,@windowsOpen));
  2414. }
  2415. readingsBulkUpdateIfChanged($hash,"sensorsTampered",$tamp);
  2416. readingsBulkUpdateIfChanged($hash,"sensorsTampered_ct",@sensorsTampered);
  2417. readingsBulkUpdateIfChanged($hash,"sensorsTampered_hr",HOMEMODE_makeHR($hash,0,@sensorsTampered));
  2418. if ($motions)
  2419. {
  2420. readingsBulkUpdateIfChanged($hash,"motionsSensors",$openm);
  2421. readingsBulkUpdateIfChanged($hash,"motionsSensors_ct",@motionsOpen);
  2422. readingsBulkUpdateIfChanged($hash,"motionsSensors_hr",HOMEMODE_makeHR($hash,0,@motionsOpen));
  2423. readingsBulkUpdateIfChanged($hash,"motionsInside",$openmi);
  2424. readingsBulkUpdateIfChanged($hash,"motionsInside_ct",@motionsInsideOpen);
  2425. readingsBulkUpdateIfChanged($hash,"motionsInside_hr",HOMEMODE_makeHR($hash,0,@motionsInsideOpen));
  2426. readingsBulkUpdateIfChanged($hash,"motionsOutside",$openmo);
  2427. readingsBulkUpdateIfChanged($hash,"motionsOutside_ct",@motionsOutsideOpen);
  2428. readingsBulkUpdateIfChanged($hash,"motionsOutside_hr",HOMEMODE_makeHR($hash,0,@motionsOutsideOpen));
  2429. }
  2430. readingsEndUpdate($hash,1);
  2431. HOMEMODE_alarmTampered($hash,@sensorsTampered) if (join(",",@sensorsTampered) ne $tampered);
  2432. if ($getter eq "contactsOpen")
  2433. {
  2434. return "open contacts: $open" if ($open && $type eq "all");
  2435. return "no open contacts" if (!$open && $type eq "all");
  2436. return "open doorsinside: $openi" if ($openi && $type eq "doorsinside");
  2437. return "no open doorsinside" if (!$openi && $type eq "doorsinside");
  2438. return "open doorsoutside: $opendo" if ($opendo && $type eq "doorsoutside");
  2439. return "no open doorsoutside" if (!$opendo && $type eq "doorsoutside");
  2440. return "open doorsmain: $opendm" if ($opendm && $type eq "doorsmain");
  2441. return "no open doorsmain" if (!$opendm && $type eq "doorsmain");
  2442. return "open outside: $openo" if ($openo && $type eq "outside");
  2443. return "no open outside" if (!$openo && $type eq "outside");
  2444. return "open windows: $openw" if ($openw && $type eq "windows");
  2445. return "no open windows" if (!$openw && $type eq "windows");
  2446. }
  2447. elsif ($getter eq "sensorsTampered")
  2448. {
  2449. return "tampered sensors: $tamp" if ($tamp);
  2450. return "no tampered sensors" if (!$tamp);
  2451. }
  2452. return;
  2453. }
  2454. sub HOMEMODE_name2alias($;$)
  2455. {
  2456. my ($name,$witharticle) = @_;
  2457. my $alias = AttrVal($name,"alias",$name);
  2458. my $art;
  2459. $art = "der" if ($alias =~ /[Ss]ensor/);
  2460. $art = "die" if ($alias =~ /[Tt](ü|ue)r/);
  2461. $art = "das" if ($alias =~ /[Ff]enster/);
  2462. my $ret = $witharticle && $art ? "$art $alias" : $alias;
  2463. return $ret;
  2464. }
  2465. sub HOMEMODE_ContactOpenCheck($$;$$)
  2466. {
  2467. my ($name,$contact,$state,$retrigger) = @_;
  2468. $retrigger = 0 if (!$retrigger);
  2469. my $maxtrigger = AttrNum($contact,"HomeOpenMaxTrigger",0);
  2470. if ($maxtrigger)
  2471. {
  2472. my $mode = ReadingsVal($name,"state","");
  2473. my $dtmode = AttrVal($contact,"HomeOpenDontTriggerModes","");
  2474. my $dtres = AttrVal($contact,"HomeOpenDontTriggerModesResidents","");
  2475. my $donttrigger = 0;
  2476. $donttrigger = 1 if ($dtmode && $mode =~ /^($dtmode)$/);
  2477. if (!$donttrigger && $dtres)
  2478. {
  2479. foreach (devspec2array($dtres))
  2480. {
  2481. $donttrigger = 1 if (ReadingsVal($_,"state","") =~ /^($dtmode)$/);
  2482. }
  2483. }
  2484. my $timer = "atTmp_HomeOpenTimer_".$contact."_$name";
  2485. CommandDelete(undef,$timer) if (IsDevice($timer) && ($retrigger || $donttrigger));
  2486. return if (!$retrigger && $donttrigger);
  2487. my $season = ReadingsVal($name,"season","");
  2488. my $seasons = AttrVal($name,"HomeSeasons",$HOMEMODE_Seasons);
  2489. my $dividers = AttrVal($contact,"HomeOpenTimeDividers",AttrVal($name,"HomeSensorsContactOpenTimeDividers",""));
  2490. my $mintime = AttrNum($name,"HomeSensorsContactOpenTimeMin",0);
  2491. my @wt = split " ",AttrVal($contact,"HomeOpenTimes",AttrVal($name,"HomeSensorsContactOpenTimes","10"));
  2492. my $waittime;
  2493. Log3 $name,5,"$name: retrigger: $retrigger";
  2494. $waittime = $wt[$retrigger] if ($wt[$retrigger]);
  2495. $waittime = $wt[scalar @wt - 1] if (!defined $waittime);
  2496. Log3 $name,5,"$name: waittime real: $waittime";
  2497. if ($dividers && AttrVal($contact,"HomeContactType","window") !~ /^door(inside|main)$/)
  2498. {
  2499. my @divs = split " ",$dividers;
  2500. my $divider;
  2501. my $count = 0;
  2502. foreach (split " ",$seasons)
  2503. {
  2504. my ($date,$text) = split /\|/;
  2505. $divider = $divs[$count] if ($season eq $text);
  2506. $count++;
  2507. }
  2508. if ($divider)
  2509. {
  2510. $waittime = $waittime / $divider;
  2511. $waittime = sprintf("%.2f",$waittime) * 1;
  2512. }
  2513. }
  2514. $waittime = $mintime if ($mintime && $waittime < $mintime);
  2515. $retrigger++;
  2516. Log3 $name,5,"$name: waittime divided: $waittime";
  2517. $waittime = HOMEMODE_hourMaker($waittime);
  2518. my $at = "{HOMEMODE_ContactOpenCheck(\"$name\",\"$contact\",\"\",$retrigger)}" if ($retrigger <= $maxtrigger);
  2519. my $contactname = HOMEMODE_name2alias($contact,1);
  2520. my $contactread = (split " ",AttrVal($contact,"HomeReadings",AttrVal($name,"HomeSensorsContactReadings","state sabotageError")))[0];
  2521. $state = $state ? $state : ReadingsVal($contact,$contactread,"");
  2522. my $opencmds = AttrVal($contact,"HomeValues",AttrVal($name,"HomeSensorsContactValues","open|tilted|on"));
  2523. if ($state =~ /^($opencmds|open)$/)
  2524. {
  2525. CommandDefine(undef,"$timer at +$waittime $at") if ($at && !IsDevice($timer));
  2526. if ($retrigger > 1)
  2527. {
  2528. my @commands;
  2529. my $hash = $defs{$name};
  2530. Log3 $name,5,"$name: maxtrigger: $maxtrigger";
  2531. my $cmd = AttrVal($name,"HomeCMDcontactOpenWarning1","");
  2532. $cmd = AttrVal($name,"HomeCMDcontactOpenWarning2","") if (AttrVal($name,"HomeCMDcontactOpenWarning2",undef) && $retrigger > 2);
  2533. $cmd = AttrVal($name,"HomeCMDcontactOpenWarningLast","") if (AttrVal($name,"HomeCMDcontactOpenWarningLast",undef) && $retrigger == $maxtrigger + 1);
  2534. if ($cmd)
  2535. {
  2536. my ($c,$o) = split /\|/,AttrVal($name,"HomeTextClosedOpen","closed|open");
  2537. $state = $state =~ /^($opencmds)$/ ? $o : $c;
  2538. $cmd =~ s/%ALIAS%/$contactname/gm;
  2539. $cmd =~ s/%SENSOR%/$contact/gm;
  2540. $cmd =~ s/%STATE%/$state/gm;
  2541. push @commands,$cmd;
  2542. }
  2543. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  2544. }
  2545. }
  2546. }
  2547. }
  2548. sub HOMEMODE_ContactOpenCheckAfterModeChange($$$;$)
  2549. {
  2550. my ($hash,$mode,$pmode,$resident) = @_;
  2551. my $name = $hash->{NAME};
  2552. my $contacts = ReadingsVal($name,"contactsOpen","");
  2553. $mode = ReadingsVal($name,"mode","") if (!$mode);
  2554. $pmode = ReadingsVal($name,"prevMode","") if (!$pmode);
  2555. my $state = ReadingsVal($resident,"state","") if ($resident);
  2556. my $pstate = ReadingsVal($resident,"lastState","") if ($resident);
  2557. if ($contacts)
  2558. {
  2559. foreach (split /,/,$contacts)
  2560. {
  2561. my $m = AttrVal($_,"HomeOpenDontTriggerModes","");
  2562. my $r = AttrVal($_,"HomeOpenDontTriggerModesResidents","");
  2563. $r = s/,/\|/g;
  2564. if ($resident && $m && $r && $resident =~ /^($r)$/ && $state =~ /^($m)$/ && $pstate !~ /^($m)$/)
  2565. {
  2566. HOMEMODE_ContactOpenCheck($name,$_,"open");
  2567. }
  2568. elsif ($m && !$r && $pmode =~ /^($m)$/ && $mode !~ /^($m)$/)
  2569. {
  2570. HOMEMODE_ContactOpenCheck($name,$_,"open");
  2571. }
  2572. }
  2573. }
  2574. }
  2575. sub HOMEMODE_ContactCommands($$$$)
  2576. {
  2577. my ($hash,$contact,$state,$kind) = @_;
  2578. my $name = $hash->{NAME};
  2579. my $alias = HOMEMODE_name2alias($contact,1);
  2580. my @cmds;
  2581. push @cmds,AttrVal($name,"HomeCMDcontact","") if (AttrVal($name,"HomeCMDcontact",undef));
  2582. push @cmds,AttrVal($name,"HomeCMDcontactOpen","") if (AttrVal($name,"HomeCMDcontactOpen",undef) && $state eq "open");
  2583. push @cmds,AttrVal($name,"HomeCMDcontactClosed","") if (AttrVal($name,"HomeCMDcontactClosed",undef) && $state eq "closed");
  2584. push @cmds,AttrVal($name,"HomeCMDcontactDoormain","") if (AttrVal($name,"HomeCMDcontactDoormain",undef) && $kind eq "doormain");
  2585. push @cmds,AttrVal($name,"HomeCMDcontactDoormainOpen","") if (AttrVal($name,"HomeCMDcontactDoormainOpen",undef) && $kind eq "doormain" && $state eq "open");
  2586. push @cmds,AttrVal($name,"HomeCMDcontactDoormainClosed","") if (AttrVal($name,"HomeCMDcontactDoormainClosed",undef) && $kind eq "doormain" && $state eq "closed");
  2587. if (@cmds)
  2588. {
  2589. my @commands;
  2590. foreach my $cmd (@cmds)
  2591. {
  2592. my ($c,$o) = split /\|/,AttrVal($name,"HomeTextClosedOpen","closed|open");
  2593. my $sta = $state eq "open" ? $o : $c;
  2594. $cmd =~ s/%ALIAS%/$alias/gm;
  2595. $cmd =~ s/%SENSOR%/$contact/gm;
  2596. $cmd =~ s/%STATE%/$sta/gm;
  2597. push @commands,$cmd;
  2598. }
  2599. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands));
  2600. }
  2601. }
  2602. sub HOMEMODE_MotionCommands($$$)
  2603. {
  2604. my ($hash,$sensor,$state) = @_;
  2605. my $name = $hash->{NAME};
  2606. my $alias = HOMEMODE_name2alias($sensor,1);
  2607. my @cmds;
  2608. push @cmds,AttrVal($name,"HomeCMDmotion","") if (AttrVal($name,"HomeCMDmotion",undef));
  2609. push @cmds,AttrVal($name,"HomeCMDmotion-on","") if (AttrVal($name,"HomeCMDmotion-on",undef) && $state eq "open");
  2610. push @cmds,AttrVal($name,"HomeCMDmotion-off","") if (AttrVal($name,"HomeCMDmotion-off",undef) && $state eq "closed");
  2611. if (@cmds)
  2612. {
  2613. my @commands;
  2614. foreach my $cmd (@cmds)
  2615. {
  2616. my ($c,$o) = split /\|/,AttrVal($name,"HomeTextClosedOpen","closed|open");
  2617. $state = $state eq "open" ? $o : $c;
  2618. $cmd =~ s/%ALIAS%/$alias/gm;
  2619. $cmd =~ s/%SENSOR%/$sensor/gm;
  2620. $cmd =~ s/%STATE%/$state/gm;
  2621. push @commands,$cmd;
  2622. }
  2623. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands));
  2624. }
  2625. }
  2626. sub HOMEMODE_EventCommands($$$)
  2627. {
  2628. my ($hash,$cal,$event) = @_;
  2629. my $name = $hash->{NAME};
  2630. my $prevevent = ReadingsVal($name,"event-$cal","");
  2631. if ($event ne $prevevent)
  2632. {
  2633. my $evt = $event;
  2634. $evt =~ s/\s+/-/g;
  2635. my $pevt = $prevevent;
  2636. $pevt =~ s/\s+/-/g;
  2637. my @cmds;
  2638. push @cmds,AttrVal($name,"HomeCMDevent","") if (AttrVal($name,"HomeCMDevent",undef));
  2639. push @cmds,AttrVal($name,"HomeCMDevent-$cal-each","") if (AttrVal($name,"HomeCMDevent-$cal-each",undef));
  2640. push @cmds,AttrVal($name,"HomeCMDevent-$cal-$evt-begin","") if (AttrVal($name,"HomeCMDevent-$cal-$evt-begin",undef));
  2641. push @cmds,AttrVal($name,"HomeCMDevent-$cal-$pevt-end","") if (AttrVal($name,"HomeCMDevent-$cal-$pevt-end",undef));
  2642. if (@cmds)
  2643. {
  2644. my @commands;
  2645. foreach my $cmd (@cmds)
  2646. {
  2647. $cmd =~ s/%CALENDAR%/$cal/gm;
  2648. $cmd =~ s/%EVENT%/$event/gm;
  2649. $cmd =~ s/%PREVEVENT%/$prevevent/gm;
  2650. push @commands,$cmd;
  2651. }
  2652. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands));
  2653. }
  2654. readingsSingleUpdate($hash,"event-$cal",$event,1);
  2655. }
  2656. }
  2657. sub HOMEMODE_UWZCommands($$)
  2658. {
  2659. my ($hash,$events) = @_;
  2660. my $name = $hash->{NAME};
  2661. my $prev = ReadingsNum($name,"uwz_warnCount",-1);
  2662. my $uwz = AttrVal($name,"HomeUWZ","");
  2663. my $count;
  2664. my $warning;
  2665. foreach my $evt (@{$events})
  2666. {
  2667. next unless (grep /^WarnCount:\s[0-9]$/,$evt);
  2668. $count = $evt;
  2669. $count =~ s/^WarnCount:\s//;
  2670. }
  2671. if (defined $count)
  2672. {
  2673. readingsSingleUpdate($hash,"uwz_warnCount",$count,1);
  2674. if ($count != $prev)
  2675. {
  2676. my $se = $count > 0 ? "begin" : "end";
  2677. my @cmds;
  2678. push @cmds,AttrVal($name,"HomeCMDuwz-warn-$se","") if (AttrVal($name,"HomeCMDuwz-warn-$se",undef));
  2679. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@cmds)) if (@cmds);
  2680. }
  2681. }
  2682. }
  2683. sub HOMEMODE_HomebridgeMapping($)
  2684. {
  2685. my ($hash) = @_;
  2686. my $name = $hash->{NAME};
  2687. my $mapping;
  2688. $mapping .= "SecuritySystemCurrentState=alarmState,values=armhome:0;armaway:1;armnight:2;disarm:3;alarm:4";
  2689. $mapping .= "\nSecuritySystemTargetState=modeAlarm,values=armhome:0;armaway:1;armnight:2;disarm:3,cmds=0:modeAlarm+armhome;1:modeAlarm+armaway;2:modeAlarm+armnight;3:modeAlarm+disarm,delay=1";
  2690. $mapping .= "\nSecuritySystemAlarmType=alarmTriggered_ct,values=0:0;/.*/:1";
  2691. $mapping .= "\nOccupancyDetected=presence,values=present:1;absent:0";
  2692. $mapping .= "\nMute=dnd,valueOn=on,cmds=1:dnd+on;0:dnd+off";
  2693. $mapping .= "\nOn=anyoneElseAtHome,valueOn=on,cmdOn=anyoneElseAtHome+on,cmdOff=anyoneElseAtHome+off";
  2694. $mapping .= "\nContactSensorState=contactsOutsideOpen_ct,values=0:0;/.*/:1" if (defined ReadingsVal($name,"contactsOutsideOpen_ct",undef));
  2695. $mapping .= "\nStatusTampered=sensorsTampered_ct,values=0:0;/.*/:1" if (defined ReadingsVal($name,"sensorsTampered_ct",undef));
  2696. $mapping .= "\nMotionDetected=motionsInside_ct,values=0:0;/.*/:1" if (defined ReadingsVal($name,"motionsInside_ct",undef));
  2697. $mapping .= "\nStatusLowBattery=batteryLow_ct,values=0:0;/.*/:1" if (defined ReadingsVal($name,"batteryLow_ct",undef));
  2698. $mapping .= "\nE863F10F-079E-48FF-8F27-9C2605A29F52=pressure,name=AirPressure,format=UINT16" if (defined ReadingsVal($name,"wind",undef));
  2699. addToDevAttrList($name,"genericDeviceType") if (!grep /^genericDeviceType/,split(" ",AttrVal("global","userattr","")));
  2700. addToDevAttrList($name,"homebridgeMapping:textField-long") if (!grep /^homebridgeMapping/,split(" ",AttrVal("global","userattr","")));
  2701. $attr{$name}{genericDeviceType} = "security";
  2702. $attr{$name}{homebridgeMapping} = $mapping;
  2703. return;
  2704. }
  2705. sub HOMEMODE_PowerEnergy($;$$$)
  2706. {
  2707. my ($hash,$trigger,$read,$val) = @_;
  2708. my $name = $hash->{NAME};
  2709. if ($trigger && $read && $val)
  2710. {
  2711. foreach (split /,/,$hash->{SENSORSENERGY})
  2712. {
  2713. next if ($_ eq $trigger);
  2714. my $v = ReadingsNum($_,$read,0);
  2715. $val += $v if ($v && $v > 0);
  2716. }
  2717. return if ($val < 0);
  2718. $val = sprintf("%.2f",$val);
  2719. readingsSingleUpdate($hash,$read,$val,1);
  2720. }
  2721. else
  2722. {
  2723. my $power = 0;
  2724. my $energy = 0;
  2725. my ($pr,$er) = split " ",AttrVal($name,"HomeSensorsPowerEnergyReadings","power energy");
  2726. foreach (split /,/,$hash->{SENSORSENERGY})
  2727. {
  2728. my $p = ReadingsNum($_,$pr,0);
  2729. my $e = ReadingsNum($_,$er,0);
  2730. $power += $p if ($p && $p > 0);
  2731. $energy += $e if ($e && $e > 0);
  2732. }
  2733. $power = sprintf("%.2f",$power);
  2734. $energy = sprintf("%.2f",$energy);
  2735. readingsBeginUpdate($hash);
  2736. readingsBulkUpdate($hash,"power",$power) if ($power * 1 > 0);
  2737. readingsBulkUpdate($hash,"energy",$energy) if ($energy * 1 > 0);
  2738. readingsEndUpdate($hash,1);
  2739. }
  2740. }
  2741. sub HOMEMODE_Weather($$)
  2742. {
  2743. my ($hash,$dev) = @_;
  2744. my $name = $hash->{NAME};
  2745. my $cond = ReadingsVal($dev,"condition","");
  2746. my ($and,$are,$is) = split /\|/,AttrVal($name,"HomeTextAndAreIs","and|are|is");
  2747. my $be = $cond =~ /(und|and|[Gg]ewitter|[Tt]hunderstorm|[Ss]chauer|[Ss]hower)/ ? $are : $is;
  2748. readingsBeginUpdate($hash);
  2749. readingsBulkUpdate($hash,"humidity",ReadingsVal($dev,"humidity",5)) if (!$hash->{helper}{externalHumidity});
  2750. readingsBulkUpdate($hash,"temperature",ReadingsVal($dev,"temperature",5)) if (!AttrVal($name,"HomeSensorTemperatureOutside",undef));
  2751. readingsBulkUpdate($hash,"wind",ReadingsVal($dev,"wind",5)) if (!AttrVal($name,"HomeSensorWindspeed",undef));
  2752. readingsBulkUpdate($hash,"pressure",ReadingsVal($dev,"pressure",5)) if (!AttrVal($name,"HomeSensorAirpressure",undef));
  2753. readingsBulkUpdate($hash,".be",$be);
  2754. readingsEndUpdate($hash,1);
  2755. HOMEMODE_ReadingTrend($hash,"humidity") if (!$hash->{helper}{externalHumidity});
  2756. HOMEMODE_ReadingTrend($hash,"temperature") if (!AttrVal($name,"HomeSensorTemperatureOutside",undef));
  2757. HOMEMODE_Icewarning($hash);
  2758. }
  2759. sub HOMEMODE_Twilight($$;$)
  2760. {
  2761. my ($hash,$dev,$force) = @_;
  2762. my $name = $hash->{NAME};
  2763. my $events = deviceEvents($defs{$dev},1);
  2764. if ($force)
  2765. {
  2766. readingsBeginUpdate($hash);
  2767. readingsBulkUpdate($hash,"light",ReadingsVal($dev,"light",5));
  2768. readingsBulkUpdate($hash,"twilight",ReadingsVal($dev,"twilight",5));
  2769. readingsBulkUpdate($hash,"twilightEvent",ReadingsVal($dev,"aktEvent",5));
  2770. readingsEndUpdate($hash,1);
  2771. }
  2772. elsif ($events)
  2773. {
  2774. my $pevent = ReadingsVal($name,"twilightEvent","");
  2775. foreach my $event (@{$events})
  2776. {
  2777. my $val = (split " ",$event)[1];
  2778. readingsBeginUpdate($hash);
  2779. readingsBulkUpdate($hash,"light",$val) if ($event =~ /^light:/);
  2780. readingsBulkUpdate($hash,"twilight",$val) if ($event =~ /^twilight:/);
  2781. if ($event =~ /^aktEvent:/)
  2782. {
  2783. readingsBulkUpdate($hash,"twilightEvent",$val);
  2784. if ($val ne $pevent)
  2785. {
  2786. my @commands;
  2787. push @commands,AttrVal($name,"HomeCMDtwilight","") if (AttrVal($name,"HomeCMDtwilight",undef));
  2788. push @commands,AttrVal($name,"HomeCMDtwilight-$val","") if (AttrVal($name,"HomeCMDtwilight-$val",undef));
  2789. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  2790. }
  2791. }
  2792. readingsEndUpdate($hash,1);
  2793. }
  2794. }
  2795. }
  2796. sub HOMEMODE_Icewarning($)
  2797. {
  2798. my ($hash) = @_;
  2799. my $name = $hash->{NAME};
  2800. my $ice = ReadingsVal($name,"icewarning",2);
  2801. my $temp = ReadingsVal($name,"temperature",5);
  2802. my $temps = AttrVal($name,"HomeIcewarningOnOffTemps","2 3");
  2803. my $iceon = (split " ",$temps)[0] * 1;
  2804. my $iceoff = (split " ",$temps)[1] ? (split " ",$temps)[1] * 1 : $iceon;
  2805. my $icewarning = 0;
  2806. my $icewarningcmd = "off";
  2807. $icewarning = 1 if ((!$ice && $temp <= $iceon) || ($ice && $temp <= $iceoff));
  2808. $icewarningcmd = "on" if ($icewarning == 1);
  2809. if ($ice != $icewarning)
  2810. {
  2811. my @commands;
  2812. push @commands,AttrVal($name,"HomeCMDicewarning-$icewarningcmd","") if (AttrVal($name,"HomeCMDicewarning-$icewarningcmd",undef));
  2813. readingsSingleUpdate($hash,"icewarning",$icewarning,1);
  2814. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  2815. }
  2816. }
  2817. sub HOMEMODE_CheckHolidayDevices($)
  2818. {
  2819. my ($specs) = @_;
  2820. my @wrongdevices;
  2821. foreach (devspec2array($specs))
  2822. {
  2823. push @wrongdevices,$_ if (!IsDevice($_,"holiday"));
  2824. }
  2825. return \@wrongdevices if (@wrongdevices);
  2826. return;
  2827. }
  2828. sub HOMEMODE_HolidayEvents($)
  2829. {
  2830. my ($calendar) = @_;
  2831. my @events;
  2832. my $fname = AttrVal("global","modpath",".")."/FHEM/".$calendar.".holiday";
  2833. my (undef,@holidayfile) = FileRead($fname);
  2834. foreach (@holidayfile)
  2835. {
  2836. next if ($_ =~ /^\s*(#|$)/);
  2837. my @parts = split;
  2838. my $part = $parts[0] =~ /^(1|2)$/ ? 2 : $parts[0] == 3 ? 4 : $parts[0] == 4 ? 3 : 5;
  2839. for (my $p = 0; $p < $part; $p++)
  2840. {
  2841. shift @parts;
  2842. }
  2843. push @events,join("-",@parts);
  2844. }
  2845. return (\@events);
  2846. }
  2847. sub HOMEMODE_checkIP($;$)
  2848. {
  2849. my ($hash,$r) = @_;
  2850. my $name = $hash->{NAME};
  2851. my $ip = GetFileFromURL("http://icanhazip.com/");
  2852. return if (!$ip);
  2853. $ip =~ s/\s+//g;
  2854. chomp $ip;
  2855. if (ReadingsVal($name,"publicIP","") ne $ip)
  2856. {
  2857. my @commands;
  2858. readingsSingleUpdate($hash,"publicIP",$ip,1);
  2859. push @commands,AttrVal($name,"HomeCMDpublic-ip-change","") if (AttrVal($name,"HomeCMDpublic-ip-change",undef));
  2860. HOMEMODE_execCMDs($hash,HOMEMODE_serializeCMD($hash,@commands)) if (@commands);
  2861. }
  2862. if (AttrNum($name,"HomePublicIpCheckInterval",0))
  2863. {
  2864. my $timer = gettimeofday() + 60 * AttrNum($name,"HomePublicIpCheckInterval",0);
  2865. $hash->{".IP_TRIGGERTIME_NEXT"} = $timer;
  2866. }
  2867. return $ip if ($r);
  2868. return;
  2869. }
  2870. sub HOMEMODE_Details($$$)
  2871. {
  2872. my ($FW_name,$name,$room) = @_;
  2873. return if (AttrVal($name,"HomeAdvancedDetails","none") eq "none" || (AttrVal($name,"HomeAdvancedDetails","") eq "room" && $FW_detail eq $name));
  2874. my $hash = $defs{$name};
  2875. my $iid = ReadingsVal($name,"lastInfo","") ? ReadingsVal($name,"lastInfo","") : "";
  2876. my $info = ReadingsVal($name,$iid,"");
  2877. my $html = "<div>";
  2878. $html .= "<style>.homehover{cursor:pointer}.homeinfo{display:none}.tar{text-align:right}.homeinfopanel{min-height:30px;max-width:480px;padding:3px 10px}</style>";
  2879. $html .= "<div class=\"homeinfopanel\" informid=\"$name-$iid\">$info</div>";
  2880. $html .= "<table class=\"wide\">";
  2881. if (AttrVal($name,"HomeYahooWeatherDevice",""))
  2882. {
  2883. $html .= "<tr class=\"homehover\">";
  2884. my $temp = $HOMEMODE_de ? "Temperatur" : "Temperature";
  2885. $html .= "<td class=\"tar\">$temp:</td>";
  2886. $html .= "<td class=\"dval\"><span informid=\"$name-temperature\">".ReadingsVal($name,"temperature","")."</span> °C<span class=\"homeinfo\" informid=\"\">".HOMEMODE_ForecastTXT($hash,1)."</span></td>";
  2887. my $humi = $HOMEMODE_de ? "Luftfeuchte" : "Humidity";
  2888. $html .= "<td class=\"tar\">$humi:";
  2889. $html .= "<td class=\"dval\"><span informid=\"$name-humidity\">".ReadingsVal($name,"humidity","")."</span> %</td>";
  2890. my $pres = $HOMEMODE_de ? "Luftdruck" : "Air pressure";
  2891. $html .= "<td class=\"tar\">$pres:</td>";
  2892. $html .= "<td class=\"dval\"><span informid=\"$name-pressure\">".ReadingsVal($name,"pressure","")."</span> hPa</td>";
  2893. $html .= "</tr>";
  2894. }
  2895. if (AttrVal($name,"HomeSensorsPowerEnergy","") && AttrVal($name,"HomeSensorsLuminance",""))
  2896. {
  2897. $html .= "<tr>";
  2898. my $power = $HOMEMODE_de ? "Leistung" : "Power";
  2899. $html .= "<td class=\"tar\">$power:</td>";
  2900. $html .= "<td class=\"dval\"><span informid=\"$name-power\">".ReadingsVal($name,"power","")."</span> W</td>";
  2901. my $energy = $HOMEMODE_de ? "Energie" : "Energy";
  2902. $html .= "<td class=\"tar\">$energy:";
  2903. $html .= "<td class=\"dval\"><span informid=\"$name-energy\">".ReadingsVal($name,"energy","")."</span> kWh</td>";
  2904. my $lum = $HOMEMODE_de ? "Licht" : "Luminance";
  2905. $html .= "<td class=\"tar\">$lum:</td>";
  2906. $html .= "<td class=\"dval\"><span informid=\"$name-luminance\">".ReadingsVal($name,"luminance","")."</span> lux</td>";
  2907. $html .= "</tr>";
  2908. }
  2909. if (AttrVal($name,"HomeSensorsContact",""))
  2910. {
  2911. $html .= "<tr>";
  2912. my $open = $HOMEMODE_de ? "Offen" : "Open";
  2913. $html .= "<td class=\"tar\">$open:</td>";
  2914. $html .= "<td class=\"dval homehover\"><span informid=\"$name-contactsOpen_ct\">".ReadingsVal($name,"contactsOpen_ct","")."</span><span class=\"homeinfo\" informid=\"$name-contactsOpen_hr\">".ReadingsVal($name,"contactsOpen_hr","")."</span></td>";
  2915. my $tamp = $HOMEMODE_de ? "Sabotiert" : "Tampered";
  2916. $html .= "<td class=\"tar\">$tamp:</td>";
  2917. $html .= "<td class=\"dval homehover\"><span informid=\"$name-sensorsTampered_ct\">".ReadingsVal($name,"sensorsTampered_ct","")."</span><span class=\"homeinfo\" informid=\"$name-sensorsTampered_hr\">".ReadingsVal($name,"sensorsTampered_hr","")."</span></td>";
  2918. my $alarms = $HOMEMODE_de ? "Alarme" : "Alarms";
  2919. $html .= "<td class=\"tar\">$alarms:</td>";
  2920. $html .= "<td class=\"dval homehover\"><span informid=\"$name-alarmTriggered_ct\">".ReadingsVal($name,"alarmTriggered_ct","")."</span><span class=\"homeinfo\" informid=\"$name-alarmTriggered_hr\">".ReadingsVal($name,"alarmTriggered_hr","")."</span></td>";
  2921. $html .= "</tr>";
  2922. }
  2923. $html .= "</table>";
  2924. $html .= "</div>";
  2925. $html .= "<script>";
  2926. $html .= "\$(\".homehover\").unbind().click(function(){";
  2927. $html .= "var t=\$(this).find(\".homeinfo\").text();";
  2928. $html .= "var id=\$(this).find(\".homeinfo\").attr(\"informid\");";
  2929. $html .= "var r=id.split(\"-\")[1];";
  2930. $html .= "\$(\".homeinfopanel\").text(t).attr(\"informid\",id);";
  2931. $html .= "if(r){\$.post(window.location.pathname+\"?cmd=setreading%20$name%20lastInfo%20\"+r+\"$FW_CSRF\")};";
  2932. $html .= "});</script>";
  2933. return $html;
  2934. }
  2935. 1;
  2936. =pod
  2937. =item helper
  2938. =item summary home device with ROOMMATE/GUEST integration
  2939. =item summary_DE Zuhause Ger&auml;t mit ROOMMATE/GUEST Integration
  2940. =begin html
  2941. <a name="HOMEMODE"></a>
  2942. <h3>HOMEMODE</h3>
  2943. <ul>
  2944. <i>HOMEMODE</i> is designed to represent the overall home state(s) in one device.<br>
  2945. It uses the attribute userattr extensively.<br>
  2946. It has been optimized for usage with homebridge as GUI.<br>
  2947. You can also configure CMDs to be executed on specific events.<br>
  2948. There is no need to create notify(s) or DOIF(s) to achieve common tasks depending on the home state(s).<br>
  2949. It's also possible to control ROOMMATE/GUEST devices states depending on their associated presence device.<br>
  2950. If the RESIDENTS device is on state home, the HOMEMODE device can automatically change its mode depending on the local time (morning,day,afternoon,evening,night)<br>
  2951. There is also a daytime reading and associated HomeCMD attributes that will execute the HOMEMODE state CMDs independend of the presence of any RESIDENT.<br>
  2952. A lot of placeholders are available for usage within the HomeCMD or HomeText attributes (see Placeholders).<br>
  2953. All your energy and power measuring sensors can be added and calculated total readings for energy and power will be created.<br>
  2954. You can also add your local outside temperature and humidity sensors and you'll get ice warning e.g.<br>
  2955. If you also add your Yahoo weather device you'll also get short and long weather informations and weather forecast.<br>
  2956. You can monitor added contact and motion sensors and execute CMDs depending on their state.<br>
  2957. A simple alarm system is included, so your contact and motion sensors can trigger alarms depending on the current alarm mode.<br>
  2958. A lot of customizations are possible, e.g. special event (holiday) calendars and locations.<br>
  2959. <p><b>General information:</b></p>
  2960. <ul>
  2961. <li>
  2962. The HOMEMODE device is refreshing itselfs every 5 seconds by calling HOMEMODE_GetUpdate and subfunctions.<br>
  2963. This is the reason why some automations (e.g. daytime or season) are delayed up to 4 seconds.<br>
  2964. All automations triggered by external events (other devices monitored by HOMEMODE) and the execution of the HomeCMD attributes will not be delayed.
  2965. </li>
  2966. <li>
  2967. Each created timer will be created as at device and its name will start with "atTmp_" and end with "_&lt;name of your HOMEMODE device&gt;". You may list them with "list TYPE=at:FILTER=NAME=atTmp_.*_&lt;name of your HOMEMODE device&gt;".
  2968. </li>
  2969. <li>
  2970. Seasons can also be adjusted (date and text) in attribute HomeSeasons
  2971. </li>
  2972. <li>
  2973. There's a special function, which you may use, which is converting given minutes (up to 5999.99) to a timestamp that can be used for creating at devices.<br>
  2974. This function is called HOMEMODE_hourMaker and the only value you need to pass is the number in minutes with max. 2 digits after the dot.
  2975. </li>
  2976. <li>
  2977. Each set command and each updated reading of the HOMEMODE device will create an event within FHEM, so you're able to create additional notify or DOIF devices if needed.
  2978. </li>
  2979. </ul>
  2980. <br>
  2981. <a name="HOMEMODE_define"></a>
  2982. <p><b>define [optional]</b></p>
  2983. <ul>
  2984. <code>define &lt;name&gt; HOMEMODE</code><br><br>
  2985. <code>define &lt;name&gt; HOMEMODE [RESIDENTS-MASTER-DEVICE]</code><br>
  2986. </ul>
  2987. <br>
  2988. <a name="HOMEMODE_set"></a>
  2989. <p><b>set &lt;required&gt;</b></p>
  2990. <ul>
  2991. <li>
  2992. <b><i>anyoneElseAtHome &lt;on/off&gt;</i></b><br>
  2993. turn this on if anyone else is alone at home who is not a registered resident<br>
  2994. e.g. an animal or unregistered guest<br>
  2995. if turned on the alarm mode will be set to armhome instead of armaway while leaving, if turned on after leaving the alarm mode will change from armaway to armhome, e.g. to disable motion sensors alerts<br>
  2996. placeholder %AEAH% is available in all HomeCMD attributes
  2997. </li>
  2998. <li>
  2999. <b><i>dnd &lt;on/off&gt;</i></b><br>
  3000. turn "do not disturb" mode off or on<br>
  3001. e.g. to disable notification or alarms or, or, or...<br>
  3002. placeholder %DND% is available in all HomeCMD attributes
  3003. </li>
  3004. <li>
  3005. <b><i>dnd-for-minutes &lt;MINUTES&gt;</i></b><br>
  3006. turn "do not disturb" mode on for given minutes<br>
  3007. will return to the current (daytime) mode
  3008. </li>
  3009. <li>
  3010. <b><i>location &lt;arrival/home/bed/underway/wayhome&gt;</i></b><br>
  3011. switch to given location manually<br>
  3012. placeholder %LOCATION% is available in all HomeCMD attributes
  3013. </li>
  3014. <li>
  3015. <b><i>mode &lt;morning/day/afternoon/evening/night/gotosleep/asleep/absent/gone/home&gt;</i></b><br>
  3016. switch to given mode manually<br>
  3017. placeholder %MODE% is available in all HomeCMD attributes
  3018. </li>
  3019. <li>
  3020. <b><i>modeAlarm &lt;armaway/armhome/armnight/disarm&gt;</i></b><br>
  3021. switch to given alarm mode manually<br>
  3022. placeholder %AMODE% is available in all HomeCMD attributes
  3023. </li>
  3024. <li>
  3025. <b><i>modeAlarm-for-minutes &lt;armaway/armhome/armnight/disarm&gt; &lt;MINUTES&gt;</i></b><br>
  3026. switch to given alarm mode for given minutes<br>
  3027. will return to the previous alarm mode
  3028. </li>
  3029. <li>
  3030. <b><i>updateHomebridgeMapping</i></b><br>
  3031. will update the attribute homebridgeMapping of the HOMEMODE device depending on the available informations
  3032. </li>
  3033. <li>
  3034. <b><i>updateInternalForce</i></b><br>
  3035. will force update all internals of the HOMEMODE device<br>
  3036. use this if you just reload this module after an update or if you made changes on any HOMEMODE monitored device, e.g. after adding residents/guest or after adding new sensors with the same devspec as before
  3037. </li>
  3038. </ul>
  3039. <br>
  3040. <a name="HOMEMODE_get"></a>
  3041. <p><b>get &lt;required&gt; [optional]</b></p>
  3042. <ul>
  3043. <li>
  3044. <b><i>contactsOpen &lt;all/doorsinside/doorsoutside/doorsmain/outside/windows&gt;</i></b><br>
  3045. get a list of all/doorsinside/doorsoutside/doorsmain/outside/windows open contacts<br>
  3046. placeholders %OPEN% (open contacts outside) and %OPENCT% (open contacts outside count) are available in all HomeCMD attributes
  3047. </li>
  3048. <li>
  3049. <b><i>publicIP</i></b><br>
  3050. get the public IP address<br>
  3051. placeholder %IP% is available in all HomeCMD attributes
  3052. </li>
  3053. <li>
  3054. <b><i>sensorsTampered</i></b><br>
  3055. get a list of all tampered sensors<br>
  3056. placeholder %TAMPERED% is available in all HomeCMD attributes
  3057. </li>
  3058. <li>
  3059. <b><i>weather &lt;long/short&gt;</i></b><br>
  3060. get weather information in given format<br>
  3061. please specify the outputs in attributes HomeTextWeatherLong and HomeTextWeatherShort<br>
  3062. placeholders %WEATHER% and %WEATHERLONG% are available in all HomeCMD attributes
  3063. </li>
  3064. <li>
  3065. <b><i>weatherForecast [DAY]</i></b><br>
  3066. get weather forecast for given day<br>
  3067. if DAY is omitted the forecast for tomorrow (2) will be returned<br>
  3068. please specify the outputs in attributes HomeTextWeatherForecastToday, HomeTextWeatherForecastTomorrow and HomeTextWeatherForecastInSpecDays<br>
  3069. placeholders %FORECAST% (tomorrow) and %FORECASTTODAY% (today) are available in all HomeCMD attributes
  3070. </li>
  3071. </ul>
  3072. <br>
  3073. <a name="HOMEMODE_attr"></a>
  3074. <p><b>Attributes</b></p>
  3075. <ul>
  3076. <li>
  3077. <b><i>HomeAdvancedDetails</i></b><br>
  3078. show more details depending on the monitored devices<br>
  3079. value detail will only show advanced details in detail view, value both will show advanced details also in room view, room will show advanced details only in room view<br>
  3080. values: none, detail, both, room<br>
  3081. default: none
  3082. </li>
  3083. <li>
  3084. <b><i>HomeAdvancedUserAttr</i></b><br>
  3085. more HomeCMD userattr will be provided<br>
  3086. additional attributes for each resident and each calendar event<br>
  3087. values: 0 or 1<br>
  3088. default: 0
  3089. </li>
  3090. <li>
  3091. <b><i>HomeAutoAlarmModes</i></b><br>
  3092. set modeAlarm automatically depending on mode<br>
  3093. if mode is set to "home", modeAlarm will be set to "disarm"<br>
  3094. if mode is set to "absent", modeAlarm will be set to "armaway"<br>
  3095. if mode is set to "asleep", modeAlarm will be set to "armnight"<br>
  3096. modeAlarm "home" can only be set manually<br>
  3097. values 0 or 1, value 0 disables automatically set modeAlarm<br>
  3098. default: 1
  3099. </li>
  3100. <li>
  3101. <b><i>HomeAutoArrival</i></b><br>
  3102. set resident's location to arrival (on arrival) and after given minutes to home<br>
  3103. values from 0 to 5999.9 in minutes, value 0 disables automatically set arrival<br>
  3104. default: 0
  3105. </li>
  3106. <li>
  3107. <b><i>HomeAutoAsleep</i></b><br>
  3108. set user from gotosleep to asleep after given minutes<br>
  3109. values from 0 to 5999.9 in minutes, value 0 disables automatically set asleep<br>
  3110. default: 0
  3111. </li>
  3112. <li>
  3113. <b><i>HomeAutoAwoken</i></b><br>
  3114. force set resident from asleep to awoken, even if changing from alseep to home<br>
  3115. after given minutes awoken will change to home<br>
  3116. values from 0 to 5999.9 in minutes, value 0 disables automatically set awoken after asleep<br>
  3117. default: 0
  3118. </li>
  3119. <li>
  3120. <b><i>HomeAutoDaytime</i></b><br>
  3121. daytime depending home mode<br>
  3122. values 0 or 1, value 0 disables automatically set daytime<br>
  3123. default: 1
  3124. </li>
  3125. <li>
  3126. <b><i>HomeAutoPresence</i></b><br>
  3127. automatically change the state of residents between home and absent depending on their associated presence device<br>
  3128. values 0 or 1, value 0 disables auto presence<br>
  3129. default: 0
  3130. </li>
  3131. <li>
  3132. <b><i>HomeCMDalarmTampered-off</i></b><br>
  3133. cmds to execute if all tamper alarms are fixed
  3134. </li>
  3135. <li>
  3136. <b><i>HomeCMDalarmTampered-on</i></b><br>
  3137. cmds to execute on tamper alarm of any device
  3138. </li>
  3139. <li>
  3140. <b><i>HomeCMDalarmTriggered-off</i></b><br>
  3141. cmds to execute if all alarms are fixed
  3142. </li>
  3143. <li>
  3144. <b><i>HomeCMDalarmTriggered-on</i></b><br>
  3145. cmds to execute on alarm of any device
  3146. </li>
  3147. <li>
  3148. <b><i>HomeCMDanyoneElseAtHome-off</i></b><br>
  3149. cmds to execute if anyoneElseAtHome is set to off
  3150. </li>
  3151. <li>
  3152. <b><i>HomeCMDanyoneElseAtHome-on</i></b><br>
  3153. cmds to execute if anyoneElseAtHome is set to on
  3154. </li>
  3155. <li>
  3156. <b><i>HomeCMDcontact</i></b><br>
  3157. cmds to execute if any contact has been triggered (open/tilted/closed)
  3158. </li>
  3159. <li>
  3160. <b><i>HomeCMDbatteryLow</i></b><br>
  3161. cmds to execute if any battery sensor has low battery
  3162. </li>
  3163. <li>
  3164. <b><i>HomeCMDcontactClosed</i></b><br>
  3165. cmds to execute if any contact has been closed
  3166. </li>
  3167. <li>
  3168. <b><i>HomeCMDcontactOpen</i></b><br>
  3169. cmds to execute if any contact has been opened
  3170. </li>
  3171. <li>
  3172. <b><i>HomeCMDcontactDoormain</i></b><br>
  3173. cmds to execute if any contact of type doormain has been triggered (open/tilted/closed)
  3174. </li>
  3175. <li>
  3176. <b><i>HomeCMDcontactDoormainClosed</i></b><br>
  3177. cmds to execute if any contact of type doormain has been closed
  3178. </li>
  3179. <li>
  3180. <b><i>HomeCMDcontactDoormainOpen</i></b><br>
  3181. cmds to execute if any contact of type doormain has been opened
  3182. </li>
  3183. <li>
  3184. <b><i>HomeCMDcontactOpenWarning1</i></b><br>
  3185. cmds to execute on first contact open warning
  3186. </li>
  3187. <li>
  3188. <b><i>HomeCMDcontactOpenWarning2</i></b><br>
  3189. cmds to execute on second (and more) contact open warning
  3190. </li>
  3191. <li>
  3192. <b><i>HomeCMDcontactOpenWarningLast</i></b><br>
  3193. cmds to execute on last contact open warning
  3194. </li>
  3195. <li>
  3196. <b><i>HomeCMDdaytime</i></b><br>
  3197. cmds to execute on any daytime change
  3198. </li>
  3199. <li>
  3200. <b><i>HomeCMDdaytime-&lt;%DAYTIME%&gt;</i></b><br>
  3201. cmds to execute on specific day time change
  3202. </li>
  3203. <li>
  3204. <b><i>HomeCMDdnd-&lt;off/on&gt;</i></b><br>
  3205. cmds to execute on if dnd is turned off/on
  3206. </li>
  3207. <li>
  3208. <b><i>HomeCMDevent</i></b><br>
  3209. cmds to execute on each calendar event
  3210. </li>
  3211. <li>
  3212. <b><i>HomeCMDevent-&lt;%CALENDAR%&gt;-each</i></b><br>
  3213. cmds to execute on each event of the calendar
  3214. </li>
  3215. <li>
  3216. <b><i>HomeCMDevent-&lt;%CALENDAR%&gt;-&lt;%EVENT%&gt;-begin</i></b><br>
  3217. cmds to execute on start of a specific calendar event
  3218. </li>
  3219. <li>
  3220. <b><i>HomeCMDevent-&lt;%CALENDAR%&gt;-&lt;%EVENT%&gt;-end</i></b><br>
  3221. cmds to execute on end of a specific calendar event
  3222. </li>
  3223. <li>
  3224. <b><i>HomeCMDfhemINITIALIZED</i></b><br>
  3225. cmds to execute on fhem (re)start
  3226. </li>
  3227. <li>
  3228. <b><i>HomeCMDicewarning-&lt;off/on&gt;</i></b><br>
  3229. cmds to execute on if ice warning is turned off/on
  3230. </li>
  3231. <li>
  3232. <b><i>HomeCMDlocation</i></b><br>
  3233. cmds to execute on any location change of the HOMEMODE device
  3234. </li>
  3235. <li>
  3236. <b><i>HomeCMDlocation-&lt;%LOCATION%&gt;</i></b><br>
  3237. cmds to execute on specific location change of the HOMEMODE device
  3238. </li>
  3239. <li>
  3240. <b><i>HomeCMDmode</i></b><br>
  3241. cmds to execute on any mode change of the HOMEMODE device
  3242. </li>
  3243. <li>
  3244. <b><i>HomeCMDmode-absent-belated</i></b><br>
  3245. cmds to execute belated to absent<br>
  3246. belated time can be adjusted with attribute "HomeModeAbsentBelatedTime"
  3247. </li>
  3248. <li>
  3249. <b><i>HomeCMDmode-&lt;%MODE%&gt;</i></b><br>
  3250. cmds to execute on specific mode change of the HOMEMODE device
  3251. </li>
  3252. <li>
  3253. <b><i>HomeCMDmode-&lt;%MODE%&gt;-resident</i></b><br>
  3254. cmds to execute on specific mode change of the HOMEMODE device triggered by any resident
  3255. </li>
  3256. <li>
  3257. <b><i>HomeCMDmode-&lt;%MODE%&gt;-&lt;%RESIDENT%&gt;</i></b><br>
  3258. cmds to execute on specific mode change of the HOMEMODE device triggered by a specific resident
  3259. </li>
  3260. <li>
  3261. <b><i>HomeCMDmodeAlarm</i></b><br>
  3262. cmds to execute on any alarm mode change
  3263. </li>
  3264. <li>
  3265. <b><i>HomeCMDmodeAlarm-&lt;armaway/armhome/armnight/disarm&gt;</i></b><br>
  3266. cmds to execute on specific alarm mode change
  3267. </li>
  3268. <li>
  3269. <b><i>HomeCMDmotion</i></b><br>
  3270. cmds to execute on any recognized motion of any motion sensor
  3271. </li>
  3272. <li>
  3273. <b><i>HomeCMDmotion-&lt;off/on&gt;</i></b><br>
  3274. cmds to execute if any recognized motion of any motion sensor ends/starts
  3275. </li>
  3276. <li>
  3277. <b><i>HomeCMDpresence-&lt;absent/present&gt;</i></b><br>
  3278. cmds to execute on specific presence change of the HOMEMODE device
  3279. </li>
  3280. <li>
  3281. <b><i>HomeCMDpresence-&lt;absent/present&gt;-device</i></b><br>
  3282. cmds to execute on specific presence change of any presence device
  3283. </li>
  3284. <li>
  3285. <b><i>HomeCMDpresence-&lt;absent/present&gt;-resident</i></b><br>
  3286. cmds to execute on specific presence change of a specific resident
  3287. </li>
  3288. <li>
  3289. <b><i>HomeCMDpresence-&lt;absent/present&gt;-&lt;%RESIDENT%&gt;</i></b><br>
  3290. cmds to execute on specific presence change of a specific resident
  3291. </li>
  3292. <li>
  3293. <b><i>HomeCMDpresence-&lt;absent/present&gt;-&lt;%RESIDENT%&gt;-&lt;%DEVICE%&gt;</i></b><br>
  3294. cmds to execute on specific presence change of a specific resident's presence device<br>
  3295. only available if more than one presence device is available for a resident
  3296. </li>
  3297. <li>
  3298. <b><i>HomeCMDseason</i></b><br>
  3299. cmds to execute on any season change
  3300. </li>
  3301. <li>
  3302. <b><i>HomeCMDseason-&lt;%SEASON%&gt;</i></b><br>
  3303. cmds to execute on specific season change
  3304. </li>
  3305. <li>
  3306. <b><i>HomeCMDuwz-warn-&lt;begin/end&gt;</i></b><br>
  3307. cmds to execute on UWZ warning begin/end
  3308. </li>
  3309. <li>
  3310. <b><i>HomeDaytimes</i></b><br>
  3311. space separated list of time|text pairs for possible daytimes starting with the first event of the day (lowest time)<br>
  3312. default: 05:00|morning 10:00|day 14:00|afternoon 18:00|evening 23:00|night
  3313. </li>
  3314. <li>
  3315. <b><i>HomeEventsHolidayDevices</i></b><br>
  3316. devspec of holiday calendars
  3317. </li>
  3318. <li>
  3319. <b><i>HomeIcewarningOnOffTemps</i></b><br>
  3320. 2 space separated temperatures for ice warning on and off<br>
  3321. default: 2 3
  3322. </li>
  3323. <li>
  3324. <b><i>HomeLanguage</i></b><br>
  3325. overwrite language from gloabl device<br>
  3326. default: EN (language setting from global device)
  3327. </li>
  3328. <li>
  3329. <b><i>HomeModeAbsentBelatedTime</i></b><br>
  3330. time in minutes after changing to absent to execute "HomeCMDmode-absent-belated"<br>
  3331. if mode changes back (to home e.g.) in this time frame "HomeCMDmode-absent-belated" will not be executed<br>
  3332. default:
  3333. </li>
  3334. <li>
  3335. <b><i>HomeModeAlarmArmDelay</i></b><br>
  3336. time in seconds for delaying modeAlarm arm... commands<br>
  3337. must be a single number (valid for all modeAlarm arm... commands) or 3 space separated numbers for each modeAlarm arm... command individually (order: armaway armnight armhome)<br>
  3338. values from 0 to 99999<br>
  3339. default: 0
  3340. </li>
  3341. <li>
  3342. <b><i>HomePresenceDeviceAbsentCount-&lt;%RESIDENT%&gt;</i></b><br>
  3343. number of resident associated presence device to turn resident to absent<br>
  3344. default: maximum number of available presence device for each resident
  3345. </li>
  3346. <li>
  3347. <b><i>HomePresenceDevicePresentCount-&lt;%RESIDENT%&gt;</i></b><br>
  3348. number of resident associated presence device to turn resident to home<br>
  3349. default: 1
  3350. </li>
  3351. <li>
  3352. <b><i>HomePresenceDeviceType</i></b><br>
  3353. comma separated list of presence device types<br>
  3354. default: PRESENCE
  3355. </li>
  3356. <li>
  3357. <b><i>HomePublicIpCheckInterval</i></b><br>
  3358. numbers from 1-99999 for interval in minutes for public IP check<br>
  3359. default: 0 (disabled)
  3360. </li>
  3361. <li>
  3362. <b><i>HomeResidentCmdDelay</i></b><br>
  3363. time in seconds to delay the execution of specific residents commands after the change of the residents master device<br>
  3364. normally the resident events occur before the HOMEMODE events, to restore this behavior set this value to 0<br>
  3365. default: 1 (second)
  3366. </li>
  3367. <li>
  3368. <b><i>HomeSeasons</i></b><br>
  3369. space separated list of date|text pairs for possible seasons starting with the first season of the year (lowest date)<br>
  3370. default: 01.01|spring 06.01|summer 09.01|autumn 12.01|winter
  3371. </li>
  3372. <li>
  3373. <b><i>HomeSensorAirpressure</i></b><br>
  3374. main outside airpressure sensor
  3375. </li>
  3376. <li>
  3377. <b><i>HomeSensorWindspeed</i></b><br>
  3378. main outside wind speed sensor
  3379. </li>
  3380. <li>
  3381. <b><i>HomeSensorsBattery</i></b><br>
  3382. devspec of battery sensors with a battery reading<br>
  3383. all sensors with a percentage battery value or a ok/low/nok battery value are applicable
  3384. </li>
  3385. <li>
  3386. <b><i>HomeSensorsBatteryLowPercentage</i></b><br>
  3387. percentage to recognize a sensors battery as low (only percentage based sensors)<br>
  3388. default: 50
  3389. </li>
  3390. <li>
  3391. <b><i>HomeSensorsBatteryReading</i></b><br>
  3392. a single word for the battery reading<br>
  3393. this is only here available as global setting for all devices<br>
  3394. default: battery
  3395. </li>
  3396. <li>
  3397. <b><i>HomeSensorsContact</i></b><br>
  3398. devspec of contact sensors<br>
  3399. each applied contact sensor will get the following attributes, attributes will be removed after removing the contact sensors from the HOMEMODE device.<br>
  3400. <ul>
  3401. <li>
  3402. <b><i>HomeContactType</i></b><br>
  3403. specify each contacts sensor's type, choose one of: doorinside, dooroutside, doormain, window<br>
  3404. while applying contact sensors to the HOMEMODE device, the value of this attribute will be guessed by device name or device alias
  3405. </li>
  3406. <li>
  3407. <b><i>HomeModeAlarmActive</i></b><br>
  3408. specify the alarm mode(s) by regex in which the contact sensor should trigger open/tilted as alerts<br>
  3409. while applying contact sensors to the HOMEMODE device, the value of this attribute will be set to armaway by default<br>
  3410. choose one or a combination of: armaway|armhome|armnight<br>
  3411. default: armaway
  3412. </li>
  3413. <li>
  3414. <b><i>HomeOpenDontTriggerModes</i></b><br>
  3415. specify the HOMEMODE mode(s)/state(s) by regex in which the contact sensor should not trigger open warnings<br>
  3416. choose one or a combination of all available modes of the HOMEMODE device<br>
  3417. if you don't want open warnings while sleeping a good choice would be: gotosleep|asleep<br>
  3418. default:
  3419. </li>
  3420. <li>
  3421. <b><i>HomeOpenDontTriggerModesResidents</i></b><br>
  3422. comma separated list of residents whose state should be the reference for HomeOpenDontTriggerModes instead of the mode of the HOMEMODE device<br>
  3423. if one of the listed residents is in the state given by attribute HomeOpenDontTriggerModes, open warnings will not be triggered for this contact sensor<br>
  3424. default:
  3425. </li>
  3426. <li>
  3427. <b><i>HomeOpenMaxTrigger</i></b><br>
  3428. maximum number how often open warning should be triggered<br>
  3429. default: 0
  3430. </li>
  3431. <li>
  3432. <b><i>HomeReadings</i></b><br>
  3433. 2 space separated readings for contact sensors open state and tamper alert<br>
  3434. this is the device setting which will override the global setting from attribute HomeSensorsContactReadings from the HOMEMODE device<br>
  3435. default: state sabotageError
  3436. </li>
  3437. <li>
  3438. <b><i>HomeValues</i></b><br>
  3439. regex of open, tilted and tamper values for contact sensors<br>
  3440. this is the device setting which will override the global setting from attribute HomeSensorsContactValues from the HOMEMODE device<br>
  3441. default: open|tilted|on
  3442. </li>
  3443. <li>
  3444. <b><i>HomeOpenTimes</i></b><br>
  3445. space separated list of minutes after open warning should be triggered<br>
  3446. first value is for first warning, second value is for second warning, ...<br>
  3447. if less values are available than the number given by HomeOpenMaxTrigger, the very last available list entry will be used<br>
  3448. this is the device setting which will override the global setting from attribute HomeSensorsContactOpenTimes from the HOMEMODE device<br>
  3449. default: 10
  3450. </li>
  3451. <li>
  3452. <b><i>HomeOpenTimesDividers</i></b><br>
  3453. space separated list of trigger time dividers for contact sensor open warnings depending on the season of the HOMEMODE device.<br>
  3454. dividers in same order and same number as seasons in attribute HomeSeasons<br>
  3455. dividers are not used for contact sensors of type doormain and doorinside!<br>
  3456. this is the device setting which will override the global setting from attribute HomeSensorsContactOpenTimeDividers from the HOMEMODE device<br>
  3457. values from 0.001 to 99.999<br>
  3458. default:
  3459. </li>
  3460. </ul>
  3461. </li>
  3462. <li>
  3463. <b><i>HomeSensorsContactReadings</i></b><br>
  3464. 2 space separated readings for contact sensors open state and tamper alert<br>
  3465. this is the global setting, you can also set these readings in each contact sensor individually in attribute HomeReadings once they are added to the HOMEMODE device<br>
  3466. default: state sabotageError
  3467. </li>
  3468. <li>
  3469. <b><i>HomeSensorsContactValues</i></b><br>
  3470. regex of open, tilted and tamper values for contact sensors<br>
  3471. this is the global setting, you can also set these values in each contact sensor individually in attribute HomeValues once they are added to the HOMEMODE device<br>
  3472. default: open|tilted|on
  3473. </li>
  3474. <li>
  3475. <b><i>HomeSensorsContactOpenTimeDividers</i></b><br>
  3476. space separated list of trigger time dividers for contact sensor open warnings depending on the season of the HOMEMODE device.<br>
  3477. dividers in same order and same number as seasons in attribute HomeSeasons<br>
  3478. dividers are not used for contact sensors of type doormain and doorinside!<br>
  3479. this is the global setting, you can also set these dividers in each contact sensor individually in attribute HomeOpenTimesDividers once they are added to the HOMEMODE device<br>
  3480. values from 0.001 to 99.999<br>
  3481. default:
  3482. </li>
  3483. <li>
  3484. <b><i>HomeSensorsContactOpenTimeMin</i></b><br>
  3485. minimal open time for contact sensors open wanings<br>
  3486. default:
  3487. </li>
  3488. <li>
  3489. <b><i>HomeSensorsContactOpenTimes</i></b><br>
  3490. space separated list of minutes after open warning should be triggered<br>
  3491. first value is for first warning, second value is for second warning, ...<br>
  3492. if less values are available than the number given by HomeOpenMaxTrigger, the very last available list entry will be used<br>
  3493. this is the global setting, you can also set these times(s) in each contact sensor individually in attribute HomeOpenTimes once they are added to the HOMEMODE device<br>
  3494. default: 10
  3495. </li>
  3496. <li>
  3497. <b><i>HomeSensorHumidityOutside</i></b><br>
  3498. main outside humidity sensor<br>
  3499. if HomeSensorTemperatureOutside also has a humidity reading, you don't need to add the same sensor here
  3500. </li>
  3501. <li>
  3502. <b><i>HomeSensorTemperatureOutside</i></b><br>
  3503. main outside temperature sensor<br>
  3504. if this sensor also has a humidity reading, you don't need to add the same sensor to HomeSensorHumidityOutside
  3505. </li>
  3506. <li>
  3507. <b><i>HomeSensorsLuminance</i></b><br>
  3508. devspec of sensors with luminance measurement capabilities<br>
  3509. these devices will be used for total luminance calculations<br>
  3510. please set the corresponding reading for luminance in attribute HomeSensorsLuminanceReading (if different to luminance) before applying snesors here
  3511. </li>
  3512. <li>
  3513. <b><i>HomeSensorsLuminanceReading</i></b><br>
  3514. a single word for the luminance reading<br>
  3515. this is only here available as global setting for all devices<br>
  3516. default: luminance
  3517. </li>
  3518. <li>
  3519. <b><i>HomeSensorsMotion</i></b><br>
  3520. devspec of motion sensors<br>
  3521. each applied motion sensor will get the following attributes, attributes will be removed after removing the motion sensors from the HOMEMODE device.<br>
  3522. <ul>
  3523. <li>
  3524. <b><i>HomeModeAlarmActive</i></b><br>
  3525. specify the alarm mode(s) by regex in which the motion sensor should trigger motions as alerts<br>
  3526. while applying motion sensors to the HOMEMODE device, the value of this attribute will be set to armaway by default<br>
  3527. choose one or a combination of: armaway|armhome|armnight<br>
  3528. default: armaway (if sensor is of type inside)
  3529. </li>
  3530. <li>
  3531. <b><i>HomeSensorLocation</i></b><br>
  3532. specify each motion sensor's location, choose one of: inside, outside<br>
  3533. default: inside
  3534. </li>
  3535. <li>
  3536. <b><i>HomeReadings</i></b><br>
  3537. 2 space separated readings for motion sensors open/closed state and tamper alert<br>
  3538. this is the device setting which will override the global setting from attribute HomeSensorsMotionReadings from the HOMEMODE device<br>
  3539. default: state sabotageError
  3540. </li>
  3541. <li>
  3542. <b><i>HomeValues</i></b><br>
  3543. regex of open and tamper values for motion sensors<br>
  3544. this is the device setting which will override the global setting from attribute HomeSensorsMotionValues from the HOMEMODE device<br>
  3545. default: open|on
  3546. </li>
  3547. </ul>
  3548. </li>
  3549. <li>
  3550. <b><i>HomeSensorsMotionReadings</i></b><br>
  3551. 2 space separated readings for motion sensors open/closed state and tamper alert<br>
  3552. this is the global setting, you can also set these readings in each motion sensor individually in attribute HomeReadings once they are added to the HOMEMODE device<br>
  3553. default: state sabotageError
  3554. </li>
  3555. <li>
  3556. <b><i>HomeSensorsMotionValues</i></b><br>
  3557. regex of open and tamper values for motion sensors<br>
  3558. this is the global setting, you can also set these values in each contact sensor individually in attribute HomeValues once they are added to the HOMEMODE device<br>
  3559. default: open|on
  3560. </li>
  3561. <li>
  3562. <b><i>HomeSensorsPowerEnergy</i></b><br>
  3563. devspec of sensors with power and energy readings<br>
  3564. these devices will be used for total calculations
  3565. </li>
  3566. <li>
  3567. <b><i>HomeSensorsPowerEnergyReadings</i></b><br>
  3568. 2 space separated readings for power/energy sensors power and energy readings<br>
  3569. default: power energy
  3570. </li>
  3571. <li>
  3572. <b><i>HomeSpecialLocations</i></b><br>
  3573. comma separated list of additional locations<br>
  3574. default:
  3575. </li>
  3576. <li>
  3577. <b><i>HomeSpecialModes</i></b><br>
  3578. comma separated list of additional modes<br>
  3579. default:
  3580. </li>
  3581. <li>
  3582. <b><i>HomeTextAndAreIs</i></b><br>
  3583. pipe separated list of your local translations for "and", "are" and "is"<br>
  3584. default: and|are|is
  3585. </li>
  3586. <li>
  3587. <b><i>HomeTextClosedOpen</i></b><br>
  3588. pipe separated list of your local translation for "closed" and "open"<br>
  3589. default: closed|open
  3590. </li>
  3591. <li>
  3592. <b><i>HomeTextRisingConstantFalling</i></b><br>
  3593. pipe separated list of your local translation for "rising", "constant" and "falling"<br>
  3594. default: rising|constant|falling
  3595. </li>
  3596. <li>
  3597. <b><i>HomeTextTodayTomorrowAfterTomorrow</i></b><br>
  3598. pipe separated list of your local translations for "today", "tomorrow" and "day after tomorrow"<br>
  3599. this is used by weather forecast<br>
  3600. default: today|tomorrow|day after tomorrow
  3601. </li>
  3602. <li>
  3603. <b><i>HomeTextWeatherForecastInSpecDays</i></b><br>
  3604. your text for weather forecast in specific days<br>
  3605. placeholders can be used!<br>
  3606. default:
  3607. </li>
  3608. <li>
  3609. <b><i>HomeTextWeatherForecastToday</i></b><br>
  3610. your text for weather forecast today<br>
  3611. placeholders can be used!<br>
  3612. default:
  3613. </li>
  3614. <li>
  3615. <b><i>HomeTextWeatherForecastTomorrow</i></b><br>
  3616. your text for weather forecast tomorrow and the day after tomorrow<br>
  3617. placeholders can be used!<br>
  3618. default:
  3619. </li>
  3620. <li>
  3621. <b><i>HomeTextWeatherNoForecast</i></b><br>
  3622. your text for no available weather forecast<br>
  3623. default: No forecast available
  3624. </li>
  3625. <li>
  3626. <b><i>HomeTextWeatherLong</i></b><br>
  3627. your text for long weather information<br>
  3628. placeholders can be used!<br>
  3629. default:
  3630. </li>
  3631. <li>
  3632. <b><i>HomeTextWeatherShort</i></b><br>
  3633. your text for short weather information<br>
  3634. placeholders can be used!<br>
  3635. default:
  3636. </li>
  3637. <li>
  3638. <b><i>HomeTrendCalcAge</i></b><br>
  3639. time in seconds for the max age of the previous measured value for calculating trends<br>
  3640. default: 900
  3641. </li>
  3642. <li>
  3643. <b><i>HomeUWZ</i></b><br>
  3644. your local UWZ device<br>
  3645. default:
  3646. </li>
  3647. <li>
  3648. <b><i>HomeYahooWeatherDevice</i></b><br>
  3649. your local yahoo weather device<br>
  3650. default:
  3651. </li>
  3652. <li>
  3653. <b><i>disable</i></b><br>
  3654. disable HOMEMODE device and stop executing CMDs<br>
  3655. values 0 or 1<br>
  3656. default: 0
  3657. </li>
  3658. <li>
  3659. <b><i>disabledForIntervals</i></b><br>
  3660. disable the HOMEMODE device for intervals
  3661. default:
  3662. </li>
  3663. </ul>
  3664. <br>
  3665. <a name="HOMEMODE_read"></a>
  3666. <p><b>Readings</b></p>
  3667. <ul>
  3668. <li>
  3669. <b><i>alarmState</i></b><br>
  3670. current state of alarm system (includes current alarms - for homebridgeMapping)
  3671. </li>
  3672. <li>
  3673. <b><i>alarmTriggered</i></b><br>
  3674. list of triggered alarm sensors (contact/motion sensors)
  3675. </li>
  3676. <li>
  3677. <b><i>alarmTriggered_ct</i></b><br>
  3678. count of triggered alarm sensors (contact/motion sensors)
  3679. </li>
  3680. <li>
  3681. <b><i>alarmTriggered_hr</i></b><br>
  3682. (human readable) list of triggered alarm sensors (contact/motion sensors)
  3683. </li>
  3684. <li>
  3685. <b><i>anyoneElseAtHome</i></b><br>
  3686. anyoneElseAtHome off or on
  3687. </li>
  3688. <li>
  3689. <b><i>contactsDoorsInsideOpen</i></b><br>
  3690. list of names of open contact sensors of type doorinside
  3691. </li>
  3692. <li>
  3693. <b><i>batteryLow</i></b><br>
  3694. list of names of sensors with low battery
  3695. </li>
  3696. <li>
  3697. <b><i>batteryLow_ct</i></b><br>
  3698. count of sensors with low battery
  3699. </li>
  3700. <li>
  3701. <b><i>batteryLow_hr</i></b><br>
  3702. (human readable) list of sensors with low battery
  3703. </li>
  3704. <li>
  3705. <b><i>contactsDoorsInsideOpen_ct</i></b><br>
  3706. count of open contact sensors of type doorinside
  3707. </li>
  3708. <li>
  3709. <b><i>contactsDoorsInsideOpen_hr</i></b><br>
  3710. (human readable) list of open contact sensors of type doorinside
  3711. </li>
  3712. <li>
  3713. <b><i>contactsDoorsMainOpen</i></b><br>
  3714. list of names of open contact sensors of type doormain
  3715. </li>
  3716. <li>
  3717. <b><i>contactsDoorsMainOpen_ct</i></b><br>
  3718. count of open contact sensors of type doormain
  3719. </li>
  3720. <li>
  3721. <b><i>contactsDoorsMainOpen_hr</i></b><br>
  3722. (human readable) list of open contact sensors of type doormain
  3723. </li>
  3724. <li>
  3725. <b><i>contactsDoorsOutsideOpen</i></b><br>
  3726. list of names of open contact sensors of type dooroutside
  3727. </li>
  3728. <li>
  3729. <b><i>contactsDoorsOutsideOpen_ct</i></b><br>
  3730. count of open contact sensors of type dooroutside
  3731. </li>
  3732. <li>
  3733. <b><i>contactsDoorsOutsideOpen_hr</i></b><br>
  3734. (human readable) list of contact sensors of type dooroutside
  3735. </li>
  3736. <li>
  3737. <b><i>contactsOpen</i></b><br>
  3738. list of names of all open contact sensors
  3739. </li>
  3740. <li>
  3741. <b><i>contactsOpen_ct</i></b><br>
  3742. count of all open contact sensors
  3743. </li>
  3744. <li>
  3745. <b><i>contactsOpen_hr</i></b><br>
  3746. (human readable) list of all open contact sensors
  3747. </li>
  3748. <li>
  3749. <b><i>contactsOutsideOpen</i></b><br>
  3750. list of names of open contact sensors outside (sensor types: dooroutside,doormain,window)
  3751. </li>
  3752. <li>
  3753. <b><i>contactsOutsideOpen_ct</i></b><br>
  3754. count of open contact sensors outside (sensor types: dooroutside,doormain,window)
  3755. </li>
  3756. <li>
  3757. <b><i>contactsOutsideOpen_hr</i></b><br>
  3758. (human readable) list of open contact sensors outside (sensor types: dooroutside,doormain,window)
  3759. </li>
  3760. <li>
  3761. <b><i>contactsWindowsOpen</i></b><br>
  3762. list of names of open contact sensors of type window
  3763. </li>
  3764. <li>
  3765. <b><i>contactsWindowsOpen_ct</i></b><br>
  3766. count of open contact sensors of type window
  3767. </li>
  3768. <li>
  3769. <b><i>contactsWindowsOpen_hr</i></b><br>
  3770. (human readable) list of open contact sensors of type window
  3771. </li>
  3772. <li>
  3773. <b><i>daytime</i></b><br>
  3774. current daytime (as configured in HomeDaytimes) - independent from the mode of the HOMEMODE device<br>
  3775. </li>
  3776. <li>
  3777. <b><i>dnd</i></b><br>
  3778. dnd (do not disturb) off or on
  3779. </li>
  3780. <li>
  3781. <b><i>energy</i></b><br>
  3782. calculated total energy
  3783. </li>
  3784. <li>
  3785. <b><i>event-&lt;%CALENDAR%&gt;</i></b><br>
  3786. current event of the (holiday) CALENDAR device(s)
  3787. </li>
  3788. <li>
  3789. <b><i>humidty</i></b><br>
  3790. current humidty of the Yahoo weather device or of your own sensor (if available)
  3791. </li>
  3792. <li>
  3793. <b><i>humidtyTrend</i></b><br>
  3794. trend of the humidty over the last hour<br>
  3795. possible values: constant, rising, falling
  3796. </li>
  3797. <li>
  3798. <b><i>icawarning</i></b><br>
  3799. ice warning<br>
  3800. values: 0 if off and 1 if on
  3801. </li>
  3802. <li>
  3803. <b><i>lastAbsentByPresenceDevice</i></b><br>
  3804. last presence device which went absent
  3805. </li>
  3806. <li>
  3807. <b><i>lastAbsentByResident</i></b><br>
  3808. last resident who went absent
  3809. </li>
  3810. <li>
  3811. <b><i>lastActivityByPresenceDevice</i></b><br>
  3812. last active presence device
  3813. </li>
  3814. <li>
  3815. <b><i>lastActivityByResident</i></b><br>
  3816. last active resident
  3817. </li>
  3818. <li>
  3819. <b><i>lastAsleepByResident</i></b><br>
  3820. last resident who went asleep
  3821. </li>
  3822. <li>
  3823. <b><i>lastAwokenByResident</i></b><br>
  3824. last resident who went awoken
  3825. </li>
  3826. <li>
  3827. <b><i>lastBatteryLow</i></b><br>
  3828. last sensor with low battery
  3829. </li>
  3830. <li>
  3831. <b><i>lastCMDerror</i></b><br>
  3832. last occured error and command(chain) while executing command(chain)
  3833. </li>
  3834. <li>
  3835. <b><i>lastContact</i></b><br>
  3836. last contact sensor which triggered open
  3837. </li>
  3838. <li>
  3839. <b><i>lastContactClosed</i></b><br>
  3840. last contact sensor which triggered closed
  3841. </li>
  3842. <li>
  3843. <b><i>lastGoneByResident</i></b><br>
  3844. last resident who went gone
  3845. </li>
  3846. <li>
  3847. <b><i>lastGotosleepByResident</i></b><br>
  3848. last resident who went gotosleep
  3849. </li>
  3850. <li>
  3851. <b><i>lastInfo</i></b><br>
  3852. last shown item on infopanel (HomeAdvancedDetails)
  3853. </li>
  3854. <li>
  3855. <b><i>lastMotion</i></b><br>
  3856. last sensor which triggered motion
  3857. </li>
  3858. <li>
  3859. <b><i>lastMotionClosed</i></b><br>
  3860. last sensor which triggered motion end
  3861. </li>
  3862. <li>
  3863. <b><i>lastPresentByPresenceDevice</i></b><br>
  3864. last presence device which came present
  3865. </li>
  3866. <li>
  3867. <b><i>lastPresentByResident</i></b><br>
  3868. last resident who came present
  3869. </li>
  3870. <li>
  3871. <b><i>light</i></b><br>
  3872. current light reading value
  3873. </li>
  3874. <li>
  3875. <b><i>location</i></b><br>
  3876. current location
  3877. </li>
  3878. <li>
  3879. <b><i>luminance</i></b><br>
  3880. average luminance of all motion sensors (if available)
  3881. </li>
  3882. <li>
  3883. <b><i>luminanceTrend</i></b><br>
  3884. trend of the luminance over the last hour<br>
  3885. possible values: constant, rising, falling
  3886. </li>
  3887. <li>
  3888. <b><i>mode</i></b><br>
  3889. current mode
  3890. </li>
  3891. <li>
  3892. <b><i>modeAlarm</i></b><br>
  3893. current mode of alarm system
  3894. </li>
  3895. <li>
  3896. <b><i>motionsInside</i></b><br>
  3897. list of names of open motion sensors of type inside
  3898. </li>
  3899. <li>
  3900. <b><i>motionsInside_ct</i></b><br>
  3901. count of open motion sensors of type inside
  3902. </li>
  3903. <li>
  3904. <b><i>motionsInside_hr</i></b><br>
  3905. (human readable) list of open motion sensors of type inside
  3906. </li>
  3907. <li>
  3908. <b><i>motionsOutside</i></b><br>
  3909. list of names of open motion sensors of type outside
  3910. </li>
  3911. <li>
  3912. <b><i>motionsOutside_ct</i></b><br>
  3913. count of open motion sensors of type outside
  3914. </li>
  3915. <li>
  3916. <b><i>motionsOutside_hr</i></b><br>
  3917. (human readable) list of open motion sensors of type outside
  3918. </li>
  3919. <li>
  3920. <b><i>motionsSensors</i></b><br>
  3921. list of all names of open motion sensors
  3922. </li>
  3923. <li>
  3924. <b><i>motionsSensors_ct</i></b><br>
  3925. count of all open motion sensors
  3926. </li>
  3927. <li>
  3928. <b><i>motionsSensors_hr</i></b><br>
  3929. (human readable) list of all open motion sensors
  3930. </li>
  3931. <li>
  3932. <b><i>power</i></b><br>
  3933. calculated total power
  3934. </li>
  3935. <li>
  3936. <b><i>prevMode</i></b><br>
  3937. previous mode
  3938. </li>
  3939. <li>
  3940. <b><i>presence</i></b><br>
  3941. presence of any resident
  3942. </li>
  3943. <li>
  3944. <b><i>pressure</i></b><br>
  3945. current air pressure of the Yahoo weather device
  3946. </li>
  3947. <li>
  3948. <b><i>prevActivityByResident</i></b><br>
  3949. previous active resident
  3950. </li>
  3951. <li>
  3952. <b><i>prevContact</i></b><br>
  3953. previous contact sensor which triggered open
  3954. </li>
  3955. <li>
  3956. <b><i>prevContactClosed</i></b><br>
  3957. previous contact sensor which triggered closed
  3958. </li>
  3959. <li>
  3960. <b><i>prevLocation</i></b><br>
  3961. previous location
  3962. </li>
  3963. <li>
  3964. <b><i>prevMode</i></b><br>
  3965. previous mode
  3966. </li>
  3967. <li>
  3968. <b><i>prevMotion</i></b><br>
  3969. previous sensor which triggered motion
  3970. </li>
  3971. <li>
  3972. <b><i>prevMotionClosed</i></b><br>
  3973. previous sensor which triggered motion end
  3974. </li>
  3975. <li>
  3976. <b><i>prevModeAlarm</i></b><br>
  3977. previous alarm mode
  3978. </li>
  3979. <li>
  3980. <b><i>publicIP</i></b><br>
  3981. last checked public IP address
  3982. </li>
  3983. <li>
  3984. <b><i>season</i></b><br>
  3985. current season as configured in HomeSeasons<br>
  3986. </li>
  3987. <li>
  3988. <b><i>sensorsTampered</i></b><br>
  3989. list of names of tampered sensors
  3990. </li>
  3991. <li>
  3992. <b><i>sensorsTampered_ct</i></b><br>
  3993. count of tampered sensors
  3994. </li>
  3995. <li>
  3996. <b><i>sensorsTampered_hr</i></b><br>
  3997. (human readable) list of tampered sensors
  3998. </li>
  3999. <li>
  4000. <b><i>state</i></b><br>
  4001. current state
  4002. </li>
  4003. <li>
  4004. <b><i>temperature</i></b><br>
  4005. current temperature of the Yahoo weather device or of your own sensor (if available)
  4006. </li>
  4007. <li>
  4008. <b><i>temperatureTrend</i></b><br>
  4009. trend of the temperature over the last hour<br>
  4010. possible values: constant, rising, falling
  4011. </li>
  4012. <li>
  4013. <b><i>twilight</i></b><br>
  4014. current twilight reading value
  4015. </li>
  4016. <li>
  4017. <b><i>twilightEvent</i></b><br>
  4018. current twilight event
  4019. </li>
  4020. <li>
  4021. <b><i>uwz_warnCount</i></b><br>
  4022. current UWZ warn count
  4023. </li>
  4024. <li>
  4025. <b><i>wind</i></b><br>
  4026. current wind speed of the Yahoo weather
  4027. </li>
  4028. </ul>
  4029. <a name="HOMEMODE_placeholders"></a>
  4030. <p><b>Placeholders</b></p>
  4031. <p>These placeholders can be used in all HomeCMD attributes</p>
  4032. <ul>
  4033. <li>
  4034. <b><i>%ADDRESS%</i></b><br>
  4035. mac address of the last triggered presence device
  4036. </li>
  4037. <li>
  4038. <b><i>%ALIAS%</i></b><br>
  4039. alias of the last triggered resident
  4040. </li>
  4041. <li>
  4042. <b><i>%ALARM%</i></b><br>
  4043. value of the alarmTriggered reading of the HOMEMODE device<br>
  4044. will return 0 if no alarm is triggered or a list of triggered sensors if alarm is triggered
  4045. </li>
  4046. <li>
  4047. <b><i>%ALARMCT%</i></b><br>
  4048. value of the alarmTriggered_ct reading of the HOMEMODE device
  4049. </li>
  4050. <li>
  4051. <b><i>%ALARMHR%</i></b><br>
  4052. value of the alarmTriggered_hr reading of the HOMEMODE device<br>
  4053. will return 0 if no alarm is triggered or a (human readable) list of triggered sensors if alarm is triggered<br>
  4054. can be used for sending msg e.g.
  4055. </li>
  4056. <li>
  4057. <b><i>%AMODE%</i></b><br>
  4058. current alarm mode
  4059. </li>
  4060. <li>
  4061. <b><i>%AEAH%</i></b><br>
  4062. state of anyoneElseAtHome, will return 1 if on and will return 0 if off
  4063. </li>
  4064. <li>
  4065. <b><i>%ARRIVERS%</i></b><br>
  4066. will return a list of aliases of all registered residents/guests with location arrival<br>
  4067. this can be used to welcome residents after main door open/close<br>
  4068. e.g. Peter, Paul and Marry
  4069. </li>
  4070. <li>
  4071. <b><i>%AUDIO%</i></b><br>
  4072. audio device of the last triggered resident (attribute msgContactAudio)<br>
  4073. if attribute msgContactAudio of the resident has no value the value is trying to be taken from device globalMsg (if available)<br>
  4074. can be used to address resident specific msg(s) of type audio, e.g. night/morning wishes
  4075. </li>
  4076. <li>
  4077. <b><i>%BE%</i></b><br>
  4078. is or are of condition reading of monitored Yahoo weather device<br>
  4079. can be used for weather (forecast) output
  4080. </li>
  4081. <li>
  4082. <b><i>%BATTERYLOW%</i></b><br>
  4083. alias (or name if alias is not set) of the last battery sensor which reported low battery
  4084. </li>
  4085. <li>
  4086. <b><i>%BATTERYLOWALL%</i></b><br>
  4087. list if aliases (or names if alias is not set) of all battery sensor which reported low battery currently
  4088. </li>
  4089. <li>
  4090. <b><i>%BATTERYLOWCT%</i></b><br>
  4091. number of battery sensors which reported low battery currently
  4092. </li>
  4093. <li>
  4094. <b><i>%CONDITION%</i></b><br>
  4095. value of the condition reading of monitored Yahoo weather device<br>
  4096. can be used for weather (forecast) output
  4097. </li>
  4098. <li>
  4099. <b><i>%CONTACT%</i></b><br>
  4100. value of the lastContact reading (last opened sensor)
  4101. </li>
  4102. <li>
  4103. <b><i>%DAYTIME%</i></b><br>
  4104. value of the daytime reading of the HOMEMODE device<br>
  4105. can be used to trigger day time specific actions
  4106. </li>
  4107. <li>
  4108. <b><i>%DEVICE%</i></b><br>
  4109. name of the last triggered presence device<br>
  4110. can be used to trigger actions depending on the last present/absent presence device
  4111. </li>
  4112. <li>
  4113. <b><i>%DEVICEA%</i></b><br>
  4114. name of the last triggered absent presence device
  4115. </li>
  4116. <li>
  4117. <b><i>%DEVICEP%</i></b><br>
  4118. name of the last triggered present presence device
  4119. </li>
  4120. <li>
  4121. <b><i>%DND%</i></b><br>
  4122. state of dnd, will return 1 if on and will return 0 if off
  4123. </li>
  4124. <li>
  4125. <b><i>%DURABSENCE%</i></b><br>
  4126. value of the durTimerAbsence_cr reading of the last triggered resident
  4127. </li>
  4128. <li>
  4129. <b><i>%DURABSENCELAST%</i></b><br>
  4130. value of the lastDurAbsence_cr reading of the last triggered resident
  4131. </li>
  4132. <li>
  4133. <b><i>%DURPRESENCE%</i></b><br>
  4134. value of the durTimerPresence_cr reading of the last triggered resident
  4135. </li>
  4136. <li>
  4137. <b><i>%DURPRESENCELAST%</i></b><br>
  4138. value of the lastDurPresence_cr reading of the last triggered resident
  4139. </li>
  4140. <li>
  4141. <b><i>%DURSLEEP%</i></b><br>
  4142. value of the durTimerSleep_cr reading of the last triggered resident
  4143. </li>
  4144. <li>
  4145. <b><i>%DURSLEEPLAST%</i></b><br>
  4146. value of the lastDurSleep_cr reading of the last triggered resident
  4147. </li>
  4148. <li>
  4149. <b><i>%CALENDARNAME%</i></b><br>
  4150. will return the current event of the given calendar name, will return 0 if event is none<br>
  4151. can be used to trigger actions on any event of the given calendar
  4152. </li>
  4153. <li>
  4154. <b><i>%CALENDARNAME-EVENTNAME%</i></b><br>
  4155. will return 1 if given event of given calendar is current, will return 0 if event is not current<br>
  4156. can be used to trigger actions during specific events only (Christmas?)
  4157. </li>
  4158. <li>
  4159. <b><i>%FORECAST%</i></b><br>
  4160. will return the weather forecast for tomorrow<br>
  4161. can be used in msg or tts
  4162. </li>
  4163. <li>
  4164. <b><i>%FORECASTTODAY%</i></b><br>
  4165. will return the weather forecast for today<br>
  4166. can be used in msg or tts
  4167. </li>
  4168. <li>
  4169. <b><i>%HUMIDITY%</i></b><br>
  4170. value of the humidity reading of the HOMEMODE device<br>
  4171. can be used for weather info in HomeTextWeather attributes e.g.
  4172. </li>
  4173. <li>
  4174. <b><i>%HUMIDITYTREND%</i></b><br>
  4175. value of the humidityTrend reading of the HOMEMODE device<br>
  4176. possible values: constant, rising, falling
  4177. </li>
  4178. <li>
  4179. <b><i>%ICE%</i></b><br>
  4180. will return 1 if ice warning is on, will return 0 if ice warning is off<br>
  4181. can be used to send ice warning specific msg(s) in specific situations, e.g. to warn leaving residents
  4182. </li>
  4183. <li>
  4184. <b><i>%IP%</i></b><br>
  4185. value of reading publicIP<br>
  4186. can be used to send msg(s) with (new) IP address
  4187. </li>
  4188. <li>
  4189. <b><i>%LIGHT%</i></b><br>
  4190. value of the light reading of the HOMEMODE device
  4191. </li>
  4192. <li>
  4193. <b><i>%LOCATION%</i></b><br>
  4194. value of the location reading of the HOMEMODE device
  4195. </li>
  4196. <li>
  4197. <b><i>%LOCATIONR%</i></b><br>
  4198. value of the location reading of the last triggered resident
  4199. </li>
  4200. <li>
  4201. <b><i>%LUMINANCE%</i></b><br>
  4202. average luminance of motion sensors (if available)
  4203. </li>
  4204. <li>
  4205. <b><i>%LUMINANCETREND%</i></b><br>
  4206. value of the luminanceTrend reading of the HOMEMODE device<br>
  4207. possible values: constant, rising, falling
  4208. </li>
  4209. <li>
  4210. <b><i>%MODE%</i></b><br>
  4211. current mode of the HOMEMODE device
  4212. </li>
  4213. <li>
  4214. <b><i>%MOTION%</i></b><br>
  4215. value of the lastMotion reading (last opened sensor)
  4216. </li>
  4217. <li>
  4218. <b><i>%OPEN%</i></b><br>
  4219. value of the contactsOutsideOpen_hr reading of the HOMEMODE device<br>
  4220. can be used to send msg(s) in specific situations, e.g. to warn leaving residents of open contact sensors
  4221. </li>
  4222. <li>
  4223. <b><i>%OPENCT%</i></b><br>
  4224. value of the contactsOutsideOpen_ct reading of the HOMEMODE device<br>
  4225. can be used to send msg(s) in specific situations depending on the number of open contact sensors, maybe in combination with placeholder %OPEN%
  4226. </li>
  4227. <li>
  4228. <b><i>%RESIDENT%</i></b><br>
  4229. name of the last triggered resident
  4230. </li>
  4231. <li>
  4232. <b><i>%PRESENT%</i></b><br>
  4233. presence of the HOMEMODE device<br>
  4234. will return 1 if present or 0 if absent
  4235. </li>
  4236. <li>
  4237. <b><i>%PRESENTR%</i></b><br>
  4238. presence of last triggered resident<br>
  4239. will return 1 if present or 0 if absent
  4240. </li>
  4241. <li>
  4242. <b><i>%PRESSURE%</i></b><br>
  4243. value of the pressure reading of the HOMEMODE device<br>
  4244. can be used for weather info in HomeTextWeather attributes e.g.
  4245. </li>
  4246. <li>
  4247. <b><i>%PRESSURETREND%</i></b><br>
  4248. value of the pressure_trend_txt reading of the Yahoo weather device<br>
  4249. can be used for weather info in HomeTextWeather attributes e.g.
  4250. </li>
  4251. <li>
  4252. <b><i>%PREVAMODE%</i></b><br>
  4253. previous alarm mode of the HOMEMODE device
  4254. </li>
  4255. <li>
  4256. <b><i>%PREVCONTACT%</i></b><br>
  4257. previous open contact sensor
  4258. </li>
  4259. <li>
  4260. <b><i>%PREVMODE%</i></b><br>
  4261. previous mode of the HOMEMODE device
  4262. </li>
  4263. <li>
  4264. <b><i>%PREVMODER%</i></b><br>
  4265. previous state of last triggered resident
  4266. </li>
  4267. <li>
  4268. <b><i>%PREVMOTION%</i></b><br>
  4269. previous open motion sensor
  4270. </li>
  4271. <li>
  4272. <b><i>%SEASON%</i></b><br>
  4273. value of the season reading of the HOMEMODE device
  4274. </li>
  4275. <li>
  4276. <b><i>%SELF%</i></b><br>
  4277. name of the HOMEMODE device itself
  4278. </li>
  4279. <li>
  4280. <b><i>%SENSORSBATTERY%</i></b><br>
  4281. all battery sensors from internal SENSORSBATTERY
  4282. </li>
  4283. <li>
  4284. <b><i>%SENSORSCONTACT%</i></b><br>
  4285. all contact sensors from internal SENSORSCONTACT
  4286. </li>
  4287. <li>
  4288. <b><i>%SENSORSENERGY%</i></b><br>
  4289. all energy sensors from internal SENSORSENERGY
  4290. </li>
  4291. <li>
  4292. <b><i>%SENSORSMOTION%</i></b><br>
  4293. all motion sensors from internal SENSORSMOTION
  4294. </li>
  4295. <li>
  4296. <b><i>%TAMPERED%</i></b><br>
  4297. will return all tampered sensors
  4298. </li>
  4299. <li>
  4300. <b><i>%TAMPEREDCT%</i></b><br>
  4301. will return the number of tampered sensors
  4302. </li>
  4303. <li>
  4304. <b><i>%TEMPERATURE%</i></b><br>
  4305. value of the temperature reading of the HOMEMODE device<br>
  4306. can be used for weather info in HomeTextWeather attributes e.g.
  4307. </li>
  4308. <li>
  4309. <b><i>%TEMPERATURETREND%</i></b><br>
  4310. value of the temperatureTrend reading of the HOMEMODE device<br>
  4311. possible values: constant, rising, falling
  4312. </li>
  4313. <li>
  4314. <b><i>%TWILIGHT%</i></b><br>
  4315. value of the twilight reading of the HOMEMODE device
  4316. </li>
  4317. <li>
  4318. <b><i>%TWILIGHTEVENT%</i></b><br>
  4319. current twilight event
  4320. </li>
  4321. <li>
  4322. <b><i>%UWZ%</i></b><br>
  4323. UWZ warnings count
  4324. </li>
  4325. <li>
  4326. <b><i>%UWZLONG%</i></b><br>
  4327. all current UWZ warnings as long text
  4328. </li>
  4329. <li>
  4330. <b><i>%UWZSHORT%</i></b><br>
  4331. all current UWZ warnings as short text
  4332. </li>
  4333. <li>
  4334. <b><i>%WEATHER%</i></b><br>
  4335. value of "get &lt;HOMEMODE&gt; weather short"<br>
  4336. can be used for for msg weather info e.g.
  4337. </li>
  4338. <li>
  4339. <b><i>%WEATHERLONG%</i></b><br>
  4340. value of "get &lt;HOMEMODE&gt; weather long"<br>
  4341. can be used for for msg weather info e.g.
  4342. </li>
  4343. <li>
  4344. <b><i>%WIND%</i></b><br>
  4345. value of the wind reading of the HOMEMODE device<br>
  4346. can be used for weather info in HomeTextWeather attributes e.g.
  4347. </li>
  4348. <li>
  4349. <b><i>%WINDCHILL%</i></b><br>
  4350. value of the wind_chill reading of the Yahoo weather device<br>
  4351. can be used for weather info in HomeTextWeather attributes e.g.
  4352. </li>
  4353. </ul>
  4354. <p>These placeholders can only be used within HomeTextWeatherForecast attributes</p>
  4355. <ul>
  4356. <li>
  4357. <b><i>%CONDITION%</i></b><br>
  4358. value of weather forecast condition
  4359. </li>
  4360. <li>
  4361. <b><i>%DAY%</i></b><br>
  4362. day number of weather forecast
  4363. </li>
  4364. <li>
  4365. <b><i>%HIGH%</i></b><br>
  4366. value of maximum weather forecast temperature
  4367. </li>
  4368. <li>
  4369. <b><i>%LOW%</i></b><br>
  4370. value of minimum weather forecast temperature
  4371. </li>
  4372. </ul>
  4373. <p>These placeholders can only be used within HomeCMDcontact and HomeCMDmotion attributes</p>
  4374. <ul>
  4375. <li>
  4376. <b><i>%ALIAS%</i></b><br>
  4377. alias of the last triggered contact/motion sensor
  4378. </li>
  4379. <li>
  4380. <b><i>%SENSOR%</i></b><br>
  4381. name of the last triggered contact/motion sensor
  4382. </li>
  4383. <li>
  4384. <b><i>%STATE%</i></b><br>
  4385. state of the last triggered contact/motion sensor
  4386. </li>
  4387. </ul>
  4388. <p>These placeholders can only be used within calendar event related HomeCMDevent attributes</p>
  4389. <ul>
  4390. <li>
  4391. <b><i>%CALENDAR%</i></b><br>
  4392. name of the calendar
  4393. </li>
  4394. <li>
  4395. <b><i>%EVENT%</i></b><br>
  4396. current event of the calendar
  4397. </li>
  4398. <li>
  4399. <b><i>%PREVEVENT%</i></b><br>
  4400. previous event of the calendar
  4401. </li>
  4402. </ul>
  4403. </ul>
  4404. =end html
  4405. =cut