73_AutoShuttersControl.pm 126 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356
  1. ###############################################################################
  2. #
  3. # Developed with Kate
  4. #
  5. # (c) 2018 Copyright: Marko Oldenburg (leongaultier at gmail dot com)
  6. # All rights reserved
  7. #
  8. # Special thanks goes to:
  9. # - Bernd (Cluni) this module is based on the logic of his script "Rollladensteuerung für HM/ROLLO inkl. Abschattung und Komfortfunktionen in Perl" (https://forum.fhem.de/index.php/topic,73964.0.html)
  10. # - Beta-User for many tests and ideas
  11. #
  12. #
  13. # This script is free software; you can redistribute it and/or modify
  14. # it under the terms of the GNU General Public License as published by
  15. # the Free Software Foundation; either version 2 of the License,or
  16. # any later version.
  17. #
  18. # The GNU General Public License can be found at
  19. # http://www.gnu.org/copyleft/gpl.html.
  20. # A copy is found in the textfile GPL.txt and important notices to the license
  21. # from the author is found in LICENSE.txt distributed with these scripts.
  22. #
  23. # This script is distributed in the hope that it will be useful,
  24. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. # GNU General Public License for more details.
  27. #
  28. #
  29. # $Id: 73_AutoShuttersControl.pm 17730 2018-11-11 16:56:09Z CoolTux $
  30. #
  31. ###############################################################################
  32. ### Notizen
  33. # - Feststellen ob ein Rolladen fährt oder nicht
  34. package main;
  35. use strict;
  36. use warnings;
  37. my $version = "0.2.0.3";
  38. sub AutoShuttersControl_Initialize($) {
  39. my ($hash) = @_;
  40. ## Da ich mit package arbeite müssen in die Initialize für die jeweiligen hash Fn Funktionen der Funktionsname
  41. # und davor mit :: getrennt der eigentliche package Name des Modules
  42. $hash->{SetFn} = "AutoShuttersControl::Set";
  43. $hash->{GetFn} = "AutoShuttersControl::Get";
  44. $hash->{DefFn} = "AutoShuttersControl::Define";
  45. $hash->{NotifyFn} = "AutoShuttersControl::Notify";
  46. $hash->{UndefFn} = "AutoShuttersControl::Undef";
  47. $hash->{AttrFn} = "AutoShuttersControl::Attr";
  48. $hash->{AttrList} =
  49. "disable:0,1 "
  50. . "disabledForIntervals "
  51. . "ASC_guestPresence:on,off "
  52. . "ASC_temperatureSensor "
  53. . "ASC_temperatureReading "
  54. . "ASC_brightnessMinVal "
  55. . "ASC_brightnessMaxVal "
  56. . "ASC_autoShuttersControlMorning:on,off "
  57. . "ASC_autoShuttersControlEvening:on,off "
  58. . "ASC_autoShuttersControl_Shading:on,off "
  59. . "ASC_autoShuttersControlComfort:on,off "
  60. . "ASC_sunPosDevice "
  61. . "ASC_sunPosReading "
  62. . "ASC_sunElevationDevice "
  63. . "ASC_sunElevationReading "
  64. . "ASC_residentsDevice "
  65. . "ASC_residentsDeviceReading "
  66. . "ASC_rainSensorDevice "
  67. . "ASC_rainSensorReading "
  68. . "ASC_rainSensorShuttersClosedPos:0,10,20,30,40,50,60,70,80,90,100 "
  69. . "ASC_autoAstroModeMorning:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON "
  70. . "ASC_autoAstroModeMorningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9 "
  71. . "ASC_autoAstroModeEvening:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON "
  72. . "ASC_autoAstroModeEveningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9 "
  73. . "ASC_freezeTemp:-5,-4,-3,-2,-1,0,1,2,3,4,5 "
  74. . "ASC_timeUpHolidayDevice "
  75. . "ASC_timeUpHolidayReading "
  76. . "ASC_shuttersDriveOffset "
  77. . "ASC_twilightDevice "
  78. . $readingFnAttributes;
  79. $hash->{NotifyOrderPrefix} = "51-"; # Order Nummer für NotifyFn
  80. ## Ist nur damit sich bei einem reload auch die Versionsnummer erneuert.
  81. foreach my $d ( sort keys %{ $modules{AutoShuttersControl}{defptr} } ) {
  82. my $hash = $modules{AutoShuttersControl}{defptr}{$d};
  83. $hash->{VERSION} = $version;
  84. }
  85. }
  86. ## unserer packagename
  87. package AutoShuttersControl;
  88. use strict;
  89. use warnings;
  90. use POSIX;
  91. use GPUtils qw(:all)
  92. ; # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt
  93. use Data::Dumper; #only for Debugging
  94. use Date::Parse;
  95. my $missingModul = "";
  96. eval "use JSON qw(decode_json encode_json);1" or $missingModul .= "JSON ";
  97. ## Import der FHEM Funktionen
  98. BEGIN {
  99. GP_Import(
  100. qw(devspec2array
  101. readingsSingleUpdate
  102. readingsBulkUpdate
  103. readingsBulkUpdateIfChanged
  104. readingsBeginUpdate
  105. readingsEndUpdate
  106. defs
  107. modules
  108. Log3
  109. CommandAttr
  110. attr
  111. CommandDeleteAttr
  112. CommandDeleteReading
  113. CommandSet
  114. AttrVal
  115. ReadingsVal
  116. Value
  117. IsDisabled
  118. deviceEvents
  119. init_done
  120. addToDevAttrList
  121. addToAttrList
  122. delFromDevAttrList
  123. delFromAttrList
  124. gettimeofday
  125. sunset_abs
  126. sunrise_abs
  127. InternalTimer
  128. RemoveInternalTimer
  129. computeAlignTime
  130. ReplaceEventMap)
  131. );
  132. }
  133. ## Die Attributsliste welche an die Rolläden verteilt wird. Zusammen mit Default Werten
  134. my %userAttrList = (
  135. 'ASC_Mode_Up:absent,always,off,home' => 'always',
  136. 'ASC_Mode_Down:absent,always,off,home' => 'always',
  137. 'ASC_Up:time,astro,brightness' => 'astro',
  138. 'ASC_Down:time,astro,brightness' => 'astro',
  139. 'ASC_AutoAstroModeMorning:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON' => 'none',
  140. 'ASC_AutoAstroModeMorningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9'
  141. => 'none',
  142. 'ASC_AutoAstroModeEvening:REAL,CIVIL,NAUTIC,ASTRONOMIC,HORIZON' => 'none',
  143. 'ASC_AutoAstroModeEveningHorizon:-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9'
  144. => 'none',
  145. 'ASC_Open_Pos:0,10,20,30,40,50,60,70,80,90,100' => [ '', 0, 100 ],
  146. 'ASC_Closed_Pos:0,10,20,30,40,50,60,70,80,90,100' => [ '', 100, 0 ],
  147. 'ASC_Pos_Reading' => [ '', 'position', 'pct' ],
  148. 'ASC_Time_Up_Early' => '04:30',
  149. 'ASC_Time_Up_Late' => '09:00',
  150. 'ASC_Time_Up_WE_Holiday' => '08:30',
  151. 'ASC_Time_Down_Early' => '15:30',
  152. 'ASC_Time_Down_Late' => '22:30',
  153. 'ASC_WindowRec' => 'none',
  154. 'ASC_Ventilate_Window_Open:on,off' => 'on',
  155. 'ASC_lock-out:soft,hard' => 'soft',
  156. 'ASC_lock-outCmd:inhibit,blocked' => 'none',
  157. # 'ASC_Shading_Direction' => 178,
  158. # 'ASC_Shading_Pos:10,20,30,40,50,60,70,80,90,100' => 30,
  159. # 'ASC_Shading:on,off,delayed,present,absent' => 'off',
  160. # 'ASC_Shading_Pos_after_Shading:-1,0,10,20,30,40,50,60,70,80,90,100' => -1,
  161. # 'ASC_Shading_Angle_Left:0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90'
  162. # => 85,
  163. # 'ASC_Shading_Angle_Right:0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90'
  164. # => 85,
  165. 'ASC_Shading_Brightness_Sensor' => 'none',
  166. 'ASC_Shading_Brightness_Reading' => 'brightness',
  167. # 'ASC_Shading_StateChange_Sunny' => '6000',
  168. # 'ASC_Shading_StateChange_Cloudy' => '4000',
  169. # 'ASC_Shading_WaitingPeriod' => 20,
  170. # 'ASC_Shading_Min_Elevation' => 'none',
  171. # 'ASC_Shading_Min_OutsideTemperature' => 18,
  172. # 'ASC_Shading_BlockingTime_After_Manual' => 20,
  173. # 'ASC_Shading_BlockingTime_Twilight' => 45,
  174. # 'ASC_Shading_Fast_Open:on,off' => 'none',
  175. # 'ASC_Shading_Fast_Close:on,off' => 'none',
  176. 'ASC_Drive_Offset' => -1,
  177. 'ASC_WindowRec_subType:twostate,threestate' => 'twostate',
  178. 'ASC_ShuttersPlace:window,terrace' => 'window',
  179. 'ASC_Ventilate_Pos:10,20,30,40,50,60,70,80,90,100' => [ '', 70, 30 ],
  180. 'ASC_Pos_after_ComfortOpen:0,10,20,30,40,50,60,70,80,90,100' =>
  181. [ '', 20, 80 ],
  182. 'ASC_GuestRoom:on,off' => 'none',
  183. 'ASC_Antifreeze:off,on' => 'off',
  184. 'ASC_Partymode:on,off' => 'off',
  185. 'ASC_Roommate_Device' => 'none',
  186. 'ASC_Roommate_Reading' => 'state',
  187. 'ASC_Self_Defense_Exclude:on,off' => 'off',
  188. 'ASC_BrightnessMinVal' => -1,
  189. 'ASC_BrightnessMaxVal' => -1,
  190. );
  191. my %posSetCmds = (
  192. ZWave => 'dim',
  193. Siro => 'position',
  194. CUL_HM => 'pct',
  195. ROLLO => 'pct',
  196. SOMFY => 'position',
  197. tahoma => 'dim',
  198. KLF200Node => 'pct',
  199. DUOFERN => 'position',
  200. );
  201. my $shutters = new ASC_Shutters();
  202. my $ascDev = new ASC_Dev();
  203. sub Define($$) {
  204. my ( $hash, $def ) = @_;
  205. my @a = split( "[ \t][ \t]*", $def );
  206. return "only one AutoShuttersControl instance allowed"
  207. if ( devspec2array('TYPE=AutoShuttersControl') > 1 )
  208. ; # es wird geprüft ob bereits eine Instanz unseres Modules existiert,wenn ja wird abgebrochen
  209. return "too few parameters: define <name> ShuttersControl" if ( @a != 2 );
  210. return
  211. "Cannot define ShuttersControl device. Perl modul ${missingModul}is missing."
  212. if ($missingModul)
  213. ; # Abbruch wenn benötigte Hilfsmodule nicht vorhanden sind / vorerst unwichtig
  214. my $name = $a[0];
  215. $hash->{VERSION} = $version;
  216. $hash->{MID} = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
  217. ; # eine Ein Eindeutige ID für interne FHEM Belange / nicht weiter wichtig
  218. $hash->{NOTIFYDEV} = "global,"
  219. . $name; # Liste aller Devices auf deren Events gehört werden sollen
  220. $ascDev->setName($name);
  221. readingsSingleUpdate(
  222. $hash,
  223. "state",
  224. "please set attribute ASC with value 1 or 2 in all auto controlled shutter devices and then execute 'set DEVICENAME scanForShutters'",
  225. 1
  226. );
  227. CommandAttr( undef, $name . ' room ASC' )
  228. if ( AttrVal( $name, 'room', 'none' ) eq 'none' );
  229. CommandAttr( undef, $name . ' icon fts_shutter_automatic' )
  230. if ( AttrVal( $name, 'icon', 'none' ) eq 'none' );
  231. CommandAttr( undef, $name . ' ASC_autoAstroModeEvening REAL' )
  232. if ( $ascDev->getAutoAstroModeEvening eq 'none' );
  233. CommandAttr( undef, $name . ' ASC_autoAstroModeMorning REAL' )
  234. if ( $ascDev->getAutoAstroModeMorning eq 'none' );
  235. CommandAttr( undef, $name . ' ASC_autoShuttersControlMorning on' )
  236. if ( $ascDev->getAutoShuttersControlMorning eq 'none' );
  237. CommandAttr( undef, $name . ' ASC_autoShuttersControlEvening on' )
  238. if ( $ascDev->getAutoShuttersControlEvening eq 'none' );
  239. CommandAttr( undef, $name . ' ASC_temperatureReading temperature' )
  240. if ( $ascDev->getTempReading eq 'none' );
  241. CommandAttr( undef, $name . ' ASC_freezeTemp 3' )
  242. if ( $ascDev->getAntifreezeTemp eq 'none' );
  243. CommandAttr( undef,
  244. $name
  245. . ' devStateIcon selfeDefense.terrace:fts_door_tilt created.new.drive.timer:clock .*asleep:scene_sleeping roommate.(awoken|home):user_available residents.(home|awoken):status_available manual:fts_shutter_manual selfeDefense.active:status_locked selfeDefense inactive:status_open day.open:scene_day night close:scene_night'
  246. ) if ( AttrVal( $name, 'devStateIcon', 'none' ) eq 'none' );
  247. addToAttrList('ASC:0,1,2');
  248. Log3( $name, 3, "AutoShuttersControl ($name) - defined" );
  249. $modules{AutoShuttersControl}{defptr}{ $hash->{MID} } = $hash;
  250. return undef;
  251. }
  252. sub Undef($$) {
  253. my ( $hash, $arg ) = @_;
  254. my $name = $hash->{NAME};
  255. UserAttributs_Readings_ForShutters( $hash, 'del' )
  256. ; # es sollen alle Attribute und Readings in den Rolläden Devices gelöscht werden welche vom Modul angelegt wurden
  257. delFromAttrList('ASC:0,1,2');
  258. delete( $modules{AutoShuttersControl}{defptr}{ $hash->{MID} } );
  259. Log3( $name, 3, "AutoShuttersControl ($name) - delete device $name" );
  260. return undef;
  261. }
  262. sub Attr(@) {
  263. my ( $cmd, $name, $attrName, $attrVal ) = @_;
  264. my $hash = $defs{$name};
  265. if ( $attrName eq "disable" ) {
  266. if ( $cmd eq "set" and $attrVal eq "1" ) {
  267. Log3( $name, 3, "AutoShuttersControl ($name) - disabled" );
  268. }
  269. elsif ( $cmd eq "del" ) {
  270. Log3( $name, 3, "AutoShuttersControl ($name) - enabled" );
  271. }
  272. }
  273. elsif ( $attrName eq "disabledForIntervals" ) {
  274. if ( $cmd eq "set" ) {
  275. return
  276. "check disabledForIntervals Syntax HH:MM-HH:MM or 'HH:MM-HH:MM HH:MM-HH:MM ...'"
  277. unless ( $attrVal =~ /^((\d{2}:\d{2})-(\d{2}:\d{2})\s?)+$/ );
  278. Log3( $name, 3,
  279. "AutoShuttersControl ($name) - disabledForIntervals" );
  280. #readingsSingleUpdate ($hash,"state","disabled",1);
  281. }
  282. elsif ( $cmd eq "del" ) {
  283. Log3( $name, 3, "AutoShuttersControl ($name) - enabled" );
  284. #readingsSingleUpdate ($hash,"state","active",1);
  285. }
  286. }
  287. return undef;
  288. }
  289. sub Notify($$) {
  290. my ( $hash, $dev ) = @_;
  291. my $name = $hash->{NAME};
  292. return if ( IsDisabled($name) );
  293. my $devname = $dev->{NAME};
  294. my $devtype = $dev->{TYPE};
  295. my $events = deviceEvents( $dev, 1 );
  296. return if ( !$events );
  297. Log3( $name, 5,
  298. "AutoShuttersControl ($name) - Devname: "
  299. . $devname
  300. . " Name: "
  301. . $name
  302. . " Notify: "
  303. . Dumper $events); # mit Dumper
  304. if (
  305. (
  306. grep /^DEFINED.$name$/,
  307. @{$events} and $devname eq 'global' and $init_done
  308. )
  309. or (
  310. grep /^INITIALIZED$/,
  311. @{$events} or grep /^REREADCFG$/,
  312. @{$events} or grep /^MODIFIED.$name$/,
  313. @{$events}
  314. )
  315. and $devname eq 'global'
  316. )
  317. {
  318. readingsSingleUpdate( $hash, 'partyMode', 'off', 0 )
  319. if ( $ascDev->getPartyMode eq 'none' );
  320. readingsSingleUpdate( $hash, 'lockOut', 'off', 0 )
  321. if ( $ascDev->getLockOut eq 'none' );
  322. readingsSingleUpdate( $hash, 'sunriseTimeWeHoliday', 'off', 0 )
  323. if ( $ascDev->getSunriseTimeWeHoliday eq 'none' );
  324. readingsSingleUpdate( $hash, 'selfDefense', 'off', 0 )
  325. if ( $ascDev->getSelfDefense eq 'none' );
  326. CommandDeleteReading( undef, $name . ' selfDefence' )
  327. if ( ReadingsVal( $name, 'selfDefence', 'none' ) ne 'none' )
  328. ; # temporär kann später entfernt werden.
  329. CommandAttr( undef, $name . ' ASC_twilightDevice ' . ( devspec2array('TYPE=(Astro|Twilight)'))[0] ) if ( AttrVal($name,'ASC_twilightDevice','none') eq 'none' );
  330. # Ist der Event ein globaler und passt zum Rest der Abfrage oben wird nach neuen Rolläden Devices gescannt und eine Liste im Rolladenmodul sortiert nach Raum generiert
  331. ShuttersDeviceScan($hash)
  332. unless ( ReadingsVal( $name, 'userAttrList', 'none' ) eq 'none' );
  333. }
  334. return
  335. unless ( ref( $hash->{helper}{shuttersList} ) eq 'ARRAY'
  336. and scalar( @{ $hash->{helper}{shuttersList} } ) > 0 );
  337. my $posReading = $shutters->getPosCmd;
  338. if ( $devname eq $name ) {
  339. if ( grep /^userAttrList:.rolled.out$/, @{$events} ) {
  340. unless ( scalar( @{ $hash->{helper}{shuttersList} } ) == 0 ) {
  341. WriteReadingsShuttersList($hash);
  342. UserAttributs_Readings_ForShutters( $hash, 'add' );
  343. InternalTimer( gettimeofday() + 3,
  344. 'AutoShuttersControl::RenewSunRiseSetShuttersTimer',
  345. $hash );
  346. }
  347. }
  348. elsif ( grep /^partyMode:.off$/, @{$events} ) {
  349. PartyModeEventProcessing($hash);
  350. }
  351. elsif ( grep /^sunriseTimeWeHoliday:.(on|off)$/, @{$events} ) {
  352. RenewSunRiseSetShuttersTimer($hash);
  353. }
  354. }
  355. elsif ( $devname eq "global" )
  356. { # Kommt ein globales Event und beinhaltet folgende Syntax wird die Funktion zur Verarbeitung aufgerufen
  357. if (
  358. grep
  359. /^(ATTR|DELETEATTR)\s(.*ASC_Roommate_Device|.*ASC_WindowRec|.*ASC_residentsDevice|.*ASC_rainSensorDevice|.*ASC_Shading_Brightness_Sensor)(\s.*|$)/,
  360. @{$events}
  361. )
  362. {
  363. GeneralEventProcessing( $hash, undef, join( ' ', @{$events} ) );
  364. }
  365. elsif (
  366. grep
  367. /^(ATTR|DELETEATTR)\s(.*ASC_Time_Up_WE_Holiday|.*ASC_Up|.*ASC_Down|.*ASC_AutoAstroModeMorning|.*ASC_AutoAstroModeMorningHorizon|.*ASC_AutoAstroModeEvening|.*ASC_AutoAstroModeEveningHorizon|.*ASC_Time_Up_Early|.*ASC_Time_Up_Late|.*ASC_Time_Down_Early|.*ASC_Time_Down_Late|.*ASC_autoAstroModeMorning|.*ASC_autoAstroModeMorningHorizon|.*ASC_autoAstroModeEvening|.*ASC_autoAstroModeEveningHorizon)(\s.*|$)/,
  368. @{$events}
  369. )
  370. {
  371. GeneralEventProcessing( $hash, undef, join( ' ', @{$events} ) );
  372. }
  373. }
  374. elsif ( grep /^($posReading):\s\d+$/, @{$events} ) {
  375. ShuttersEventProcessing( $hash, $devname, join( ' ', @{$events} ) );
  376. }
  377. else {
  378. GeneralEventProcessing( $hash, $devname, join( ' ', @{$events} ) )
  379. ; # bei allen anderen Events wird die entsprechende Funktion zur Verarbeitung aufgerufen
  380. }
  381. return;
  382. }
  383. sub GeneralEventProcessing($$$) {
  384. my ( $hash, $devname, $events ) = @_;
  385. my $name = $hash->{NAME};
  386. if ( defined($devname) and ($devname) )
  387. { # es wird lediglich der Devicename der Funktion mitgegeben wenn es sich nicht um global handelt daher hier die Unterschiedung
  388. while ( my ( $device, $deviceAttr ) =
  389. each %{ $hash->{monitoredDevs}{$devname} } )
  390. {
  391. WindowRecEventProcessing( $hash, $device, $events )
  392. if ( $deviceAttr eq 'ASC_WindowRec' )
  393. ; # ist es ein Fensterdevice wird die Funktion gestartet
  394. RoommateEventProcessing( $hash, $device, $events )
  395. if ( $deviceAttr eq 'ASC_Roommate_Device' )
  396. ; # ist es ein Bewohner Device wird diese Funktion gestartet
  397. ResidentsEventProcessing( $hash, $device, $events )
  398. if ( $deviceAttr eq 'ASC_residentsDevice' );
  399. RainEventProcessing( $hash, $device, $events )
  400. if ( $deviceAttr eq 'ASC_rainSensorDevice' );
  401. $shutters->setShuttersDev($device)
  402. if ( $deviceAttr eq 'ASC_Shading_Brightness_Sensor' );
  403. BrightnessEventProcessing( $hash, $device, $events )
  404. if (
  405. $deviceAttr eq 'ASC_Shading_Brightness_Sensor'
  406. and ( $shutters->getDown eq 'brightness'
  407. or $shutters->getUp eq 'brightness' )
  408. );
  409. }
  410. }
  411. else { # alles was kein Devicenamen mit übergeben hat landet hier
  412. if ( $events =~
  413. m#^ATTR\s(.*)\s(ASC_Roommate_Device|ASC_WindowRec|ASC_residentsDevice|ASC_rainSensorDevice|ASC_Shading_Brightness_Sensor)\s(.*)$#
  414. )
  415. { # wurde den Attributen unserer Rolläden ein Wert zugewiesen ?
  416. AddNotifyDev( $hash, $3, $1, $2 ) if ( $3 ne 'none' );
  417. Log3( $name, 4,
  418. "AutoShuttersControl ($name) - EventProcessing: ATTR" );
  419. }
  420. elsif ( $events =~
  421. m#^DELETEATTR\s(.*)\s(ASC_Roommate_Device|ASC_WindowRec|ASC_residentsDevice|ASC_rainSensorDevice|ASC_Shading_Brightness_Sensor)$#
  422. )
  423. { # wurde das Attribut unserer Rolläden gelöscht ?
  424. Log3( $name, 4,
  425. "AutoShuttersControl ($name) - EventProcessing: DELETEATTR" );
  426. DeleteNotifyDev( $hash, $1, $2 );
  427. }
  428. elsif ( $events =~
  429. m#^ATTR\s(.*)\s(ASC_Time_Up_WE_Holiday|ASC_Up|ASC_Down|ASC_AutoAstroModeMorning|ASC_AutoAstroModeMorningHorizon|ASC_AutoAstroModeEvening|ASC_AutoAstroModeEveningHorizon|ASC_Time_Up_Early|ASC_Time_Up_Late|ASC_Time_Down_Early|ASC_Time_Down_Late)\s(.*)$#
  430. )
  431. {
  432. CreateSunRiseSetShuttersTimer( $hash, $1 )
  433. if (
  434. $2 ne 'ASC_Time_Up_WE_Holiday'
  435. or ( $2 eq 'ASC_Time_Up_WE_Holiday'
  436. and $ascDev->getSunriseTimeWeHoliday eq 'on' )
  437. );
  438. }
  439. elsif ( $events =~
  440. m#^ATTR\s(.*)\s(ASC_autoAstroModeMorning|ASC_autoAstroModeMorningHorizon|ASC_autoAstroModeEvening|ASC_autoAstroModeEveningHorizon)\s(.*)$#
  441. )
  442. {
  443. RenewSunRiseSetShuttersTimer($hash);
  444. }
  445. }
  446. }
  447. sub Set($$@) {
  448. my ( $hash, $name, @aa ) = @_;
  449. my ( $cmd, @args ) = @aa;
  450. if ( lc $cmd eq 'renewsetsunrisesunsettimer' ) {
  451. return "usage: $cmd" if ( @args != 0 );
  452. RenewSunRiseSetShuttersTimer($hash);
  453. }
  454. elsif ( lc $cmd eq 'scanforshutters' ) {
  455. return "usage: $cmd" if ( @args != 0 );
  456. ShuttersDeviceScan($hash);
  457. }
  458. elsif ( lc $cmd eq 'createnewnotifydev' ) {
  459. return "usage: $cmd" if ( @args != 0 );
  460. CreateNewNotifyDev($hash);
  461. }
  462. elsif ( lc $cmd eq 'partymode' ) {
  463. return "usage: $cmd" if ( @args > 1 );
  464. readingsSingleUpdate( $hash, $cmd, join( ' ', @args ), 1 );
  465. }
  466. elsif ( lc $cmd eq 'lockout' ) {
  467. return "usage: $cmd" if ( @args > 1 );
  468. readingsSingleUpdate( $hash, $cmd, join( ' ', @args ), 1 );
  469. SetHardewareBlockForShutters( $hash, join( ' ', @args ) );
  470. }
  471. elsif ( lc $cmd eq 'sunrisetimeweholiday' ) {
  472. return "usage: $cmd" if ( @args > 1 );
  473. readingsSingleUpdate( $hash, $cmd, join( ' ', @args ), 1 );
  474. }
  475. elsif ( lc $cmd eq 'selfdefense' ) {
  476. return "usage: $cmd" if ( @args > 1 );
  477. readingsSingleUpdate( $hash, $cmd, join( ' ', @args ), 1 );
  478. }
  479. elsif ( lc $cmd eq 'wiggle' ) {
  480. return "usage: $cmd" if ( @args > 1 );
  481. ( $args[0] eq 'all' ? wiggleAll($hash) : wiggle( $hash, $args[0] ) );
  482. }
  483. else {
  484. my $list = "scanForShutters:noArg";
  485. $list .=
  486. " renewSetSunriseSunsetTimer:noArg partyMode:on,off lockOut:on,off sunriseTimeWeHoliday:on,off selfDefense:on,off wiggle:all,"
  487. . join( ',', @{ $hash->{helper}{shuttersList} } )
  488. if ( ReadingsVal( $name, 'userAttrList', 'none' ) eq 'rolled out' );
  489. $list .= " createNewNotifyDev:noArg"
  490. if ( ReadingsVal( $name, 'userAttrList', 'none' ) eq 'rolled out'
  491. and AttrVal( $name, 'verbose', 3 ) > 3 );
  492. return "Unknown argument $cmd,choose one of $list";
  493. }
  494. return undef;
  495. }
  496. sub Get($$@) {
  497. my ( $hash, $name, @aa ) = @_;
  498. my ( $cmd, @args ) = @aa;
  499. if ( lc $cmd eq 'showshuttersinformations' ) {
  500. return "usage: $cmd" if ( @args != 0 );
  501. my $ret = GetShuttersInformation($hash);
  502. return $ret;
  503. }
  504. elsif ( lc $cmd eq 'shownotifydevsinformations' ) {
  505. return "usage: $cmd" if ( @args != 0 );
  506. my $ret = GetMonitoredDevs($hash);
  507. return $ret;
  508. }
  509. else {
  510. my $list = "";
  511. $list .= " showShuttersInformations:noArg"
  512. if ( ReadingsVal( $name, 'userAttrList', 'none' ) eq 'rolled out' );
  513. $list .= " showNotifyDevsInformations:noArg"
  514. if ( ReadingsVal( $name, 'userAttrList', 'none' ) eq 'rolled out'
  515. and AttrVal( $name, 'verbose', 3 ) > 3 );
  516. return "Unknown argument $cmd,choose one of $list";
  517. }
  518. }
  519. sub ShuttersDeviceScan($) {
  520. my $hash = shift;
  521. my $name = $hash->{NAME};
  522. delete $hash->{helper}{shuttersList};
  523. my @list;
  524. @list = devspec2array('ASC=[1-2]');
  525. CommandDeleteReading( undef, $name . ' .*_nextAstroTimeEvent' );
  526. unless ( scalar(@list) > 0 ) {
  527. readingsBeginUpdate($hash);
  528. readingsBulkUpdate( $hash, 'userAttrList', 'none' );
  529. readingsBulkUpdate( $hash, 'state', 'no shutters found' );
  530. readingsEndUpdate( $hash, 1 );
  531. return;
  532. }
  533. my $shuttersList = '';
  534. foreach (@list) {
  535. push( @{ $hash->{helper}{shuttersList} }, $_ )
  536. ; ## einem Hash wird ein Array zugewiesen welches die Liste der erkannten Rollos beinhaltet
  537. delFromDevAttrList( $_, 'ASC_Up:time,astro' )
  538. if (
  539. AttrVal( $_, 'userattr', 'none' ) =~ /\sASC_Up:time,astro\sASC_/ )
  540. ; # temporär muss später gelöscht werden ab Version 0.1.80
  541. delFromDevAttrList( $_, 'ASC_Down:time,astro' )
  542. if (
  543. AttrVal( $_, 'userattr', 'none' ) =~ /\sASC_Down:time,astro\sASC_/ )
  544. ; # temporär muss später gelöscht werden ab Version 0.1.80
  545. delFromDevAttrList( $_, 'ASC_Mode_Up:absent,always,off' )
  546. if ( AttrVal( $_, 'userattr', 'none' ) =~
  547. /\sASC_Mode_Up:absent,always,off\sASC_/ )
  548. ; # temporär muss später gelöscht werden ab Version 0.1.81
  549. delFromDevAttrList( $_, 'ASC_Mode_Down:absent,always,off' )
  550. if ( AttrVal( $_, 'userattr', 'none' ) =~
  551. /\sASC_Mode_Down:absent,always,off\sASC_/ )
  552. ; # temporär muss später gelöscht werden ab Version 0.1.81
  553. delFromDevAttrList( $_, 'ASC_Self_Defence_Exclude:on,off' )
  554. ; # temporär muss später gelöscht werden ab Version 0.1.80
  555. delFromDevAttrList( $_, 'ASC_Offset_Minutes_Morning' )
  556. ; # temporär muss später gelöscht werden ab Version 0.1.81
  557. delFromDevAttrList( $_, 'ASC_Offset_Minutes_Evening' )
  558. ; # temporär muss später gelöscht werden ab Version 0.1.81
  559. delFromDevAttrList( $_, 'ASC_Direction' )
  560. ; # temporär muss später gelöscht werden ab Version 0.1.89
  561. delFromDevAttrList( $_,
  562. 'ASC_Shading_Pos:10,20,30,40,50,60,70,80,90,100' )
  563. ; # temporär muss später gelöscht werden ab Version 0.1.89
  564. delFromDevAttrList( $_, 'ASC_Rand_Minutes' )
  565. ; # temporär muss später gelöscht werden ab Version 0.1.89
  566. delFromDevAttrList( $_, 'ASC_Shading:on,off,delayed,present,absent' )
  567. ; # temporär muss später gelöscht werden ab Version 0.1.89
  568. delFromDevAttrList( $_,
  569. 'ASC_Shading_Pos_after_Shading:-1,0,10,20,30,40,50,60,70,80,90,100'
  570. ); # temporär muss später gelöscht werden ab Version 0.1.89
  571. delFromDevAttrList( $_,
  572. 'ASC_Shading_Angle_Left:0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90'
  573. ); # temporär muss später gelöscht werden ab Version 0.1.89
  574. delFromDevAttrList( $_,
  575. 'ASC_Shading_Angle_Right:0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90'
  576. ); # temporär muss später gelöscht werden ab Version 0.1.89
  577. delFromDevAttrList( $_, 'ASC_Shading_StateChange_Sunny' )
  578. ; # temporär muss später gelöscht werden ab Version 0.1.89
  579. delFromDevAttrList( $_, 'ASC_Shading_StateChange_Cloudy' )
  580. ; # temporär muss später gelöscht werden ab Version 0.1.89
  581. delFromDevAttrList( $_, 'ASC_Shading_WaitingPeriod' )
  582. ; # temporär muss später gelöscht werden ab Version 0.1.89
  583. delFromDevAttrList( $_, 'ASC_Shading_Min_Elevation' )
  584. ; # temporär muss später gelöscht werden ab Version 0.1.89
  585. delFromDevAttrList( $_, 'ASC_Shading_Min_OutsideTemperature' )
  586. ; # temporär muss später gelöscht werden ab Version 0.1.89
  587. delFromDevAttrList( $_, 'ASC_Shading_BlockingTime_After_Manual' )
  588. ; # temporär muss später gelöscht werden ab Version 0.1.89
  589. delFromDevAttrList( $_, 'ASC_Shading_BlockingTime_Twilight' )
  590. ; # temporär muss später gelöscht werden ab Version 0.1.89
  591. delFromDevAttrList( $_, 'ASC_Shading_Fast_Open:on,off' )
  592. ; # temporär muss später gelöscht werden ab Version 0.1.89
  593. delFromDevAttrList( $_, 'ASC_Shading_Fast_Close:on,off' )
  594. ; # temporär muss später gelöscht werden ab Version 0.1.89
  595. delFromDevAttrList( $_, 'ASC_Pos_Cmd' )
  596. ; # temporär muss später gelöscht werden ab Version 0.1.93
  597. CommandDeleteReading( undef,
  598. $_ . ' .AutoShuttersControl_InternalTimerFuncHash' )
  599. ; # temporär muss später gelöscht werden ab Version 0.1.81
  600. CommandDeleteReading( undef,
  601. $_ . ' .AutoShuttersControl_LastPosition' )
  602. ; # temporär muss später gelöscht werden ab Version 0.1.81
  603. CommandDeleteReading( undef, $_ . ' .AutoShuttersControl_DelayCmd' )
  604. ; # temporär muss später gelöscht werden ab Version 0.1.82
  605. $shuttersList = $shuttersList . ',' . $_;
  606. $shutters->setShuttersDev($_);
  607. $shutters->setLastManPos( $shutters->getStatus );
  608. $shutters->setLastPos( $shutters->getStatus );
  609. $shutters->setDelayCmd('none');
  610. $shutters->setNoOffset(0);
  611. $shutters->setPosSetCmd( $posSetCmds{ $defs{$_}->{TYPE} } );
  612. }
  613. $hash->{NOTIFYDEV} = $hash->{NOTIFYDEV} . $shuttersList;
  614. if ( $ascDev->getMonitoredDevs ne 'none' ) {
  615. $hash->{monitoredDevs} =
  616. eval { decode_json( $ascDev->getMonitoredDevs ) };
  617. my $notifyDevString = $hash->{NOTIFYDEV};
  618. while ( each %{ $hash->{monitoredDevs} } ) {
  619. $notifyDevString .= ',' . $_;
  620. }
  621. $hash->{NOTIFYDEV} = $notifyDevString;
  622. }
  623. readingsSingleUpdate( $hash, 'userAttrList', 'rolled out', 1 );
  624. }
  625. ## Die Funktion schreibt in das Moduldevice Readings welche Rolläden in welchen Räumen erfasst wurden.
  626. sub WriteReadingsShuttersList($) {
  627. my $hash = shift;
  628. my $name = $hash->{NAME};
  629. CommandDeleteReading( undef, $name . ' room_.*' );
  630. readingsBeginUpdate($hash);
  631. foreach ( @{ $hash->{helper}{shuttersList} } ) {
  632. readingsBulkUpdate(
  633. $hash,
  634. 'room_' . makeReadingName( AttrVal( $_, 'room', 'unsorted' ) ),
  635. ReadingsVal(
  636. $name,
  637. 'room_' . makeReadingName( AttrVal( $_, 'room', 'unsorted' ) ),
  638. ''
  639. )
  640. . ','
  641. . $_
  642. )
  643. if (
  644. ReadingsVal(
  645. $name,
  646. 'room_' . makeReadingName( AttrVal( $_, 'room', 'unsorted' ) ),
  647. 'none'
  648. ) ne 'none'
  649. );
  650. readingsBulkUpdate( $hash,
  651. 'room_' . makeReadingName( AttrVal( $_, 'room', 'unsorted' ) ), $_ )
  652. if (
  653. ReadingsVal(
  654. $name,
  655. 'room_' . makeReadingName( AttrVal( $_, 'room', 'unsorted' ) ),
  656. 'none'
  657. ) eq 'none'
  658. );
  659. }
  660. readingsBulkUpdate( $hash, 'state', 'active' );
  661. readingsEndUpdate( $hash, 0 );
  662. }
  663. sub UserAttributs_Readings_ForShutters($$) {
  664. my ( $hash, $cmd ) = @_;
  665. my $name = $hash->{NAME};
  666. while ( my ( $attrib, $attribValue ) = each %{userAttrList} ) {
  667. foreach ( @{ $hash->{helper}{shuttersList} } ) {
  668. addToDevAttrList( $_, $attrib )
  669. ; ## fhem.pl bietet eine Funktion um ein userAttr Attribut zu befüllen. Wir schreiben also in den Attribut userAttr alle unsere Attribute rein. Pro Rolladen immer ein Attribut pro Durchlauf
  670. ## Danach werden die Attribute die im userAttr stehen gesetzt und mit default Werten befüllt
  671. if ( $cmd eq 'add' ) {
  672. if ( ref($attribValue) ne 'ARRAY' ) {
  673. $attr{$_}{ ( split( ':', $attrib ) )[0] } = $attribValue
  674. if (
  675. not
  676. defined( $attr{$_}{ ( split( ':', $attrib ) )[0] } ) );
  677. }
  678. else {
  679. $attr{$_}{ ( split( ':', $attrib ) )[0] } =
  680. $attribValue->[ AttrVal( $_, 'ASC', 2 ) ]
  681. if (
  682. not
  683. defined( $attr{$_}{ ( split( ':', $attrib ) )[0] } ) );
  684. }
  685. ## Oder das Attribut wird wieder gelöscht.
  686. }
  687. elsif ( $cmd eq 'del' ) {
  688. $shutters->setShuttersDev($_);
  689. RemoveInternalTimer( $shutters->getInTimerFuncHash );
  690. CommandDeleteReading( undef,
  691. $_ . ' .?(AutoShuttersControl|ASC)_.*' );
  692. CommandDeleteAttr( undef, $_ . ' ASC' );
  693. delFromDevAttrList( $_, $attrib );
  694. }
  695. }
  696. }
  697. }
  698. ## Fügt dem NOTIFYDEV Hash weitere Devices hinzu
  699. sub AddNotifyDev($@) {
  700. my ( $hash, $dev, $shuttersDev, $shuttersAttr ) = @_;
  701. my $name = $hash->{NAME};
  702. my $notifyDev = $hash->{NOTIFYDEV};
  703. $notifyDev = "" if ( !$notifyDev );
  704. my %hash;
  705. %hash = map { ( $_ => 1 ) }
  706. split( ",", "$notifyDev,$dev" );
  707. $hash->{NOTIFYDEV} = join( ",", sort keys %hash );
  708. my @devs = split( ',', $dev );
  709. foreach (@devs) {
  710. $hash->{monitoredDevs}{$_}{$shuttersDev} = $shuttersAttr;
  711. }
  712. readingsSingleUpdate( $hash, '.monitoredDevs',
  713. eval { encode_json( $hash->{monitoredDevs} ) }, 0 );
  714. }
  715. ## entfernt aus dem NOTIFYDEV Hash Devices welche als Wert in Attributen steckten
  716. sub DeleteNotifyDev($@) {
  717. my ( $hash, $shuttersDev, $shuttersAttr ) = @_;
  718. my $name = $hash->{NAME};
  719. my $notifyDevs =
  720. ExtractNotifyDevFromEvent( $hash, $shuttersDev, $shuttersAttr );
  721. foreach my $notifyDev ( keys( %{$notifyDevs} ) ) {
  722. Log3( $name, 4,
  723. "AutoShuttersControl ($name) - DeleteNotifyDev - NotifyDev: "
  724. . $_ );
  725. delete $hash->{monitoredDevs}{$notifyDev}{$shuttersDev};
  726. if ( !keys %{ $hash->{monitoredDevs}{$notifyDev} } ) {
  727. delete $hash->{monitoredDevs}{$notifyDev};
  728. my $notifyDevString = $hash->{NOTIFYDEV};
  729. $notifyDevString = "" if ( !$notifyDevString );
  730. my %hash;
  731. %hash = map { ( $_ => 1 ) }
  732. grep { " $notifyDev " !~ m/ $_ / }
  733. split( ",", "$notifyDevString,$notifyDev" );
  734. $hash->{NOTIFYDEV} = join( ",", sort keys %hash );
  735. }
  736. }
  737. readingsSingleUpdate( $hash, '.monitoredDevs',
  738. eval { encode_json( $hash->{monitoredDevs} ) }, 0 );
  739. }
  740. ## Sub zum steuern der Rolläden bei einem Fenster Event
  741. sub WindowRecEventProcessing($@) {
  742. my ( $hash, $shuttersDev, $events ) = @_;
  743. my $name = $hash->{NAME};
  744. if ( $events =~ m#state:\s(open|closed|tilted)# ) {
  745. $shutters->setShuttersDev($shuttersDev);
  746. $shutters->setNoOffset(1);
  747. my $queryShuttersPosWinRecTilted = (
  748. $shutters->getShuttersPosCmdValueNegate
  749. ? $shutters->getStatus > $shutters->getVentilatePos
  750. : $shutters->getStatus < $shutters->getVentilatePos
  751. );
  752. if ( $shutters->getDelayCmd ne 'none' )
  753. { # Es wird geschaut ob wärend der Fenster offen Phase ein Fahrbefehl über das Modul kam,wenn ja wird dieser aus geführt
  754. if ( $1 eq 'closed' ) {
  755. ShuttersCommandSet( $hash, $shuttersDev,
  756. $shutters->getClosedPos );
  757. }
  758. elsif (
  759. (
  760. $1 eq 'tilted'
  761. or ( $1 eq 'open' and $shutters->getSubTyp eq 'twostate' )
  762. )
  763. and $shutters->getVentilateOpen eq 'on'
  764. and $queryShuttersPosWinRecTilted
  765. )
  766. {
  767. ShuttersCommandSet( $hash, $shuttersDev,
  768. $shutters->getVentilatePos );
  769. }
  770. }
  771. elsif ( $1 eq 'closed'
  772. ) # wenn nicht dann wird entsprechend dem Fensterkontakt Event der Rolladen geschlossen oder zum lüften geöffnet
  773. {
  774. ShuttersCommandSet( $hash, $shuttersDev, $shutters->getClosedPos )
  775. if ( $shutters->getStatus == $shutters->getVentilatePos
  776. or $shutters->getStatus == $shutters->getPosAfterComfortOpen );
  777. }
  778. elsif (
  779. (
  780. $1 eq 'tilted'
  781. or ( $1 eq 'open' and $shutters->getSubTyp eq 'twostate' )
  782. )
  783. and $shutters->getVentilateOpen eq 'on'
  784. and $queryShuttersPosWinRecTilted
  785. )
  786. {
  787. ShuttersCommandSet( $hash, $shuttersDev,
  788. $shutters->getVentilatePos );
  789. }
  790. elsif ( $1 eq 'open'
  791. and $shutters->getSubTyp eq 'threestate'
  792. and $ascDev->getAutoShuttersControlComfort eq 'on'
  793. and $queryShuttersPosWinRecTilted )
  794. {
  795. ShuttersCommandSet( $hash, $shuttersDev,
  796. $shutters->getPosAfterComfortOpen );
  797. }
  798. }
  799. }
  800. ## Sub zum steuern der Rolladen bei einem Bewohner/Roommate Event
  801. sub RoommateEventProcessing($@) {
  802. my ( $hash, $shuttersDev, $events ) = @_;
  803. my $name = $hash->{NAME};
  804. $shutters->setShuttersDev($shuttersDev);
  805. my $reading = $shutters->getRoommatesReading;
  806. if ( $events =~ m#$reading:\s(absent|gotosleep|asleep|awoken|home)# ) {
  807. Log3( $name, 4,
  808. "AutoShuttersControl ($name) - RoommateEventProcessing: $shutters->getRoommatesReading"
  809. );
  810. Log3( $name, 4,
  811. "AutoShuttersControl ($name) - RoommateEventProcessing: $shuttersDev und Events $events"
  812. );
  813. if (
  814. ( $1 eq 'home' or $1 eq 'awoken' )
  815. and ( $shutters->getRoommatesStatus eq 'home'
  816. or $shutters->getRoommatesStatus eq 'awoken' )
  817. and $ascDev->getAutoShuttersControlMorning eq 'on'
  818. and ( $shutters->getModeUp eq 'always'
  819. or $shutters->getModeUp eq 'home' )
  820. )
  821. {
  822. if (
  823. (
  824. $shutters->getRoommatesLastStatus eq 'asleep'
  825. or $shutters->getRoommatesLastStatus eq 'awoken'
  826. )
  827. and IsDay( $hash, $shuttersDev )
  828. )
  829. {
  830. $shutters->setLastDrive('roommate awoken');
  831. ShuttersCommandSet( $hash, $shuttersDev,
  832. $shutters->getOpenPos );
  833. }
  834. if (
  835. (
  836. $shutters->getRoommatesLastStatus eq 'absent'
  837. or $shutters->getRoommatesLastStatus eq 'gone'
  838. or $shutters->getRoommatesLastStatus eq 'home'
  839. )
  840. and ( $shutters->getModeUp eq 'home'
  841. or $shutters->getModeUp eq 'always'
  842. or $shutters->getModeDown eq 'home'
  843. or $shutters->getModeDown eq 'always' )
  844. and $shutters->getRoommatesStatus eq 'home'
  845. )
  846. {
  847. if ( not IsDay( $hash, $shuttersDev ) ) {
  848. my $position;
  849. if ( CheckIfShuttersWindowRecOpen($shuttersDev) == 0
  850. or $shutters->getVentilateOpen eq 'off' )
  851. {
  852. $position = $shutters->getClosedPos;
  853. }
  854. else { $position = $shutters->getVentilatePos; }
  855. $shutters->setLastDrive('roommate home');
  856. ShuttersCommandSet( $hash, $shuttersDev, $position );
  857. }
  858. elsif ( IsDay( $hash, $shuttersDev )
  859. and $shutters->getStatus == $shutters->getClosedPos )
  860. {
  861. $shutters->setLastDrive('roommate home');
  862. ShuttersCommandSet( $hash, $shuttersDev,
  863. $shutters->getOpenPos );
  864. }
  865. }
  866. }
  867. elsif (
  868. (
  869. $shutters->getModeDown eq 'always'
  870. or $shutters->getModeDown eq 'home'
  871. )
  872. and ( $1 eq 'gotosleep' or $1 eq 'asleep' )
  873. and $ascDev->getAutoShuttersControlEvening eq 'on'
  874. )
  875. {
  876. my $position;
  877. if ( CheckIfShuttersWindowRecOpen($shuttersDev) == 0
  878. or $shutters->getVentilateOpen eq 'off' )
  879. {
  880. $position = $shutters->getClosedPos;
  881. }
  882. else { $position = $shutters->getVentilatePos; }
  883. $shutters->setLastDrive('roommate asleep');
  884. ShuttersCommandSet( $hash, $shuttersDev, $position );
  885. }
  886. elsif ( $shutters->getModeDown eq 'absent'
  887. and $1 eq 'absent' )
  888. {
  889. $shutters->setLastDrive('roommate absent');
  890. ShuttersCommandSet( $hash, $shuttersDev, $shutters->getClosedPos );
  891. }
  892. }
  893. }
  894. sub ResidentsEventProcessing($@) {
  895. my ( $hash, $device, $events ) = @_;
  896. my $name = $device;
  897. my $reading = $ascDev->getResidentsReading;
  898. if ( $events =~ m#$reading:\s(absent)# ) {
  899. foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) {
  900. $shutters->setShuttersDev($shuttersDev);
  901. if (
  902. CheckIfShuttersWindowRecOpen($shuttersDev) != 0
  903. and $ascDev->getSelfDefense eq 'on'
  904. and $shutters->getSelfDefenseExclude eq 'off'
  905. or (
  906. (
  907. $shutters->getModeDown eq 'absent'
  908. or $shutters->getModeDown eq 'always'
  909. )
  910. and not IsDay( $hash, $shuttersDev )
  911. )
  912. )
  913. {
  914. if ( CheckIfShuttersWindowRecOpen($shuttersDev) != 0
  915. and $ascDev->getSelfDefense eq 'on'
  916. and $shutters->getSelfDefenseExclude eq 'off' )
  917. {
  918. $shutters->setLastDrive('selfeDefense active');
  919. }
  920. else { $shutters->setLastDrive('residents absent'); }
  921. $shutters->setDriveCmd( $shutters->getClosedPos );
  922. }
  923. }
  924. }
  925. elsif ( $events =~ m#$reading:\s(gone)#
  926. and $ascDev->getSelfDefense eq 'on' )
  927. {
  928. foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) {
  929. $shutters->setShuttersDev($shuttersDev);
  930. if ( $shutters->getShuttersPlace eq 'terrace' ) {
  931. $shutters->setLastDrive('selfeDefense terrace');
  932. $shutters->setDriveCmd( $shutters->getClosedPos );
  933. }
  934. }
  935. }
  936. elsif (
  937. $events =~ m#$reading:\s(home)#
  938. and ( $ascDev->getResidentsLastStatus eq 'absent'
  939. or $ascDev->getResidentsLastStatus eq 'gone'
  940. or $ascDev->getResidentsLastStatus eq 'asleep'
  941. or $ascDev->getResidentsLastStatus eq 'awoken' )
  942. )
  943. {
  944. foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) {
  945. $shutters->setShuttersDev($shuttersDev);
  946. if (
  947. $shutters->getStatus != $shutters->getClosedPos
  948. and not IsDay( $hash, $shuttersDev )
  949. and $shutters->getRoommatesStatus eq 'none'
  950. and ( $shutters->getModeDown eq 'home'
  951. or $shutters->getModeDown eq 'always' )
  952. )
  953. {
  954. $shutters->setLastDrive('residents home');
  955. $shutters->setDriveCmd( $shutters->getClosedPos );
  956. }
  957. elsif (
  958. $ascDev->getSelfDefense eq 'on'
  959. and CheckIfShuttersWindowRecOpen($shuttersDev) != 0
  960. and $shutters->getSelfDefenseExclude eq 'off'
  961. or ( $ascDev->getResidentsLastStatus eq 'gone'
  962. and $shutters->getShuttersPlace eq 'terrace' )
  963. and ( $shutters->getModeUp eq 'absent'
  964. or $shutters->getModeUp eq 'off' )
  965. )
  966. {
  967. $shutters->setLastDrive('selfeDefense inactive');
  968. $shutters->setDriveCmd( $shutters->getLastPos );
  969. }
  970. elsif (
  971. $shutters->getStatus == $shutters->getClosedPos
  972. and IsDay( $hash, $shuttersDev )
  973. and $shutters->getRoommatesStatus eq 'none'
  974. and ( $shutters->getModeUp eq 'home'
  975. or $shutters->getModeUp eq 'always' )
  976. )
  977. {
  978. if ( $ascDev->getResidentsLastStatus eq 'asleep'
  979. or $ascDev->getResidentsLastStatus eq 'awoken' )
  980. {
  981. $shutters->setLastDrive('residents awoken');
  982. }
  983. else { $shutters->setLastDrive('residents home'); }
  984. $shutters->setDriveCmd( $shutters->getOpenPos );
  985. }
  986. }
  987. }
  988. }
  989. sub RainEventProcessing($@) {
  990. my ( $hash, $device, $events ) = @_;
  991. my $name = $device;
  992. my $reading = $ascDev->getRainSensorReading;
  993. my $val;
  994. if ( $events =~ m#$reading:\s(\d+|rain|dry)# ) {
  995. if ( $1 eq 'rain' ) { $val = 1000 }
  996. elsif ( $1 eq 'dry' ) { $val = 0 }
  997. else { $val = $1 }
  998. foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) {
  999. $shutters->setShuttersDev($shuttersDev);
  1000. if ( $val > 100
  1001. and $shutters->getStatus !=
  1002. $ascDev->getRainSensorShuttersClosedPos )
  1003. {
  1004. $shutters->setLastDrive('rain protection');
  1005. $shutters->setDriveCmd(
  1006. $ascDev->getRainSensorShuttersClosedPos );
  1007. }
  1008. elsif ( $val == 0
  1009. and $shutters->getStatus ==
  1010. $ascDev->getRainSensorShuttersClosedPos )
  1011. {
  1012. $shutters->setLastDrive('rain un-protection');
  1013. $shutters->setDriveCmd( $shutters->getLastPos );
  1014. }
  1015. }
  1016. }
  1017. }
  1018. sub BrightnessEventProcessing($@) {
  1019. my ( $hash, $shuttersDev, $events ) = @_;
  1020. my $name = $hash->{NAME};
  1021. $shutters->setShuttersDev($shuttersDev);
  1022. return
  1023. unless (
  1024. int( gettimeofday() / 86400 ) !=
  1025. int( computeAlignTime( '24:00', $shutters->getTimeUpEarly ) / 86400 )
  1026. and int( gettimeofday() / 86400 ) ==
  1027. int( computeAlignTime( '24:00', $shutters->getTimeUpLate ) / 86400 )
  1028. or int( gettimeofday() / 86400 ) !=
  1029. int( computeAlignTime( '24:00', $shutters->getTimeDownEarly ) / 86400 )
  1030. and int( gettimeofday() / 86400 ) ==
  1031. int( computeAlignTime( '24:00', $shutters->getTimeDownLate ) / 86400 )
  1032. );
  1033. my $reading = $shutters->getShadingBrightnessReading;
  1034. if ( $events =~ m#$reading:\s(\d+)# ) {
  1035. my $brightnessMinVal;
  1036. if ( $shutters->getBrightnessMinVal > -1 ) {
  1037. $brightnessMinVal = $shutters->getBrightnessMinVal;
  1038. }
  1039. else {
  1040. $brightnessMinVal = $ascDev->getBrightnessMinVal;
  1041. }
  1042. if (
  1043. int( gettimeofday() / 86400 ) != int(
  1044. computeAlignTime( '24:00', $shutters->getTimeUpEarly ) / 86400
  1045. )
  1046. and int( gettimeofday() / 86400 ) == int(
  1047. computeAlignTime( '24:00', $shutters->getTimeUpLate ) / 86400
  1048. )
  1049. and $1 > $brightnessMinVal
  1050. and $shutters->getUp eq 'brightness'
  1051. )
  1052. {
  1053. Log3( $name, 4,
  1054. "AutoShuttersControl ($shuttersDev) - BrightnessEventProcessing: Steuerung für Morgens"
  1055. );
  1056. my $homemode = $shutters->getRoommatesStatus;
  1057. $homemode = $ascDev->getResidentsStatus
  1058. if ( $homemode eq 'none' );
  1059. $shutters->setLastDrive('minimum brightness threshold exceeded');
  1060. if ( $shutters->getModeUp eq $homemode
  1061. or $homemode eq 'none'
  1062. or $shutters->getModeUp eq 'always' )
  1063. {
  1064. ShuttersCommandSet( $hash, $shuttersDev, $shutters->getOpenPos )
  1065. if (
  1066. (
  1067. $shutters->getRoommatesStatus eq 'home'
  1068. or $shutters->getRoommatesStatus eq 'awoken'
  1069. or $shutters->getRoommatesStatus eq 'absent'
  1070. or $shutters->getRoommatesStatus eq 'gone'
  1071. or $shutters->getRoommatesStatus eq 'none'
  1072. )
  1073. and $ascDev->getSelfDefense eq 'off'
  1074. or ( $ascDev->getSelfDefense eq 'on'
  1075. and CheckIfShuttersWindowRecOpen($shuttersDev) == 0 )
  1076. );
  1077. }
  1078. }
  1079. elsif (
  1080. int( gettimeofday() / 86400 ) != int(
  1081. computeAlignTime( '24:00', $shutters->getTimeDownEarly ) / 86400
  1082. )
  1083. and int( gettimeofday() / 86400 ) == int(
  1084. computeAlignTime( '24:00', $shutters->getTimeDownLate ) / 86400
  1085. )
  1086. and $1 < $brightnessMinVal
  1087. and $shutters->getDown eq 'brightness'
  1088. )
  1089. {
  1090. Log3( $name, 4,
  1091. "AutoShuttersControl ($shuttersDev) - BrightnessEventProcessing: Steuerung für Abends"
  1092. );
  1093. my $posValue;
  1094. if ( CheckIfShuttersWindowRecOpen($shuttersDev) == 0
  1095. or $shutters->getVentilateOpen eq 'off' )
  1096. {
  1097. $posValue = $shutters->getClosedPos;
  1098. }
  1099. else { $posValue = $shutters->getVentilatePos; }
  1100. my $homemode = $shutters->getRoommatesStatus;
  1101. $homemode = $ascDev->getResidentsStatus
  1102. if ( $homemode eq 'none' );
  1103. $shutters->setLastDrive('minimum brightness threshold fell below');
  1104. ShuttersCommandSet( $hash, $shuttersDev, $shutters->getClosedPos )
  1105. if ( $shutters->getModeDown eq $homemode
  1106. or $homemode eq 'none'
  1107. or $shutters->getModeDown eq 'always' );
  1108. }
  1109. }
  1110. }
  1111. sub PartyModeEventProcessing($) {
  1112. my ($hash) = @_;
  1113. my $name = $hash->{NAME};
  1114. foreach my $shuttersDev ( @{ $hash->{helper}{shuttersList} } ) {
  1115. $shutters->setShuttersDev($shuttersDev);
  1116. if ( not IsDay( $hash, $shuttersDev ) ) {
  1117. if ( CheckIfShuttersWindowRecOpen($shuttersDev) == 2
  1118. and $shutters->getSubTyp eq 'threestate' )
  1119. {
  1120. Log3( $name, 4,
  1121. "AutoShuttersControl ($name) - PartyModeEventProcessing Fenster offen"
  1122. );
  1123. $shutters->setDelayCmd( $shutters->getClosedPos );
  1124. Log3( $name, 4,
  1125. "AutoShuttersControl ($name) - PartyModeEventProcessing - Spring in ShuttersCommandDelaySet"
  1126. );
  1127. }
  1128. else {
  1129. Log3( $name, 4,
  1130. "AutoShuttersControl ($name) - PartyModeEventProcessing Fenster nicht offen"
  1131. );
  1132. ShuttersCommandSet(
  1133. $hash,
  1134. $shuttersDev,
  1135. (
  1136. CheckIfShuttersWindowRecOpen($shuttersDev) == 0
  1137. ? $shutters->getClosedPos
  1138. : $shutters->getVentilatePos
  1139. )
  1140. );
  1141. }
  1142. }
  1143. }
  1144. }
  1145. sub ShuttersEventProcessing($@) {
  1146. my ( $hash, $shuttersDev, $events ) = @_;
  1147. my $name = $hash->{NAME};
  1148. if ( $events =~ m#.*:\s(\d+)# ) {
  1149. $shutters->setShuttersDev($shuttersDev);
  1150. $ascDev->setPosReading;
  1151. if ( ( int( gettimeofday() ) - $shutters->getLastPosTimestamp ) > 60
  1152. and $shutters->getLastPos != $shutters->getStatus )
  1153. {
  1154. $shutters->setLastDrive('manual');
  1155. $shutters->setLastDriveReading;
  1156. $ascDev->setStateReading;
  1157. $shutters->setLastManPos($1);
  1158. }
  1159. }
  1160. }
  1161. # Sub für das Zusammensetzen der Rolläden Steuerbefehle
  1162. sub ShuttersCommandSet($$$) {
  1163. my ( $hash, $shuttersDev, $posValue ) = @_;
  1164. my $name = $hash->{NAME};
  1165. $shutters->setShuttersDev($shuttersDev);
  1166. if (
  1167. ( $shutters->getPartyMode eq 'on' and $ascDev->getPartyMode eq 'on' )
  1168. or ( CheckIfShuttersWindowRecOpen($shuttersDev) == 2
  1169. and $shutters->getSubTyp eq 'threestate'
  1170. and $ascDev->getAutoShuttersControlComfort eq 'off'
  1171. and $shutters->getVentilateOpen eq 'on' )
  1172. or (
  1173. CheckIfShuttersWindowRecOpen($shuttersDev) == 2
  1174. and ( $shutters->getLockOut eq 'soft'
  1175. or $shutters->getLockOut eq 'hard' )
  1176. and $ascDev->getLockOut eq 'on'
  1177. )
  1178. or ( $shutters->getAntiFreeze eq 'on'
  1179. and $ascDev->getOutTemp <= $ascDev->getAntifreezeTemp )
  1180. )
  1181. {
  1182. $shutters->setDelayCmd($posValue);
  1183. $ascDev->setDelayCmdReading;
  1184. }
  1185. else {
  1186. $shutters->setDriveCmd($posValue);
  1187. $shutters->setDelayCmd('none')
  1188. if ( $shutters->getDelayCmd ne 'none' )
  1189. ; # setzt den Wert auf none da der Rolladen nun gesteuert werden kann.
  1190. $ascDev->setLastPosReading;
  1191. }
  1192. }
  1193. ## Sub welche die InternalTimer nach entsprechenden Sunset oder Sunrise zusammen stellt
  1194. sub CreateSunRiseSetShuttersTimer($$) {
  1195. my ( $hash, $shuttersDev ) = @_;
  1196. my $name = $hash->{NAME};
  1197. my $shuttersDevHash = $defs{$shuttersDev};
  1198. $shutters->setShuttersDev($shuttersDev);
  1199. return if ( IsDisabled($name) );
  1200. my $shuttersSunriseUnixtime =
  1201. ShuttersSunrise( $hash, $shuttersDev, 'unix' ) + 1;
  1202. my $shuttersSunsetUnixtime =
  1203. ShuttersSunset( $hash, $shuttersDev, 'unix' ) + 1;
  1204. $shutters->setSunriseUnixTime($shuttersSunriseUnixtime);
  1205. $shutters->setSunsetUnixTime($shuttersSunsetUnixtime);
  1206. ## In jedem Rolladen werden die errechneten Zeiten hinterlegt,es sei denn das autoShuttersControlEvening/Morning auf off steht
  1207. readingsBeginUpdate($shuttersDevHash);
  1208. readingsBulkUpdate(
  1209. $shuttersDevHash,
  1210. 'ASC_Time_DriveDown',
  1211. (
  1212. $ascDev->getAutoShuttersControlEvening eq 'on'
  1213. ? strftime(
  1214. "%e.%m.%Y - %H:%M", localtime($shuttersSunsetUnixtime)
  1215. )
  1216. : 'AutoShuttersControl off'
  1217. ),
  1218. 1
  1219. );
  1220. readingsBulkUpdate(
  1221. $shuttersDevHash,
  1222. 'ASC_Time_DriveUp',
  1223. (
  1224. $ascDev->getAutoShuttersControlMorning eq 'on'
  1225. ? strftime( "%e.%m.%Y - %H:%M",
  1226. localtime($shuttersSunriseUnixtime) )
  1227. : 'AutoShuttersControl off'
  1228. ),
  1229. 1
  1230. );
  1231. readingsEndUpdate( $shuttersDevHash, 0 );
  1232. readingsBeginUpdate($hash);
  1233. readingsBulkUpdateIfChanged(
  1234. $hash,
  1235. $shuttersDev . '_nextAstroTimeEvent',
  1236. (
  1237. $shuttersSunriseUnixtime < $shuttersSunsetUnixtime
  1238. ? strftime( "%e.%m.%Y - %H:%M",
  1239. localtime($shuttersSunriseUnixtime) )
  1240. : strftime(
  1241. "%e.%m.%Y - %H:%M", localtime($shuttersSunsetUnixtime)
  1242. )
  1243. )
  1244. );
  1245. readingsEndUpdate( $hash, 1 );
  1246. CommandDeleteReading( undef,
  1247. $name . ' ' . $shuttersDev . '_nextAstroEvent' )
  1248. if ( ReadingsVal( $name, $shuttersDev . '_nextAstroEvent', 'none' ) ne
  1249. 'none' ); # temporär
  1250. CommandDeleteReading( undef,
  1251. $shuttersDev . ' AutoShuttersControl_Time_Sunrise' )
  1252. if (
  1253. ReadingsVal( $shuttersDev, 'AutoShuttersControl_Time_Sunrise', 'none' )
  1254. ne 'none' ); # temporär
  1255. CommandDeleteReading( undef,
  1256. $shuttersDev . ' AutoShuttersControl_Time_Sunset' )
  1257. if (
  1258. ReadingsVal( $shuttersDev, 'AutoShuttersControl_Time_Sunset', 'none' )
  1259. ne 'none' ); # temporär
  1260. CommandDeleteReading( undef,
  1261. $shuttersDev . ' AutoShuttersControl_Time_DriveDown' )
  1262. if (
  1263. ReadingsVal( $shuttersDev, 'AutoShuttersControl_Time_DriveDown',
  1264. 'none' ) ne 'none'
  1265. ); # temporär
  1266. CommandDeleteReading( undef,
  1267. $shuttersDev . ' AutoShuttersControl_Time_DriveUp' )
  1268. if (
  1269. ReadingsVal( $shuttersDev, 'AutoShuttersControl_Time_DriveUp', 'none' )
  1270. ne 'none' ); # temporär
  1271. RemoveInternalTimer( $shutters->getInTimerFuncHash )
  1272. if ( defined( $shutters->getInTimerFuncHash ) );
  1273. ## kleine Hilfe für InternalTimer damit ich alle benötigten Variablen an die Funktion übergeben kann welche von Internal Timer aufgerufen wird.
  1274. my %funcHash = (
  1275. hash => $hash,
  1276. shuttersdevice => $shuttersDev,
  1277. sunsettime => $shuttersSunsetUnixtime,
  1278. sunrisetime => $shuttersSunriseUnixtime
  1279. );
  1280. ## Ich brauche beim löschen des InternalTimer den Hash welchen ich mitgegeben habe,dieser muss gesichert werden
  1281. $shutters->setInTimerFuncHash( \%funcHash );
  1282. InternalTimer( $shuttersSunsetUnixtime,
  1283. 'AutoShuttersControl::SunSetShuttersAfterTimerFn', \%funcHash )
  1284. if ( $ascDev->getAutoShuttersControlEvening eq 'on' );
  1285. InternalTimer( $shuttersSunriseUnixtime,
  1286. 'AutoShuttersControl::SunRiseShuttersAfterTimerFn', \%funcHash )
  1287. if ( $ascDev->getAutoShuttersControlMorning eq 'on' );
  1288. $ascDev->setStateReading('created new drive timer');
  1289. }
  1290. ## Funktion zum neu setzen der Timer und der Readings für Sunset/Rise
  1291. sub RenewSunRiseSetShuttersTimer($) {
  1292. my $hash = shift;
  1293. foreach ( @{ $hash->{helper}{shuttersList} } ) {
  1294. $shutters->setShuttersDev($_);
  1295. RemoveInternalTimer( $shutters->getInTimerFuncHash );
  1296. $shutters->setInTimerFuncHash(undef);
  1297. CreateSunRiseSetShuttersTimer( $hash, $_ );
  1298. }
  1299. }
  1300. ## Funktion zum hardwareseitigen setzen des lock-out oder blocking beim Rolladen selbst
  1301. sub SetHardewareBlockForShutters($$) {
  1302. my ( $hash, $cmd ) = @_;
  1303. foreach ( @{ $hash->{helper}{shuttersList} } ) {
  1304. if ( AttrVal( $_, 'ASC_lock-out', 'soft' ) eq 'hard'
  1305. and AttrVal( $_, 'ASC_lock-outCmd', 'none' ) ne 'none' )
  1306. {
  1307. CommandSet( undef, $_ . ' inhibit ' . $cmd )
  1308. if ( AttrVal( $_, 'ASC_lock-outCmd', 'none' ) eq 'inhibit' );
  1309. CommandSet( undef,
  1310. $_ . ' ' . ( $cmd eq 'on' ? 'blocked' : 'unblocked' ) )
  1311. if ( AttrVal( $_, 'ASC_lock-outCmd', 'none' ) eq 'blocked' );
  1312. }
  1313. }
  1314. }
  1315. ## Funktion für das wiggle aller Shutters zusammen
  1316. sub wiggleAll($) {
  1317. my $hash = shift;
  1318. foreach ( @{ $hash->{helper}{shuttersList} } ) {
  1319. wiggle( $hash, $_ );
  1320. }
  1321. }
  1322. sub wiggle($$) {
  1323. my ( $hash, $shuttersDev ) = @_;
  1324. $shutters->setShuttersDev($shuttersDev);
  1325. $shutters->setNoOffset(1);
  1326. my %h = (
  1327. shuttersDev => $shutters->getShuttersDev,
  1328. posValue => $shutters->getStatus,
  1329. );
  1330. if ( $shutters->getShuttersPosCmdValueNegate ) {
  1331. if ( $shutters->getStatus >= $shutters->getOpenPos / 2 ) {
  1332. $shutters->setDriveCmd( $shutters->getStatus + 5 );
  1333. }
  1334. else { $shutters->setDriveCmd( $shutters->getStatus - 5 ); }
  1335. }
  1336. else {
  1337. if ( $shutters->getStatus >= $shutters->getOpenPos / 2 ) {
  1338. $shutters->setDriveCmd( $shutters->getStatus - 5 );
  1339. }
  1340. else { $shutters->setDriveCmd( $shutters->getStatus + 5 ); }
  1341. }
  1342. InternalTimer( gettimeofday() + 60, 'AutoShuttersControl::SetCmdFn', \%h );
  1343. }
  1344. ####
  1345. ## Funktion welche beim Ablaufen des Timers für Sunset aufgerufen werden soll
  1346. sub SunSetShuttersAfterTimerFn($) {
  1347. my $funcHash = shift;
  1348. my $hash = $funcHash->{hash};
  1349. my $shuttersDev = $funcHash->{shuttersdevice};
  1350. $shutters->setShuttersDev($shuttersDev);
  1351. my $posValue;
  1352. if ( CheckIfShuttersWindowRecOpen($shuttersDev) == 0
  1353. or $shutters->getVentilateOpen eq 'off' )
  1354. {
  1355. $posValue = $shutters->getClosedPos;
  1356. }
  1357. else { $posValue = $shutters->getVentilatePos; }
  1358. my $homemode = $shutters->getRoommatesStatus;
  1359. $homemode = $ascDev->getResidentsStatus if ( $homemode eq 'none' );
  1360. if ( $shutters->getModeDown eq $homemode
  1361. or $homemode eq 'none'
  1362. or $shutters->getModeDown eq 'always' )
  1363. {
  1364. $shutters->setLastDrive('night close');
  1365. ShuttersCommandSet( $hash, $shuttersDev, $posValue );
  1366. }
  1367. CreateSunRiseSetShuttersTimer( $hash, $shuttersDev );
  1368. }
  1369. ## Funktion welche beim Ablaufen des Timers für Sunrise aufgerufen werden soll
  1370. sub SunRiseShuttersAfterTimerFn($) {
  1371. my $funcHash = shift;
  1372. my $hash = $funcHash->{hash};
  1373. my $shuttersDev = $funcHash->{shuttersdevice};
  1374. $shutters->setShuttersDev($shuttersDev);
  1375. my $homemode = $shutters->getRoommatesStatus;
  1376. $homemode = $ascDev->getResidentsStatus if ( $homemode eq 'none' );
  1377. if ( $shutters->getModeUp eq $homemode
  1378. or $homemode eq 'none'
  1379. or $shutters->getModeUp eq 'always' )
  1380. {
  1381. if (
  1382. (
  1383. $shutters->getRoommatesStatus eq 'home'
  1384. or $shutters->getRoommatesStatus eq 'awoken'
  1385. or $shutters->getRoommatesStatus eq 'absent'
  1386. or $shutters->getRoommatesStatus eq 'gone'
  1387. or $shutters->getRoommatesStatus eq 'none'
  1388. )
  1389. and $ascDev->getSelfDefense eq 'off'
  1390. or ( $ascDev->getSelfDefense eq 'on'
  1391. and CheckIfShuttersWindowRecOpen($shuttersDev) == 0 )
  1392. )
  1393. {
  1394. $shutters->setLastDrive('day open');
  1395. ShuttersCommandSet( $hash, $shuttersDev, $shutters->getOpenPos );
  1396. }
  1397. }
  1398. CreateSunRiseSetShuttersTimer( $hash, $shuttersDev );
  1399. }
  1400. sub CreateNewNotifyDev($) {
  1401. my $hash = shift;
  1402. my $name = $hash->{NAME};
  1403. $hash->{NOTIFYDEV} = "global," . $name;
  1404. delete $hash->{monitoredDevs};
  1405. CommandDeleteReading( undef, $name . ' .monitoredDevs' );
  1406. my $shuttersList = '';
  1407. foreach ( @{ $hash->{helper}{shuttersList} } ) {
  1408. AddNotifyDev( $hash, AttrVal( $_, 'ASC_Roommate_Device', 'none' ),
  1409. $_, 'ASC_Roommate_Device' )
  1410. if ( AttrVal( $_, 'ASC_Roommate_Device', 'none' ) ne 'none' );
  1411. AddNotifyDev( $hash, AttrVal( $_, 'ASC_WindowRec', 'none' ),
  1412. $_, 'ASC_WindowRec' )
  1413. if ( AttrVal( $_, 'ASC_WindowRec', 'none' ) ne 'none' );
  1414. AddNotifyDev( $hash,
  1415. AttrVal( $_, 'ASC_Shading_Brightness_Sensor', 'none' ),
  1416. $_, 'ASC_Shading_Brightness_Sensor' )
  1417. if (
  1418. AttrVal( $_, 'ASC_Shading_Brightness_Sensor', 'none' ) ne 'none' );
  1419. $shuttersList = $shuttersList . ',' . $_;
  1420. }
  1421. AddNotifyDev( $hash, AttrVal( $name, 'ASC_residentsDevice', 'none' ),
  1422. $name, 'ASC_residentsDevice' )
  1423. if ( AttrVal( $name, 'ASC_residentsDevice', 'none' ) ne 'none' );
  1424. AddNotifyDev( $hash, AttrVal( $name, 'ASC_rainSensorDevice', 'none' ),
  1425. $name, 'ASC_rainSensorDevice' )
  1426. if ( AttrVal( $name, 'ASC_rainSensorDevice', 'none' ) ne 'none' );
  1427. $hash->{NOTIFYDEV} = $hash->{NOTIFYDEV} . $shuttersList;
  1428. }
  1429. sub GetShuttersInformation($) {
  1430. my $hash = shift;
  1431. my $ret = '<html><table><tr><td>';
  1432. $ret .= '<table class="block wide">';
  1433. $ret .= '<tr class="even">';
  1434. $ret .= "<td><b>Shutters</b></td>";
  1435. $ret .= "<td> </td>";
  1436. $ret .= "<td><b>Next DriveUp</b></td>";
  1437. $ret .= "<td> </td>";
  1438. $ret .= "<td><b>Next DriveDown</b></td>";
  1439. $ret .= "<td> </td>";
  1440. $ret .= "<td><b>ASC Up</b></td>";
  1441. $ret .= "<td> </td>";
  1442. $ret .= "<td><b>ASC Down</b></td>";
  1443. $ret .= "<td> </td>";
  1444. $ret .= "<td><b>ASC Mode Up</b></td>";
  1445. $ret .= "<td> </td>";
  1446. $ret .= "<td><b>ASC Mode Down</b></td>";
  1447. $ret .= "<td> </td>";
  1448. $ret .= "<td><b>Partymode</b></td>";
  1449. $ret .= "<td> </td>";
  1450. $ret .= "<td><b>Lock-Out</b></td>";
  1451. $ret .= "<td> </td>";
  1452. $ret .= "<td><b>Last Drive</b></td>";
  1453. $ret .= "<td> </td>";
  1454. $ret .= "<td><b>Position</b></td>";
  1455. $ret .= "<td> </td>";
  1456. $ret .= "<td><b>Last Position</b></td>";
  1457. $ret .= '</tr>';
  1458. my $linecount = 1;
  1459. foreach my $shutter ( @{ $hash->{helper}{shuttersList} } ) {
  1460. $shutters->setShuttersDev($shutter);
  1461. if ( $linecount % 2 == 0 ) { $ret .= '<tr class="even">'; }
  1462. else { $ret .= '<tr class="odd">'; }
  1463. $ret .= "<td>$shutter</td>";
  1464. $ret .= "<td> </td>";
  1465. $ret .= "<td>"
  1466. . strftime( "%e.%m.%Y - %H:%M:%S",
  1467. localtime( $shutters->getSunriseUnixTime ) )
  1468. . "</td>";
  1469. $ret .= "<td> </td>";
  1470. $ret .= "<td>"
  1471. . strftime( "%e.%m.%Y - %H:%M:%S",
  1472. localtime( $shutters->getSunsetUnixTime ) )
  1473. . "</td>";
  1474. $ret .= "<td> </td>";
  1475. $ret .= "<td>" . $shutters->getUp . "</td>";
  1476. $ret .= "<td> </td>";
  1477. $ret .= "<td>" . $shutters->getDown . "</td>";
  1478. $ret .= "<td> </td>";
  1479. $ret .= "<td>" . $shutters->getModeUp . "</td>";
  1480. $ret .= "<td> </td>";
  1481. $ret .= "<td>" . $shutters->getModeDown . "</td>";
  1482. $ret .= "<td> </td>";
  1483. $ret .= "<td>" . $shutters->getPartyMode . "</td>";
  1484. $ret .= "<td> </td>";
  1485. $ret .= "<td>" . $shutters->getLockOut . "</td>";
  1486. $ret .= "<td> </td>";
  1487. $ret .= "<td>" . $shutters->getLastDrive . "</td>";
  1488. $ret .= "<td> </td>";
  1489. $ret .= "<td>" . $shutters->getStatus . "</td>";
  1490. $ret .= "<td> </td>";
  1491. $ret .= "<td>" . $shutters->getLastPos . "</td>";
  1492. $ret .= '</tr>';
  1493. $linecount++;
  1494. }
  1495. $ret .= '</table></td></tr>';
  1496. $ret .= '</table></html>';
  1497. return $ret;
  1498. }
  1499. sub GetMonitoredDevs($) {
  1500. my $hash = shift;
  1501. my $notifydevs = eval {
  1502. decode_json( ReadingsVal( $hash->{NAME}, '.monitoredDevs', 'none' ) );
  1503. };
  1504. my $ret = '<html><table><tr><td>';
  1505. $ret .= '<table class="block wide">';
  1506. $ret .= '<tr class="even">';
  1507. $ret .= "<td><b>Shutters/ASC-Device</b></td>";
  1508. $ret .= "<td> </td>";
  1509. $ret .= "<td><b>NOTIFYDEV</b></td>";
  1510. $ret .= "<td> </td>";
  1511. $ret .= "<td><b>Attribut</b></td>";
  1512. $ret .= "<td> </td>";
  1513. $ret .= '</tr>';
  1514. if ( ref($notifydevs) eq "HASH" ) {
  1515. my $linecount = 1;
  1516. foreach my $notifydev ( sort keys( %{$notifydevs} ) ) {
  1517. if ( ref( $notifydevs->{$notifydev} ) eq "HASH" ) {
  1518. foreach
  1519. my $shutters ( sort keys( %{ $notifydevs->{$notifydev} } ) )
  1520. {
  1521. if ( $linecount % 2 == 0 ) { $ret .= '<tr class="even">'; }
  1522. else { $ret .= '<tr class="odd">'; }
  1523. $ret .= "<td>$shutters</td>";
  1524. $ret .= "<td> </td>";
  1525. $ret .= "<td>$notifydev</td>";
  1526. $ret .= "<td> </td>";
  1527. $ret .= "<td>$notifydevs->{$notifydev}{$shutters}</td>";
  1528. $ret .= "<td> </td>";
  1529. $ret .= '</tr>';
  1530. $linecount++;
  1531. }
  1532. }
  1533. }
  1534. }
  1535. ###### create Links
  1536. my $aHref;
  1537. # create define Link
  1538. # $aHref="<a href=\"".$::FW_httpheader->{host}."/fhem?cmd=set+".$::FW_CSRF."\">Create new NOTIFYDEV structure</a>";
  1539. # $aHref="<a href=\"/fhem?cmd=set+\">Create new NOTIFYDEV structure</a>";
  1540. # $aHref="<a href=\"".$headerHost[0]."/fhem?cmd=define+".makeDeviceName($dataset->{station}{name})."+Aqicn+".$dataset->{uid}.$FW_CSRF."\">Create Station Device</a>";
  1541. # $ret .= '<tr class="odd"> </tr>';
  1542. # $ret .= '<tr class="even"> </tr>';
  1543. # $ret .= "<td> </td>";
  1544. # $ret .= "<td> </td>";
  1545. # $ret .= "<td> </td>";
  1546. # $ret .= "<td> </td>";
  1547. # $ret .= "<td>".$aHref."</td>";
  1548. $ret .= '</table></td></tr>';
  1549. $ret .= '</table></html>';
  1550. return $ret;
  1551. }
  1552. #################################
  1553. ## my little helper
  1554. #################################
  1555. # Hilfsfunktion welche meinen ReadingString zum finden der getriggerten Devices und der Zurdnung was das Device überhaupt ist und zu welchen Rolladen es gehört aus liest und das Device extraiert
  1556. sub ExtractNotifyDevFromEvent($$$) {
  1557. my ( $hash, $shuttersDev, $shuttersAttr ) = @_;
  1558. my %notifyDevs;
  1559. while ( my $notifyDev = each %{ $hash->{monitoredDevs} } ) {
  1560. Log3( $hash->{NAME}, 4,
  1561. "AutoShuttersControl ($hash->{NAME}) - ExtractNotifyDevFromEvent - NotifyDev: "
  1562. . $notifyDev );
  1563. Log3( $hash->{NAME}, 5,
  1564. "AutoShuttersControl ($hash->{NAME}) - ExtractNotifyDevFromEvent - ShuttersDev: "
  1565. . $shuttersDev );
  1566. if ( defined( $hash->{monitoredDevs}{$notifyDev}{$shuttersDev} )
  1567. and $hash->{monitoredDevs}{$notifyDev}{$shuttersDev} eq
  1568. $shuttersAttr )
  1569. {
  1570. Log3( $hash->{NAME}, 4,
  1571. "AutoShuttersControl ($hash->{NAME}) - ExtractNotifyDevFromEvent - ShuttersDevHash: "
  1572. . $hash->{monitoredDevs}{$notifyDev}{$shuttersDev} );
  1573. Log3( $hash->{NAME}, 5,
  1574. "AutoShuttersControl ($hash->{NAME}) - ExtractNotifyDevFromEvent - return ShuttersDev: "
  1575. . $notifyDev );
  1576. $notifyDevs{$notifyDev} = $shuttersDev;
  1577. }
  1578. }
  1579. return \%notifyDevs;
  1580. }
  1581. ## Ist Tag oder Nacht für den entsprechende Rolladen
  1582. sub IsDay($$) {
  1583. my ( $hash, $shuttersDev ) = @_;
  1584. my $name = $hash->{NAME};
  1585. return ( ShuttersSunrise( $hash, $shuttersDev, 'unix' ) >
  1586. ShuttersSunset( $hash, $shuttersDev, 'unix' ) ? 1 : 0 );
  1587. }
  1588. sub ShuttersSunrise($$$) {
  1589. my ( $hash, $shuttersDev, $tm ) =
  1590. @_; # Tm steht für Timemode und bedeutet Realzeit oder Unixzeit
  1591. my $name = $hash->{NAME};
  1592. my $autoAstroMode;
  1593. $shutters->setShuttersDev($shuttersDev);
  1594. if ( $shutters->getAutoAstroModeMorning ne 'none' ) {
  1595. $autoAstroMode = $shutters->getAutoAstroModeMorning;
  1596. $autoAstroMode =
  1597. $autoAstroMode . '=' . $shutters->getAutoAstroModeMorningHorizon
  1598. if ( $autoAstroMode eq 'HORIZON' );
  1599. }
  1600. else {
  1601. $autoAstroMode = $ascDev->getAutoAstroModeMorning;
  1602. $autoAstroMode =
  1603. $autoAstroMode . '=' . $ascDev->getAutoAstroModeMorningHorizon
  1604. if ( $autoAstroMode eq 'HORIZON' );
  1605. }
  1606. my $oldFuncHash = $shutters->getInTimerFuncHash;
  1607. my $shuttersSunriseUnixtime;
  1608. if ( $tm eq 'unix' ) {
  1609. if ( $shutters->getUp eq 'astro' ) {
  1610. if ( ( IsWe() or IsWeTomorrow() )
  1611. and $ascDev->getSunriseTimeWeHoliday eq 'on' )
  1612. {
  1613. if ( not IsWeTomorrow() ) {
  1614. if (
  1615. IsWe()
  1616. and int( gettimeofday() / 86400 ) == int(
  1617. (
  1618. computeAlignTime(
  1619. '24:00',
  1620. sunrise_abs(
  1621. $autoAstroMode, 0,
  1622. $shutters->getTimeUpWeHoliday
  1623. )
  1624. ) + 1
  1625. ) / 86400
  1626. )
  1627. )
  1628. {
  1629. $shuttersSunriseUnixtime = (
  1630. computeAlignTime(
  1631. '24:00',
  1632. sunrise_abs(
  1633. $autoAstroMode, 0,
  1634. $shutters->getTimeUpWeHoliday
  1635. )
  1636. ) + 1
  1637. );
  1638. }
  1639. elsif (
  1640. int( gettimeofday() / 86400 ) == int(
  1641. (
  1642. computeAlignTime(
  1643. '24:00',
  1644. sunrise_abs(
  1645. $autoAstroMode,
  1646. 0,
  1647. $shutters->getTimeUpEarly,
  1648. $shutters->getTimeUpLate
  1649. )
  1650. ) + 1
  1651. ) / 86400
  1652. )
  1653. )
  1654. {
  1655. $shuttersSunriseUnixtime = (
  1656. computeAlignTime(
  1657. '24:00',
  1658. sunrise_abs(
  1659. $autoAstroMode, 0,
  1660. $shutters->getTimeUpWeHoliday
  1661. )
  1662. ) + 1
  1663. );
  1664. }
  1665. else {
  1666. $shuttersSunriseUnixtime = (
  1667. computeAlignTime(
  1668. '24:00',
  1669. sunrise_abs(
  1670. $autoAstroMode,
  1671. 0,
  1672. $shutters->getTimeUpEarly,
  1673. $shutters->getTimeUpLate
  1674. )
  1675. ) + 1
  1676. );
  1677. }
  1678. }
  1679. else {
  1680. $shuttersSunriseUnixtime = (
  1681. computeAlignTime(
  1682. '24:00',
  1683. sunrise_abs(
  1684. $autoAstroMode, 0,
  1685. $shutters->getTimeUpWeHoliday
  1686. )
  1687. ) + 1
  1688. );
  1689. }
  1690. }
  1691. else {
  1692. $shuttersSunriseUnixtime = (
  1693. computeAlignTime(
  1694. '24:00',
  1695. sunrise_abs(
  1696. $autoAstroMode,
  1697. 0,
  1698. $shutters->getTimeUpEarly,
  1699. $shutters->getTimeUpLate
  1700. )
  1701. ) + 1
  1702. );
  1703. }
  1704. if ( defined($oldFuncHash)
  1705. and ref($oldFuncHash) eq 'HASH'
  1706. and ( IsWe() or IsWeTomorrow() )
  1707. and $ascDev->getSunriseTimeWeHoliday eq 'on' )
  1708. {
  1709. if ( not IsWeTomorrow() ) {
  1710. if (
  1711. int( gettimeofday() / 86400 ) == int(
  1712. (
  1713. computeAlignTime(
  1714. '24:00',
  1715. sunrise_abs(
  1716. $autoAstroMode,
  1717. 0,
  1718. $shutters->getTimeUpEarly,
  1719. $shutters->getTimeUpLate
  1720. )
  1721. ) + 1
  1722. ) / 86400
  1723. )
  1724. )
  1725. {
  1726. $shuttersSunriseUnixtime =
  1727. ( $shuttersSunriseUnixtime + 86400 )
  1728. if ( $shuttersSunriseUnixtime <
  1729. ( $oldFuncHash->{sunrisetime} + 180 )
  1730. and $oldFuncHash->{sunrisetime} < gettimeofday() );
  1731. }
  1732. }
  1733. }
  1734. elsif ( defined($oldFuncHash) and ref($oldFuncHash) eq 'HASH' ) {
  1735. $shuttersSunriseUnixtime = ( $shuttersSunriseUnixtime + 86400 )
  1736. if ( $shuttersSunriseUnixtime <
  1737. ( $oldFuncHash->{sunrisetime} + 180 )
  1738. and $oldFuncHash->{sunrisetime} < gettimeofday() );
  1739. }
  1740. }
  1741. elsif ( $shutters->getUp eq 'time' ) {
  1742. $shuttersSunriseUnixtime =
  1743. computeAlignTime( '24:00', $shutters->getTimeUpEarly );
  1744. }
  1745. elsif ( $shutters->getUp eq 'brightness' ) {
  1746. $shuttersSunriseUnixtime =
  1747. computeAlignTime( '24:00', $shutters->getTimeUpLate );
  1748. }
  1749. return $shuttersSunriseUnixtime;
  1750. }
  1751. elsif ( $tm eq 'real' ) {
  1752. return sunrise_abs( $autoAstroMode, 0, $shutters->getTimeUpEarly,
  1753. $shutters->getTimeUpLate )
  1754. if ( $shutters->getUp eq 'astro' );
  1755. return $shutters->getTimeUpEarly if ( $shutters->getUp eq 'time' );
  1756. }
  1757. }
  1758. sub ShuttersSunset($$$) {
  1759. my ( $hash, $shuttersDev, $tm ) =
  1760. @_; # Tm steht für Timemode und bedeutet Realzeit oder Unixzeit
  1761. my $name = $hash->{NAME};
  1762. my $autoAstroMode;
  1763. $shutters->setShuttersDev($shuttersDev);
  1764. if ( $shutters->getAutoAstroModeEvening ne 'none' ) {
  1765. $autoAstroMode = $shutters->getAutoAstroModeEvening;
  1766. $autoAstroMode =
  1767. $autoAstroMode . '=' . $shutters->getAutoAstroModeEveningHorizon
  1768. if ( $autoAstroMode eq 'HORIZON' );
  1769. }
  1770. else {
  1771. $autoAstroMode = $ascDev->getAutoAstroModeEvening;
  1772. $autoAstroMode =
  1773. $autoAstroMode . '=' . $ascDev->getAutoAstroModeEveningHorizon
  1774. if ( $autoAstroMode eq 'HORIZON' );
  1775. }
  1776. my $oldFuncHash = $shutters->getInTimerFuncHash;
  1777. my $shuttersSunsetUnixtime;
  1778. if ( $tm eq 'unix' ) {
  1779. if ( $shutters->getDown eq 'astro' ) {
  1780. $shuttersSunsetUnixtime = (
  1781. computeAlignTime(
  1782. '24:00',
  1783. sunset_abs(
  1784. $autoAstroMode,
  1785. 0,
  1786. $shutters->getTimeDownEarly,
  1787. $shutters->getTimeDownLate
  1788. )
  1789. ) + 1
  1790. );
  1791. if ( defined($oldFuncHash) and ref($oldFuncHash) eq 'HASH' ) {
  1792. $shuttersSunsetUnixtime = ( $shuttersSunsetUnixtime + 86400 )
  1793. if ( $shuttersSunsetUnixtime <
  1794. ( $oldFuncHash->{sunsettime} + 180 )
  1795. and $oldFuncHash->{sunsettime} < gettimeofday() );
  1796. }
  1797. }
  1798. elsif ( $shutters->getDown eq 'time' ) {
  1799. $shuttersSunsetUnixtime =
  1800. computeAlignTime( '24:00', $shutters->getTimeDownEarly );
  1801. }
  1802. elsif ( $shutters->getDown eq 'brightness' ) {
  1803. $shuttersSunsetUnixtime =
  1804. computeAlignTime( '24:00', $shutters->getTimeDownLate );
  1805. }
  1806. return $shuttersSunsetUnixtime;
  1807. }
  1808. elsif ( $tm eq 'real' ) {
  1809. return sunset_abs(
  1810. $autoAstroMode, 0,
  1811. $shutters->getTimeDownEarly,
  1812. $shutters->getTimeDownLate
  1813. ) if ( $shutters->getDown eq 'astro' );
  1814. return $shutters->getTimeDownEarly
  1815. if ( $shutters->getDown eq 'time' );
  1816. }
  1817. }
  1818. ## Kontrolliert ob das Fenster von einem bestimmten Rolladen offen ist
  1819. sub CheckIfShuttersWindowRecOpen($) {
  1820. my $shuttersDev = shift;
  1821. $shutters->setShuttersDev($shuttersDev);
  1822. if ( $shutters->getWinStatus eq 'open' ) { return 2; }
  1823. elsif ( $shutters->getWinStatus eq 'tilted'
  1824. and $shutters->getSubTyp eq 'threestate' )
  1825. {
  1826. return 1;
  1827. }
  1828. elsif ( $shutters->getWinStatus eq 'closed' ) { return 0; }
  1829. }
  1830. sub makeReadingName($) {
  1831. my ($name) = @_;
  1832. my %charHash = (
  1833. "ä" => "ae",
  1834. "Ä" => "Ae",
  1835. "ü" => "ue",
  1836. "Ü" => "Ue",
  1837. "ö" => "oe",
  1838. "Ö" => "Oe",
  1839. "ß" => "ss"
  1840. );
  1841. my $charHashkeys = join( "|", keys(%charHash) );
  1842. $name = "UNDEFINED" if ( !defined($name) );
  1843. return $name if ( $name =~ m/^\./ );
  1844. $name =~ s/($charHashkeys)/$charHash{$1}/gi;
  1845. $name =~ s/[^a-z0-9._\-\/]/_/gi;
  1846. return $name;
  1847. }
  1848. sub TimeMin2Sec($) {
  1849. my $min = shift;
  1850. my $sec;
  1851. $sec = $min * 60;
  1852. return $sec;
  1853. }
  1854. sub IsWe() {
  1855. my ( undef, undef, undef, undef, undef, undef, $wday, undef, undef ) =
  1856. localtime( gettimeofday() );
  1857. my $we = ( ( $wday == 0 || $wday == 6 ) ? 1 : 0 );
  1858. if ( !$we ) {
  1859. foreach my $h2we ( split( ",", AttrVal( "global", "holiday2we", "" ) ) )
  1860. {
  1861. my ( $a, $b ) =
  1862. ReplaceEventMap( $h2we, [ $h2we, Value($h2we) ], 0 );
  1863. $we = 1 if ( $b && $b ne "none" );
  1864. }
  1865. }
  1866. return $we;
  1867. }
  1868. sub IsWeTomorrow() {
  1869. my ( undef, undef, undef, undef, undef, undef, $wday, undef, undef ) =
  1870. localtime( gettimeofday() );
  1871. my $we = (
  1872. ( ( ( $wday + 1 == 7 ? 0 : $wday + 1 ) ) == 0 || ( $wday + 1 ) == 6 )
  1873. ? 1
  1874. : 0
  1875. );
  1876. if ( !$we ) {
  1877. foreach my $h2we ( split( ",", AttrVal( "global", "holiday2we", "" ) ) )
  1878. {
  1879. my ( $a, $b ) = ReplaceEventMap( $h2we,
  1880. [ $h2we, ReadingsVal( $h2we, "tomorrow", "none" ) ], 0 );
  1881. $we = 1 if ( $b && $b ne "none" );
  1882. }
  1883. }
  1884. return $we;
  1885. }
  1886. sub IsHoliday($) {
  1887. my $hash = shift;
  1888. my $name = $hash->{NAME};
  1889. return (
  1890. ReadingsVal( AttrVal( $name, 'ASC_timeUpHolidayDevice', 'none' ),
  1891. AttrVal( $name, 'ASC_timeUpHolidayReading', 'state' ), 0 ) == 1 ? 1 : 0
  1892. );
  1893. }
  1894. sub SetCmdFn($) {
  1895. my $h = shift;
  1896. my $shuttersDev = $h->{shuttersDev};
  1897. my $posValue = $h->{posValue};
  1898. $shutters->setShuttersDev($shuttersDev);
  1899. if ( $shutters->getStatus != $posValue ) {
  1900. $shutters->setLastPos( $shutters->getStatus );
  1901. $shutters->setLastDriveReading;
  1902. $ascDev->setStateReading;
  1903. }
  1904. else {
  1905. $shutters->setLastDrive(
  1906. ReadingsVal( $shuttersDev, 'ASC_ShuttersLastDrive', 'none' ) );
  1907. }
  1908. CommandSet( undef,
  1909. $shuttersDev
  1910. . ':FILTER='
  1911. . $shutters->getPosCmd . '!='
  1912. . $posValue . ' '
  1913. . $shutters->getPosSetCmd . ' '
  1914. . $posValue );
  1915. }
  1916. ########## Begin der Klassendeklarierungen für OOP (Objektorientierte Programmierung) #########################
  1917. ## Klasse Rolläden (Shutters) und die Subklassen Attr und Readings ##
  1918. ## desweiteren wird noch die Klasse ASC_Roommate mit eingebunden
  1919. package ASC_Shutters;
  1920. our @ISA =
  1921. qw(ASC_Shutters::Readings ASC_Shutters::Attr ASC_Roommate ASC_Window);
  1922. use strict;
  1923. use warnings;
  1924. use GPUtils qw(GP_Import);
  1925. ## Import der FHEM Funktionen
  1926. BEGIN {
  1927. GP_Import(
  1928. qw(
  1929. defs
  1930. ReadingsVal
  1931. readingsSingleUpdate
  1932. gettimeofday
  1933. InternalTimer)
  1934. );
  1935. }
  1936. sub new {
  1937. my $class = shift;
  1938. my $self = {
  1939. shuttersDev => undef,
  1940. defaultarg => undef,
  1941. roommate => undef,
  1942. };
  1943. bless $self, $class;
  1944. return $self;
  1945. }
  1946. sub setShuttersDev {
  1947. my ( $self, $shuttersDev ) = @_;
  1948. $self->{shuttersDev} = $shuttersDev if ( defined($shuttersDev) );
  1949. return $self->{shuttersDev};
  1950. }
  1951. sub getShuttersDev {
  1952. my $self = shift;
  1953. return $self->{shuttersDev};
  1954. }
  1955. sub setNoOffset {
  1956. my ( $self, $noOffset ) = @_;
  1957. $self->{ $self->{shuttersDev} }{noOffset} = $noOffset;
  1958. return 0;
  1959. }
  1960. sub setDriveCmd {
  1961. my ( $self, $posValue ) = @_;
  1962. my $offSet = 0;
  1963. my %h = (
  1964. shuttersDev => $self->{shuttersDev},
  1965. posValue => $posValue,
  1966. );
  1967. $offSet = $shutters->getOffset if ( $shutters->getOffset > 0 );
  1968. $offSet = $ascDev->getShuttersOffset if ( $shutters->getOffset == -1 );
  1969. InternalTimer( gettimeofday() + int( rand($offSet) ),
  1970. 'AutoShuttersControl::SetCmdFn', \%h )
  1971. if ( $offSet > 0 and not $shutters->getNoOffset );
  1972. AutoShuttersControl::SetCmdFn( \%h )
  1973. if ( $offSet == 0 or $shutters->getNoOffset );
  1974. $shutters->setNoOffset(0);
  1975. return 0;
  1976. }
  1977. sub setSunsetUnixTime {
  1978. my ( $self, $unixtime ) = @_;
  1979. $self->{ $self->{shuttersDev} }{sunsettime} = $unixtime;
  1980. return 0;
  1981. }
  1982. sub setSunriseUnixTime {
  1983. my ( $self, $unixtime ) = @_;
  1984. $self->{ $self->{shuttersDev} }{sunrisetime} = $unixtime;
  1985. return 0;
  1986. }
  1987. sub setDelayCmd {
  1988. my ( $self, $posValue ) = @_;
  1989. $self->{ $self->{shuttersDev} }{delayCmd} = $posValue;
  1990. return 0;
  1991. }
  1992. sub setLastDrive {
  1993. my ( $self, $lastDrive ) = @_;
  1994. $self->{ $self->{shuttersDev} }{lastDrive} = $lastDrive;
  1995. return 0;
  1996. }
  1997. sub setPosSetCmd {
  1998. my ( $self, $posSetCmd ) = @_;
  1999. $self->{ $self->{shuttersDev} }{posSetCmd} = $posSetCmd;
  2000. return 0;
  2001. }
  2002. sub setLastDriveReading {
  2003. my $self = shift;
  2004. my $shuttersDevHash = $defs{ $self->{shuttersDev} };
  2005. readingsSingleUpdate( $shuttersDevHash, 'ASC_ShuttersLastDrive',
  2006. $shutters->getLastDrive, 1 );
  2007. return 0;
  2008. }
  2009. sub setLastPos
  2010. { # letzte ermittelte Position bevor die Position des Rolladen über ASC geändert wurde
  2011. my ( $self, $position ) = @_;
  2012. $self->{ $self->{shuttersDev} }{lastPos}{VAL} = $position
  2013. if ( defined($position) );
  2014. $self->{ $self->{shuttersDev} }{lastPos}{TIME} = int( gettimeofday() )
  2015. if ( defined( $self->{ $self->{shuttersDev} }{lastPos} ) );
  2016. return 0;
  2017. }
  2018. sub setLastManPos
  2019. { # letzte ermittelte Position bevor die Position des Rolladen manuell (nicht über ASC) geändert wurde
  2020. my ( $self, $position ) = @_;
  2021. $self->{ $self->{shuttersDev} }{lastManPos}{VAL} = $position
  2022. if ( defined($position) );
  2023. $self->{ $self->{shuttersDev} }{lastManPos}{TIME} = int( gettimeofday() )
  2024. if ( defined( $self->{ $self->{shuttersDev} }{lastManPos} ) );
  2025. return 0;
  2026. }
  2027. sub setDefault {
  2028. my ( $self, $defaultarg ) = @_;
  2029. $self->{defaultarg} = $defaultarg if ( defined($defaultarg) );
  2030. return $self->{defaultarg};
  2031. }
  2032. sub setRoommate {
  2033. my ( $self, $roommate ) = @_;
  2034. $self->{roommate} = $roommate if ( defined($roommate) );
  2035. return $self->{roommate};
  2036. }
  2037. sub setInTimerFuncHash {
  2038. my ( $self, $inTimerFuncHash ) = @_;
  2039. $self->{ $self->{shuttersDev} }{inTimerFuncHash} = $inTimerFuncHash
  2040. if ( defined($inTimerFuncHash) );
  2041. return 0;
  2042. }
  2043. sub getShuttersPosCmdValueNegate {
  2044. my $self = shift;
  2045. return ( $shutters->getOpenPos < $shutters->getClosedPos ? 1 : 0 );
  2046. }
  2047. sub getPosSetCmd {
  2048. my $self = shift;
  2049. return (
  2050. defined( $self->{ $self->{shuttersDev} }{posSetCmd} )
  2051. ? $self->{ $self->{shuttersDev} }{posSetCmd}
  2052. : $shutters->getPosCmd );
  2053. }
  2054. sub getNoOffset {
  2055. my $self = shift;
  2056. return $self->{ $self->{shuttersDev} }{noOffset};
  2057. }
  2058. sub getLastDrive {
  2059. my $self = shift;
  2060. $self->{ $self->{shuttersDev} }{lastDrive} =
  2061. ReadingsVal( $self->{shuttersDev}, 'ASC_ShuttersLastDrive', 'none' )
  2062. if ( not defined( $self->{ $self->{shuttersDev} }{lastDrive} ) );
  2063. return $self->{ $self->{shuttersDev} }{lastDrive};
  2064. }
  2065. sub getLastPos
  2066. { # letzte ermittelte Position bevor die Position des Rolladen über ASC geändert wurde
  2067. my $self = shift;
  2068. return $self->{ $self->{shuttersDev} }{lastPos}{VAL}
  2069. if ( defined( $self->{ $self->{shuttersDev} }{lastPos} )
  2070. and defined( $self->{ $self->{shuttersDev} }{lastPos}{VAL} ) );
  2071. }
  2072. sub getLastPosTimestamp {
  2073. my $self = shift;
  2074. return $self->{ $self->{shuttersDev} }{lastPos}{TIME}
  2075. if ( defined( $self->{ $self->{shuttersDev} } )
  2076. and defined( $self->{ $self->{shuttersDev} }{lastPos} )
  2077. and defined( $self->{ $self->{shuttersDev} }{lastPos}{TIME} ) );
  2078. }
  2079. sub getLastManPos
  2080. { # letzte ermittelte Position bevor die Position des Rolladen manuell (nicht über ASC) geändert wurde
  2081. my $self = shift;
  2082. return $self->{ $self->{shuttersDev} }{lastManPos}{VAL}
  2083. if ( defined( $self->{ $self->{shuttersDev} }{lastManPos} )
  2084. and defined( $self->{ $self->{shuttersDev} }{lastManPos}{VAL} ) );
  2085. }
  2086. sub getLastManPosTimestamp {
  2087. my $self = shift;
  2088. return $self->{ $self->{shuttersDev} }{lastManPos}{TIME}
  2089. if ( defined( $self->{ $self->{shuttersDev} } )
  2090. and defined( $self->{ $self->{shuttersDev} }{lastManPos} )
  2091. and defined( $self->{ $self->{shuttersDev} }{lastManPos}{TIME} ) );
  2092. }
  2093. sub getInTimerFuncHash {
  2094. my $self = shift;
  2095. return $self->{ $self->{shuttersDev} }{inTimerFuncHash};
  2096. }
  2097. sub getSunsetUnixTime {
  2098. my $self = shift;
  2099. return $self->{ $self->{shuttersDev} }{sunsettime};
  2100. }
  2101. sub getSunriseUnixTime {
  2102. my $self = shift;
  2103. return $self->{ $self->{shuttersDev} }{sunrisetime};
  2104. }
  2105. sub getRoommatesStatus {
  2106. my $self = shift;
  2107. my $loop = 0;
  2108. my @roState;
  2109. my %statePrio = (
  2110. 'asleep' => 1,
  2111. 'gotosleep' => 2,
  2112. 'awoken' => 3,
  2113. 'home' => 4,
  2114. 'absent' => 5,
  2115. 'gone' => 6,
  2116. 'none' => 7
  2117. );
  2118. my $minPrio = 10;
  2119. foreach my $ro ( split( ",", $shutters->getRoommates ) ) {
  2120. $shutters->setRoommate($ro);
  2121. my $currentPrio = $statePrio{ $shutters->_getRoommateStatus };
  2122. $minPrio = $currentPrio if ( $minPrio > $currentPrio );
  2123. }
  2124. my %revStatePrio = reverse %statePrio;
  2125. return $revStatePrio{$minPrio};
  2126. }
  2127. sub getRoommatesLastStatus {
  2128. my $self = shift;
  2129. my $loop = 0;
  2130. my @roState;
  2131. my %statePrio = (
  2132. 'asleep' => 1,
  2133. 'gotosleep' => 2,
  2134. 'awoken' => 3,
  2135. 'home' => 4,
  2136. 'absent' => 5,
  2137. 'gone' => 6,
  2138. 'none' => 7
  2139. );
  2140. my $minPrio = 10;
  2141. foreach my $ro ( split( ",", $shutters->getRoommates ) ) {
  2142. $shutters->setRoommate($ro);
  2143. my $currentPrio = $statePrio{ $shutters->_getRoommateLastStatus };
  2144. $minPrio = $currentPrio if ( $minPrio > $currentPrio );
  2145. }
  2146. my %revStatePrio = reverse %statePrio;
  2147. return $revStatePrio{$minPrio};
  2148. }
  2149. ## Subklasse Attr von ASC_Shutters##
  2150. package ASC_Shutters::Attr;
  2151. use strict;
  2152. use warnings;
  2153. use GPUtils qw(GP_Import);
  2154. ## Import der FHEM Funktionen
  2155. BEGIN {
  2156. GP_Import(
  2157. qw(
  2158. AttrVal)
  2159. );
  2160. }
  2161. sub getShuttersPlace {
  2162. my $self = shift;
  2163. return AttrVal( $self->{shuttersDev}, 'ASC_ShuttersPlace', 'window' );
  2164. }
  2165. sub getSelfDefenseExclude {
  2166. my $self = shift;
  2167. return AttrVal( $self->{shuttersDev}, 'ASC_Self_Defense_Exclude', 'off' );
  2168. }
  2169. sub getShadingBrightnessSensor {
  2170. my $self = shift;
  2171. my $default = $self->{defaultarg};
  2172. $default = 'none' if ( not defined($default) );
  2173. return AttrVal( $self->{shuttersDev}, 'ASC_Shading_Brightness_Sensor',
  2174. $default );
  2175. }
  2176. sub getShadingBrightnessReading {
  2177. my $self = shift;
  2178. my $default = $self->{defaultarg};
  2179. $default = 'brightness' if ( not defined($default) );
  2180. return AttrVal( $self->{shuttersDev}, 'ASC_Shading_Brightness_Reading',
  2181. $default );
  2182. }
  2183. sub getOffset {
  2184. my $self = shift;
  2185. return AttrVal( $self->{shuttersDev}, 'ASC_Drive_Offset', 0 );
  2186. }
  2187. sub getPosCmd {
  2188. my $self = shift;
  2189. return AttrVal( $self->{shuttersDev}, 'ASC_Pos_Reading', 'pct' );
  2190. }
  2191. sub getOpenPos {
  2192. my $self = shift;
  2193. return AttrVal( $self->{shuttersDev}, 'ASC_Open_Pos', 0 );
  2194. }
  2195. sub getVentilatePos {
  2196. my $self = shift;
  2197. return AttrVal( $self->{shuttersDev}, 'ASC_Ventilate_Pos', 80 );
  2198. }
  2199. sub getClosedPos {
  2200. my $self = shift;
  2201. return AttrVal( $self->{shuttersDev}, 'ASC_Closed_Pos', 100 );
  2202. }
  2203. sub getVentilateOpen {
  2204. my $self = shift;
  2205. return AttrVal( $self->{shuttersDev}, 'ASC_Ventilate_Window_Open', 'off' );
  2206. }
  2207. sub getPosAfterComfortOpen {
  2208. my $self = shift;
  2209. return AttrVal( $self->{shuttersDev}, 'ASC_Pos_after_ComfortOpen', 50 );
  2210. }
  2211. sub getPartyMode {
  2212. my $self = shift;
  2213. return AttrVal( $self->{shuttersDev}, 'ASC_Partymode', 'off' );
  2214. }
  2215. sub getRoommates {
  2216. my $self = shift;
  2217. my $default = $self->{defaultarg};
  2218. $default = 'none' if ( not defined($default) );
  2219. return AttrVal( $self->{shuttersDev}, 'ASC_Roommate_Device', $default );
  2220. }
  2221. sub getRoommatesReading {
  2222. my $self = shift;
  2223. my $default = $self->{defaultarg};
  2224. $default = 'state' if ( not defined($default) );
  2225. return AttrVal( $self->{shuttersDev}, 'ASC_Roommate_Reading', $default );
  2226. }
  2227. sub getModeUp {
  2228. my $self = shift;
  2229. return AttrVal( $self->{shuttersDev}, 'ASC_Mode_Up', 'off' );
  2230. }
  2231. sub getModeDown {
  2232. my $self = shift;
  2233. return AttrVal( $self->{shuttersDev}, 'ASC_Mode_Down', 'off' );
  2234. }
  2235. sub getLockOut {
  2236. my $self = shift;
  2237. return AttrVal( $self->{shuttersDev}, 'ASC_lock-out', 'soft' );
  2238. }
  2239. sub getAntiFreeze {
  2240. my $self = shift;
  2241. return AttrVal( $self->{shuttersDev}, 'ASC_Antifreeze', 'off' );
  2242. }
  2243. sub getAutoAstroModeMorning {
  2244. my $self = shift;
  2245. my $default = $self->{defaultarg};
  2246. $default = 'none' if ( not defined($default) );
  2247. return AttrVal( $self->{shuttersDev}, 'ASC_AutoAstroModeMorning',
  2248. $default );
  2249. }
  2250. sub getAutoAstroModeEvening {
  2251. my $self = shift;
  2252. my $default = $self->{defaultarg};
  2253. $default = 'none' if ( not defined($default) );
  2254. return AttrVal( $self->{shuttersDev}, 'ASC_AutoAstroModeEvening',
  2255. $default );
  2256. }
  2257. sub getAutoAstroModeMorningHorizon {
  2258. my $self = shift;
  2259. return AttrVal( $self->{shuttersDev}, 'ASC_AutoAstroModeMorningHorizon',
  2260. 0 );
  2261. }
  2262. sub getAutoAstroModeEveningHorizon {
  2263. my $self = shift;
  2264. return AttrVal( $self->{shuttersDev}, 'ASC_AutoAstroModeEveningHorizon',
  2265. 0 );
  2266. }
  2267. sub getUp {
  2268. my $self = shift;
  2269. return AttrVal( $self->{shuttersDev}, 'ASC_Up', 'astro' );
  2270. }
  2271. sub getDown {
  2272. my $self = shift;
  2273. return AttrVal( $self->{shuttersDev}, 'ASC_Down', 'astro' );
  2274. }
  2275. sub getTimeUpEarly {
  2276. my $self = shift;
  2277. return AttrVal( $self->{shuttersDev}, 'ASC_Time_Up_Early', '04:30:00' );
  2278. }
  2279. sub getTimeUpLate {
  2280. my $self = shift;
  2281. return AttrVal( $self->{shuttersDev}, 'ASC_Time_Up_Late', '09:00:00' );
  2282. }
  2283. sub getTimeDownEarly {
  2284. my $self = shift;
  2285. return AttrVal( $self->{shuttersDev}, 'ASC_Time_Down_Early', '15:30:00' );
  2286. }
  2287. sub getTimeDownLate {
  2288. my $self = shift;
  2289. return AttrVal( $self->{shuttersDev}, 'ASC_Time_Down_Late', '22:00:00' );
  2290. }
  2291. sub getTimeUpWeHoliday {
  2292. my $self = shift;
  2293. return AttrVal( $self->{shuttersDev}, 'ASC_Time_Up_WE_Holiday',
  2294. '04:00:00' );
  2295. }
  2296. sub getBrightnessMinVal {
  2297. my $self = shift;
  2298. return AttrVal( $self->{shuttersDev}, 'ASC_BrightnessMinVal', -1 );
  2299. }
  2300. sub getBrightnessMaxVal {
  2301. my $self = shift;
  2302. return AttrVal( $self->{shuttersDev}, 'ASC_BrightnessMaxVal', -1 );
  2303. }
  2304. ## Subklasse Readings von ASC_Shutters ##
  2305. package ASC_Shutters::Readings;
  2306. use strict;
  2307. use warnings;
  2308. use GPUtils qw(GP_Import);
  2309. ## Import der FHEM Funktionen
  2310. BEGIN {
  2311. GP_Import(
  2312. qw(
  2313. ReadingsVal)
  2314. );
  2315. }
  2316. sub getBrightness {
  2317. my $self = shift;
  2318. return ReadingsVal( $shutters->getShadingBrightnessSensor,
  2319. $shutters->getShadingBrightnessReading, 0 );
  2320. }
  2321. sub getStatus {
  2322. my $self = shift;
  2323. return ReadingsVal( $self->{shuttersDev}, $shutters->getPosCmd, 0 );
  2324. }
  2325. sub getDelayCmd {
  2326. my $self = shift;
  2327. my $default = $self->{defaultarg};
  2328. return $self->{ $self->{shuttersDev} }{delayCmd};
  2329. }
  2330. ## Klasse Fenster (Window) und die Subklassen Attr und Readings ##
  2331. package ASC_Window;
  2332. our @ISA = qw(ASC_Window::Attr ASC_Window::Readings);
  2333. ## Subklasse Attr von Klasse ASC_Window ##
  2334. package ASC_Window::Attr;
  2335. use strict;
  2336. use warnings;
  2337. use GPUtils qw(GP_Import);
  2338. ## Import der FHEM Funktionen
  2339. BEGIN {
  2340. GP_Import(
  2341. qw(
  2342. AttrVal)
  2343. );
  2344. }
  2345. sub getSubTyp {
  2346. my $self = shift;
  2347. my $default = $self->{defaultarg};
  2348. $default = 'twostate' if ( not defined($default) );
  2349. return AttrVal( $self->{shuttersDev}, 'ASC_WindowRec_subType', $default );
  2350. }
  2351. sub _getWinDev {
  2352. my $self = shift;
  2353. my $default = $self->{defaultarg};
  2354. $default = 'none' if ( not defined($default) );
  2355. return AttrVal( $self->{shuttersDev}, 'ASC_WindowRec', $default );
  2356. }
  2357. ## Subklasse Readings von Klasse ASC_Window ##
  2358. package ASC_Window::Readings;
  2359. use strict;
  2360. use warnings;
  2361. use GPUtils qw(GP_Import);
  2362. ## Import der FHEM Funktionen
  2363. BEGIN {
  2364. GP_Import(
  2365. qw(
  2366. ReadingsVal)
  2367. );
  2368. }
  2369. sub getWinStatus {
  2370. my $self = shift;
  2371. my $default = $self->{defaultarg};
  2372. $default = 'closed' if ( not defined($default) );
  2373. return ReadingsVal( $shutters->_getWinDev, 'state', $default );
  2374. }
  2375. ## Klasse ASC_Roommate ##
  2376. package ASC_Roommate;
  2377. use strict;
  2378. use warnings;
  2379. use GPUtils qw(GP_Import);
  2380. ## Import der FHEM Funktionen
  2381. BEGIN {
  2382. GP_Import(
  2383. qw(
  2384. ReadingsVal)
  2385. );
  2386. }
  2387. sub _getRoommateStatus {
  2388. my $self = shift;
  2389. my $roommate = $self->{roommate};
  2390. my $default = $self->{defaultarg};
  2391. $default = 'none' if ( not defined($default) );
  2392. return ReadingsVal( $roommate, $shutters->getRoommatesReading, $default );
  2393. }
  2394. sub _getRoommateLastStatus {
  2395. my $self = shift;
  2396. my $roommate = $self->{roommate};
  2397. my $default = $self->{defaultarg};
  2398. $default = 'none' if ( not defined($default) );
  2399. return ReadingsVal( $roommate, 'lastState', $default );
  2400. }
  2401. ## Klasse ASC_Dev plus Subklassen ASC_Attr_Dev und ASC_Readings_Dev##
  2402. package ASC_Dev;
  2403. our @ISA = qw(ASC_Dev::Readings ASC_Dev::Attr);
  2404. use strict;
  2405. use warnings;
  2406. sub new {
  2407. my $class = shift;
  2408. my $self = { name => undef, };
  2409. bless $self, $class;
  2410. return $self;
  2411. }
  2412. sub setName {
  2413. my ( $self, $name ) = @_;
  2414. $self->{name} = $name if ( defined($name) );
  2415. return $self->{name};
  2416. }
  2417. sub setDefault {
  2418. my ( $self, $defaultarg ) = @_;
  2419. $self->{defaultarg} = $defaultarg if ( defined($defaultarg) );
  2420. return $self->{defaultarg};
  2421. }
  2422. ## Subklasse Readings ##
  2423. package ASC_Dev::Readings;
  2424. use strict;
  2425. use warnings;
  2426. use GPUtils qw(GP_Import);
  2427. ## Import der FHEM Funktionen
  2428. BEGIN {
  2429. GP_Import(
  2430. qw(
  2431. readingsSingleUpdate
  2432. ReadingsVal
  2433. defs)
  2434. );
  2435. }
  2436. sub setDelayCmdReading {
  2437. my $self = shift;
  2438. my $name = $self->{name};
  2439. my $hash = $defs{$name};
  2440. readingsSingleUpdate( $hash,
  2441. $shutters->getShuttersDev . '_lastDelayPosValue',
  2442. $shutters->getDelayCmd, 1 );
  2443. return 0;
  2444. }
  2445. sub setStateReading {
  2446. my $self = shift;
  2447. my $value = shift;
  2448. my $name = $self->{name};
  2449. my $hash = $defs{$name};
  2450. readingsSingleUpdate( $hash, 'state',
  2451. ( defined($value) ? $value : $shutters->getLastDrive ), 1 );
  2452. return 0;
  2453. }
  2454. sub setPosReading {
  2455. my $self = shift;
  2456. my $name = $self->{name};
  2457. my $hash = $defs{$name};
  2458. readingsSingleUpdate( $hash, $shutters->getShuttersDev . '_PosValue',
  2459. $shutters->getStatus, 1 );
  2460. return 0;
  2461. }
  2462. sub setLastPosReading {
  2463. my $self = shift;
  2464. my $name = $self->{name};
  2465. my $hash = $defs{$name};
  2466. readingsSingleUpdate( $hash, $shutters->getShuttersDev . '_lastPosValue',
  2467. $shutters->getLastPos, 1 );
  2468. return 0;
  2469. }
  2470. sub getPartyMode {
  2471. my $self = shift;
  2472. my $name = $self->{name};
  2473. my $default = $self->{defaultarg};
  2474. $default = 'none' if ( not defined($default) );
  2475. return ReadingsVal( $name, 'partyMode', $default );
  2476. }
  2477. sub getLockOut {
  2478. my $self = shift;
  2479. my $name = $self->{name};
  2480. my $default = $self->{defaultarg};
  2481. $default = 'none' if ( not defined($default) );
  2482. return ReadingsVal( $name, 'lockOut', $default );
  2483. }
  2484. sub getSunriseTimeWeHoliday {
  2485. my $self = shift;
  2486. my $name = $self->{name};
  2487. my $default = $self->{defaultarg};
  2488. $default = 'none' if ( not defined($default) );
  2489. return ReadingsVal( $name, 'sunriseTimeWeHoliday', $default );
  2490. }
  2491. sub getMonitoredDevs {
  2492. my $self = shift;
  2493. my $name = $self->{name};
  2494. $self->{monitoredDevs} = ReadingsVal( $name, '.monitoredDevs', 'none' );
  2495. return $self->{monitoredDevs};
  2496. }
  2497. sub getOutTemp {
  2498. my $self = shift;
  2499. my $name = $self->{name};
  2500. return ReadingsVal( $ascDev->getTempSensor, $ascDev->getTempReading, 100 );
  2501. }
  2502. sub getResidentsStatus {
  2503. my $self = shift;
  2504. my $name = $self->{name};
  2505. return ReadingsVal( $ascDev->_getResidentsDev, $ascDev->getResidentsReading,
  2506. 'none' );
  2507. }
  2508. sub getResidentsLastStatus {
  2509. my $self = shift;
  2510. my $name = $self->{name};
  2511. return ReadingsVal( $ascDev->_getResidentsDev, 'lastState', 'none' );
  2512. }
  2513. sub getSelfDefense {
  2514. my $self = shift;
  2515. my $name = $self->{name};
  2516. return ReadingsVal( $name, 'selfDefense', 'none' );
  2517. }
  2518. ## Subklasse Attr ##
  2519. package ASC_Dev::Attr;
  2520. use strict;
  2521. use warnings;
  2522. use GPUtils qw(GP_Import);
  2523. ## Import der FHEM Funktionen
  2524. BEGIN {
  2525. GP_Import(
  2526. qw(
  2527. AttrVal)
  2528. );
  2529. }
  2530. sub getShuttersOffset {
  2531. my $self = shift;
  2532. my $name = $self->{name};
  2533. return AttrVal( $name, 'ASC_shuttersDriveOffset', 0 );
  2534. }
  2535. sub getBrightnessMinVal {
  2536. my $self = shift;
  2537. my $name = $self->{name};
  2538. my $default = $self->{defaultarg};
  2539. $default = 8000 if ( not defined($default) );
  2540. return AttrVal( $name, 'ASC_brightnessMinVal', $default );
  2541. }
  2542. sub getBrightnessMaxVal {
  2543. my $self = shift;
  2544. my $name = $self->{name};
  2545. my $default = $self->{defaultarg};
  2546. $default = 20000 if ( not defined($default) );
  2547. return AttrVal( $name, 'ASC_brightnessMaxVal', $default );
  2548. }
  2549. sub getAutoAstroModeEvening {
  2550. my $self = shift;
  2551. my $name = $self->{name};
  2552. my $default = $self->{defaultarg};
  2553. $default = 'none' if ( not defined($default) );
  2554. return AttrVal( $name, 'ASC_autoAstroModeEvening', $default );
  2555. }
  2556. sub getAutoAstroModeEveningHorizon {
  2557. my $self = shift;
  2558. my $name = $self->{name};
  2559. return AttrVal( $name, 'ASC_autoAstroModeEveningHorizon', 0 );
  2560. }
  2561. sub getAutoAstroModeMorning {
  2562. my $self = shift;
  2563. my $name = $self->{name};
  2564. my $default = $self->{defaultarg};
  2565. $default = 'none' if ( not defined($default) );
  2566. return AttrVal( $name, 'ASC_autoAstroModeMorning', $default );
  2567. }
  2568. sub getAutoAstroModeMorningHorizon {
  2569. my $self = shift;
  2570. my $name = $self->{name};
  2571. return AttrVal( $name, 'ASC_autoAstroModeMorningHorizon', 0 );
  2572. }
  2573. sub getAutoShuttersControlMorning {
  2574. my $self = shift;
  2575. my $name = $self->{name};
  2576. my $default = $self->{defaultarg};
  2577. $default = 'none' if ( not defined($default) );
  2578. return AttrVal( $name, 'ASC_autoShuttersControlMorning', $default );
  2579. }
  2580. sub getAutoShuttersControlEvening {
  2581. my $self = shift;
  2582. my $name = $self->{name};
  2583. my $default = $self->{defaultarg};
  2584. $default = 'none' if ( not defined($default) );
  2585. return AttrVal( $name, 'ASC_autoShuttersControlEvening', $default );
  2586. }
  2587. sub getAutoShuttersControlComfort {
  2588. my $self = shift;
  2589. my $name = $self->{name};
  2590. return AttrVal( $name, 'ASC_autoShuttersControlComfort', 'off' );
  2591. }
  2592. sub getAntifreezeTemp {
  2593. my $self = shift;
  2594. my $name = $self->{name};
  2595. my $default = $self->{defaultarg};
  2596. $default = 'none' if ( not defined($default) );
  2597. return AttrVal( $name, 'ASC_antifreezeTemp', $default );
  2598. }
  2599. sub getTempSensor {
  2600. my $self = shift;
  2601. my $name = $self->{name};
  2602. my $default = $self->{defaultarg};
  2603. $default = 'none' if ( not defined($default) );
  2604. return AttrVal( $name, 'ASC_temperatureSensor', $default );
  2605. }
  2606. sub getTempReading {
  2607. my $self = shift;
  2608. my $name = $self->{name};
  2609. my $default = $self->{defaultarg};
  2610. $default = 'none' if ( not defined($default) );
  2611. return AttrVal( $name, 'ASC_temperatureReading', $default );
  2612. }
  2613. sub _getResidentsDev {
  2614. my $self = shift;
  2615. my $name = $self->{name};
  2616. my $default = $self->{defaultarg};
  2617. $default = 'none' if ( not defined($default) );
  2618. return AttrVal( $name, 'ASC_residentsDevice', $default );
  2619. }
  2620. sub getResidentsReading {
  2621. my $self = shift;
  2622. my $name = $self->{name};
  2623. my $default = $self->{defaultarg};
  2624. $default = 'state' if ( not defined($default) );
  2625. return AttrVal( $name, 'ASC_residentsDeviceReading', $default );
  2626. }
  2627. sub getRainSensor {
  2628. my $self = shift;
  2629. my $name = $self->{name};
  2630. my $default = $self->{defaultarg};
  2631. $default = 'none' if ( not defined($default) );
  2632. return AttrVal( $name, 'ASC_rainSensorDevice', $default );
  2633. }
  2634. sub getRainSensorReading {
  2635. my $self = shift;
  2636. my $name = $self->{name};
  2637. my $default = $self->{defaultarg};
  2638. $default = 'state' if ( not defined($default) );
  2639. return AttrVal( $name, 'ASC_rainSensorReading', $default );
  2640. }
  2641. sub getRainSensorShuttersClosedPos {
  2642. my $self = shift;
  2643. my $name = $self->{name};
  2644. return AttrVal( $name, 'ASC_rainSensorShuttersClosedPos', 50 );
  2645. }
  2646. 1;
  2647. =pod
  2648. =item device
  2649. =item summary Modul
  2650. =item summary_DE Modul zur Automatischen Rolladensteuerung auf Basis bestimmter Ereignisse
  2651. =begin html
  2652. <a name="AutoShuttersControl"></a>
  2653. <h3>Automatic shutter control - ASC</h3>
  2654. <ul>
  2655. <u><b>AutoShuttersControl in short ASC,controls automatically your shutters following defined rules. i.e. sunrise, sunset or any window event</b></u>
  2656. <br>
  2657. This modul shall control all shutters which are supervised by this Modul following the configuration of attributes in the shutter device. With fitting configuration a shutter will drive up if a resident gets awake and the sun has risen already. It is also possible by tilting a window to bring a closed shutter into airing position.
  2658. <br><br>
  2659. <a name="AutoShuttersControlDefine"></a>
  2660. <b>Define</b>
  2661. <ul><br>
  2662. <code>define &lt;name&gt; AutoShuttersControl</code>
  2663. <br><br>
  2664. Example:
  2665. <ul><br>
  2666. <code>define shuttersteuerung AutoShuttersControl</code><br>
  2667. </ul>
  2668. <br>
  2669. This command creates a AutoShuttersControl device named shutter.<br>
  2670. After creating the device, all shutter devices which shall be controlled have to get set the attribut ASC with value 1 or 2.<br>
  2671. Value 1 means "Inverse or shutter e.g.: shutter up 0,shutter down 100 and the command for percentual movement is position",2 = "Homematic Style e.g.: shutter up 100,shutter down 0 and the command for percentual movement is pct.<br>
  2672. If the attribute is set, you may start automatic scan for your devices .
  2673. </ul>
  2674. <br><br>
  2675. <a name="AutoShuttersControlReadings"></a>
  2676. <b>Readings</b>
  2677. <ul>
  2678. Im Modul Device
  2679. <ul>
  2680. <li>..._nextAstroTimeEvent - time of the next astro event,sunrise,sunset or fixed time per shuttername</li>
  2681. <li>..._PosValue - actual position of shutter</li>
  2682. <li>..._lastPosValue - last position of shutter</li>
  2683. <li>..._lastDelayPosValue - last drive command which is executed at the next permitted event (example: delay because Partymode)</li>
  2684. <li>partyMode - on/off activates the global partymode, all shutters with the attribute ASC_Partymode set to on will not be moved. The last command which had been send by a window event or resident state, will be send again if ASC-Device partyMode is set to off</li>
  2685. <li>lockOut - on/off to activate the lock out mode for the selected shutter. (see description of attributes for die shutterdevices)</li>
  2686. <li>room_... - list of all shutters found in respective rooms, e.g.: room_sleepingroom,terrasse</li>
  2687. <li>state - state of the devices active,enabled,disabled</li>
  2688. <li>sunriseTimeWeHoliday - on/off respects the attribute ASC_Time_Up_WE_Holiday </li>
  2689. <li>userAttrList - list of user attributea which will be send to shutters</li>
  2690. </ul><br>
  2691. Inside the shutter devices
  2692. <ul>
  2693. <li>ASC_Time_DriveUp - sunrise time for this shutter</li>
  2694. <li>ASC_Time_DriveDown - sunset time for this shutter</li>
  2695. <li>ASC_ShuttersLastDrive - last reason for the shutter to move</li>
  2696. </ul>
  2697. </ul>
  2698. <br><br>
  2699. <a name="AutoShuttersControlSet"></a>
  2700. <b>Set</b>
  2701. <ul>
  2702. <li>partyMode - on/off activates the global party mode. see reading partyMode</li>
  2703. <li>lockOut - on/off activates the global lock out mode. see reading lockOut</li>
  2704. <li>renewSetSunriseSunsetTimer - refreshes the timer for sunset, sunrise and the internal timers.</li>
  2705. <li>scanForShutters - searches all FHEM devices with attribute "AutoShuttersControl" 1/2</li>
  2706. <li>sunriseTimeWeHoliday - on/off activates/deactivates respecting attribute ASC_Time_Up_WE_Holiday</li>
  2707. <li>createNewNotifyDev - recreates the internal structure for NOTIFYDEV - attribute verbose has to be greater than 3.</li>
  2708. <li>selfDefense - on/off,activates/deactivates the mode self defense. If the resident device says absent and selfDefense is active, each shutter for open windows will be closed.</li>
  2709. <li>wiggle - moves any shutter (for deterrence purposes) by 5% up, and after 1 minute down again to last position.</li>
  2710. </ul>
  2711. <br><br>
  2712. <a name="AutoShuttersControlGet"></a>
  2713. <b>Get</b>
  2714. <ul>
  2715. <li>showShuttersInformations - shows an overview of all times/timers</li>
  2716. <li>showNotifyDevsInformations - shows an overview of all notify devices. Is used for control</li>
  2717. </ul>
  2718. <br><br>
  2719. <a name="AutoShuttersControlAttributes"></a>
  2720. <b>Attributes</b>
  2721. <ul>
  2722. In module device
  2723. <ul>
  2724. <li>ASC_antifreezeTemp - temperature which inhibits movement of shutter. The last drive command will be stored.</li>
  2725. <li>ASC_autoAstroModeEvening - actual REAL,CIVIL,NAUTIC,ASTRONOMIC</li>
  2726. <li>ASC_autoAstroModeEveningHorizon - heighth above horizon if HORIZON is selected at attribute ASC_autoAstroModeEvening.</li>
  2727. <li>ASC_autoAstroModeMorning - actual REAL,CIVIL,NAUTIC,ASTRONOMIC</li>
  2728. <li>ASC_autoAstroModeMorningHorizon - heighth above horizon if HORIZON is selected at attribute ASC_autoAstroModeMorning.</li>
  2729. <li>ASC_autoShuttersControlComfort - on/off turns on comfort function. Means a shutter with threestate sensor moves to a wide open position. The open position is set at shutter with the attribute ASC_Pos_after_ComfortOpen.</li>
  2730. <li>ASC_autoShuttersControlEvening - on/off if the shutters shall be controlled by time in the evening.</li>
  2731. <li>ASC_autoShuttersControlMorning - on/off if the shutters shall be controlled by time in the morning.</li>
  2732. <li>ASC_temperatureReading - Reading for outside temperature.</li>
  2733. <li>ASC_temperatureSensor - Device for outside temperature.</li>
  2734. <li>ASC_timeUpHolidayDevice - Device for holiday detection or similar.</li>
  2735. <li>ASC_timeUpHolidayReading - corrsponding reading for ASC_timeUpHolidayDevice to detect holiday or similar / has to content 0 or 1.</li>
  2736. <li>ASC_residentsDevice - devicename of the residents device</li>
  2737. <li>ASC_residentsDeviceReading - state of the residents device</li>
  2738. <li>ASC_brightnessMinVal - minimum brightness value to activate check of conditions</li>
  2739. <li>ASC_brightnessMaxVal - maximum brightness value to activate check of conditions</li>
  2740. <li>ASC_rainSensorDevice - device which triggers when it is raining</li>
  2741. <li>ASC_rainSensorReading - reading of rain sensor device</li>
  2742. <li>ASC_rainSensorShuttersClosedPos - position to be reached if it is raining.</li>
  2743. <li>ASC_shuttersDriveOffset - maximum delay time in seconds for drivetimes, 0 means no delay</li>
  2744. </ul><br>
  2745. In the shutter devices
  2746. <ul>
  2747. <li>ASC - 0/1/2 1 = "Inverse or shutter e.g.: shutter upn 0,shutter down 100 and the command to travel is position",2 = "Homematic Style e.g.: shutter up 100,shutter down 0 and the command to travel is pct</li>
  2748. <li>ASC_Antifreeze - on/off antifreeze on or off</li>
  2749. <li>ASC_AutoAstroModeEvening - actual REAL,CIVIL,NAUTIC,ASTRONOMIC</li>
  2750. <li>ASC_AutoAstroModeEveningHorizon - heighth above horizon if HORIZON is selected at attribute ASC_autoAstroModeEvening.</li>
  2751. <li>ASC_AutoAstroModeMorning - actual REAL,CIVIL,NAUTIC,ASTRONOMIC</li>
  2752. <li>ASC_AutoAstroModeMorningHorizon - heighth above horizon if HORIZON is selected at attribute ASC_autoAstroModeMorning.</li>
  2753. <li>ASC_Closed_Pos - in 10th steps from 0 to 100, default value is pending on attribute AutoShuttersControl</li>
  2754. <li>ASC_Down - astro/time/brightness with astro sunset will be calculated, with time the value of ASC_Time_Down_Early will be used and with brightness ASC_Time_Down_Early and ASC_Time_Down_Late has to be defined corectly. The timer uses ASC_Time_Down_Late time, during this time ASC_Time_Down_Early and ASC_Time_Down_Late are respected also, to control ASC_brightnessMinVal. If reached the shutter will travel down.</li>
  2755. <li>ASC_Mode_Down - always/home/absent/off automatic is used: always/home/absent/off (if no roommate defined and absent is set no control will happen)</li>
  2756. <li>ASC_Mode_Up - always/home/absent/off automatic is used: always/home/absent/off (if no roommate defined and absent is set no control will happen)</li>
  2757. <li>ASC_Drive_Offset - maximum random delay in seconds for calculating drivetimes, 0 means no delay, -1 means the corresponding attribute of the ASC device shall be taken into account.</li>
  2758. <li>ASC_Open_Pos - in 10th steps from 0 bis 100, default value is pending from attribute AutoShuttersControl</li>
  2759. <li>ASC_Partymode - on/off turns the partymode on or off. In case of setting ASC-DEVICE to partyMode on, all drive commands of the shutters which have the attribute set to on, will be stored for later usage.</li>
  2760. <li>ASC_Pos_Reading - name of the reading which represents the position of the shutter in percent, is used at unknown device types for set command.</li>
  2761. <li>ASC_Pos_after_ComfortOpen - in 10th steps from 0 bis 100, default value is pending from attribute AutoShuttersControl</li>
  2762. <li>ASC_Roommate_Reading - the reading of the roommate device which represents the state</li>
  2763. <li>ASC_Roommate_Device - comma seperated names of the roommate device/s representing the habitants of the room of the shutter. Senseless in in any rooms besides sleepingroom and childrens room.</li>
  2764. <li>ASC_Time_Down_Early - Sunset earliest time to travel down</li>
  2765. <li>ASC_Time_Down_Late - Sunset latest time to travel down</li>
  2766. <li>ASC_Time_Up_Early - Sunrise earliest time to travel up</li>
  2767. <li>ASC_Time_Up_Late - Sunrise latest time to travel up</li>
  2768. <li>ASC_Time_Up_WE_Holiday - Sunrise earliest time to travel up at weekend and/or holiday (we2holiday is respected). Attention should not be bigger than ASC_Time_Up_Late otherwise ASC_Time_Up_Late will be used.</li>
  2769. <li>ASC_Up - astro/time/brightness with astro sunrise is calculated, with time the value of ASC_Time_Up_Early is used and with brightness ASC_Time_Up_Early and ASC_Time_Up_Late has to be set correctly. The Timer starts after ASC_Time_Up_Late, but during this time ASC_Time_Up_Early and ASC_Time_Up_Late are used, in combination with the attribute ASC_brightnessMinVal reached, if yes the shutter will travel down</li>
  2770. <li>ASC_Ventilate_Pos - in 10th steps from 0 bis 100, default value is pending from attribute AutoShuttersControl</li>
  2771. <li>ASC_Ventilate_Window_Open - drive to airing position if the window is tilted or opened and actual position is below airing position</li>
  2772. <li>ASC_WindowRec - name of the window sensor mounted to window</li>
  2773. <li>ASC_WindowRec_subType - type of the used window sensor: twostate (optical oder magnetic) or threestate (rotating handle sensor)</li>
  2774. <li>ASC_lock-out - soft/hard sets the lock out mode. With global activated lock out mode (set ASC-Device lockOut soft) and window sensor open, the shutter stays up. This is true only, if commands are given by ASC module. Is global set to hard, the shutter is blocked by hardware if possible. In this case a locally mounted switch can't be used either.</li>
  2775. <li>ASC_lock-outCmd - inhibit/blocked set command for the shutter-device for hardware interlock. Possible if "ASC_lock-out" is set to hard</li>
  2776. <li>ASC_Self_Defense_Exclude - on/off to exclude this shutter from active Self Defense. Shutter will not be closed if window is open and residents are absent.</li>
  2777. <li>ASC_Shading_Brightness_Sensor - Sensor device used for brightness. ATTENTION! Is used also for ASC_Down - brightness</li>
  2778. <li>ASC_BrightnessMinVal - minimum brightness value to activate check of conditions / if the value -1 is not changed, the value of the module device is used.</li>
  2779. <li>ASC_BrightnessMaxVal - maximum brightness value to activate check of conditions / if the value -1 is not changed, the value of the module device is used.</li>
  2780. <li>ASC_ShuttersPlace - window/terrace, if this attribute is set to terrace and the residents device are in state "gone"and SelfDefence is active the shutter will be closed</li>
  2781. </ul>
  2782. </ul>
  2783. </ul>
  2784. =end html
  2785. =begin html_DE
  2786. <a name="AutoShuttersControl"></a>
  2787. <h3>Automatische Rolladensteuerung - ASC</h3>
  2788. <ul>
  2789. <u><b>AutoShuttersControl oder kurz ASC,steuert automatisch Deine Rolladen nach bestimmten Vorgaben. Zum Beispiel Sonnenaufgang und Sonnenuntergang oder je nach Fenstervent</b></u>
  2790. <br>
  2791. Dieses Modul soll alle vom Modul &uuml;berwachten Roll&auml;den entsprechend der Konfiguration &uuml;ber die Attribute im Rolladen Device steuern. Es wird bei entsprechender Konfiguration zum Beispiel die Roll&auml;den hochfahren wenn ein Bewohner erwacht ist und draussen bereits die Sonne aufgegangen ist. Auch ist es m&ouml;glich das bei ankippen eines Fensters der geschlossene Rolladen in eine L&uuml;ftungsposition f&auml;hrt.
  2792. <br><br>
  2793. <a name="AutoShuttersControlDefine"></a>
  2794. <b>Define</b>
  2795. <ul><br>
  2796. <code>define &lt;name&gt; AutoShuttersControl</code>
  2797. <br><br>
  2798. Example:
  2799. <ul><br>
  2800. <code>define Rolladensteuerung AutoShuttersControl</code><br>
  2801. </ul>
  2802. <br>
  2803. Der Befehl erstellt ein AutoShuttersControl Device mit Namen Rolladen.<br>
  2804. Nachdem das Device angelegt wurde,m&uuml;ssen in allen Roll&auml;den Devices welche gesteuert werden sollen das Attribut ASC mit Wert 1 oder 2 gesetzt werden.<br>
  2805. Dabei bedeutet 1 = "Inverse oder Rollo Bsp.: Rollo Oben 0,Rollo Unten 100 und der Befehl zum Prozentualen fahren ist position",2 = "Homematic Style Bsp.: Rollo Oben 100,Rollo Unten 0 und der Befehl zum Prozentualen fahren ist pct.<br>
  2806. Habt Ihr das Attribut gesetzt,k&ouml;nnt Ihr den automatischen Scan nach den Devices anstossen.
  2807. </ul>
  2808. <br><br>
  2809. <a name="AutoShuttersControlReadings"></a>
  2810. <b>Readings</b>
  2811. <ul>
  2812. Im Modul Device
  2813. <ul>
  2814. <li>..._nextAstroTimeEvent - Uhrzeit des n&auml;chsten Astro Events,Sonnenauf,Sonnenuntergang oder feste Zeit pro Rollonamen</li>
  2815. <li>..._PosValue - aktuelle Position des Rolladen</li>
  2816. <li>..._lastPosValue - letzte Position des Rolladen</li>
  2817. <li>..._lastDelayPosValue - letzter abgesetzter Fahrbefehl welcher beim n&auml;chsten zul&auml;ssigen Event ausgef&uuml;hrt wird.</li>
  2818. <li>partyMode - on/off aktiviert den globalen Partymodus,alle Roll&auml;den welche das Attribut ASC_Partymode bei sich auf on gestellt haben werden nicht mehr gesteuert. Der letzte Schaltbefehle welcher durch ein Fensterevent oder Bewohnerstatus an die Roll&auml;den gesendet wurde,wird beim off setzen durch set ASC-Device partyMode off ausgef&uuml;hrt</li>
  2819. <li>lockOut - on/off f&uuml;r das aktivieren des Aussperrschutzes gem&auml;&szlig; dem entsprechenden Attribut ASC_lock-out im jeweiligen Rolladen. (siehe Beschreibung bei den Attributen f&uuml;r die Rolladendevices)</li>
  2820. <li>room_... - Auflistung aller Roll&auml;den welche in den jeweiligen R&auml;men gefunden wurde,Bsp.: room_Schlafzimmer,Terrasse</li>
  2821. <li>state - Status des Devices active,enabled,disabled</li>
  2822. <li>sunriseTimeWeHoliday - on/off wird das Rolladen Device Attribut Attributes ASC_Time_Up_WE_Holiday Beachtet oder nicht</li>
  2823. <li>userAttrList - Status der UserAttribute welche an die Roll&auml;den gesendet werden</li>
  2824. </ul><br>
  2825. In den Roll&auml;den Devices
  2826. <ul>
  2827. <li>ASC_Time_DriveUp - Sonnenaufgangszei f&uuml;r das Rollo</li>
  2828. <li>ASC_Time_DriveDown - Sonnenuntergangszeit f&uuml;r das Rollo</li>
  2829. <li>ASC_ShuttersLastDrive - Grund des letzten fahrens vom Rolladen</li>
  2830. </ul>
  2831. </ul>
  2832. <br><br>
  2833. <a name="AutoShuttersControlSet"></a>
  2834. <b>Set</b>
  2835. <ul>
  2836. <li>partyMode - on/off aktiviert den globalen Partymodus. Siehe Reading partyMode</li>
  2837. <li>lockOut - on/off aktiviert den globalen Aussperrschutz. Siehe Reading partyMode</li>
  2838. <li>renewSetSunriseSunsetTimer - erneuert bei allen Roll&auml;den die Zeiten f&uuml;r Sunset und Sunrise und setzt die internen Timer neu.</li>
  2839. <li>scanForShutters - sucht alle FHEM Devices mit dem Attribut "AutoShuttersControl" 1/2</li>
  2840. <li>sunriseTimeWeHoliday - on/off aktiviert/deaktiviert die Beachtung des Rolladen Device Attributes ASC_Time_Up_WE_Holiday</li>
  2841. <li>createNewNotifyDev - Legt die interne Struktur f&uuml;r NOTIFYDEV neu an - Attribut verbose muss gr&ouml;$szlig;er 3 sein.</li>
  2842. <li>selfDefense - on/off,aktiviert/deaktiviert den Selbstschutz,wenn das Residents Device absent meldet und selfDefense aktiv ist und ein Fenster im Haus steht noch offen,wird an diesem Fenster das Rollo runter gefahren</li>
  2843. <li>wiggle - bewegt einen Rollladen oder alle Rolll&auml;den (f&uuml;r Abschreckungszwecke bei der Alarmierung) um 5%, und nach 1 Minute wieder zur&uuml;ck zur Ursprungsposition</li>
  2844. </ul>
  2845. <br><br>
  2846. <a name="AutoShuttersControlGet"></a>
  2847. <b>Get</b>
  2848. <ul>
  2849. <li>showShuttersInformations - zeigt eine &Uuml;bersicht der Autofahrzeiten</li>
  2850. <li>showNotifyDevsInformations - zeigt eine &Uuml;bersicht der abgelegten NOTIFYDEV Struktur. Diehnt zur Kontrolle</li>
  2851. </ul>
  2852. <br><br>
  2853. <a name="AutoShuttersControlAttributes"></a>
  2854. <b>Attributes</b>
  2855. <ul>
  2856. Im Modul Device
  2857. <ul>
  2858. <li>ASC_antifreezeTemp - Temperatur ab welcher der Frostschutz greifen soll und das Rollo nicht mehr f&auml;hrt. Der letzte Fahrbefehl wird gespeichert.</li>
  2859. <li>ASC_autoAstroModeEvening - aktuell REAL,CIVIL,NAUTIC,ASTRONOMIC</li>
  2860. <li>ASC_autoAstroModeEveningHorizon - H&ouml;he &uuml;ber Horizont wenn beim Attribut ASC_autoAstroModeEvening HORIZON ausgew&auml;hlt</li>
  2861. <li>ASC_autoAstroModeMorning - aktuell REAL,CIVIL,NAUTIC,ASTRONOMIC</li>
  2862. <li>ASC_autoAstroModeMorningHorizon - H&ouml;he &uuml;ber Horizont wenn beim Attribut ASC_autoAstroModeMorning HORIZON ausgew&auml;hlt</li>
  2863. <li>ASC_autoShuttersControlComfort - on/off schaltet die Komfortfunktion an. Bedeutet das ein Rolladen mit einem threestate Sensor am Fenster beim &ouml;ffnen in eine weit offen Position f&auml;hrt. Die Offenposition wird beim Rolladen &uuml;ber das Attribut ASC_Pos_after_ComfortOpen eingestellt.</li>
  2864. <li>ASC_autoShuttersControlEvening - on/off,ob Abends die Roll&auml;den automatisch nach Zeit gesteuert werden sollen</li>
  2865. <li>ASC_autoShuttersControlMorning - on/off,ob Morgens die Roll&auml;den automatisch nach Zeit gesteuert werden sollen</li>
  2866. <li>ASC_temperatureReading - Reading f&uuml;r die Aussentemperatur</li>
  2867. <li>ASC_temperatureSensor - Device f&uuml;r die Aussentemperatur</li>
  2868. <li>ASC_timeUpHolidayDevice - Device zur Urlaubserkennung oder Sonstiges / muss 0 oder 1 im Reading beinhalten.</li>
  2869. <li>ASC_timeUpHolidayReading - passendes Reading zum ASC_timeUpHolidayDevice zur Urlaubserkennung oder Sonstiges / muss 0 oder 1 beinhalten.</li>
  2870. <li>ASC_residentsDevice - Devicenamen vom Residents Device der obersten Ebene</li>
  2871. <li>ASC_residentsDeviceReading - Status Reading vom Residents Device der obersten Ebene</li>
  2872. <li>ASC_brightnessMinVal - minimaler Lichtwert ab welchen Schaltbedingungen gepr&uuml;ft werden sollen</li>
  2873. <li>ASC_brightnessMaxVal - maximaler Lichtwert ab welchen Schaltbedingungen gepr&uuml;ft werden sollen</li>
  2874. <li>ASC_rainSensorDevice - Device welches bei Regen getriggert werden soll</li>
  2875. <li>ASC_rainSensorReading - das ensprechende Reading zum Regendevice</li>
  2876. <li>ASC_rainSensorShuttersClosedPos - Position n welche der Rolladen fahren soll wenn es Regnet</li>
  2877. <li>ASC_shuttersDriveOffset - maximale zuf&auml;llige Verz&ouml;gerung in Sekunden bei der Berechnung der Fahrzeiten, 0 bedeutet sofort</li>
  2878. </ul><br>
  2879. In den Roll&auml;den Devices
  2880. <ul>
  2881. <li>ASC - 0/1/2 1 = "Inverse oder Rollo Bsp.: Rollo Oben 0,Rollo Unten 100 und der Befehl zum Prozentualen fahren ist position",2 = "Homematic Style Bsp.: Rollo Oben 100,Rollo Unten 0 und der Befehl zum Prozentualen fahren ist pct</li>
  2882. <li>ASC_Antifreeze - on/off Frostschutz an oder aus</li>
  2883. <li>ASC_AutoAstroModeEvening - aktuell REAL,CIVIL,NAUTIC,ASTRONOMIC</li>
  2884. <li>ASC_AutoAstroModeEveningHorizon - H&ouml;he &uuml;ber Horizont wenn beim Attribut ASC_autoAstroModeEvening HORIZON ausgew&auml;hlt</li>
  2885. <li>ASC_AutoAstroModeMorning - aktuell REAL,CIVIL,NAUTIC,ASTRONOMIC</li>
  2886. <li>ASC_AutoAstroModeMorningHorizon - H&ouml;he &uuml;ber Horizont wenn beim Attribut ASC_autoAstroModeMorning HORIZON ausgew&auml;hlt</li>
  2887. <li>ASC_Closed_Pos - in 10 Schritten von 0 bis 100,default Vorgabe ist abh&auml;ngig vom Attribut AutoShuttersControl</li>
  2888. <li>ASC_Down - astro/time/brightness bei Astro wird Sonnenuntergang berechnet,bei time wird der Wert aus ASC_Time_Down_Early als Fahrzeit verwendet und bei brightness muss ASC_Time_Down_Early und ASC_Time_Down_Late korrekt gesetzt werden. Der Timer l&auml;uft dann nach ASC_Time_Down_Late Zeit,es wird aber in der Zeit zwischen ASC_Time_Down_Early und ASC_Time_Down_Late geschaut ob die als Attribut im Moduldevice hinterlegte ASC_brightnessMinVal erreicht wurde,wenn ja wird der Rolladen runter gefahren</li>
  2889. <li>ASC_Mode_Down - always/home/absent/off wann darf die Automatik steuern. immer,niemals,bei abwesenheit des Roommate (ist kein Roommate und absent eingestellt wird gar nicht gesteuert)</li>
  2890. <li>ASC_Mode_Up - always/home/absent/off wann darf die Automatik steuern. immer,niemals,bei abwesenheit des Roommate (ist kein Roommate und absent eingestellt wird gar nicht gesteuert)</li>
  2891. <li>ASC_Drive_Offset - maximale zuf&auml;llige Verz&ouml;gerung in Sekunden bei der Berechnung der Fahrzeiten, 0 bedeutet sofort, -1 bedeutet das das gleichwertige Attribut aus dem ASC Device ausgewertet werden soll.</li>
  2892. <li>ASC_Open_Pos - in 10 Schritten von 0 bis 100,default Vorgabe ist abh&auml;ngig vom Attribut AutoShuttersControl</li>
  2893. <li>ASC_Partymode - on/off schaltet den Partymodus an oder aus,Wird dann am ASC Device set ASC-DEVICE partyMode on geschalten,werden alle Fahrbefehle an den Roll&auml;den welche das Attribut auf on haben zwischen gespeichert und sp&auml;ter erst ausgef&uuml;hrt</li>
  2894. <li>ASC_Pos_Reading - Name des Readings welches die Position des Rolladen in Prozent an gibt, wird bei unbekannten Device Typen auch als set Befehl zum fahren verwendet</li>
  2895. <li>ASC_Pos_after_ComfortOpen - in 10 Schritten von 0 bis 100,default Vorgabe ist abh&auml;ngig vom Attribut AutoShuttersControl</li>
  2896. <li>ASC_Roommate_Reading - das Reading zum Roommate Device welches den Status wieder gibt</li>
  2897. <li>ASC_Roommate_Device - mit Komma getrennte Namen des/der Roommate Device/s welche den/die Bewohner des Raumes vom Rolladen wieder gibt. Es macht nur Sinn in Schlaf- oder Kinderzimmern</li>
  2898. <li>ASC_Time_Down_Early - Sunset fr&uuml;hste Zeit zum runter fahren</li>
  2899. <li>ASC_Time_Down_Late - Sunset sp&auml;teste Zeit zum runter fahren</li>
  2900. <li>ASC_Time_Up_Early - Sunrise fr&uuml;hste Zeit zum hoch fahren</li>
  2901. <li>ASC_Time_Up_Late - Sunrise sp&auml;teste Zeit zum hoch fahren</li>
  2902. <li>ASC_Time_Up_WE_Holiday - Sunrise fr&uuml;hste Zeit zum hochfahren am Wochenende und/oder Urlaub (we2holiday wird beachtet),Achtung sollte nicht gr&ouml;&szlig;er sein wie ASC_Time_Up_Late sonst wird ASC_Time_Up_Late verwendet</li>
  2903. <li>ASC_Up - astro/time/brightness bei Astro wird Sonnenaufgang berechnet,bei time wird der Wert aus ASC_Time_Up_Early als Fahrzeit verwendet und bei brightness muss ASC_Time_Up_Early und ASC_Time_Up_Late korrekt gesetzt werden. Der Timer l&auml;uft dann nach ASC_Time_Up_Late Zeit,es wird aber in der Zeit zwischen ASC_Time_Up_Early und ASC_Time_Up_Late geschaut ob die als Attribut im Moduldevice hinterlegte ASC_brightnessMinVal erreicht wurde,wenn ja wird der Rolladen runter gefahren</li>
  2904. <li>ASC_Ventilate_Pos - in 10 Schritten von 0 bis 100,default Vorgabe ist abh&auml;ngig vom Attribut AutoShuttersControl</li>
  2905. <li>ASC_Ventilate_Window_Open - auf l&uuml;ften,wenn das Fenster gekippt/ge&ouml;ffnet wird und aktuelle Position unterhalb der L&uuml;ften-Position ist</li>
  2906. <li>ASC_WindowRec - Name des Fensterkontaktes an welchen Fenster der Rolladen angebracht ist</li>
  2907. <li>ASC_WindowRec_subType - Typ des verwendeten Fensterkontakts: twostate (optisch oder magnetisch) oder threestate (Drehgriffkontakt)</li>
  2908. <li>ASC_lock-out - soft/hard stellt entsprechend den Aussperrschutz ein. Bei global aktiven Aussperrschutz (set ASC-Device lockOut soft) und einem Fensterkontakt open bleibt dann der Rolladen oben. Dies gilt nur bei Steuerbefehle über das ASC Modul. Stellt man global auf hard,wird bei entsprechender M&ouml;glichkeit versucht den Rolladen Hardwareseitig zu blockieren. Dann ist auch ein fahren &uuml;ber die Taster nicht mehr m&ouml;glich.</li>
  2909. <li>ASC_lock-outCmd - inhibit/blocked set Befehl f&uuml;r das Rolladen-Device zum Hardware sperren. Zum gesetzt werden wenn man "ASC_lock-out" auf hard setzt</li>
  2910. <li>ASC_Self_Defense_Exclude - on/off bei on Wert wird dieser Rolladen bei aktiven Self Defense und offenen Fenster nicht runter gefahren wenn Residents absent ist.</li>
  2911. <li>ASC_Shading_Brightness_Sensor - Sensor Device welches f&uuml;r die Lichtwerte verwendet wird. ACHTUNG! Findet auch Verwendung bei ASC_Down - brightness</li>
  2912. <li>ASC_BrightnessMinVal - minimaler Lichtwert ab welchen Schaltbedingungen gepr&uuml;ft werden sollen / wird der Wert von -1 nicht ge&auml;ndert, so wird automatisch der Wert aus dem Moduldevice genommen</li>
  2913. <li>ASC_BrightnessMaxVal - maximaler Lichtwert ab welchen Schaltbedingungen gepr&uuml;ft werden sollen / wird der Wert von -1 nicht ge&auml;ndert, so wird automatisch der Wert aus dem Moduldevice genommen</li>
  2914. <li>ASC_ShuttersPlace - window/terrace, wenn dieses Attribut auf terrace gesetzt ist und das Residence Device in den Status "done" geht und SelfDefence aktiv ist wird das Rollo geschlossen</li>
  2915. </ul>
  2916. </ul>
  2917. </ul>
  2918. =end html_DE
  2919. =cut