98_MSwitch.pm 251 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902
  1. # $Id: 98_MSwitch.pm 17513 2018-10-12 08:39:03Z Byte09 $
  2. # 98_MSwitch.pm
  3. #
  4. # copyright #####################################################
  5. #
  6. # 98_MSwitch.pm
  7. #
  8. # written by Byte09
  9. # Maintained by Byte09
  10. #
  11. # This file is part of FHEM.
  12. #
  13. # FHEM 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. # (at your option) any later version.
  17. #
  18. # FHEM is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. # GNU General Public License for more details.
  22. #
  23. # You should have received a copy of the GNU General Public License
  24. # along with FHEM. If not, see <http://www.gnu.org/licenses/>.
  25. #################################################################
  26. # Todo's:
  27. #
  28. #
  29. #################################################################
  30. package main;
  31. use Time::Local;
  32. use strict;
  33. use warnings;
  34. use POSIX;
  35. # Version #######################################################
  36. my $autoupdate = 'on'; #off/on
  37. my $version = 'V2.01a';
  38. my $vupdate = 'V2.00';
  39. my $savecount = 30;
  40. my $standartstartdelay =60;
  41. # standartlist ignorierter Devices
  42. my @doignore =qw(notify allowed at watchdog doif fhem2fhem telnet FileLog readingsGroup FHEMWEB autocreate eventtypes readingsproxy svg cul);
  43. ##################### ############################################
  44. sub MSwitch_Checkcond_time($$);
  45. sub MSwitch_Checkcond_state($$);
  46. sub MSwitch_Checkcond_day($$$$);
  47. sub MSwitch_Createtimer($);
  48. sub MSwitch_Execute_Timer($);
  49. sub MSwitch_LoadHelper($);
  50. sub MSwitch_debug2($$);
  51. sub MSwitch_ChangeCode($$);
  52. sub MSwitch_Add_Device($$);
  53. sub MSwitch_Del_Device($$);
  54. sub MSwitch_Debug($);
  55. sub MSwitch_Exec_Notif($$$$$);
  56. sub MSwitch_checkcondition($$$);
  57. sub MSwitch_Delete_Delay($$);
  58. sub MSwitch_Check_Event($$);
  59. sub MSwitch_makeAffected($);
  60. sub MSwitch_backup($);
  61. sub MSwitch_backup_this($);
  62. sub MSwitch_backup_all($);
  63. sub MSwitch_backup_done($);
  64. sub MSwitch_checktrigger(@);
  65. sub MSwitch_Cmd(@);
  66. sub MSwitch_toggle($$);
  67. sub MSwitch_Getconfig($);
  68. sub MSwitch_saveconf($$);
  69. sub MSwitch_replace_delay($$);
  70. sub MSwitch_repeat($);
  71. sub MSwitch_Createrandom($$$);
  72. sub MSwitch_Execute_randomtimer($);
  73. sub MSwitch_Clear_timer($);
  74. sub MSwitch_Createnumber($);
  75. sub MSwitch_Createnumber1($);
  76. sub MSwitch_Savemode($);
  77. sub MSwitch_set_dev($);
  78. sub MSwitch_EventBulk($$$);
  79. sub MSwitch_priority ;
  80. sub MSwitch_dec($$);
  81. sub MSwitch_makefreecmd($$);
  82. sub MSwitch_clearlog($);
  83. sub MSwitch_LOG($$$);
  84. sub MSwitch_Getsupport($);
  85. sub MSwitch_confchange($$);
  86. my %sets = (
  87. "on" => "noArg",
  88. "off" => "noArg",
  89. "reload_timer" => "noArg",
  90. "active" => "noArg",
  91. "inactive" => "noArg",
  92. "devices" => "noArg",
  93. "details" => "noArg",
  94. "del_trigger" => "noArg",
  95. "del_delays" => "noArg",
  96. "trigger" => "noArg",
  97. "filter_trigger" => "noArg",
  98. "add_device" => "noArg",
  99. "del_device" => "noArg",
  100. "addevent" => "noArg",
  101. "backup_MSwitch" => "noArg",
  102. "import_config" => "noArg",
  103. "saveconfig" => "noArg",
  104. "savesys" => "noArg",
  105. "fakeevent" => "noArg",
  106. "exec_cmd1" => "noArg",
  107. "exec_cmd2" => "noArg",
  108. "exec_cmd1+2" => "noArg",
  109. "wait" => "noArg",
  110. "VUpdate" => "noArg",
  111. "confchange" => "noArg",
  112. "clearlog" => "noArg",
  113. "set_trigger" => "noArg"
  114. );
  115. my %gets = (
  116. "active_timer" => "noArg",
  117. "restore_MSwitch_Data" => "noArg",
  118. "get_config" => "noArg"
  119. );
  120. ####################
  121. sub MSwitch_Initialize($) {
  122. my ($hash) = @_;
  123. $hash->{SetFn} = "MSwitch_Set";
  124. $hash->{AsyncOutput} = "MSwitch_AsyncOutput";
  125. $hash->{RenameFn} = "MSwitch_Rename";
  126. $hash->{CopyFn} = "MSwitch_Copy";
  127. $hash->{GetFn} = "MSwitch_Get";
  128. $hash->{DefFn} = "MSwitch_Define";
  129. $hash->{UndefFn} = "MSwitch_Undef";
  130. $hash->{DeleteFn} = "MSwitch_Delete";
  131. $hash->{ParseFn} = "MSwitch_Parse";
  132. $hash->{AttrFn} = "MSwitch_Attr";
  133. $hash->{NotifyFn} = "MSwitch_Notify";
  134. $hash->{FW_detailFn} = "MSwitch_fhemwebFn";
  135. $hash->{FW_deviceOverview} = 1;
  136. $hash->{FW_summaryFn} = "MSwitch_summary";
  137. $hash->{NotifyOrderPrefix} = "45-";
  138. $hash->{AttrList} =
  139. " disable:0,1"
  140. . " disabledForIntervals"
  141. . " MSwitch_Help:0,1"
  142. . " MSwitch_Debug:0,1,2,3,4"
  143. . " MSwitch_Expert:0,1"
  144. . " MSwitch_Delete_Delays:0,1"
  145. . " MSwitch_Include_Devicecmds:0,1"
  146. . " MSwitch_Include_Webcmds:0,1"
  147. . " MSwitch_Include_MSwitchcmds:0,1"
  148. . " MSwitch_Activate_MSwitchcmds:0,1"
  149. . " MSwitch_Lock_Quickedit:0,1"
  150. . " MSwitch_Ignore_Types"
  151. . " MSwitch_Trigger_Filter"
  152. . " MSwitch_Extensions:0,1"
  153. . " MSwitch_Inforoom"
  154. . " MSwitch_Mode:Full,Notify,Toggle"
  155. . " MSwitch_Condition_Time:0,1"
  156. . " MSwitch_RandomTime"
  157. . " MSwitch_RandomNumber"
  158. . " MSwitch_Safemode:0,1"
  159. . " MSwitch_Startdelay:0,10,20,30,60,90,120"
  160. . " MSwitch_Wait";
  161. $hash->{FW_addDetailToSummary} = 0;
  162. }
  163. ####################
  164. sub MSwitch_Rename ($)
  165. {
  166. my ( $new_name, $old_name ) = @_;
  167. my $hash_new = $defs{$new_name};
  168. #Log3( $new_name, 0,"new_name " .$new_name );
  169. #Log3( $new_name, 0,"old_name " .$old_name );
  170. $modules{MSwitch}{defptr}{$new_name} = $hash_new;
  171. #foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) #
  172. # {
  173. # Log3( $new_name, 0,"dev " .$testdevice );
  174. # Log3( $new_name, 0,"devnhash " .$defs{$testdevice} );
  175. #}
  176. }
  177. ####################
  178. sub MSwitch_Copy ($)
  179. {
  180. my ( $old_name, $new_name ) = @_;
  181. my $hash = $defs{$new_name};
  182. my @areadings =
  183. qw(.Device_Affected .Device_Affected_Details .Device_Events .First_init .Trigger_Whitelist .Trigger_cmd_off .Trigger_cmd_on .Trigger_condition .Trigger_off .Trigger_on .Trigger_time .V_Check Exec_cmd Trigger_device Trigger_log last_event state .sysconf Sys_Extension) ; #alle readings
  184. my $cs = "attr $new_name disable 1";
  185. my $errors = AnalyzeCommandChain( undef, $cs );
  186. if ( defined($errors) )
  187. {
  188. Log3( $new_name, 1, "ERROR $cs" );
  189. }
  190. foreach my $key (@areadings)
  191. {
  192. my $tmp = ReadingsVal( $old_name, $key, 'undef' );
  193. fhem("setreading ".$new_name." ".$key." ".$tmp);
  194. }
  195. MSwitch_LoadHelper($hash);
  196. }
  197. ####################
  198. sub MSwitch_summary($) {
  199. my ( $wname, $name, $room ) = @_;
  200. my $hash = $defs{$name};
  201. my $testroom = AttrVal( $name, 'MSwitch_Inforoom', 'undef' );
  202. if ( $testroom ne $room ) { return; }
  203. my $test = AttrVal( $name, 'comment', '0' );
  204. my $info = AttrVal( $name, 'comment', 'No Info saved at ATTR omment' );
  205. my $image = ReadingsVal( $name, 'state', 'undef' );
  206. my $ret = '';
  207. my $devtitle = '';
  208. my $option = '';
  209. my $html = '';
  210. my $triggerc = 1;
  211. my $timer = 1;
  212. my $trigger = ReadingsVal( $name, 'Trigger_device', 'undef' );
  213. my @devaff = split( / /, MSwitch_makeAffected($hash) );
  214. $option .= "<option value=\"affected devices\">affected devices</option>";
  215. foreach (@devaff)
  216. {
  217. $devtitle .= $_ . ", ";
  218. $option .= "<option value=\"$_\">" . $_ . "</option>";
  219. }
  220. chop($devtitle);
  221. chop($devtitle);
  222. my $affected = "<select style='width: 12em;' title=\"". $devtitle . "\" >". $option. "</select>";
  223. ### time
  224. my $optiontime;
  225. my $devtitletime = '';
  226. my $triggertime = ReadingsVal( $name, 'Trigger_device', 'not defined' );
  227. my $devtime = ReadingsVal( $name, '.Trigger_time', '' );
  228. $devtime =~ s/\[//g;
  229. $devtime =~ s/\]/ /g;
  230. my @devtime = split( /~/, $devtime );
  231. $optiontime .= "<option value=\"Time:\">At: aktiv</option>";
  232. my $count = @devtime;
  233. $devtime[0] =~ s/on/on+cmd1: /g if defined $devtime[0];
  234. $devtime[1] =~ s/off/off+cmd2: /g if defined $devtime[1];
  235. $devtime[2] =~ s/ononly/only cmd1: /g if defined $devtime[2];
  236. $devtime[3] =~ s/offonly/only cmd2: /g if defined $devtime[3];
  237. if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) ne "Notify" )
  238. {
  239. $optiontime .= "<option value=\"$devtime[0]\">" . $devtime[0] . "</option>" if defined $devtime[0];
  240. $optiontime .= "<option value=\"$devtime[1]\">" . $devtime[1] . "</option>" if defined $devtime[1];
  241. }
  242. $optiontime .= "<option value=\"$devtime[2]\">" . $devtime[2] . "</option>" if defined $devtime[2];
  243. $optiontime .= "<option value=\"$devtime[3]\">" . $devtime[3] . "</option>" if defined $devtime[3];
  244. my $affectedtime = '';
  245. if ( $count == 0 )
  246. {
  247. $timer = 0;
  248. $affectedtime =
  249. "<select style='width: 12em;' title=\""
  250. . $devtitletime
  251. . "\" disabled ><option value=\"Time:\">At: inaktiv</option></select>";
  252. }
  253. else
  254. {
  255. chop($devtitletime);
  256. chop($devtitletime);
  257. $affectedtime =
  258. "<select style='width: 12em;' title=\""
  259. . $devtitletime . "\" >"
  260. . $optiontime
  261. . "</select>";
  262. }
  263. if ( $info eq 'No Info saved at ATTR omment' )
  264. {
  265. $ret .=
  266. "<input disabled title=\""
  267. . $info
  268. . "\" name='info' type='button' value='Info' onclick =\"FW_okDialog('"
  269. . $info . "')\">";
  270. }
  271. else
  272. {
  273. $ret .=
  274. "<input title=\""
  275. . $info
  276. . "\" name='info' type='button' value='Info' onclick =\"FW_okDialog('"
  277. . $info . "')\">";
  278. }
  279. if ( $trigger eq 'no_trigger' || $trigger eq 'undef' )
  280. {
  281. $triggerc = 0;
  282. if ( $triggerc != 0 || $timer != 0 )
  283. {
  284. $ret .="<select style='width: 18em;' title=\"\" disabled ><option value=\"Trigger:\">Trigger: inaktiv</option></select>";
  285. }
  286. else
  287. {
  288. $affectedtime = "";
  289. $ret .= "&nbsp;&nbsp;Multiswitchmode (no trigger / no timer)&nbsp;";
  290. }
  291. }
  292. else
  293. {
  294. $ret .= "<select style='width: 18em;' title=\"\" >";
  295. $ret .= "<option value=\"Trigger:\">Trigger: " . $trigger . "</option>";
  296. $ret .=
  297. "<option value=\"Trigger:\">on+cmd1: "
  298. . ReadingsVal( $name, '.Trigger_on', 'not defined' )
  299. . "</option>";
  300. $ret .=
  301. "<option value=\"Trigger:\">off+cmd2: "
  302. . ReadingsVal( $name, '.Trigger_off', 'not defined' )
  303. . "</option>";
  304. $ret .=
  305. "<option value=\"Trigger:\">only cmd1: "
  306. . ReadingsVal( $name, '.Trigger_cmd_on', 'not defined' )
  307. . "</option>";
  308. $ret .=
  309. "<option value=\"Trigger:\">only cmd2: "
  310. . ReadingsVal( $name, '.Trigger_cmd_off', 'not defined' )
  311. . "</option>";
  312. $ret .= "</select>";
  313. }
  314. $ret .= $affectedtime;
  315. $ret .= $affected;
  316. if (ReadingsVal( $name, '.V_Check', 'not defined' ) ne $vupdate)
  317. {
  318. $ret .= "
  319. </td><td informId=\"" . $name . "tmp\">Versionskonflikt !
  320. </td><td informId=\"" . $name . "tmp\">
  321. <div class=\"dval\" informid=\"" . $name . "-state\"></div>
  322. </td><td informId=\"" . $name . "tmp\">
  323. <div informid=\"" . $name . "-state-ts\">(please help)</div>
  324. ";
  325. }
  326. else{
  327. if ( AttrVal( $name, 'disable', "0" ) eq '1' )
  328. {
  329. $ret .= "
  330. </td><td informId=\"" . $name . "tmp\">State:
  331. </td><td informId=\"" . $name . "tmp\">
  332. <div class=\"dval\" informid=\"" . $name . "-state\"></div>
  333. </td><td informId=\"" . $name . "tmp\">
  334. <div informid=\"" . $name . "-state-ts\">disabled</div>
  335. ";
  336. }
  337. else
  338. {
  339. $ret .= "
  340. </td><td informId=\"" . $name . "tmp\">
  341. State: </td><td informId=\"" . $name . "tmp\">
  342. <div class=\"dval\" informid=\"". $name . "-state\">" . ReadingsVal( $name, 'state', '' ) . "</div>
  343. </td><td informId=\"" . $name . "tmp\">";
  344. if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) ne "Notify" )
  345. {
  346. $ret .=
  347. "<div informid=\""
  348. . $name
  349. . "-state-ts\">"
  350. . ReadingsTimestamp( $name, 'state', '' )
  351. . "</div>";
  352. }
  353. else
  354. {
  355. $ret .=
  356. "<div informid=\""
  357. . $name
  358. . "-state-ts\">"
  359. . ReadingsTimestamp( $name, 'state', '' )
  360. . "</div>";
  361. }
  362. }
  363. }
  364. $ret .= "<script>
  365. \$( \"td[informId|=\'" . $name . "\']\" ).attr(\"informId\", \'test\');
  366. \$(document).ready(function(){
  367. \$( \".col3\" ).text( \"\" );
  368. \$( \".devType\" ).text( \"MSwitch Inforoom: Anzeige der Deviceinformationen, Änderungen sind nur in den Details möglich.\" );
  369. });
  370. </script>";
  371. return $ret;
  372. }
  373. ####################
  374. sub MSwitch_LoadHelper($) {
  375. my ($hash) = @_;
  376. my $Name = $hash->{NAME};
  377. my $oldtrigger = ReadingsVal( $Name, 'Trigger_device', 'undef' );
  378. my $devhash = undef;
  379. my $cdev = '';
  380. my $ctrigg = '';
  381. if ( defined $hash->{DEF} )
  382. {
  383. $devhash = $hash->{DEF};
  384. my @dev = split( /#/, $devhash );
  385. $devhash = $dev[0];
  386. ( $cdev, $ctrigg ) = split( / /, $devhash );
  387. if ( defined $ctrigg )
  388. {
  389. $ctrigg =~ s/\.//g;
  390. }
  391. else
  392. {
  393. $ctrigg = ''
  394. }
  395. if ( defined $devhash )
  396. {
  397. $hash->{NOTIFYDEV} = $cdev; # stand aug global ... änderung auf ...
  398. readingsSingleUpdate( $hash, "Trigger_device", $cdev, 0 );
  399. if ( defined $cdev && $cdev ne '' )
  400. {
  401. readingsSingleUpdate( $hash, "Trigger_device", $cdev, 0 );
  402. }
  403. }
  404. else
  405. {
  406. $hash->{NOTIFYDEV} = 'no_trigger';
  407. readingsSingleUpdate( $hash, "Trigger_device", 'no_trigger', 0 );
  408. }
  409. }
  410. if ( !defined $hash->{NOTIFYDEV} || $hash->{NOTIFYDEV} eq 'undef' || $hash->{NOTIFYDEV} eq '' )
  411. {
  412. $hash->{NOTIFYDEV} = 'no_trigger';
  413. }
  414. if ( $oldtrigger ne 'undef' )
  415. {
  416. $hash->{NOTIFYDEV} = $oldtrigger;
  417. readingsSingleUpdate( $hash, "Trigger_device", $oldtrigger, 0 );
  418. }
  419. ####################
  420. MSwitch_set_dev($hash);
  421. #################
  422. if ( AttrVal( $Name, 'MSwitch_Activate_MSwitchcmds', "0" ) eq '1' )
  423. {
  424. addToAttrList('MSwitchcmd');
  425. }
  426. ################erste initialisierung eines devices
  427. if ( ReadingsVal( $Name, '.V_Check', 'undef' ) ne $vupdate && $autoupdate eq "on")
  428. {
  429. MSwitch_VUpdate($hash);
  430. }
  431. ################
  432. if ( ReadingsVal( $Name, '.First_init', 'undef' ) ne 'done' )
  433. {
  434. readingsBeginUpdate($hash);
  435. readingsBulkUpdate( $hash, ".V_Check", $vupdate );
  436. readingsBulkUpdate( $hash, "state", 'off' );
  437. if ( defined $ctrigg && $ctrigg ne '' )
  438. {
  439. readingsBulkUpdate( $hash, ".Device_Events", $ctrigg );
  440. $hash->{DEF} = $cdev;
  441. }
  442. else
  443. {
  444. readingsBulkUpdate( $hash, ".Device_Events", 'no_trigger' );
  445. }
  446. readingsBulkUpdate( $hash, ".Trigger_on", 'no_trigger' );
  447. readingsBulkUpdate( $hash, ".Trigger_off", 'no_trigger' );
  448. readingsBulkUpdate( $hash, ".Trigger_cmd_on", 'no_trigger' );
  449. readingsBulkUpdate( $hash, ".Trigger_cmd_off", 'no_trigger' );
  450. readingsBulkUpdate( $hash, "Trigger_log", 'off' );
  451. readingsBulkUpdate( $hash, ".Device_Affected", 'no_device' );
  452. readingsBulkUpdate( $hash, ".First_init", 'done' );
  453. readingsEndUpdate( $hash, 0 );
  454. # setze ignoreliste
  455. $attr{$Name}{MSwitch_Ignore_Types} = join( " ", @doignore );
  456. # setze attr inforoom
  457. my $testdev = '';
  458. LOOP22:
  459. foreach my $testdevices ( keys %{ $modules{MSwitch}{defptr} } ) #
  460. {
  461. if ( $Name eq $testdevices ) { next LOOP22; }
  462. $testdev = AttrVal( $testdevices, 'MSwitch_Inforoom', '' );
  463. }
  464. if ( $testdev ne '' )
  465. {
  466. $attr{$Name}{MSwitch_Inforoom} = $testdev ,
  467. }
  468. #setze alle attrs
  469. $attr{$Name}{MSwitch_Help} = '0';
  470. $attr{$Name}{MSwitch_Debug} = '0';
  471. $attr{$Name}{MSwitch_Expert} = '0';
  472. $attr{$Name}{MSwitch_Delete_Delays} = '1';
  473. $attr{$Name}{MSwitch_Include_Devicecmds} = '1';
  474. $attr{$Name}{MSwitch_Include_Webcmds} = '0';
  475. $attr{$Name}{MSwitch_Include_MSwitchcmds} = '0';
  476. $attr{$Name}{MSwitch_Include_MSwitchcmds} = '0';
  477. $attr{$Name}{MSwitch_Lock_Quickedit} = '1';
  478. $attr{$Name}{MSwitch_Extensions} = '0';
  479. $attr{$Name}{MSwitch_Mode} = 'Full';
  480. }
  481. # NEU; ZUVOR IN SET
  482. my $testnew = ReadingsVal( $Name, '.Trigger_on', 'undef' );
  483. if ( $testnew eq 'undef' )
  484. {
  485. readingsBeginUpdate($hash);
  486. readingsBulkUpdate( $hash, ".Device_Events", 'no_trigger' );
  487. readingsBulkUpdate( $hash, ".Trigger_on", 'no_trigger' );
  488. readingsBulkUpdate( $hash, ".Trigger_off", 'no_trigger' );
  489. readingsBulkUpdate( $hash, "Trigger_log", 'on' );
  490. readingsBulkUpdate( $hash, ".Device_Affected", 'no_device' );
  491. readingsEndUpdate( $hash, 0 );
  492. }
  493. MSwitch_Createtimer($hash); #Neustart aller timer
  494. }
  495. ####################
  496. sub MSwitch_Define($$) {
  497. my $loglevel = 0;
  498. my ( $hash, $def ) = @_;
  499. my @a = split( "[ \t][ \t]*", $def );
  500. my $name = $a[0];
  501. my $devpointer = $name;
  502. my $devhash = '';
  503. my $old=$hash->{OLDDEF};
  504. $old = '' if !defined $old;
  505. $modules{MSwitch}{defptr}{$devpointer} = $hash;
  506. $hash->{Version_Modul} = $version;
  507. $hash->{Version_Datenstruktur} = $vupdate;
  508. $hash->{Version_autoupdate} = $autoupdate;
  509. if ($init_done && $old ne '')
  510. {
  511. my $timecond = gettimeofday() + 5;
  512. InternalTimer( $timecond, "MSwitch_LoadHelper", $hash);
  513. }
  514. return;
  515. }
  516. ####################
  517. sub MSwitch_Get($$@) {
  518. my ( $hash, $name, $opt, @args ) = @_;
  519. my $ret;
  520. if ( ReadingsVal( $name, '.change', '' ) ne '' )
  521. {
  522. return "Unknown argument, choose one of ";
  523. }
  524. return "\"get $name\" needs at least one argument" unless ( defined($opt) );
  525. ####################
  526. if ( $opt eq 'restore_MSwitch_Data' && $args[0] eq "this_Device" ) {
  527. $ret = MSwitch_backup_this($hash);
  528. return $ret;
  529. }
  530. ####################
  531. if ( $opt eq 'restore_MSwitch_Data' && $args[0] eq "all_Devices" ) {
  532. open( BACKUPDATEI, "<MSwitch_backup_$vupdate.cfg" )
  533. || return "no Backupfile found\n";
  534. close(BACKUPDATEI);
  535. $hash->{helper}{RESTORE_ANSWER} = $hash->{CL};
  536. my $ret = MSwitch_backup_all($hash);
  537. return $ret;
  538. }
  539. ####################
  540. if ( $opt eq 'checkevent' ) {
  541. $ret = MSwitch_Check_Event( $hash, $args[0] );
  542. return $ret;
  543. }
  544. ####################
  545. if ( $opt eq 'get_config' ) {
  546. $ret = MSwitch_Getconfig($hash);
  547. return $ret;
  548. }
  549. ####################
  550. if ( $opt eq 'get_support_site' ) {
  551. $ret = MSwitch_Getsupport($hash);
  552. return $ret;
  553. }
  554. ####################
  555. if ( $opt eq 'get_sysextension' ) {
  556. $ret = MSwitch_Sysextension($hash);
  557. return $ret;
  558. }
  559. ####################
  560. if ( $opt eq 'checkcondition' ) {
  561. my ( $condstring, $eventstring ) = split( /\|/, $args[0] );
  562. $condstring =~ s/#\[dp\]/:/g;
  563. $condstring =~ s/#\[pt\]/./g;
  564. $condstring =~ s/#\[ti\]/~/g;
  565. $condstring =~ s/#\[sp\]/ /g;
  566. $eventstring =~ s/#\[dp\]/:/g;
  567. $eventstring =~ s/#\[pt\]/./g;
  568. $eventstring =~ s/#\[ti\]/~/g;
  569. $eventstring =~ s/#\[sp\]/ /g;
  570. $condstring =~ s/\(DAYS\)/|/g;
  571. my $ret1 = MSwitch_checkcondition( $condstring, $name, $eventstring );
  572. my $condstring1 = $hash->{helper}{conditioncheck};
  573. my $errorstring = $hash->{helper}{conditionerror};
  574. if ( !defined $errorstring ) { $errorstring = '' }
  575. $condstring1 =~ s/</\&lt\;/g;
  576. $condstring1 =~ s/>/\&gt\;/g;
  577. $errorstring =~ s/</\&lt\;/g;
  578. $errorstring =~ s/>/\&gt\;/g;
  579. if ( $errorstring ne '' && $condstring1 ne 'Klammerfehler' )
  580. {
  581. $ret1 =
  582. '<div style="color: #FF0000">Syntaxfehler:<br>'
  583. . $errorstring
  584. . '</div><br>';
  585. }
  586. elsif ( $condstring1 eq 'Klammerfehler' )
  587. {
  588. $ret1 =
  589. '<div style="color: #FF0000">Syntaxfehler:<br>Fehler in der Klammersetzung, die Anzahl öffnender und schliessender Klammern stimmt nicht überein . </div><br>';
  590. }
  591. else
  592. {
  593. if ( $ret1 eq 'true' )
  594. {
  595. $ret1 = 'Bedingung ist Wahr und wird ausgeführt';
  596. }
  597. if ( $ret1 eq 'false' )
  598. {
  599. $ret1 = 'Bedingung ist nicht Wahr und wird nicht ausgeführt';
  600. }
  601. }
  602. $condstring =~ s/~/ /g;
  603. my $condmarker = $condstring1;
  604. my $x = 0; # exit
  605. while ( $condmarker =~ m/(.*)(\d{10})(.*)/ )
  606. {
  607. $x++; # exit
  608. last if $x > 20; # exit
  609. my $timestamp = FmtDateTime($2);
  610. chop $timestamp;
  611. chop $timestamp;
  612. chop $timestamp;
  613. my ( $st1, $st2 ) = split( / /, $timestamp );
  614. $condmarker = $1 . $st2 . $3;
  615. }
  616. $ret ="eingehender String:<br>$condstring<br><br>If Anweisung Perl:<br>$condstring1<br><br>";
  617. $ret .= "If Anweisung Perl Klarzeiten:<br>$condmarker<br><br>"
  618. if $x > 0;
  619. $ret .= $ret1;
  620. my $condsplit = $condmarker;
  621. my $reads ='<br><br>States der geprüften Readings:<br>';
  622. $x = 0; # exit
  623. while ( $condsplit =~ m/(.*')(.*)',\s'(.*)',\s(.*)/ )
  624. {
  625. $x++; # exit
  626. last if $x > 20; # exit
  627. $reads .="Reading: [$2:$3] - Inhalt: ".ReadingsVal( $2, $3, 'undef' );
  628. $reads .="<div style=\"color: #FF0000\">Reading nicht vorhanden !</div>" if (ReadingsVal( $2, $3, 'undef' )) eq "undef";
  629. $reads .="<br>";
  630. $condsplit = $1.$4;
  631. }
  632. $ret .= $reads if $x > 0;
  633. my $err1;
  634. my $err2;
  635. if ( $errorstring ne '' )
  636. {
  637. ( $err1, $err2 ) = split( /near /, $errorstring );
  638. chop $err2;
  639. chop $err2;
  640. $err2 = substr( $err2, 1 );
  641. $ret =~ s/$err2/<span style="color: #FF0000">$err2<\/span>/ig;
  642. }
  643. $hash->{helper}{conditioncheck} = '';
  644. $hash->{helper}{conditionerror} = '';
  645. return "<span style=\"font-size: medium\">" . $ret . "<\/span>";
  646. }
  647. #################################################
  648. if ( $opt eq 'active_timer' && $args[0] eq 'delete' )
  649. {
  650. MSwitch_Clear_timer($hash);
  651. MSwitch_Createtimer($hash);
  652. MSwitch_Delete_Delay( $hash, 'all' );
  653. $ret .="<br>INFO: Alle anstehenden Timer wurden neu berechnet, alle Delays wurden gelöscht<br>";
  654. return $ret;
  655. }
  656. #################################################
  657. if ( $opt eq 'active_timer' && $args[0] eq 'show' )
  658. {
  659. $ret .= "<div nowrap>Systemzeit: ".localtime()."</div><hr>";
  660. $ret .= "<div nowrap>Schaltzeiten (at - kommandos).</div><hr>";
  661. #timer
  662. my $timehash = $hash->{helper}{timer};
  663. foreach my $a ( sort keys %{$timehash} )
  664. {
  665. my $time = FmtDateTime( $hash->{helper}{timer}{$a} );
  666. my @timers = split( /,/, $a );
  667. if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '1' )
  668. {
  669. $ret .=
  670. "<div nowrap>"
  671. . $time
  672. . " switch MSwitch on + execute 'on' cmds</div>";
  673. }
  674. if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '2' )
  675. {
  676. $ret .=
  677. "<div nowrap>"
  678. . $time
  679. . " switch MSwitch off + execute 'off' cmds</div>";
  680. }
  681. if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '3' )
  682. {
  683. $ret .=
  684. "<div nowrap>" . $time . " execute 'on' commands only</div>";
  685. }
  686. if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '4' )
  687. {
  688. $ret .=
  689. "<div nowrap>" . $time . " execute 'off' commands only</div>";
  690. }
  691. if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '5' )
  692. {
  693. $ret .=
  694. "<div nowrap>"
  695. . $time
  696. . " neuberechnung aller Schaltzeiten </div>";
  697. }
  698. }
  699. #delays
  700. $ret .= "<br>&nbsp;<br><div nowrap>aktive Delays:</div><hr>";
  701. $timehash = $hash->{helper}{delays};
  702. foreach my $a ( sort keys %{$timehash} )
  703. {
  704. my $b = substr( $hash->{helper}{delays}{$a}, 0, 10 );
  705. my $time = FmtDateTime($b);
  706. my @timers = split( /#\[tr\]/, $a );
  707. $ret .= "<div nowrap>" . $time . " " . $timers[0] . "</div>";
  708. }
  709. if ( $ret ne "<div nowrap>Schaltzeiten (at - kommandos).</div><hr><div nowrap>aktive Delays:</div><hr>")
  710. {
  711. return $ret;
  712. }
  713. return "<span style=\"font-size: medium\">Keine aktiven Delays/Ats gefunden <\/span>";
  714. }
  715. my $extension='';
  716. if (ReadingsVal( $name, 'Sys_Extension', '') eq 'on')
  717. {
  718. $extension='get_sysextension:noArg';
  719. }
  720. return "Unknown argument $opt, choose one of get_config:noArg active_timer:show,delete restore_MSwitch_Data:this_Device,all_Devices $extension";
  721. }
  722. ####################
  723. sub MSwitch_AsyncOutput ($) {
  724. my ( $client_hash, $text ) = @_;
  725. return $text;
  726. }
  727. ####################
  728. sub MSwitch_Set($@) {
  729. my ( $hash, $name, $cmd, @args ) = @_;
  730. return "" if ( IsDisabled($name) && ($cmd eq 'on' || $cmd eq 'off') );# Return without any further action if the module is disabled
  731. my $execids = "0";
  732. # verry special commands readingactivated
  733. my $special='';
  734. my $cs = ReadingsVal( $name,'.sysconf', 'undef' );
  735. if ($cs ne "undef")
  736. {
  737. $cs =~ s/#\[wa\]/|/g;
  738. $cs =~ s/#\[sp\]/ /g;
  739. $cs =~ s/#\[nl\]/\n/g;
  740. $cs =~ s/#\[se\]/;/g;
  741. $cs =~ s/#\[dp\]/:/g;
  742. $cs =~ s/#\[st\]/'/g;
  743. $cs =~ s/#\[dst\]/\"/g;
  744. $cs =~ s/#\[tab\]/ /g;
  745. $cs =~ s/#\[ko\]/,/g;
  746. $cs =~ s/#.*\n//g;
  747. $cs =~ s/\n//g;
  748. my $return ="no value";
  749. $return = eval($cs);
  750. if ($@)
  751. {
  752. Log3( $name, 1,"$name MSwitch_repeat: ERROR $cs: $@ " . __LINE__ );
  753. #MSwitch_LOG( $name, 5,"$name MSwitch_repeat: ERROR $cs: $@ " . __LINE__ );
  754. }
  755. #MSwitch_LOG( $name, 5,"$name MSwitch_repeat: $return" );
  756. return if $return eq "exit";
  757. }
  758. ############################
  759. if (!defined $args[0]) { $args[0]='';}
  760. if ( $cmd eq 'exec_cmd1' && $args[0] eq 'ID')
  761. {
  762. Log3( $name, 5,"$name: execids werden gesetzt -> ".$args[1] );
  763. $execids = $args[1];
  764. $args[0] = 'ID' ;
  765. }
  766. if ( $cmd eq 'exec_cmd2' && $args[0] eq 'ID')
  767. {
  768. Log3( $name, 5,"$name: execids werden gesetzt als -> ".$args[1] );
  769. $execids = $args[1];
  770. $args[0] = 'ID' ;
  771. }
  772. my $ic ='';
  773. $ic = $hash->{IncommingHandle};
  774. #######################################
  775. if ((($cmd eq 'on') || ($cmd eq 'off')) && ($args[0] ne '') && ($ic ne 'fromnotify'))
  776. {
  777. readingsSingleUpdate( $hash, "Parameter", $args[0], 1 );
  778. if ($cmd eq 'on'){$args[0] = "$name:on_with_Parameter:$args[0]";}
  779. if ($cmd eq 'off'){$args[0] = "$name:off_with_Parameter:$args[0]";}
  780. }
  781. delete( $hash->{IncommingHandle} );
  782. #######################################
  783. if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '4' )
  784. #AUFRUF DEBUGFUNKTIONEN
  785. {
  786. MSwitch_Debug($hash);
  787. }
  788. if ( !exists( $sets{$cmd} ))
  789. {
  790. my @cList;
  791. # Overwrite %sets with setList
  792. my $atts = AttrVal( $name, 'setList', "" );
  793. my %setlist = split( "[: ][ ]*", $atts );
  794. foreach my $k ( sort keys %sets )
  795. {
  796. my $opts = undef;
  797. $opts = $sets{$k};
  798. $opts = $setlist{$k} if ( exists( $setlist{$k} ) );
  799. if ( defined($opts) )
  800. {
  801. push( @cList, $k . ':' . $opts );
  802. }
  803. else
  804. {
  805. push( @cList, $k );
  806. }
  807. }# end foreach
  808. if ( ReadingsVal( $name, '.change', '' ) ne '' )
  809. {
  810. return "Unknown argument $cmd, choose one of ";
  811. }
  812. if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) eq "Notify" )
  813. {
  814. return "Unknown argument $cmd, choose one of active:noArg inactive:noArg del_delays:noArg backup_MSwitch:all_devices fakeevent exec_cmd1 exec_cmd2 exec_cmd1+2 wait reload_timer:noArg";
  815. }
  816. elsif ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) eq "Toggle" )
  817. {
  818. return "Unknown argument $cmd, choose one of on offdel_delays:noArg backup_MSwitch:all_devices fakeevent wait reload_timer:noArg";
  819. }
  820. else
  821. {
  822. return "Unknown argument $cmd, choose one of on off del_delays:noArg backup_MSwitch:all_devices fakeevent exec_cmd1 exec_cmd2 exec_cmd1+2 wait reload_timer:noArg $special";
  823. }
  824. }
  825. if ( AttrVal( $name, 'MSwitch_RandomNumber', '' ) ne '' )
  826. {
  827. # randomnunner erzeugen wenn attr an
  828. MSwitch_Createnumber1($hash);
  829. }
  830. #######################################
  831. if ( $cmd eq 'reload_timer' )
  832. {
  833. MSwitch_Clear_timer($hash);
  834. MSwitch_Createtimer($hash);
  835. return;
  836. }
  837. #######################################
  838. if ( $cmd eq 'VUpdate' )
  839. {
  840. MSwitch_VUpdate($hash);
  841. return;
  842. }
  843. #######################################
  844. if ( $cmd eq 'confchange' )
  845. {
  846. MSwitch_confchange($hash,$args[0]);
  847. return;
  848. }
  849. ###################################
  850. if ( $cmd eq 'clearlog' )
  851. {
  852. MSwitch_clearlog($hash);
  853. return;
  854. }
  855. ##############################
  856. if ( $cmd eq 'wait' )
  857. {
  858. readingsSingleUpdate( $hash, "waiting", ( time + $args[0] ),0 );
  859. return;
  860. }
  861. ##############################
  862. if ( $cmd eq 'inactive' )
  863. {
  864. # setze device auf inaktiv
  865. my $cs = "setstate $name inactive";
  866. my $errors = AnalyzeCommandChain( undef, $cs );
  867. if ( defined($errors) )
  868. {
  869. Log3( $name, 1,"$name MSwitch_Notify: Fehler bei Befehlsausführung $errors -> Comand: $_ " . __LINE__ );
  870. }
  871. return;
  872. }
  873. ##############################
  874. if ( $cmd eq 'aktive' )
  875. {
  876. # setze device auf aktiv
  877. my $cs = "setstate $name active";
  878. my $errors = AnalyzeCommandChain( undef, $cs );
  879. if ( defined($errors) )
  880. {
  881. Log3( $name, 1,"$name MSwitch_Notify: Fehler bei Befehlsausführung $errors -> Comand: $_ ". __LINE__ );
  882. }
  883. return;
  884. }
  885. ##############################
  886. if ( $cmd eq 'fakeevent' )
  887. {
  888. # fakeevent abarbeiten
  889. MSwitch_Check_Event($hash,$args[0]);
  890. return;
  891. }
  892. ##############################
  893. if ( $cmd eq 'exec_cmd1' )
  894. {
  895. # cmd1 abarbeiten
  896. MSwitch_Exec_Notif($hash,'on','nocheck','',$execids) ;
  897. return;
  898. }
  899. ##############################
  900. if ( $cmd eq 'exec_cmd2' )
  901. {
  902. # cmd1 abarbeiten
  903. MSwitch_Exec_Notif($hash,'off','nocheck','',$execids) ;
  904. return;
  905. }
  906. ##############################
  907. if ( $cmd eq 'backup_MSwitch' )
  908. {
  909. # backup erstellen
  910. MSwitch_backup($hash);
  911. return;
  912. }
  913. ##############################
  914. if ( $cmd eq 'del_delays' )
  915. {
  916. # löschen aller delays
  917. MSwitch_Delete_Delay( $hash, $name );
  918. MSwitch_Createtimer($hash);
  919. return;
  920. }
  921. ##############################
  922. if ( $cmd eq 'saveconfig' )
  923. {
  924. # configfile speichern
  925. $args[0] =~ s/\[s\]/ /g;
  926. MSwitch_saveconf( $hash, $args[0] );
  927. return;
  928. }
  929. ##############################
  930. if ( $cmd eq 'savesys' )
  931. {
  932. # sysfile speichern
  933. MSwitch_savesys( $hash, $args[0] );
  934. return;
  935. }
  936. ##############################
  937. if ( $cmd eq "addevent" )
  938. {
  939. # event manuell zufügen
  940. my $devName = ReadingsVal( $name, 'Trigger_device', '' );
  941. $args[0] =~ s/~/ /g;
  942. my @newevents = split( /,/, $args[0] );
  943. if ( ReadingsVal( $name, 'Trigger_device', '' ) eq "all_events" )
  944. {
  945. foreach (@newevents)
  946. {
  947. $hash->{helper}{events}{all_events}{$_} = "on";
  948. }
  949. }
  950. else
  951. {
  952. foreach (@newevents)
  953. {
  954. $hash->{helper}{events}{$devName}{$_} = "on";
  955. }
  956. }
  957. my $events = '';
  958. my $eventhash = $hash->{helper}{events}{$devName};
  959. foreach my $name ( keys %{$eventhash} )
  960. {
  961. $events = $events . $name . '#[tr]';
  962. }
  963. chop($events);
  964. chop($events);
  965. chop($events);
  966. chop($events);
  967. chop($events);
  968. readingsSingleUpdate( $hash, ".Device_Events", $events, 1 );
  969. return;
  970. }
  971. ##############################
  972. if ( $cmd eq "add_device" )
  973. {
  974. #add device
  975. MSwitch_Add_Device( $hash, $args[0] );
  976. return;
  977. }
  978. ##############################
  979. if ( $cmd eq "del_device" )
  980. {
  981. #del device
  982. MSwitch_Del_Device( $hash, $args[0] );
  983. return;
  984. }
  985. ##############################
  986. if ( $cmd eq "del_trigger" )
  987. {
  988. #lösche trigger
  989. MSwitch_Delete_Triggermemory($hash);
  990. return;
  991. }
  992. ##############################
  993. if ( $cmd eq "filter_trigger" )
  994. {
  995. #filter to trigger
  996. MSwitch_Filter_Trigger($hash);
  997. return;
  998. }
  999. ##############################
  1000. if ( $cmd eq "set_trigger" )
  1001. {
  1002. # setze trigger
  1003. chop( $args[1], $args[2], $args[3], $args[4], $args[5] );
  1004. my $triggertime = 'on'
  1005. . $args[1] . '~off'
  1006. . $args[2]
  1007. . '~ononly'
  1008. . $args[3]
  1009. . '~offonly'
  1010. . $args[4];
  1011. my $oldtrigger = ReadingsVal( $name, 'Trigger_device', '' );
  1012. readingsSingleUpdate( $hash, "Trigger_device", $args[0], '1' );
  1013. readingsSingleUpdate( $hash, ".Trigger_condition", $args[5], 0 );
  1014. if ( !defined $args[6] )
  1015. {
  1016. readingsDelete( $hash, '.Trigger_Whitelist' );
  1017. }
  1018. else
  1019. {
  1020. readingsSingleUpdate( $hash, ".Trigger_Whitelist", $args[6], 0 );
  1021. }
  1022. my $testtrig = ReadingsVal( $name, 'Trigger_device', '' );
  1023. if ( $oldtrigger ne $args[0] )
  1024. {
  1025. # lösche alle events
  1026. MSwitch_Delete_Triggermemory($hash);
  1027. }
  1028. if ( $args[1] ne '' || $args[2] ne '' || $args[3] ne '' || $args[4] ne '' )
  1029. {
  1030. readingsSingleUpdate( $hash, ".Trigger_time", $triggertime, 0 );
  1031. MSwitch_Createtimer($hash);
  1032. }
  1033. else
  1034. {
  1035. readingsSingleUpdate( $hash, ".Trigger_time", '', 0 );
  1036. MSwitch_Clear_timer($hash);
  1037. }
  1038. $hash->{helper}{events}{ $args[0] }{'no_trigger'} = "on";
  1039. if ( $args[0] ne 'no_trigger' )
  1040. {
  1041. if ( $args[0] eq "all_events" )
  1042. {
  1043. delete( $hash->{NOTIFYDEV} );
  1044. if ( ReadingsVal( $name, '.Trigger_Whitelist', '' ) ne '' )
  1045. {
  1046. $hash->{NOTIFYDEV} =
  1047. ReadingsVal( $name, '.Trigger_Whitelist', '' );
  1048. }
  1049. }
  1050. else
  1051. {
  1052. $hash->{NOTIFYDEV} = $args[0];
  1053. my $devices = MSwitch_makeAffected($hash);
  1054. $hash->{DEF} = $args[0] . ' # ' . $devices;
  1055. }
  1056. }
  1057. else
  1058. {
  1059. $hash->{NOTIFYDEV} = 'no_trigger';
  1060. delete $hash->{DEF};
  1061. }
  1062. return;
  1063. }
  1064. ##############################
  1065. if ( $cmd eq "trigger" )
  1066. {
  1067. # setze trigger events
  1068. my $triggeron = '';
  1069. my $triggeroff = '';
  1070. my $triggercmdon = '';
  1071. my $triggercmdoff = '';
  1072. $args[0] =~ s/~/ /g;
  1073. $args[1] =~ s/~/ /g;
  1074. $args[2] =~ s/~/ /g;
  1075. $args[3] =~ s/~/ /g;
  1076. $args[4] =~ s/~/ /g;
  1077. if ( !defined $args[1] ) { $args[1] = "" }
  1078. if ( !defined $args[3] ) { $args[3] = "" }
  1079. $triggeron = $args[0];
  1080. $triggeroff = $args[1];
  1081. if ( !defined $args[3] ) { $args[3] = "" }
  1082. if ( !defined $args[4] ) { $args[4] = "" }
  1083. $triggercmdon = $args[3];
  1084. $triggercmdoff = $args[4];
  1085. readingsBeginUpdate($hash);
  1086. readingsBulkUpdate( $hash, ".Trigger_on", $triggeron );
  1087. readingsBulkUpdate( $hash, ".Trigger_off", $triggeroff );
  1088. if ( $args[2] eq 'nein' )
  1089. {
  1090. readingsBulkUpdate( $hash, "Trigger_log", 'off' );
  1091. }
  1092. if ( $args[2] eq 'ja' )
  1093. {
  1094. readingsBulkUpdate( $hash, "Trigger_log", 'on' );
  1095. }
  1096. readingsBulkUpdate( $hash, ".Trigger_cmd_on", $triggercmdon );
  1097. readingsBulkUpdate( $hash, ".Trigger_cmd_off", $triggercmdoff );
  1098. readingsEndUpdate( $hash, 0 );
  1099. return;
  1100. }
  1101. ##############################
  1102. if ( $cmd eq "devices" )
  1103. {
  1104. # setze devices
  1105. my $devices = $args[0];
  1106. if ( $devices eq 'null' )
  1107. {
  1108. readingsSingleUpdate( $hash, ".Device_Affected", 'no_device', 0 );
  1109. return;
  1110. }
  1111. my @olddevices = split( /,/, ReadingsVal( $name, '.Device_Affected', 'no_device' ) );
  1112. my @devices = split( /,/, $args[0] );
  1113. my $addolddevice = '';
  1114. foreach (@devices)
  1115. {
  1116. my $testdev = $_;
  1117. LOOP6:foreach my $olddev (@olddevices) {
  1118. my $oldcmd = '';
  1119. my $oldname = '';
  1120. ( $oldname, $oldcmd ) = split( /-AbsCmd/, $olddev );
  1121. if ( !defined $oldcmd ) { $oldcmd = '' }
  1122. if ( $oldcmd eq '1' ) { next LOOP6 }
  1123. if ( $oldname eq $testdev )
  1124. {
  1125. $addolddevice = $addolddevice . $olddev . ',';
  1126. }
  1127. }
  1128. $_ = $_ . '-AbsCmd1';
  1129. }
  1130. chop($addolddevice);
  1131. $devices = join( ',', @devices ) . ',' . $addolddevice;
  1132. my @sortdevices = split( /,/, $devices );
  1133. @sortdevices = sort @sortdevices;
  1134. $devices = join( ',', @sortdevices );
  1135. readingsSingleUpdate( $hash, ".Device_Affected", $devices, 0 );
  1136. $devices = MSwitch_makeAffected($hash);
  1137. if ( defined $hash->{DEF} )
  1138. {
  1139. my $devhash = $hash->{DEF};
  1140. my @dev = split( /#/, $devhash );
  1141. $hash->{DEF} = $dev[0] . ' # ' . $devices;
  1142. }
  1143. else
  1144. {
  1145. $hash->{DEF} = ' # ' . $devices;
  1146. }
  1147. return;
  1148. }
  1149. ##############################
  1150. if ( $cmd eq "details" )
  1151. {
  1152. # setze devices details
  1153. #Log3( 'test', 0, 'array: '.$args[0] );
  1154. $args[0] = urlDecode( $args[0] );
  1155. $args[0] =~ s/#\[pr\]/%/g;
  1156. #Log3( 'test', 0, 'array: '.$args[0] );
  1157. my @devices =split( /,/, ReadingsVal( $name, '.Device_Affected', '' ) );
  1158. my @inputcmds = split( /#\[ND\]/, $args[0] );
  1159. my $counter = 0;
  1160. my $error = '';
  1161. my $key = '';
  1162. my $savedetails = '';
  1163. LOOP10: foreach (@devices)
  1164. {
  1165. if ( $inputcmds[$counter] eq '' ) { next LOOP10; }
  1166. #new
  1167. my @devicecmds = split( /#\[NF\]/, $inputcmds[$counter] );
  1168. $savedetails = $savedetails . $_ . '#[NF]';
  1169. $savedetails = $savedetails . $devicecmds[0] . '#[NF]';
  1170. $savedetails = $savedetails . $devicecmds[1] . '#[NF]';
  1171. $savedetails = $savedetails . $devicecmds[2] . '#[NF]';
  1172. $savedetails = $savedetails . $devicecmds[3] . '#[NF]';
  1173. $savedetails = $savedetails . $devicecmds[4] . '#[NF]';
  1174. $savedetails = $savedetails . $devicecmds[5] . '#[NF]';
  1175. $savedetails = $savedetails . $devicecmds[7] . '#[NF]';
  1176. $savedetails = $savedetails . $devicecmds[6] . '#[NF]';
  1177. if ( defined $devicecmds[8] )
  1178. {
  1179. $savedetails = $savedetails . $devicecmds[8] . '#[NF]';
  1180. }
  1181. else
  1182. {
  1183. $savedetails = $savedetails . '' . '#[NF]';
  1184. }
  1185. if ( defined $devicecmds[9] )
  1186. {
  1187. $savedetails = $savedetails . $devicecmds[9] . '#[NF]';
  1188. }
  1189. else
  1190. {
  1191. $savedetails = $savedetails . '' . '#[NF]';
  1192. }
  1193. if ( defined $devicecmds[10] )
  1194. {
  1195. $savedetails = $savedetails . $devicecmds[10] . '#[NF]';
  1196. }
  1197. else
  1198. {
  1199. $savedetails = $savedetails . '' . '#[NF]';
  1200. }
  1201. if ( defined $devicecmds[11] )
  1202. {
  1203. $savedetails = $savedetails . $devicecmds[11] . '#[NF]';
  1204. }
  1205. else
  1206. {
  1207. $savedetails = $savedetails . '' . '#[NF]';
  1208. }
  1209. # priority
  1210. if ( defined $devicecmds[12] && $devicecmds[12] ne 'undefined')
  1211. {
  1212. $savedetails = $savedetails . $devicecmds[12] . '#[NF]';
  1213. }
  1214. else
  1215. {
  1216. $savedetails = $savedetails . '1' . '#[NF]';
  1217. }
  1218. # id
  1219. if ( defined $devicecmds[13] && $devicecmds[13] ne 'undefined')
  1220. {
  1221. $savedetails = $savedetails . $devicecmds[13] . '#[ND]';
  1222. }
  1223. else
  1224. {
  1225. $savedetails = $savedetails . '0' . '#[ND]';
  1226. }
  1227. $counter++;
  1228. }
  1229. chop($savedetails);
  1230. chop($savedetails);
  1231. chop($savedetails);
  1232. chop($savedetails);
  1233. chop($savedetails);
  1234. # ersetzung sonderzeichen etc mscode
  1235. # auskommentierte wurden bereits dur jscript ersetzt
  1236. #$args[0] = urlDecode( $args[0] );
  1237. $savedetails =~ s/\n/#[nl]/g;
  1238. $savedetails =~ s/\t/ /g;
  1239. $savedetails =~ s/ /#[sp]/g;
  1240. $savedetails =~ s/\\/#[bs]/g;
  1241. $savedetails =~ s/,/#[ko]/g;
  1242. $savedetails =~ s/^#\[/#[eo]/g;
  1243. $savedetails =~ s/^#\]/#[ec]/g;
  1244. $savedetails =~ s/\|/#[wa]/g;
  1245. $savedetails =~ s/\|/#[ti]/g;
  1246. #$savedetails =~ s/%/#[ti]/g;
  1247. readingsSingleUpdate( $hash, ".Device_Affected_Details", $savedetails,0 );
  1248. return;
  1249. }
  1250. ##################################################################
  1251. my $update = '';
  1252. # unbedingt überarbeiten !!!
  1253. my @testdetails = qw(_on _off _onarg _offarg _playback _record _timeon _timeoff _conditionon _conditionoff);
  1254. my @testdetailsstandart =( 'no_action', 'no_action', '', '', 'nein', 'nein', 0, 0, '', '' );
  1255. ##################################
  1256. #neu ausführung on/off
  1257. if ( $cmd eq "off" || $cmd eq "on")
  1258. {
  1259. # ausführen des off befehls
  1260. my $zweig = 'nicht definiert';
  1261. $zweig = "cmd1" if $cmd eq "on";
  1262. $zweig = "cmd2" if $cmd eq "off";
  1263. MSwitch_Safemode($hash);
  1264. MSwitch_LOG( $name, 5, "----------------------------------------" );
  1265. MSwitch_LOG( $name, 5, "$name: aufruf on/off -> $cmd" );
  1266. MSwitch_LOG( $name, 5, "----------------------------------------" );
  1267. my @cmdpool;
  1268. my %devicedetails = MSwitch_makeCmdHash($name);
  1269. my @devices = split( /,/, ReadingsVal( $name, '.Device_Affected', '' ) );
  1270. # liste anpassen ( reihenfolge ) wenn expert = 1
  1271. @devices = MSwitch_priority($hash,$execids,@devices);
  1272. LOOP1: foreach my $device (@devices)
  1273. {
  1274. MSwitch_LOG( $name, 5, "$name: angesprochener zweig ".$zweig." -> device -> -".$device."-" );
  1275. # teste auf on kommando
  1276. next LOOP1 if $device eq "no_device" ;
  1277. my @devicesplit = split( /-AbsCmd/, $device );
  1278. my $devicenamet = $devicesplit[0];
  1279. my $count = 0;
  1280. foreach my $testset (@testdetails)
  1281. {
  1282. if ( !defined( $devicedetails{ $device . $testset } ) )
  1283. {
  1284. my $key = '';
  1285. $key = $device . $testset;
  1286. $devicedetails{$key} = $testdetailsstandart[$count];
  1287. }
  1288. $count++;
  1289. }
  1290. my $key = $device . "_".$cmd;
  1291. my $timerkey = $device . "_time".$cmd;
  1292. my $testtstate = $devicedetails{$timerkey};
  1293. # teste auf delayinhalt
  1294. MSwitch_LOG( $name, 5, "$name: teste auf timerstatus -> $testtstate" );
  1295. $testtstate =~ s/[A-Za-z0-9#\.\-_]//g;
  1296. if ( $testtstate eq "[:]" || $testtstate eq "[\$:]")
  1297. {
  1298. $devicedetails{$timerkey} =
  1299. eval MSwitch_Checkcond_state( $devicedetails{$timerkey}, $name );
  1300. if ($devicedetails{$timerkey} =~ m/[0-9]\d:[0-9]\d:[0-9]\d/)
  1301. {
  1302. MSwitch_LOG( $name, 5,"$name: format ok ");
  1303. my $hdel = ( substr( $devicedetails{$timerkey}, 0, 2 ) ) * 3600;
  1304. my $mdel = ( substr( $devicedetails{$timerkey}, 3, 2 ) ) * 60;
  1305. my $sdel = ( substr( $devicedetails{$timerkey}, 6, 2 ) ) * 1;
  1306. $devicedetails{$timerkey} = $hdel + $mdel + $sdel;
  1307. }
  1308. else
  1309. {
  1310. MSwitch_LOG( $name, 1,"$name: ERROR Timerformat ".$devicedetails{$timerkey}." fehlerhaf ");
  1311. $devicedetails{$timerkey} = 0;
  1312. }
  1313. }
  1314. MSwitch_LOG( $name, 5, "$name: timerstatus nach test -> ".$devicedetails{$timerkey} );
  1315. # suche befehl
  1316. if ( $devicedetails{$key} ne "" && $devicedetails{$key} ne "no_action" ) #befehl gefunden
  1317. {
  1318. my $cs='';
  1319. $cs ="set $devicenamet $devicedetails{$device.'_off'} $devicedetails{$device.'_offarg'}" if $cmd eq "off";
  1320. $cs ="set $devicenamet $devicedetails{$device.'_on'} $devicedetails{$device.'_onarg'}" if $cmd eq "on";
  1321. if ( $devicenamet eq 'FreeCmd' )
  1322. {
  1323. $cs = "$devicedetails{$device.'_'.$cmd.'arg'}";
  1324. $cs = MSwitch_makefreecmd($hash,$cs);
  1325. }
  1326. MSwitch_LOG( $name, 5, "$name: befehl gefunden -> ".$cs );
  1327. MSwitch_LOG( $name, 5, "$name: teste auf delay -> ".$devicedetails{$timerkey} );
  1328. my $conditionkey = $device . "_condition".$cmd;
  1329. MSwitch_LOG( $name, 5, "$name: TIMERKEY -> ".$devicedetails{$timerkey} );
  1330. if ( $devicedetails{$timerkey} eq "0" || $devicedetails{$timerkey} eq "" )
  1331. {
  1332. # $conditionkey = $device . "_conditionoff";
  1333. MSwitch_LOG( $name, 5, "$name: teste auf condition -> aufruf sub checkcondition mit ".$devicedetails{$conditionkey} )if $devicedetails{$conditionkey} ne '';
  1334. MSwitch_LOG( $name, 5, "$name: teste auf condition -> wird nicht getestet - kein eintrag".$devicedetails{$conditionkey} )if $devicedetails{$conditionkey} eq '';
  1335. my $execute ="true";
  1336. $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $args[0] ) if $devicedetails{$conditionkey} ne '';
  1337. MSwitch_LOG( $name, 5, "$name: ergebniss condition -> ergebniss ".$execute );
  1338. if ( $execute eq 'true' )
  1339. {
  1340. $cs =~ s/\$NAME/$hash->{helper}{eventfrom}/;
  1341. $cs =~ s/\$SELF/$name/;
  1342. MSwitch_LOG( $name, 5, "$name: in exec-cmdpool geschrieben ->".$cs );
  1343. push @cmdpool, $cs . '|' . $device;
  1344. $update = $device . ',' . $update;
  1345. }
  1346. }
  1347. else
  1348. {
  1349. MSwitch_LOG( $name, 5, "$name: teste auf condition -> keine vorhanden " );
  1350. if ( AttrVal( $name, 'MSwitch_RandomTime', '' ) ne '' && $devicedetails{$timerkey} eq '[random]' )
  1351. {
  1352. MSwitch_LOG( $name, 5, "$name: randomtimer gefunden attr gesetzt -> ".$devicedetails{$timerkey} );
  1353. $devicedetails{$timerkey} =MSwitch_Execute_randomtimer($hash);
  1354. # ersetzt $devicedetails{$timerkey} gegen randomtimer
  1355. MSwitch_LOG( $name, 5, "$name: timerd ersetzt-> ".$devicedetails{$timerkey} );
  1356. }
  1357. elsif ( AttrVal( $name, 'MSwitch_RandomTime', '' ) eq '' && $devicedetails{$timerkey} eq '[random]' )
  1358. {
  1359. MSwitch_LOG( $name, 5, "$name: randomtimer gefunden attr nicht gesetzt -> 0" );
  1360. $devicedetails{$timerkey} = 0;
  1361. }
  1362. # ?
  1363. my $execute ="true";
  1364. # conditiontest nur dann, wenn cond-test nicht nur nach verzögerung
  1365. if ($devicedetails{$device . "_delayat".$cmd} ne "delay2" && $devicedetails{$device . "_delayat".$cmd} ne "at02")
  1366. {
  1367. MSwitch_LOG( $name, 5, "$name: checkcondition bei gefundem delay -> ".$devicedetails{$device . "_delayat".$cmd} );
  1368. $execute = MSwitch_checkcondition( $devicedetails{$conditionkey},$name, $args[0] ) ;
  1369. MSwitch_LOG( $name, 5, "$name: ergebniss checkcondition für delay-> ".$execute );
  1370. }
  1371. MSwitch_LOG( $name, 5,"$name: ----------------- Delay -> ".$devicedetails{$timerkey} );
  1372. if ( $execute eq 'true' )
  1373. {
  1374. MSwitch_LOG( $name, 5,"$name: conidtion ok - Befehl mt at/delay wird ausgefuehrt -> ".$cs );
  1375. my $delaykey = $device . "_delayat".$cmd;
  1376. my $delayinhalt = $devicedetails{$delaykey};
  1377. my $delaykey1 = $device . "_delayat".$cmd."org";
  1378. my $teststateorg = $devicedetails{$delaykey1};
  1379. MSwitch_LOG( $name, 5,"$name: delaykey -> ".$delaykey );
  1380. MSwitch_LOG( $name, 5,"$name: delaykeyinhalt -> ".$delayinhalt);
  1381. MSwitch_LOG( $name, 5,"$name: delaykeyinhaltorg -> ".$teststateorg );
  1382. if ( $delayinhalt eq 'at0' || $delayinhalt eq 'at1' )
  1383. {
  1384. MSwitch_LOG( $name, 5,"$name: delay mit at erkannt -> ".$devicedetails{$timerkey} );
  1385. MSwitch_LOG( $name, 5,"$name: delay wird ersetzt " );
  1386. $devicedetails{$timerkey} = MSwitch_replace_delay( $hash, $teststateorg );
  1387. Log3( $name, 5,"$name: delay ersetzt -> ".$devicedetails{$timerkey} );
  1388. }
  1389. if ( $delayinhalt eq 'at1' || $delayinhalt eq 'delay0' )
  1390. {
  1391. MSwitch_LOG( $name, 5,"$name: delay ohne zusatzprüfung erkannt -> ".$delayinhalt );
  1392. $conditionkey = 'nocheck';
  1393. MSwitch_LOG( $name, 5,"$name: conditionkey ersetzt -> ".$conditionkey );
  1394. }
  1395. my $timecond = gettimeofday() + $devicedetails{$timerkey};
  1396. my $msg =
  1397. $cs . "#[tr]"
  1398. . $name . "#[tr]"
  1399. . $conditionkey . "#[tr]#[tr]"
  1400. . $timecond . "#[tr]"
  1401. . $device;
  1402. # variabelersetzung
  1403. $msg =~ s/\$NAME/$hash->{helper}{eventfrom}/;
  1404. $msg =~ s/\$SELF/$name/;
  1405. $hash->{helper}{delays}{$msg} = $timecond;
  1406. InternalTimer( $timecond, "MSwitch_Restartcmd", $msg );
  1407. MSwitch_LOG( $name, 5,"$name: verzögerte befehl gesetzt -> ".$timecond." : ".$msg );
  1408. }
  1409. }
  1410. }
  1411. }
  1412. if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) ne "Notify" )
  1413. {
  1414. readingsSingleUpdate( $hash, "state", $cmd, 1 );
  1415. }
  1416. else
  1417. {
  1418. readingsSingleUpdate( $hash, "state", 'active', 1 );
  1419. }
  1420. MSwitch_EventBulk($hash,$args[0],'0');
  1421. my $anzahl = @cmdpool;
  1422. MSwitch_LOG( $name, 5,"$name: anzahl der auszufuehrenden befehle -> ".$anzahl );
  1423. MSwitch_LOG( $name, 5,"$name: uebergabe an sub execute " ) if $anzahl > 0;
  1424. MSwitch_Cmd( $hash, @cmdpool ) if $anzahl > 0;
  1425. return;
  1426. }
  1427. return;
  1428. }
  1429. ###################################
  1430. sub MSwitch_Cmd(@) {
  1431. my ( $hash, @cmdpool ) = @_;
  1432. my $Name = $hash->{NAME};
  1433. my %devicedetails = MSwitch_makeCmdHash($Name);
  1434. foreach my $cmds (@cmdpool)
  1435. {
  1436. MSwitch_LOG( $Name, 5,"$Name: execute -> ".$cmds );
  1437. my @cut = split( /\|/, $cmds );
  1438. $cmds = $cut[0];
  1439. # ersetze platzhakter vor ausführung
  1440. #change # $cmds =~ s/#\[wa\]/|/g; #neu
  1441. my $device = $cut[1];
  1442. my $toggle = '';
  1443. if ( $cmds =~ m/set (.*)(MSwitchtoggle)(.*)/ )
  1444. {
  1445. MSwitch_LOG( $Name, 5,"$Name: togglemode erkannt -> ".$cmds );
  1446. $toggle = $cmds;
  1447. $cmds = MSwitch_toggle( $hash, $cmds );
  1448. }
  1449. if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeatcount' } ne '')
  1450. {
  1451. MSwitch_LOG( $Name, 5,"$Name: teste auf repeatcount -> ".$devicedetails{ $device . '_repeatcount' } );
  1452. my $x =0;
  1453. while ( $devicedetails{ $device . '_repeatcount' } =~ m/\[(.*)\:(.*)\]/ )
  1454. {
  1455. $x++; # exit
  1456. last if $x > 20; # exitg
  1457. my $setmagic = ReadingsVal( $1, $2, 0 );
  1458. $devicedetails{ $device . '_repeatcount' } = $setmagic
  1459. }
  1460. MSwitch_LOG( $Name, 5,"$Name: repeatcount nach setmagicersetzung -> ".$devicedetails{ $device . '_repeatcount' } );
  1461. }
  1462. if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeattime' } ne '')
  1463. {
  1464. MSwitch_LOG( $Name, 5,"$Name: teste auf repeattime -> ".$devicedetails{ $device . '_repeattime' } );
  1465. my $x =0;
  1466. while ( $devicedetails{ $device . '_repeattime' } =~ m/\[(.*)\:(.*)\]/ )
  1467. {
  1468. $x++; # exit
  1469. last if $x > 20; # exitg
  1470. my $setmagic = ReadingsVal( $1, $2, 0 );
  1471. $devicedetails{ $device . '_repeattime' } = $setmagic
  1472. }
  1473. MSwitch_LOG( $Name, 5,"$Name: _repeattime nach setmagicersetzung -> ".$devicedetails{ $device . '_repeattime' } );
  1474. }
  1475. if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1'&& $devicedetails{ $device . '_repeatcount' } > 0 && $devicedetails{ $device . '_repeattime' } > 0 )
  1476. {
  1477. my $i;
  1478. for ( $i = 0; $i <= $devicedetails{ $device . '_repeatcount' };$i++)
  1479. {
  1480. my $msg = $cmds . "|" . $Name;
  1481. if ( $toggle ne '' )
  1482. {
  1483. $msg = $toggle . "|" . $Name;
  1484. }
  1485. my $timecond = gettimeofday()+(($i+1)*$devicedetails{ $device . '_repeattime' } );
  1486. $msg = $msg."|".$timecond;
  1487. $hash->{helper}{repeats}{$timecond} = "$msg";
  1488. MSwitch_LOG( $Name, 5,"$Name: repeat gesetzt -> ".$timecond." : ".$msg );
  1489. InternalTimer( $timecond, "MSwitch_repeat", $msg );
  1490. }
  1491. }
  1492. my $todec = $cmds;
  1493. $cmds = MSwitch_dec($hash,$todec);
  1494. MSwitch_LOG( $Name, 5,"$Name: cmd nach decodierung -> ".$cmds );
  1495. ############################
  1496. # debug2 mode , kein execute
  1497. if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '2' )
  1498. {
  1499. MSwitch_LOG( $Name, 5,"$Name: exec comand -> ".$cmds );
  1500. }
  1501. else
  1502. {
  1503. if ( $cmds =~ m/{.*}/ )
  1504. {
  1505. MSwitch_LOG( $Name, 5,"$Name: exec als perlcode -> ".$cmds );
  1506. eval($cmds);
  1507. if ($@)
  1508. {
  1509. MSwitch_LOG( $Name, 1,"$Name MSwitch_Set: ERROR $cmds: $@ " . __LINE__ );
  1510. }
  1511. }
  1512. else
  1513. {
  1514. MSwitch_LOG( $Name, 5,"$Name: execute als fhemcode -> ".$cmds );
  1515. my $errors = AnalyzeCommandChain( undef, $cmds );
  1516. if ( defined($errors) )
  1517. {
  1518. MSwitch_LOG( $Name, 1, "$Name MSwitch_Set: ERROR $cmds: $errors " . __LINE__ );
  1519. }
  1520. }
  1521. }
  1522. #############################
  1523. }
  1524. my $showpool = join( ',', @cmdpool );
  1525. if (length($showpool) > 100 ){ $showpool = substr($showpool,0,100).'....';}
  1526. readingsSingleUpdate( $hash, "Exec_cmd", $showpool, 1 ) if $showpool ne '';
  1527. }
  1528. ####################
  1529. sub MSwitch_toggle($$) {
  1530. my ( $hash, $cmds ) = @_;
  1531. my $Name = $hash->{NAME};
  1532. $cmds =~ m/(set) (.*)( )MSwitchtoggle (.*)/;
  1533. my @tcmd = split( /\//, $4 );
  1534. if ( !defined $tcmd[2] ) { $tcmd[2] = 'state' }
  1535. if ( !defined $tcmd[3] ) { $tcmd[3] = $tcmd[0] }
  1536. if ( !defined $tcmd[4] ) { $tcmd[4] = $tcmd[1] }
  1537. my $cmd1 = $1 . " " . $2 . " " . $tcmd[0];
  1538. my $cmd2 = $1 . " " . $2 . " " . $tcmd[1];
  1539. my $chk1 = $tcmd[0];
  1540. my $chk2 = $tcmd[1];
  1541. my $testnew = ReadingsVal( $2, $tcmd[2], 'undef' );
  1542. if ( $testnew =~ m/$tcmd[3]/ )
  1543. {
  1544. $cmds = $cmd2;
  1545. }
  1546. elsif ( $testnew =~ m/$tcmd[4]/ )
  1547. {
  1548. $cmds = $cmd1;
  1549. }
  1550. else
  1551. {
  1552. $cmds = $cmd1;
  1553. }
  1554. return $cmds;
  1555. }
  1556. ##############################
  1557. sub MSwitch_Attr(@) {
  1558. my ( $cmd, $name, $aName, $aVal ) = @_;
  1559. my $hash = $defs{$name};
  1560. if ( $aName eq 'MSwitch_Debug' && ( $aVal == 0 || $aVal == 1 || $aVal == 2 || $aVal == 3 ) )
  1561. {
  1562. delete( $hash->{READINGS}{Device_Affected} );
  1563. delete( $hash->{READINGS}{Device_Affected_Details} );
  1564. delete( $hash->{READINGS}{Device_Events} );
  1565. }
  1566. if ( $aName eq 'MSwitch_RandomTime' && $aVal ne '' )
  1567. {
  1568. if ( $aVal !~ m/([0-9]{2}:[0-9]{2}:[0-9]{2}-[0-9]{2}:[0-9]{2}:[0-9]{2})/ )
  1569. {
  1570. return 'wrong syntax !<br>the syntax must be: HH:MM:SS-HH:MM:SS';
  1571. }
  1572. else
  1573. {
  1574. $aVal =~ s/\://g;
  1575. my @test = split( /-/, $aVal );
  1576. if ( $test[0] >= $test[1] )
  1577. {
  1578. return'fist '. $test[0]. ' parameter must be lower than second parameter '. $test[1];
  1579. }
  1580. }
  1581. return;
  1582. }
  1583. if ( $cmd eq 'set' && $aName eq 'disable' && $aVal == 1 )
  1584. {
  1585. $hash->{NOTIFYDEV} = 'no_trigger';
  1586. MSwitch_Delete_Delay($hash,'all');
  1587. MSwitch_Clear_timer($hash);
  1588. }
  1589. if ( $cmd eq 'set' && $aName eq 'disable' && $aVal == 0 )
  1590. {
  1591. delete( $hash->{helper}{savemodeblock} );
  1592. delete( $hash->{READINGS}{Safemode} );
  1593. MSwitch_Createtimer($hash);
  1594. }
  1595. if ($cmd eq 'set'&& $aName eq 'disable'&& $aVal == 0 && ReadingsVal($name, 'Trigger_device', 'no_trigger') ne'no_trigger' )
  1596. {
  1597. $hash->{NOTIFYDEV} =
  1598. ReadingsVal( $name, 'Trigger_device', 'no_trigger' );
  1599. }
  1600. if ($cmd eq 'del'&& $aName eq 'disable'&& ReadingsVal($name, 'Trigger_device', 'no_trigger') ne 'no_trigger' )
  1601. {
  1602. $hash->{NOTIFYDEV} =
  1603. ReadingsVal( $name, 'Trigger_device', 'no_trigger' );
  1604. }
  1605. if ($aName eq 'MSwitch_Activate_MSwitchcmds' && $aVal == 1 )
  1606. {
  1607. addToAttrList('MSwitchcmd');
  1608. }
  1609. if ($aName eq 'MSwitch_Debug' && $aVal eq '0' )
  1610. {
  1611. unlink ("./log/MSwitch_debug_$name.log") ;
  1612. }
  1613. if ($aName eq 'MSwitch_Debug' && $aVal eq '2' || $aVal eq '3' )
  1614. {
  1615. MSwitch_clearlog($hash);
  1616. }
  1617. if ( $cmd eq 'set' && $aName eq 'MSwitch_Inforoom' )
  1618. {
  1619. my $testarg = $aVal;
  1620. foreach my $testdevices ( keys %{ $modules{MSwitch}{defptr} } )
  1621. {
  1622. $attr{$testdevices}{MSwitch_Inforoom} = $testarg;
  1623. }
  1624. }
  1625. if ( $aName eq 'MSwitch_Mode' && ( $aVal eq 'Full' || $aVal eq 'Toggle' ) )
  1626. {
  1627. my $cs = "setstate $name ???";
  1628. my $errors = AnalyzeCommandChain( undef, $cs );
  1629. }
  1630. if ( $aName eq 'MSwitch_Mode' && $aVal eq 'Notify' )
  1631. {
  1632. readingsSingleUpdate( $hash, "state", 'active', 1 );
  1633. my $cs = "setstate $name active";
  1634. my $errors = AnalyzeCommandChain( undef, $cs );
  1635. if ( defined($errors) )
  1636. {
  1637. Log3( $name, 1,"$name MSwitch_Notify: Fehler bei Befehlsausführung $errors -> Comand: $_ ". __LINE__ );
  1638. }
  1639. }
  1640. #############
  1641. if ( $cmd eq 'del' )
  1642. {
  1643. my $testarg = $aName;
  1644. my $errors;
  1645. if ( $testarg eq 'MSwitch_Inforoom' )
  1646. {
  1647. LOOP21:
  1648. foreach my $testdevices ( keys %{ $modules{MSwitch}{defptr} } )
  1649. {
  1650. if ( $testdevices eq $name ) { next LOOP21; }
  1651. delete( $attr{$testdevices}{MSwitch_Inforoom} );
  1652. }
  1653. }
  1654. if ( $testarg eq 'disable' )
  1655. {
  1656. MSwitch_Delete_Delay($hash, "all");
  1657. MSwitch_Clear_timer($hash);
  1658. delete( $hash->{helper}{savemodeblock} );
  1659. delete( $hash->{READINGS}{Safemode} );
  1660. }
  1661. }
  1662. return undef;
  1663. }
  1664. ####################
  1665. sub MSwitch_Delete($$) {
  1666. my ( $hash, $name ) = @_;
  1667. RemoveInternalTimer($hash);
  1668. return undef;
  1669. }
  1670. ####################
  1671. sub MSwitch_Undef($$) {
  1672. my ( $hash, $name ) = @_;
  1673. RemoveInternalTimer($hash);
  1674. delete( $modules{MSwitch}{defptr}{$name} );
  1675. return undef;
  1676. }
  1677. ####################
  1678. sub MSwitch_Notify($$) {
  1679. my $testtoggle = '';
  1680. my ( $own_hash, $dev_hash ) = @_;
  1681. my $ownName = $own_hash->{NAME}; # own name / hash
  1682. my $devName = $dev_hash->{NAME};
  1683. my $events = deviceEvents( $dev_hash, 1 );
  1684. my $trigevent='';
  1685. my $execids = "0";
  1686. # nur abfragen für eigenes Notify
  1687. if ($init_done && $devName eq "global" && grep( m/^MODIFIED $ownName$/, @{$events} ) )
  1688. {
  1689. # reaktion auf eigenes notify start / define / modify
  1690. #Log3( $ownName, 5, 'FOUND MODIFIED' );
  1691. my $timecond = gettimeofday() + 5;
  1692. InternalTimer( $timecond, "MSwitch_LoadHelper", $own_hash);
  1693. # return;
  1694. }
  1695. if ($init_done && $devName eq "global" && grep( m/^DEFINED $ownName$/, @{$events} ) )
  1696. {
  1697. # reaktion auf eigenes notify start / define / modify
  1698. #Log3( $ownName, 5, 'FOUND DEFINED' );
  1699. #MSwitch_LoadHelper($own_hash);
  1700. my $timecond = gettimeofday() + 5;
  1701. InternalTimer( $timecond, "MSwitch_LoadHelper", $own_hash);
  1702. # return;
  1703. }
  1704. if ( $devName eq "global" && grep( m/^INITIALIZED|REREADCFG$/, @{$events} ) )
  1705. {
  1706. # reaktion auf eigenes notify start / define / modify
  1707. #Log3( $ownName, 5, 'FOUND INITIALIZED|REREADCF' );
  1708. MSwitch_LoadHelper($own_hash);
  1709. # return;
  1710. }
  1711. # nur abfragen für eigenes Notify ENDE
  1712. return "" if ( IsDisabled($ownName) );# Return without any further action if the module is disabled
  1713. # startverzöferung abwarten
  1714. my $startdelay = AttrVal( $ownName, 'MSwitch_Startdelay', $standartstartdelay );
  1715. my $diff = int(time) - $fhem_started;
  1716. if ($diff < $startdelay)
  1717. {
  1718. MSwitch_LOG( $ownName, 4, 'Anfrage fuer '.$ownName.' blockiert - Zeit seit start:'. $diff );
  1719. return;
  1720. }
  1721. # safemode testen
  1722. MSwitch_Safemode($own_hash);
  1723. MSwitch_LOG( $ownName, 5, "----------------------------------------" );
  1724. MSwitch_LOG( $ownName, 5, "$ownName: eingehendes Event von -> ".$devName );
  1725. MSwitch_LOG( $ownName, 5, "----------------------------------------" );
  1726. # versionscheck
  1727. if ( ReadingsVal( $ownName, '.V_Check', $vupdate ) ne $vupdate )
  1728. {
  1729. my $ver = ReadingsVal( $ownName, '.V_Check', '' );
  1730. MSwitch_LOG( $ownName, 4, $ownName.' Versionskonflikt, aktion abgebrochen ! erwartet:'.$vupdate.' vorhanden:'.$ver );
  1731. return;
  1732. }
  1733. if ( AttrVal( $ownName, 'MSwitch_RandomNumber', '' ) ne '' )
  1734. {
  1735. # create randomnumber wenn attr an
  1736. MSwitch_Createnumber1($own_hash);
  1737. }
  1738. if ( ReadingsVal( $ownName, "waiting", '0' ) > time )
  1739. {
  1740. MSwitch_LOG( $ownName, 5, '$ownName: Aktion abgebrochen - wait gesetzt ->'. ReadingsVal( $ownName, "waiting", '0'));
  1741. # teste auf attr waiting verlesse wenn gesetzt
  1742. return "";
  1743. }
  1744. else
  1745. {
  1746. # reading löschen
  1747. delete( $own_hash->{READINGS}{waiting} );
  1748. }
  1749. my $incommingdevice = '';
  1750. if ( defined( $own_hash->{helper}{testevent_device} ) )
  1751. {
  1752. # unklar
  1753. $events = 'x';
  1754. $incommingdevice = ( $own_hash->{helper}{testevent_device} );
  1755. }
  1756. else
  1757. {
  1758. $incommingdevice = $dev_hash->{NAME}; # aufrufendes device
  1759. }
  1760. return if ( !$events );
  1761. my $triggerdevice = ReadingsVal( $ownName, 'Trigger_device', '' );# Triggerdevice
  1762. my @cmdarray;
  1763. my @cmdarray1;# enthält auszuführende befehle nach conditiontest
  1764. ########### ggf. löschen
  1765. my $triggeron = ReadingsVal( $ownName, '.Trigger_on', '' );
  1766. my $triggeroff = ReadingsVal( $ownName, '.Trigger_off', '' );
  1767. my $triggercmdon = ReadingsVal( $ownName, '.Trigger_cmd_on', '' );
  1768. my $triggercmdoff = ReadingsVal( $ownName, '.Trigger_cmd_off', '' );
  1769. if ( AttrVal( $ownName, 'MSwitch_Mode', 'Full' ) eq "Notify" )
  1770. {
  1771. # passt triggerfelder an attr an
  1772. $triggeron = 'no_trigger';
  1773. $triggeroff = 'no_trigger';
  1774. }
  1775. if ( AttrVal( $ownName, 'MSwitch_Mode', 'Full' ) eq "Toggle" )
  1776. {
  1777. # passt triggerfelder an attr an
  1778. $triggeroff = 'no_trigger';
  1779. $triggercmdon = 'no_trigger';
  1780. $triggercmdoff = 'no_trigger';
  1781. }
  1782. my $set = "noset";
  1783. my $eventcopy = "";
  1784. # notify für eigenes device
  1785. my $devcopyname = $devName;
  1786. $own_hash->{helper}{eventfrom} = $devName;
  1787. my @eventscopy;
  1788. if ( defined( $own_hash->{helper}{testevent_event} ) )
  1789. {
  1790. # unklar
  1791. # wenn global , sonst ohne 1
  1792. @eventscopy = "$own_hash->{helper}{testevent_event}";
  1793. }
  1794. else
  1795. {
  1796. @eventscopy = ( @{$events} );
  1797. }
  1798. my $triggerlog = ReadingsVal( $ownName, 'Trigger_log', 'off' );
  1799. if ( $incommingdevice eq $triggerdevice || $triggerdevice eq "all_events" )
  1800. {
  1801. # teste auf triggertreffer oder GLOBAL trigger
  1802. my $activecount = 0;
  1803. my $anzahl ;
  1804. EVENT: foreach my $event (@eventscopy)
  1805. {
  1806. MSwitch_LOG( $ownName, 5, "$ownName: eingehendes Event -> ".$incommingdevice." ".$event );
  1807. # durchlauf für jedes ankommende event
  1808. #
  1809. $event = "" if ( !defined($event) );
  1810. $eventcopy = $event;
  1811. $eventcopy =~ s/: /:/s; # BUG !!!!!!!!!!!!!!!!!!!!!!!!
  1812. if ( $triggerlog eq 'on' )
  1813. {
  1814. # wird nur ausgefüht wenn ankommende events gelogd werden
  1815. my @filters =split( /,/, AttrVal( $ownName, 'MSwitch_Trigger_Filter', '' ));# beinhaltet filter durch komma getrennt
  1816. foreach my $filter (@filters)
  1817. {
  1818. my $wildcarttest = index( $filter, "*", 0 );
  1819. if ( $wildcarttest > -1 ) ### filter auf wildcart
  1820. {
  1821. $filter = substr( $filter, 0, $wildcarttest );
  1822. my $testwildcart = index( $eventcopy, $filter, 0 );
  1823. if ( $testwildcart eq '0' ) { next EVENT; }
  1824. }
  1825. else ### filter genauen ausdruck
  1826. {
  1827. if ( $eventcopy eq $filter ) { next EVENT; }
  1828. }
  1829. }
  1830. if ( $triggerdevice eq "all_events" )
  1831. {
  1832. $own_hash->{helper}{events}{'all_events'}{ $devName . ':' . $eventcopy } = "on";
  1833. }
  1834. else
  1835. {
  1836. $own_hash->{helper}{events}{$devName}{$eventcopy} = "on";
  1837. }
  1838. }
  1839. my $eventcopy1 = $eventcopy;
  1840. if ( $triggerdevice eq "all_events" )
  1841. {
  1842. # fügt dem event den devicenamen hinzu , wenn global getriggert wird
  1843. $eventcopy1 = "$devName:$eventcopy";
  1844. }
  1845. my $direktswitch = 0;
  1846. my @eventsplit = split( /\:/, $eventcopy );
  1847. my $eventstellen = @eventsplit;
  1848. my $testvar = '';
  1849. my $check=0;
  1850. #test auf zweige cmd1/2 and switch MSwitch on/off
  1851. if ( $triggeron ne 'no_trigger' )
  1852. {
  1853. MSwitch_LOG( $ownName, 5, "$ownName: checktrigger trigger cmd1 -> " );
  1854. $testvar = MSwitch_checktrigger( $own_hash, $ownName, $eventstellen,$triggeron, $incommingdevice, 'on',$eventcopy,@eventsplit );
  1855. if( $testvar ne 'undef')
  1856. {
  1857. $set = $testvar ;
  1858. $check=1;
  1859. $trigevent = $eventcopy;
  1860. }
  1861. MSwitch_LOG( $ownName, 5, "$ownName: checktrigger ergebniss -> ".$testvar );
  1862. }
  1863. if ( $triggeroff ne 'no_trigger' )
  1864. {
  1865. MSwitch_LOG( $ownName, 5, "$ownName: checktrigger trigger cmd2 -> " );
  1866. $testvar = MSwitch_checktrigger( $own_hash, $ownName, $eventstellen,$triggeroff, $incommingdevice, 'off',$eventcopy, @eventsplit );
  1867. if ($testvar ne 'undef')
  1868. {
  1869. $set = $testvar ;
  1870. $check=1;
  1871. $trigevent = $eventcopy;
  1872. }
  1873. MSwitch_LOG( $ownName, 5, "$ownName: checktrigger ergebniss -> ".$testvar );
  1874. }
  1875. #test auf zweige cmd1/2 and switch MSwitch on/off ENDE
  1876. #test auf zweige cmd1/2 only
  1877. # ergebnisse werden in @cmdarray geschrieben
  1878. if ( $triggercmdoff ne 'no_trigger' )
  1879. {
  1880. MSwitch_LOG( $ownName, 5, "$ownName: checktrigger trigger cmd4 -> " );
  1881. $testvar = MSwitch_checktrigger( $own_hash, $ownName, $eventstellen,$triggercmdoff, $incommingdevice, 'offonly', $eventcopy, @eventsplit );
  1882. if ($testvar ne 'undef')
  1883. {
  1884. push @cmdarray, $own_hash . ',off,check,' . $eventcopy1;
  1885. $check=1;
  1886. }
  1887. MSwitch_LOG( $ownName, 5, "$ownName: checktrigger ergebniss -> ".$testvar );
  1888. }
  1889. if ( $triggercmdon ne 'no_trigger' )
  1890. {
  1891. MSwitch_LOG( $ownName, 5, "$ownName: checktrigger trigger cmd4 -> " );
  1892. $testvar = MSwitch_checktrigger( $own_hash, $ownName, $eventstellen,$triggercmdon, $incommingdevice, 'ononly', $eventcopy, @eventsplit );
  1893. if ( $testvar ne 'undef')
  1894. {
  1895. push @cmdarray, $own_hash . ',on,check,' . $eventcopy1;
  1896. $check=1;
  1897. }
  1898. MSwitch_LOG( $ownName, 5, "$ownName: checktrigger ergebniss -> ".$testvar );
  1899. }
  1900. #test auf zweige cmd1/2 only ENDE
  1901. $anzahl = @cmdarray;
  1902. MSwitch_LOG( $ownName, 5, "$ownName: anzahl gefundener Befehle -> ".$anzahl );
  1903. MSwitch_LOG( $ownName, 5, "$ownName: inhalt gefundener Befehle -> ".@cmdarray );
  1904. $own_hash->{IncommingHandle}='fromnotify';
  1905. $event =~ s/ //ig; #?
  1906. $event =~ s/~/ /g; #?
  1907. if ( AttrVal( $ownName, 'MSwitch_Mode', 'Full' ) eq "Notify" and $activecount == 0 )
  1908. {
  1909. # reading activity aktualisieren
  1910. readingsSingleUpdate( $own_hash, "state", 'active', 1 );
  1911. $activecount = 1;
  1912. }
  1913. #Readings aktualisieren, wenn gleiches event nicht schom gesetzt
  1914. if (ReadingsVal( $ownName, 'last_event', '' ) ne $event && $event ne '' && $anzahl > 0 && $check ==1 && $anzahl > 0)
  1915. {
  1916. MSwitch_EventBulk($own_hash ,$event ,'0')
  1917. }
  1918. # abfrage und setzten von blocking
  1919. # schalte blocking an , wenn anzahl grösser 0 und MSwitch_Wait gesetzt
  1920. my $mswait = $attr{$ownName}{MSwitch_Wait};
  1921. if ( !defined $mswait ) { $mswait = '0'; }
  1922. if ( $anzahl > 0 && $mswait > 0 )
  1923. {
  1924. readingsSingleUpdate( $own_hash, "waiting", ( time + $mswait ),0 );
  1925. }
  1926. # abfrage und setzten von blocking ENDE
  1927. if ( AttrVal( $ownName, 'MSwitch_Mode', 'Full' ) eq "Toggle" && $set eq 'on' )
  1928. {# umschalten des devices nur im togglemode
  1929. my $cmd = '';
  1930. my $statetest = ReadingsVal( $ownName, 'state', 'on' );
  1931. $cmd = "set $ownName off" if $statetest eq 'on';
  1932. $cmd = "set $ownName on" if $statetest eq 'off';
  1933. MSwitch_LOG( $ownName, 5, "$ownName: togglemode execute -> ".$cmd);
  1934. if ( AttrVal( $ownName, 'MSwitch_Debug', "0" ) ne '2' )
  1935. {
  1936. my $errors = AnalyzeCommandChain( undef, $cmd );
  1937. if ( defined($errors) )
  1938. {
  1939. MSwitch_LOG( $ownName, 1,"$ownName MSwitch_Notify: Fehler bei Befehlsausführung $errors -> Comand: $_ " . __LINE__ );
  1940. }
  1941. }
  1942. return;
  1943. }
  1944. }
  1945. #ausführen aller cmds in @cmdarray nach triggertest aber vor conditiontest
  1946. #my @cmdarray1; #enthält auszuführende befehle nach conditiontest
  1947. #schaltet zweig 3 und 4
  1948. if ( $anzahl != 0 )
  1949. {
  1950. MSwitch_LOG( $ownName, 5, "$ownName: abarbeiten aller befehle aus eventprüfung ");
  1951. #aberabeite aller befehlssätze in cmdarray
  1952. MSwitch_Safemode($own_hash);
  1953. LOOP31: foreach (@cmdarray)
  1954. {
  1955. MSwitch_LOG( $ownName, 5, "$ownName: Befehl -> ".$_);
  1956. if ( $_ eq 'undef' ) { next LOOP31; }
  1957. my ( $ar1, $ar2, $ar3, $ar4 ) = split( /,/, $_ );
  1958. if ( !defined $ar2 ) { $ar2 =''; }
  1959. if ( $ar2 eq '' ) { next LOOP31; }
  1960. my $returncmd = 'undef';
  1961. #MSwitch_LOG( $ownName, 0,"$ownName: aufruf execnotif $_ $ar2, $ar3, $ar4 ");
  1962. $returncmd = MSwitch_Exec_Notif( $own_hash, $ar2, $ar3, $ar4,$execids );
  1963. #MSwitch_LOG( $ownName, 0,"$ownName: ergebniss execnotif -> ".$returncmd);
  1964. if ( defined $returncmd && $returncmd ne 'undef' )
  1965. {
  1966. # datensatz nur in cmdarray1 übernehme wenn
  1967. chop $returncmd; #CHANGE
  1968. MSwitch_LOG( $ownName, 5,"$ownName: ergebniss execnotif datensatz to array -> ".$returncmd);
  1969. push( @cmdarray1, $returncmd );
  1970. }
  1971. }
  1972. my $befehlssatz = join( ',', @cmdarray1 );
  1973. foreach ( split( /,/, $befehlssatz ) )
  1974. {
  1975. my $ecec = $_;
  1976. if ( !$ecec =~ m/set (.*)(MSwitchtoggle)(.*)/ )
  1977. {
  1978. if ( AttrVal( $ownName, 'MSwitch_RandomNumber', '' ) ne '' )
  1979. {
  1980. MSwitch_Createnumber($own_hash);
  1981. }
  1982. MSwitch_LOG( $ownName, 5,"$ownName: Befehlsausfuehrung -> ".$ecec);
  1983. if ( AttrVal( $ownName, 'MSwitch_Debug', "0" ) ne '2' )
  1984. {
  1985. my $errors = AnalyzeCommandChain( undef, $_ );
  1986. if ( defined($errors) )
  1987. {
  1988. MSwitch_LOG( $ownName, 1,"$ownName MSwitch_Notify: Fehler bei Befehlsausführung $errors -> Comand: $_ ". __LINE__ );
  1989. }
  1990. }
  1991. if (length($ecec) > 100 ){ $ecec = substr($ecec,0,100).'....';}
  1992. readingsSingleUpdate( $own_hash, "Exec_cmd", $ecec, 1 ) if $ecec ne '';
  1993. }
  1994. else
  1995. {
  1996. }
  1997. }
  1998. }
  1999. # ende loopeinzeleventtest
  2000. # schreibe gruppe mit events
  2001. my $events = '';
  2002. my $eventhash = $own_hash->{helper}{events}{$devName};
  2003. if ( $triggerdevice eq "all_events" )
  2004. {
  2005. $eventhash = $own_hash->{helper}{events}{all_events};
  2006. }
  2007. else
  2008. {
  2009. $eventhash = $own_hash->{helper}{events}{$devName};
  2010. }
  2011. foreach my $name ( keys %{$eventhash} )
  2012. {
  2013. $events = $events . $name . '#[tr]';
  2014. }
  2015. chop($events);
  2016. chop($events);
  2017. chop($events);
  2018. chop($events);
  2019. chop($events);
  2020. if ( $events ne "" )
  2021. {
  2022. readingsSingleUpdate( $own_hash, ".Device_Events", $events, 1 );
  2023. }
  2024. # schreiben ende
  2025. # schalte modul an/aus bei entsprechendem notify
  2026. # teste auf condition
  2027. return if $set eq 'noset';# keine MSwitch on/off incl cmd1/2 gefunden
  2028. # Teste auf einhaltung Triggercondition für ausführung zweig 1 und zweig 2
  2029. # kann ggf an den anfang der routine gesetzt werden ? test erforderlich
  2030. my $triggercondition =ReadingsVal( $ownName, '.Trigger_condition', '' );
  2031. $triggercondition =~ s/#\[dp\]/:/g;
  2032. $triggercondition =~ s/#\[pt\]/./g;
  2033. $triggercondition =~ s/#\[ti\]/~/g;
  2034. $triggercondition =~ s/#\[sp\]/ /g;
  2035. if ( $triggercondition ne '')
  2036. {
  2037. MSwitch_LOG( $ownName, 5,"$ownName: teste Triggercondition -> ".$triggercondition);
  2038. my $ret =MSwitch_checkcondition( $triggercondition, $ownName, $eventcopy );
  2039. MSwitch_LOG( $ownName, 5,"$ownName: ergebniss Triggercondition -> ".$ret);
  2040. if ( $ret eq 'false' )
  2041. {
  2042. MSwitch_LOG( $ownName, 5,"$ownName: ergebniss Triggercondition false-> abbruch");
  2043. return;
  2044. }
  2045. }
  2046. # Teste auf einhaltung Triggercondition ENDE
  2047. # schaltet zweig 1 und 2 , wenn $set befehl enthält , es wird nur MSwitch geschaltet, Devices werden dann 'mitgerissen'
  2048. my $cs;
  2049. if ( $triggerdevice eq "all_events" )
  2050. {
  2051. $cs = "set $ownName $set $devName:$trigevent";
  2052. }
  2053. else
  2054. {
  2055. $cs = "set $ownName $set $trigevent";
  2056. }
  2057. MSwitch_LOG( $ownName, 3,"$ownName MSwitch_Notif: Befehlsausfuehrung -> $cs " . __LINE__ );
  2058. # variabelersetzung
  2059. $cs =~ s/\$NAME/$own_hash->{helper}{eventfrom}/;
  2060. $cs =~ s/\$SELF/$ownName/;
  2061. if ( AttrVal( $ownName, 'MSwitch_RandomNumber', '' ) ne '' )
  2062. {
  2063. MSwitch_Createnumber($own_hash);
  2064. }
  2065. MSwitch_LOG( $ownName, 5,"$ownName: Befehlsausführung -> ".$cs);
  2066. if ( AttrVal( $ownName, 'MSwitch_Debug', "0" ) ne '2' )
  2067. {
  2068. my $errors = AnalyzeCommandChain( undef, $cs );
  2069. }
  2070. return;
  2071. }
  2072. }
  2073. #########################
  2074. sub MSwitch_fhemwebFn($$$$) {
  2075. # my $loglevel = 5;
  2076. my ( $FW_wname, $d, $room, $pageHash ) =
  2077. @_; # pageHash is set for summaryFn.
  2078. my $hash = $defs{$d};
  2079. my $Name = $hash->{NAME};
  2080. my $jsvarset = '';
  2081. my $j1 = '';
  2082. my $border =0;
  2083. #Log3( $Name, 0,"hash ---> $hash " . __LINE__ );
  2084. #Log3( $Name, 0,"name ---> $Name " . __LINE__ );
  2085. if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '4' )
  2086. {
  2087. $border =1;
  2088. }
  2089. #versetzen nach ATTR
  2090. if ( AttrVal( $Name, 'MSwitch_RandomNumber', '' ) eq '' )
  2091. {
  2092. delete( $hash->{READINGS}{RandomNr} );
  2093. delete( $hash->{READINGS}{RandomNr1} );
  2094. }
  2095. ####################
  2096. ### teste auf new defined device
  2097. my $hidden = '';
  2098. if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '4' )
  2099. {
  2100. $hidden = ''
  2101. }
  2102. else
  2103. {
  2104. $hidden = 'hidden'
  2105. }
  2106. my $triggerdevices = '';
  2107. my $events = ReadingsVal( $Name, '.Device_Events', '' );
  2108. my @eventsall = split( /#\[tr\]/, $events );
  2109. my $Triggerdevice = ReadingsVal( $Name, 'Trigger_device', '' );
  2110. my $triggeron = ReadingsVal( $Name, '.Trigger_on', '' );
  2111. if ( !defined $triggeron ) { $triggeron = "" }
  2112. my $triggeroff = ReadingsVal( $Name, '.Trigger_off', '' );
  2113. if ( !defined $triggeroff ) { $triggeroff = "" }
  2114. my $triggercmdon = ReadingsVal( $Name, '.Trigger_cmd_on', '' );
  2115. if ( !defined $triggercmdon ) { $triggercmdon = "" }
  2116. my $triggercmdoff = ReadingsVal( $Name, '.Trigger_cmd_off', '' );
  2117. if ( !defined $triggercmdoff ) { $triggercmdoff = "" }
  2118. my $disable = "";
  2119. my %korrekt;
  2120. foreach (@eventsall)
  2121. {
  2122. $korrekt{$_} = 'ok';
  2123. }
  2124. $korrekt{$triggeron} = 'ok';
  2125. $korrekt{$triggeroff} = 'ok';
  2126. $korrekt{$triggercmdon} = 'ok';
  2127. $korrekt{$triggercmdoff} = 'ok';
  2128. my @eventsallnew;
  2129. for my $name ( sort keys %korrekt )
  2130. {
  2131. push( @eventsallnew, $name );
  2132. }
  2133. @eventsall = @eventsallnew;
  2134. if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Notify" )
  2135. {
  2136. readingsSingleUpdate( $hash, "state", 'active', 1 );
  2137. $triggeroff = "";
  2138. $triggeron = "";
  2139. }
  2140. if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Toggle" )
  2141. {
  2142. $triggeroff = "";
  2143. $triggercmdoff = "";
  2144. $triggercmdon = "";
  2145. }
  2146. #eigene trigger festlegen
  2147. my $optionon = '';
  2148. my $optiongeneral = '';
  2149. my $optioncmdon = '';
  2150. my $alltriggers = '';
  2151. my $to = '';
  2152. my $toc = '';
  2153. LOOP12: foreach (@eventsall)
  2154. {
  2155. $alltriggers =
  2156. $alltriggers . "<option value=\"$_\">" . $_ . "</option>";
  2157. if ( $_ eq 'no_trigger' )
  2158. {
  2159. next LOOP12;
  2160. }
  2161. if ( $triggeron eq $_ )
  2162. {
  2163. $optionon =$optionon
  2164. . "<option selected=\"selected\" value=\"$_\">". $_. "</option>";
  2165. $to = '1';
  2166. }
  2167. else
  2168. {
  2169. $optionon = $optionon . "<option value=\"$_\">" . $_ . "</option>";
  2170. }
  2171. if ( $triggercmdon eq $_ )
  2172. {
  2173. $optioncmdon =$optioncmdon. "<option selected=\"selected\" value=\"$_\">". $_. "</option>";
  2174. $toc = '1';
  2175. }
  2176. else
  2177. {
  2178. $optioncmdon =$optioncmdon . "<option value=\"$_\">" . $_ . "</option>";
  2179. }
  2180. #################### nur bei entsprechender regex
  2181. my $test = $_;
  2182. if ( $test =~ m/(.*)\((.*)\)(.*)/ )
  2183. {
  2184. }
  2185. else
  2186. {
  2187. if ( index( $_, '*', 0 ) == -1 )
  2188. {
  2189. if ( ReadingsVal( $Name, 'Trigger_device', '' ) ne "all_events" )
  2190. {
  2191. $optiongeneral = $optiongeneral. "<option value=\"$_\">". $_. "</option>";
  2192. }
  2193. else
  2194. {
  2195. $optiongeneral =$optiongeneral. "<option value=\"$_\">". $_. "</option>";
  2196. }
  2197. }
  2198. }
  2199. #####################
  2200. }
  2201. if ( $to eq '1' )
  2202. {
  2203. $optionon ="<option value=\"no_trigger\">no_trigger</option>" . $optionon;
  2204. }
  2205. else
  2206. {
  2207. $optionon ="<option selected=\"selected\" value=\"no_trigger\">no_trigger</option>" . $optionon;
  2208. }
  2209. if ( $toc eq '1' )
  2210. {
  2211. $optioncmdon ="<option value=\"no_trigger\">no_trigger</option>" . $optioncmdon;
  2212. }
  2213. else
  2214. {
  2215. $optioncmdon ="<option selected=\"selected\" value=\"no_trigger\">no_trigger</option>". $optioncmdon;
  2216. }
  2217. my $optioncmdoff = '';
  2218. my $optionoff = '';
  2219. $to = '';
  2220. $toc = '';
  2221. LOOP14: foreach (@eventsall)
  2222. {
  2223. if ( $_ eq 'no_trigger' ) { next LOOP14 }
  2224. if ( $triggeroff eq $_ )
  2225. {
  2226. $optionoff = $optionoff. "<option selected=\"selected\" value=\"$_\">$_</option>";
  2227. $to = '1';
  2228. }
  2229. else
  2230. {
  2231. $optionoff = $optionoff . "<option value=\"$_\">$_</option>";
  2232. }
  2233. if ( $triggercmdoff eq $_ )
  2234. {
  2235. $optioncmdoff = $optioncmdoff . "<option selected=\"selected\" value=\"$_\">$_</option>";
  2236. $toc = '1';
  2237. }
  2238. else
  2239. {
  2240. $optioncmdoff = $optioncmdoff . "<option value=\"$_\">$_</option>";
  2241. }
  2242. }
  2243. if ( $to eq '1' )
  2244. {
  2245. $optionoff = "<option value=\"no_trigger\">no_trigger</option>" . $optionoff;
  2246. }
  2247. else
  2248. {
  2249. $optionoff ="<option selected=\"selected\" value=\"no_trigger\">no_trigger</option>". $optionoff;
  2250. }
  2251. if ( $toc eq '1' )
  2252. {
  2253. $optioncmdoff = "<option value=\"no_trigger\">no_trigger</option>" . $optioncmdoff;
  2254. }
  2255. else
  2256. {
  2257. $optioncmdoff ="<option selected=\"selected\" value=\"no_trigger\">no_trigger</option>". $optioncmdoff;
  2258. }
  2259. $optionon =~ s/\[bs\]/|/g;
  2260. $optionoff =~ s/\[bs\]/|/g;
  2261. $optioncmdon =~ s/\[bs\]/|/g;
  2262. $optioncmdoff =~ s/\[bs\]/|/g;
  2263. ####################
  2264. # mögliche affected devices und mögliche triggerdevices
  2265. my $devicesets;
  2266. my $deviceoption = "";
  2267. my $selected = "";
  2268. my $errors = "";
  2269. my $javaform = ""; # erhält javacode für übergabe devicedetail
  2270. my $cs = "";
  2271. my %cmdsatz; # ablage desbefehlssatzes jedes devices
  2272. my $globalon = 'off';
  2273. if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq 'no_trigger' )
  2274. {
  2275. $triggerdevices ="<option selected=\"selected\" value=\"no_trigger\">no_trigger</option>";
  2276. }
  2277. else
  2278. {
  2279. $triggerdevices = "<option value=\"no_trigger\">no_trigger</option>";
  2280. }
  2281. if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' )
  2282. {
  2283. if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq 'all_events' )
  2284. {
  2285. $triggerdevices .="<option selected=\"selected\" value=\"all_events\">GLOBAL</option>";
  2286. $globalon = 'on';
  2287. }
  2288. else
  2289. {
  2290. $triggerdevices .= "<option value=\"all_events\">GLOBAL</option>";
  2291. }
  2292. }
  2293. my @notype = split( / /, AttrVal( $Name, 'MSwitch_Ignore_Types', "" ) );
  2294. my $affecteddevices = ReadingsVal( $Name, '.Device_Affected', 'no_device' );
  2295. # affected devices to hash
  2296. my %usedevices;
  2297. my @deftoarray = split( /,/, $affecteddevices );
  2298. my $anzahl = @deftoarray;
  2299. my $reihenfolgehtml="";
  2300. if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' )
  2301. {
  2302. $reihenfolgehtml="<select name = 'reihe' id=''>";
  2303. for (my $i=1; $i<$anzahl+1; $i++)
  2304. {
  2305. $reihenfolgehtml.="<option value='$i'>$i</option>";
  2306. }
  2307. $reihenfolgehtml.="</select>";
  2308. }
  2309. my $idfolgehtml="";
  2310. if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' )
  2311. {
  2312. $idfolgehtml="<select name = 'idreihe' id=''>";
  2313. for (my $i=-1; $i<$anzahl+1; $i++)
  2314. {
  2315. $idfolgehtml.="<option value='$i'>$i</option>" if $i > 0 ;
  2316. $idfolgehtml.="<option value='$i'>-</option>" if $i == 0 ;
  2317. }
  2318. $idfolgehtml.="</select>";
  2319. }
  2320. foreach (@deftoarray)
  2321. {
  2322. my ( $a, $b ) = split( /-/, $_ );
  2323. $usedevices{$a} = 'on';
  2324. }
  2325. LOOP9: for my $name ( sort keys %defs )
  2326. {
  2327. my $selectedtrigger = '';
  2328. my $devicealias = AttrVal( $name, 'alias', "" );
  2329. my $devicewebcmd =AttrVal( $name, 'webCmd', "noArg" ); # webcmd des devices
  2330. my $devicehash = $defs{$name}; #devicehash
  2331. my $deviceTYPE = $devicehash->{TYPE};
  2332. # triggerfile erzeugen
  2333. foreach (@notype)
  2334. {
  2335. if ( lc($_) eq lc($deviceTYPE) ) { next LOOP9; }
  2336. }
  2337. if ( ReadingsVal( $Name, 'Trigger_device', '' ) eq $name )
  2338. {
  2339. $selectedtrigger = 'selected=\"selected\"';
  2340. if ( $name eq 'all_events' ) { $globalon = 'on' }
  2341. }
  2342. $triggerdevices .="<option $selectedtrigger value=\"$name\">$name (a:$devicealias t:$deviceTYPE)</option>";
  2343. # filter auf argumente on oder off ;
  2344. if ( $name eq '' ) { next LOOP9; }
  2345. my $cs = "set $name ?";
  2346. # abfrage und auswertung befehlssatz
  2347. if ( AttrVal( $Name, 'MSwitch_Include_Devicecmds', "1" ) eq '1' )
  2348. {
  2349. $errors = AnalyzeCommandChain( undef, $cs );
  2350. if ($errors) { }
  2351. }
  2352. else
  2353. {
  2354. $errors = '';
  2355. }
  2356. if ( !defined $errors ) { $errors = '' }
  2357. my @tmparg = split( /of /, $errors );
  2358. if (!defined $tmparg[1]){$tmparg[1]=""};
  2359. #if ( defined $tmparg[1] && $tmparg[1] ne '' ) { $errors = $tmparg[1]; }
  2360. if ( $tmparg[1] ne '' )
  2361. {
  2362. $errors = $tmparg[1];
  2363. }
  2364. else{
  2365. $errors = '';
  2366. }
  2367. $errors = '|' . $errors;
  2368. $errors =~ s/\| //g;
  2369. $errors =~ s/\|//g;
  2370. if ( $errors eq '' && AttrVal( $Name, 'MSwitch_Include_Webcmds', "1" ) eq '1' )
  2371. {
  2372. if ( $devicewebcmd ne "noArg" )
  2373. {
  2374. my $device = '';
  2375. my @webcmd = split( /:/, $devicewebcmd );
  2376. foreach (@webcmd) {
  2377. $_ =~ tr/ /:/;
  2378. my @parts = split( /:/, $_ );
  2379. if ( !defined $parts[1] || $parts[1] eq '' )
  2380. {
  2381. $device .= $parts[0] . ':noArg ';
  2382. }
  2383. else
  2384. {
  2385. $device .= $parts[0] . ':' . $parts[1] . ' ';
  2386. }
  2387. }
  2388. chop $device;
  2389. $devicewebcmd = $device;
  2390. $errors = $devicewebcmd;
  2391. }
  2392. }
  2393. my $usercmds = AttrVal( $name, 'MSwitchcmd', '' );
  2394. if ( $usercmds ne ''&& AttrVal( $Name, 'MSwitch_Include_MSwitchcmds', "1" ) eq '1' )
  2395. {
  2396. $usercmds =~ tr/:/ /;
  2397. $errors .= ' ' . $usercmds;
  2398. }
  2399. my $extensions = AttrVal( $Name, 'MSwitch_Extensions', "0" );
  2400. if ( $extensions eq '1' )
  2401. {
  2402. $errors .= ' ' . 'MSwitchtoggle';
  2403. }
  2404. if ( $errors ne '' )
  2405. {
  2406. $selected = "";
  2407. if ( exists $usedevices{$name} && $usedevices{$name} eq 'on' )
  2408. {
  2409. $selected = "selected=\"selected\" ";
  2410. }
  2411. $deviceoption =
  2412. $deviceoption
  2413. . "<option "
  2414. . $selected
  2415. . "value=\""
  2416. . $name . "\">"
  2417. . $name . " (a:"
  2418. . $devicealias
  2419. . ")</option>";
  2420. # befehlssatz für device in scalar speichern
  2421. $cmdsatz{$name} = $errors;
  2422. }
  2423. else
  2424. {}
  2425. }
  2426. my $select = index( $affecteddevices, 'FreeCmd', 0 );
  2427. $selected = "";
  2428. if ( $select > -1 ) { $selected = "selected=\"selected\" " }
  2429. $deviceoption =
  2430. "<option "
  2431. . "value=\"FreeCmd\" "
  2432. . $selected
  2433. . ">Free Cmd (nicht an ein Device gebunden)</option>"
  2434. . $deviceoption;
  2435. $select = index( $affecteddevices, 'MSwitch_Self', 0 );
  2436. $selected = "";
  2437. if ( $select > -1 ) { $selected = "selected=\"selected\" " }
  2438. $deviceoption =
  2439. "<option "
  2440. . "value=\"MSwitch_Self\" "
  2441. . $selected
  2442. . ">MSwitch_Self (".$Name.")</option>"
  2443. . $deviceoption;
  2444. ####################
  2445. # #devices details
  2446. # detailsatz in scalar laden
  2447. # my @devicedatails = split(/:/,ReadingsVal($Name, '.Device_Affected_Details', '')); #inhalt decice und cmds # durch komma getrennt
  2448. my %savedetails = MSwitch_makeCmdHash($Name);
  2449. my $detailhtml = "";
  2450. my @affecteddevices = split( /,/, ReadingsVal( $Name, '.Device_Affected', 'no_device' ) );
  2451. if ( $affecteddevices[0] ne 'no_device' )
  2452. {
  2453. $detailhtml =
  2454. "<table border='$border' class='block wide' id='MSwitchDetails' nm='MSwitch'>
  2455. <tr class='even'>
  2456. <td colspan='5'>device actions :<br>&nbsp;
  2457. <input type='hidden' id='affected' name='affected' size='40' value ='"
  2458. . ReadingsVal( $Name, '.Device_Affected', 'no_device' ) . "'>
  2459. </td></tr>"; #start
  2460. foreach (@affecteddevices)
  2461. {
  2462. # $cmdsatz{$_} enthält befehlssatz als string getrennt durch " " und :
  2463. my @devicesplit = split( /-AbsCmd/, $_ );
  2464. my $devicenamet = $devicesplit[0];
  2465. my $zusatz ="";
  2466. if ($devicenamet eq "MSwitch_Self")
  2467. {
  2468. $devicenamet = $Name;
  2469. $zusatz ="MSwitch_Self -> ";
  2470. }
  2471. my $devicenumber = $devicesplit[1];
  2472. my @befehlssatz = '';
  2473. if ($devicenamet eq "FreeCmd")
  2474. {
  2475. $cmdsatz{$devicenamet}='';
  2476. }
  2477. @befehlssatz = split( / /, $cmdsatz{$devicenamet} );
  2478. my $aktdevice = $_;
  2479. ## optionen erzeugen
  2480. my $option1html = '';
  2481. my $option2html = '';
  2482. my $selectedhtml = "";
  2483. if ( !defined( $savedetails{ $aktdevice . '_on' } ) )
  2484. {
  2485. my $key = '';
  2486. $key = $aktdevice . "_on";
  2487. $savedetails{$key} = 'no_action';
  2488. }
  2489. if ( !defined( $savedetails{ $aktdevice . '_off' } ) )
  2490. {
  2491. my $key = '';
  2492. $key = $aktdevice . "_off";
  2493. $savedetails{$key} = 'no_action';
  2494. }
  2495. if ( !defined( $savedetails{ $aktdevice . '_onarg' } ) )
  2496. {
  2497. my $key = '';
  2498. $key = $aktdevice . "_onarg";
  2499. $savedetails{$key} = '';
  2500. }
  2501. if ( !defined( $savedetails{ $aktdevice . '_offarg' } ) )
  2502. {
  2503. my $key = '';
  2504. $key = $aktdevice . "_offarg";
  2505. $savedetails{$key} = '';
  2506. }
  2507. if ( !defined( $savedetails{ $aktdevice . '_delayaton' } ) )
  2508. {
  2509. my $key = '';
  2510. $key = $aktdevice . "_delayaton";
  2511. $savedetails{$key} = 'delay1';
  2512. }
  2513. if ( !defined( $savedetails{ $aktdevice . '_delayatoff' } ) )
  2514. {
  2515. my $key = '';
  2516. $key = $aktdevice . "_delayatoff";
  2517. $savedetails{$key} = 'delay1';
  2518. }
  2519. if ( !defined( $savedetails{ $aktdevice . '_timeon' } ) )
  2520. {
  2521. my $key = '';
  2522. $key = $aktdevice . "_timeon";
  2523. $savedetails{$key} = '000000';
  2524. }
  2525. if ( !defined( $savedetails{ $aktdevice . '_timeoff' } ) )
  2526. {
  2527. my $key = '';
  2528. $key = $aktdevice . "_timeoff";
  2529. $savedetails{$key} = '000000';
  2530. }
  2531. if ( !defined( $savedetails{ $aktdevice . '_conditionon' } ) )
  2532. {
  2533. my $key = '';
  2534. $key = $aktdevice . "_conditionon";
  2535. $savedetails{$key} = '';
  2536. }
  2537. if ( !defined( $savedetails{ $aktdevice . '_conditionoff' } ) )
  2538. {
  2539. my $key = '';
  2540. $key = $aktdevice . "_conditionoff";
  2541. $savedetails{$key} = '';
  2542. }
  2543. foreach (@befehlssatz) #befehlssatz einfügen
  2544. {
  2545. my @aktcmdset = split( /:/, $_ ); # befehl von noarg etc. trennen
  2546. $selectedhtml = "";
  2547. next if !defined $aktcmdset[0]; #changed 19.06
  2548. if ( $aktcmdset[0] eq $savedetails{ $aktdevice . '_on' } )
  2549. {
  2550. $selectedhtml = "selected=\"selected\"";
  2551. }
  2552. $option1html = $option1html . "<option $selectedhtml value=\"$aktcmdset[0]\">$aktcmdset[0]</option>";
  2553. $selectedhtml = "";
  2554. if ( $aktcmdset[0] eq $savedetails{ $aktdevice . '_off' } )
  2555. {
  2556. $selectedhtml = "selected=\"selected\"";
  2557. }
  2558. $option2html = $option2html . "<option $selectedhtml value=\"$aktcmdset[0]\">$aktcmdset[0]</option>";
  2559. }
  2560. if ( '' eq $savedetails{ $aktdevice . '_delayaton' } )
  2561. {
  2562. $savedetails{ $aktdevice . '_delayaton' } = 'delay1';
  2563. }
  2564. if ( '' eq $savedetails{ $aktdevice . '_delayatoff' } )
  2565. {
  2566. $savedetails{ $aktdevice . '_delayatoff' } = 'delay1';
  2567. }
  2568. if ( '' eq $savedetails{ $aktdevice . '_timeoff' } )
  2569. {
  2570. $savedetails{ $aktdevice . '_timeoff' } = '0';
  2571. }
  2572. if ( '' eq $savedetails{ $aktdevice . '_timeon' } )
  2573. {
  2574. $savedetails{ $aktdevice . '_timeon' } = '0';
  2575. }
  2576. $savedetails{ $aktdevice . '_onarg' } =~ s/~/ /g;
  2577. $savedetails{ $aktdevice . '_offarg' } =~ s/~/ /g;
  2578. $savedetails{ $aktdevice . '_onarg' } =~ s/#\[ti\]/~/g;;
  2579. $savedetails{ $aktdevice . '_offarg' } =~ s/#\[ti\]/~/g;;
  2580. $savedetails{ $aktdevice . '_onarg' } =~ s/#\[wa\]/|/g; #neu
  2581. $savedetails{ $aktdevice . '_offarg' } =~ s/#\[wa\]/|/g; #neu
  2582. my $dalias='';
  2583. if ($devicenamet ne "FreeCmd")
  2584. {
  2585. $dalias = "(a: " . AttrVal( $devicenamet, 'alias', "no" ) . ")" if AttrVal( $devicenamet, 'alias', "no" ) ne "no";
  2586. }
  2587. if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' )
  2588. {
  2589. $detailhtml = $detailhtml . "
  2590. <tr class='odd'>
  2591. <td colspan='4' class='col1' style=\"width: 100%\">";
  2592. $detailhtml = $detailhtml . "$zusatz $devicenamet&nbsp&nbsp;&nbsp;$dalias
  2593. </td>";
  2594. # priority
  2595. my $aktfolge = $reihenfolgehtml;
  2596. my $newname = "reihe".$_;
  2597. my $tochange = "<option value='$savedetails{ $aktdevice . '_priority' }'>$savedetails{ $aktdevice . '_priority' }</option>";
  2598. my $change = "<option selected value='$savedetails{ $aktdevice . '_priority' }'>$savedetails{ $aktdevice . '_priority' }</option>";
  2599. $aktfolge =~ s/reihe/$newname/g;
  2600. $aktfolge =~ s/$tochange/$change/g;
  2601. $detailhtml = $detailhtml ."<td nowrap style='text-align: right;' class='col1'>";
  2602. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2603. {
  2604. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('priority')\">&nbsp;";
  2605. }
  2606. $detailhtml = $detailhtml ."priority: ". $aktfolge ."&nbsp;";
  2607. #$detailhtml = $detailhtml ."</td>";
  2608. # ende
  2609. # ID
  2610. $aktfolge = $idfolgehtml;
  2611. $newname = "idreihe".$_;
  2612. $tochange = "<option value='$savedetails{ $aktdevice . '_id' }'>$savedetails{ $aktdevice . '_id' }</option>";
  2613. $change = "<option selected value='$savedetails{ $aktdevice . '_id' }'>$savedetails{ $aktdevice . '_id' }</option>";
  2614. $aktfolge =~ s/idreihe/$newname/g;
  2615. $aktfolge =~ s/$tochange/$change/g;
  2616. $detailhtml = $detailhtml ."ID: ". $aktfolge;
  2617. $detailhtml = $detailhtml ."</td>";
  2618. # ende
  2619. }
  2620. else
  2621. {
  2622. $detailhtml = $detailhtml . "
  2623. <tr class='odd'>
  2624. <td colspan='5' class='col1'>";
  2625. $detailhtml = $detailhtml . "$zusatz $devicenamet&nbsp&nbsp;&nbsp;$dalias
  2626. </td>";
  2627. }
  2628. $detailhtml = $detailhtml . "</td></tr>
  2629. <tr class=''>
  2630. ";
  2631. my $rephide = "style='display:none;'";
  2632. my $rows = 7;
  2633. if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' )
  2634. {
  2635. $rephide = '';
  2636. $rows = 8;
  2637. }
  2638. $detailhtml = $detailhtml . "<td rowspan='$rows' class='col2'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
  2639. if ( $devicenamet ne 'FreeCmd' )
  2640. {
  2641. $detailhtml = $detailhtml . "</td>
  2642. <td nowrap class='col2' style='text-align: left;'>
  2643. <table border='0'><tr>
  2644. <td nowrap class='col2' style='text-align: left;'>
  2645. <br>";
  2646. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2647. {
  2648. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('onoff')\">&nbsp;";
  2649. }
  2650. $detailhtml = $detailhtml. "MSwitch 'cmd1':
  2651. Set <select class=\"devdetails2\" id='"
  2652. . $_
  2653. . "_on' name='cmdon"
  2654. . $_
  2655. . "' onchange=\"javascript: activate(document.getElementById('"
  2656. . $_
  2657. . "_on').value,'"
  2658. . $_
  2659. . "_on_sel','"
  2660. . $cmdsatz{$devicenamet}
  2661. . "','cmdonopt"
  2662. . $_
  2663. . "1')\" >
  2664. <option value='no_action'>no_action</option>";
  2665. $detailhtml = $detailhtml . $option1html;
  2666. $detailhtml = $detailhtml . "
  2667. </select>
  2668. <td nowrap valign=bottom id='" . $_ . "_on_sel'>&nbsp;</td>
  2669. </tr></table>
  2670. <td nowrap>
  2671. </td>
  2672. <td class='col2' style=\"width: 100%\">&nbsp;<br><input type='$hidden' id='cmdseton"
  2673. . $_
  2674. . "' name='cmdseton"
  2675. . $_
  2676. . "' size='20' value ='"
  2677. . $cmdsatz{$devicenamet} . "'>
  2678. <input type='$hidden' id='cmdonopt"
  2679. . $_
  2680. . "1' name='cmdonopt"
  2681. . $_
  2682. . "' size='20' value ='"
  2683. . $savedetails{ $aktdevice . '_onarg' }
  2684. . "'>&nbsp;&nbsp;&nbsp;";
  2685. }
  2686. else
  2687. {
  2688. $savedetails{ $aktdevice . '_onarg' }=~ s/'/&#039/g;
  2689. $detailhtml = $detailhtml . "</td>
  2690. <td class='col2' nowrap style='text-align: left;vertical-align: middle;'>
  2691. <table><tr>
  2692. <td>";
  2693. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2694. {
  2695. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('onoff')\">&nbsp;";
  2696. }
  2697. $detailhtml = $detailhtml. "MSwitch 'cmd1':</td>
  2698. <td><textarea class=\"devdetails\" cols='50' rows='3' id='cmdonopt". $_. "1' name='cmdonopt".$_. "'
  2699. >".$savedetails{ $aktdevice . '_onarg' }."</textarea>
  2700. </td>
  2701. </tr></table>
  2702. </td>";
  2703. $detailhtml = $detailhtml . "
  2704. <td style='text-align: left;' class='col2' nowrap id='" . $_ . "_on_sel'></td>
  2705. <td nowrap><input type='$hidden' id='". $_ . "_on' name='cmdon" . $_ . "' size='20' value ='cmd'></td>
  2706. <td class='col2' style=\"width: 100%\">&nbsp;<br><input type='$hidden' id='cmdseton"
  2707. . $_ . "' name='cmdseton" . $_ . "' size='20' value ='cmd'>";
  2708. }
  2709. $detailhtml = $detailhtml . "</td><td></td></tr>";
  2710. # block off #$devicename
  2711. if ( $devicenamet ne 'FreeCmd' )
  2712. {
  2713. $detailhtml = $detailhtml . "
  2714. <tr class='even'>
  2715. <td class='col2' nowrap style='text-align: left;'>
  2716. <table><tr>
  2717. <td class='col2' nowrap style='text-align: left;'>
  2718. ";
  2719. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2720. {
  2721. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('onoff')\">&nbsp;";
  2722. }
  2723. $detailhtml = $detailhtml. "MSwitch 'cmd2':
  2724. Set <select class=\"devdetails2\" id='"
  2725. . $_
  2726. . "_off' name='cmdoff"
  2727. . $_
  2728. . "' onchange=\"javascript: activate(document.getElementById('"
  2729. . $_
  2730. . "_off').value,'"
  2731. . $_
  2732. . "_off_sel','"
  2733. . $cmdsatz{$devicenamet}
  2734. . "','cmdoffopt"
  2735. . $_
  2736. . "1')\" >
  2737. <option value='no_action'>no_action</option>";
  2738. $detailhtml = $detailhtml
  2739. . $option2html; #achtung tausch $_ devicenamet oben unten
  2740. $detailhtml = $detailhtml . "
  2741. </select>
  2742. </td>
  2743. <td class='col2' nowrap id='" . $_ . "_off_sel' >&nbsp;</td>
  2744. </tr></table>
  2745. </td>
  2746. <td></td>
  2747. <td class='col2' nowrap>
  2748. <input type='$hidden' id='cmdsetoff"
  2749. . $_
  2750. . "' name='cmdsetoff"
  2751. . $_
  2752. . "' size='20' value ='"
  2753. . $cmdsatz{$devicenamet} . "'>
  2754. <input type='$hidden' id='cmdoffopt"
  2755. . $_
  2756. . "1' name='cmdoffopt"
  2757. . $_
  2758. . "' size='20' value ='"
  2759. . $savedetails{ $aktdevice . '_offarg' } . "'>&nbsp;&nbsp;&nbsp;";
  2760. }
  2761. else
  2762. {
  2763. $savedetails{ $aktdevice . '_offarg' }=~ s/'/&#039/g;
  2764. $detailhtml = $detailhtml . "
  2765. <tr class='even'>
  2766. <td class='col2' nowrap style='text-align: left;'>
  2767. <table><tr>
  2768. <td>";
  2769. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2770. {
  2771. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('onoff')\">&nbsp;";
  2772. }
  2773. $detailhtml = $detailhtml. "MSwitch 'cmd2':</td>
  2774. <td>
  2775. <textarea class=\"devdetails\" cols='50' rows='3' id='cmdoffopt"
  2776. . $_
  2777. . "1' name='cmdoffopt".$_
  2778. . "'
  2779. >".$savedetails{ $aktdevice . '_offarg' }."</textarea>
  2780. </td>
  2781. </tr></table>
  2782. </td>
  2783. <td style='text-align: left;' class='col2' nowrap id='" . $_ . "_off_sel' ></td>
  2784. <td><input type='$hidden' id='". $_ . "_off' name='cmdoff" . $_ . "' size='20' value ='cmd'></td>
  2785. <td class='col2' nowrap>
  2786. <input type='$hidden' id='cmdsetoff"
  2787. . $_
  2788. . "' name='cmdsetoff"
  2789. . $_
  2790. . "' size='20' value ='cmd'>";
  2791. }
  2792. $detailhtml = $detailhtml . "</td><td></td></tr>";
  2793. $detailhtml = $detailhtml . "
  2794. <tr class='even'>
  2795. <td class='col2' colspan='4' nowrap style='text-align: left;'>";
  2796. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2797. {
  2798. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('condition')\">&nbsp;";
  2799. }
  2800. $detailhtml = $detailhtml. "'cmd1' condition: <input class=\"devdetails\" type='text' id='conditionon"
  2801. . $_
  2802. . "' name='conditionon"
  2803. . $_
  2804. . "' size='55' value ='"
  2805. . $savedetails{ $aktdevice . '_conditionon' }
  2806. . "' onClick=\"javascript:bigwindow(this.id);\">&nbsp;&nbsp;&nbsp;";
  2807. if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '1' )
  2808. {
  2809. $detailhtml =$detailhtml
  2810. . "<input name='info' type='button' value='check condition' onclick=\"javascript: checkcondition('conditionon"
  2811. . $_
  2812. . "',document.querySelector('#checkon"
  2813. . $_
  2814. . "').value)\"> with \$EVENT=<select id = \"checkon"
  2815. . $_
  2816. . "\" name=\"checkon"
  2817. . $_ . "\">"
  2818. . $optiongeneral
  2819. . "</select>";
  2820. }
  2821. #alltriggers
  2822. $detailhtml = $detailhtml . "</td></tr>
  2823. <tr class='even'>
  2824. <td class='col2' colspan='4' nowrap style='text-align: left;'>";
  2825. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2826. {
  2827. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('condition')\">&nbsp;";
  2828. }
  2829. $detailhtml = $detailhtml. "'cmd2' condition: <input class=\"devdetails\" type='text' id='conditionoff"
  2830. . $_
  2831. . "' name='conditionoff"
  2832. . $_
  2833. . "' size='55' value ='"
  2834. . $savedetails{ $aktdevice . '_conditionoff' }
  2835. . "' onClick=\"javascript:bigwindow(this.id);\">&nbsp;&nbsp;&nbsp;";
  2836. if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '1' )
  2837. {
  2838. $detailhtml = $detailhtml
  2839. . "<input name='info' type='button' value='check condition' onclick=\"javascript: checkcondition('conditionoff"
  2840. . $_
  2841. . "',document.querySelector('#checkoff"
  2842. . $_
  2843. . "').value)\"> with \$EVENT=<select id = \"checkoff"
  2844. . $_
  2845. . "\" name=\"checkoff"
  2846. . $_ . "\">"
  2847. . $optiongeneral
  2848. . "</select>";
  2849. }
  2850. #### zeitrechner
  2851. my $delaym = 0;
  2852. my $delays = 0;
  2853. my $delayh = 0;
  2854. my $timestroff;
  2855. my $testtimestroff = $savedetails{ $aktdevice . '_timeoff' };
  2856. if ( $testtimestroff ne '[random]' )
  2857. {
  2858. $testtimestroff =~ s/[A-Za-z0-9#\.\-_]//g;
  2859. if ( $testtimestroff eq "[:]" || $testtimestroff eq "[\$:]" )
  2860. {
  2861. $timestroff =
  2862. $savedetails{ $aktdevice . '_timeoff' }; #sekunden
  2863. }
  2864. else
  2865. {
  2866. $timestroff =
  2867. $savedetails{ $aktdevice . '_timeoff' }; #sekunden
  2868. $delaym = int $timestroff / 60;
  2869. $delays = $timestroff - ( $delaym * 60 );
  2870. $delayh = int $delaym / 60;
  2871. $delaym = $delaym - ( $delayh * 60 );
  2872. $timestroff =
  2873. sprintf( "%02d:%02d:%02d", $delayh, $delaym, $delays );
  2874. }
  2875. }
  2876. else
  2877. {
  2878. $timestroff = "[random]";
  2879. }
  2880. my $timestron;
  2881. my $testtimestron = $savedetails{ $aktdevice . '_timeon' };
  2882. #Log3( $Name, 0,"testtimestron -> $testtimestron " . __LINE__ );
  2883. if ( $testtimestron ne '[random]' )
  2884. {
  2885. $testtimestron =~ s/[A-Za-z0-9#\.\-_]//g;
  2886. if ( $testtimestron eq "[:]" || $testtimestron eq "[\$:]" )
  2887. {
  2888. $timestron =$savedetails{ $aktdevice . '_timeon' }; #sekunden
  2889. }
  2890. else
  2891. {
  2892. $timestron =
  2893. $savedetails{ $aktdevice . '_timeon' }; #sekunden
  2894. $delaym = int $timestron / 60;
  2895. $delays = $timestron - ( $delaym * 60 );
  2896. $delayh = int $delaym / 60;
  2897. $delaym = $delaym - ( $delayh * 60 );
  2898. $timestron =
  2899. sprintf( "%02d:%02d:%02d", $delayh, $delaym, $delays );
  2900. }
  2901. }
  2902. else
  2903. {
  2904. $timestron = "[random]";
  2905. }
  2906. $detailhtml = $detailhtml . "</td></tr><tr class='even'>
  2907. <td class='col2' colspan='4' nowrap style='text-align: left;'>";
  2908. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2909. {
  2910. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('timer')\">&nbsp;";
  2911. }
  2912. $detailhtml = $detailhtml. "'cmd1'&nbsp;
  2913. <select id = '' name='onatdelay" . $_ . "'>";
  2914. my $se11 = '';
  2915. my $sel2 = '';
  2916. my $sel3 = '';
  2917. my $sel4 = '';
  2918. my $sel5 = '';
  2919. my $sel6 = '';
  2920. my $testkey = $aktdevice . '_delaylaton';
  2921. $se11 = 'selected' if ( $savedetails{ $aktdevice . '_delayaton' } eq "delay1" ) ;
  2922. $sel2 = 'selected' if ( $savedetails{ $aktdevice . '_delayaton' } eq "delay0" ) ;
  2923. $sel5 = 'selected' if ( $savedetails{ $aktdevice . '_delayaton' } eq "delay2" ) ;
  2924. $sel4 = 'selected' if ( $savedetails{ $aktdevice . '_delayaton' } eq "at0" ) ;
  2925. $sel3 = 'selected' if ( $savedetails{ $aktdevice . '_delayaton' } eq "at1" );
  2926. $sel6 = 'selected' if ( $savedetails{ $aktdevice . '_delayaton' } eq "at2" );
  2927. $detailhtml = $detailhtml . "<option $se11 value='delay1'>delay with Cond-check immediately and delayed: +</option>";
  2928. $detailhtml = $detailhtml . "<option $sel2 value='delay0'>delay with Cond-check immediately only: +</option>";
  2929. $detailhtml = $detailhtml . "<option $sel5 value='delay2'>delay with Cond-check delayed only: +</option>";
  2930. $detailhtml = $detailhtml . "<option $sel4 value='at0'>at with Cond-check immediately and delayed:</option>";
  2931. $detailhtml = $detailhtml . "<option $sel3 value='at1'>at with Cond-check immediately only:</option>";
  2932. $detailhtml = $detailhtml . "<option $sel6 value='at0'>at with Cond-check delayed only:</option>";
  2933. $detailhtml = $detailhtml . "</select><input type='text' class=\"devdetails\" id='timeseton"
  2934. . $_
  2935. . "' name='timeseton"
  2936. . $_
  2937. . "' size='30' value ='"
  2938. . $timestron
  2939. . "'> (hh:mm:ss)</td></tr>";
  2940. $detailhtml = $detailhtml . "
  2941. <tr class='even'>
  2942. <td class='col2' colspan='4' nowrap style='text-align: left;'>";
  2943. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2944. {
  2945. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('timer')\">&nbsp;";
  2946. }
  2947. $detailhtml = $detailhtml. "'cmd2'&nbsp;
  2948. <select id = '' name='offatdelay" . $_ . "'>";
  2949. $se11 = '';
  2950. $sel2 = '';
  2951. $sel3 = '';
  2952. $sel4 = '';
  2953. $sel5 = '';
  2954. $sel6 = '';
  2955. $testkey = $aktdevice . '_delaylatoff';
  2956. $se11 = 'selected' if ( $savedetails{ $aktdevice . '_delayatoff' } eq "delay1" ) ;
  2957. $sel2 = 'selected' if ( $savedetails{ $aktdevice . '_delayatoff' } eq "delay0" ) ;
  2958. $sel5 = 'selected' if ( $savedetails{ $aktdevice . '_delayatoff' } eq "delay2" ) ;
  2959. $sel4 = 'selected' if ( $savedetails{ $aktdevice . '_delayatoff' } eq "at0" ) ;
  2960. $sel3 = 'selected' if ( $savedetails{ $aktdevice . '_delayatoff' } eq "at1" );
  2961. $sel6 = 'selected' if ( $savedetails{ $aktdevice . '_delayatoff' } eq "at2" );
  2962. $detailhtml = $detailhtml . "<option $se11 value='delay1'>delay with Cond-check immediately and delayed: +</option>";
  2963. $detailhtml = $detailhtml . "<option $sel2 value='delay0'>delay with Cond-check immediately only: +</option>";
  2964. $detailhtml = $detailhtml . "<option $sel5 value='delay2'>delay with Cond-check delayed only: +</option>";
  2965. $detailhtml = $detailhtml . "<option $sel4 value='at0'>at with Cond-check immediately and delayed:</option>";
  2966. $detailhtml = $detailhtml . "<option $sel3 value='at1'>at with Cond-check immediately only:</option>";
  2967. $detailhtml = $detailhtml . "<option $sel6 value='at0'>at with Cond-check delayed only:</option>";
  2968. $detailhtml = $detailhtml . "</select><input type='text' class=\"devdetails\" id='timesetoff"
  2969. . $_
  2970. . "' name='timesetoff"
  2971. . $_
  2972. . "' size='30' value ='"
  2973. . $timestroff
  2974. . "'> (hh:mm:ss)&nbsp;&nbsp;&nbsp;";
  2975. $detailhtml = $detailhtml . "</td></tr>";
  2976. $detailhtml = $detailhtml . "<tr $rephide class='even'>
  2977. <td class='col2' colspan='4' style='text-align: left;'>";
  2978. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  2979. {
  2980. $detailhtml = $detailhtml. "<input name='info' type='button' value='?' onclick=\"javascript: info('repeats')\">&nbsp;";
  2981. }
  2982. $detailhtml = $detailhtml. "Repeats:
  2983. <input type='text' id='repeatcount' name='repeatcount"
  2984. . $_
  2985. . "' size='10' value ='"
  2986. . $savedetails{ $aktdevice . '_repeatcount' } . "'>
  2987. &nbsp;&nbsp;&nbsp;
  2988. Repeatdelay in sec:
  2989. <input type='text' id='repeattime' name='repeattime"
  2990. . $_
  2991. . "' size='10' value ='"
  2992. . $savedetails{ $aktdevice . '_repeattime' } . "'>
  2993. </td></tr>";
  2994. $detailhtml = $detailhtml . "<tr $rephide class='even'>
  2995. <td class='col2' colspan='4' style='text-align: left;'>
  2996. <br>
  2997. </td></tr>";
  2998. $detailhtml = $detailhtml . "<tr class='even'>
  2999. <td class='col2' colspan='5' style='text-align: left;'>";
  3000. if ( $devicenumber == 1 )
  3001. {
  3002. $detailhtml = $detailhtml . "<input name='info' class=\"randomidclass\" id=\"add_action1_".rand(1000000)."\" type='button' value='add action for $devicenamet' onclick=\"javascript: addevice('$devicenamet')\">";
  3003. }
  3004. $detailhtml = $detailhtml . "<input name='info' id=\"del_action1_".rand(1000000)."\" class=\"randomidclass\" type='button' value='delete this action for $devicenamet' onclick=\"javascript: deletedevice('$_')\">";
  3005. $detailhtml = $detailhtml . "<br>&nbsp;</td></tr>";
  3006. #middle
  3007. ####################change1 = change.replace(/,/g,'##');
  3008. # javazeile für übergabe erzeugen
  3009. $javaform = $javaform . "
  3010. devices += \$(\"[name=cmdon$_]\").val()+'#[NF]';
  3011. devices += \$(\"[name=cmdoff$_]\").val()+'#[NF]';
  3012. change = \$(\"[name=cmdonopt$_]\").val();
  3013. devices += change+'#[NF]';;
  3014. change = \$(\"[name=cmdoffopt$_]\").val();
  3015. devices += change+'#[NF]';;
  3016. devices += \$(\"[name=onatdelay$_]\").val();
  3017. devices += '#[NF]';
  3018. devices += \$(\"[name=offatdelay$_]\").val();
  3019. devices += '#[NF]';
  3020. delay1 = \$(\"[name=timesetoff$_]\").val();
  3021. devices += delay1+'#[NF]';
  3022. delay2 = \$(\"[name=timeseton$_]\").val();
  3023. devices += delay2+'#[NF]';
  3024. devices1 = \$(\"[name=conditionon$_]\").val();
  3025. devices2 = \$(\"[name=conditionoff$_]\").val();
  3026. devices2 = devices2.replace(/\\|/g,'(DAYS)');
  3027. devices += devices1+'#[NF]';
  3028. devices += devices2;
  3029. devices += '#[NF]';
  3030. devices3 = \$(\"[name=repeatcount$_]\").val();
  3031. devices += devices3;
  3032. devices += '#[NF]';
  3033. devices += \$(\"[name=repeattime$_]\").val();
  3034. devices += '#[NF]';
  3035. devices += \$(\"[name=reihe$_]\").val();
  3036. devices += '#[NF]';
  3037. devices += \$(\"[name=idreihe$_]\").val();
  3038. devices += '#[ND]';
  3039. ";
  3040. }
  3041. ####################
  3042. $detailhtml = $detailhtml;
  3043. $detailhtml = $detailhtml . "<tr class='even'><td colspan='5'><left>
  3044. <input type='button' id='aw_det' value='modify Actions' >
  3045. </td></tr></table>"; #end
  3046. }
  3047. ####################
  3048. my $triggercondition = ReadingsVal( $Name, '.Trigger_condition', '' );
  3049. $triggercondition =~ s/~/ /g;
  3050. $triggercondition =~ s/#\[dp\]/:/g;
  3051. $triggercondition =~ s/#\[pt\]/./g;
  3052. $triggercondition =~ s/#\[ti\]/~/g;
  3053. $triggercondition =~ s/#\[sp\]/ /g;
  3054. #MSwitch_LOG( $name, 5, "$name: aufruf on/off -> $cmd" );
  3055. my $triggertime = ReadingsVal( $Name, '.Trigger_time', '' );
  3056. $triggertime =~ s/#\[dp\]/:/g;
  3057. my @triggertimes = split( /~/, $triggertime );
  3058. my $condition = ReadingsVal( $Name, '.Trigger_time', '' );
  3059. my $lenght = length($condition);
  3060. my $timeon = '';
  3061. my $timeoff = '';
  3062. my $timeononly = '';
  3063. my $timeoffonly = '';
  3064. if ( $lenght != 0 ) {
  3065. $timeon = substr( $triggertimes[0], 2 );
  3066. $timeoff = substr( $triggertimes[1], 3 );
  3067. $timeononly = substr( $triggertimes[2], 6 );
  3068. $timeoffonly = substr( $triggertimes[3], 7 );
  3069. }
  3070. my $ret ='';
  3071. $ret .="<p id=\"triggerdevice\">";
  3072. ########################
  3073. my $blocking ='' ;
  3074. $blocking =$hash->{helper}{savemodeblock}{blocking} if ( defined $hash->{helper}{savemodeblock}{blocking}) ;
  3075. if ($blocking eq 'on')
  3076. {
  3077. $ret .="<table border='$border' class='block wide' id=''>
  3078. <tr class='even'>
  3079. <td><center>&nbsp;<br>ACHTUNG: Der Safemodus hat eine Endlosschleife erkannt, welche zum Fhemabsturz führen könnte.<br>Dieses Device wurde automatisch deaktiviert ( ATTR 'disable') !<br>&nbsp;
  3080. </td></tr></table><br>&nbsp;<br>
  3081. ";
  3082. }
  3083. my $errortest="";
  3084. $errortest = $hash->{helper}{error} if ( defined $hash->{helper}{error}) ;
  3085. if ($errortest ne "")
  3086. {
  3087. $ret .="<table border='$border' class='block wide' id=''>
  3088. <tr class='even'>
  3089. <td><center>&nbsp;<br>AT-Kommandos können nicht ausgeführt werden !<br>".$errortest."<br>&nbsp;
  3090. </td></tr></table><br>&nbsp;<br>
  3091. ";
  3092. }
  3093. if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '2' || AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '3' )
  3094. {
  3095. my $Zeilen = ("");
  3096. open( BACKUPDATEI, "./log/MSwitch_debug_$Name.log" ) ;
  3097. while (<BACKUPDATEI>)
  3098. {
  3099. $Zeilen = $Zeilen . $_;
  3100. }
  3101. close(BACKUPDATEI);
  3102. my $text ="";
  3103. $text = "Das Device befindet sich im Debug 2 Mode. Es werden keine Befehle ausgeführt, sondern nur protokolliert." if AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '2';
  3104. $text = "Das Device befindet sich im Debug 3 Mode. Alle Aktionen werden protokolliert." if AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '3';
  3105. $ret .="<table border='$border' class='block wide' id=''>
  3106. <tr class='even'>
  3107. <td><center>&nbsp;<br>
  3108. $text<br>&nbsp;<br>
  3109. <textarea name=\"log\" id=\"log\" rows=\"5\" cols=\"160\" STYLE=\"font-family:Arial;font-size:9pt;\">"
  3110. . $Zeilen
  3111. . "</textarea>
  3112. <br>&nbsp;<br>
  3113. <input type=\"button\" id=\"\"
  3114. value=\"clear log\" onClick=\"clearlog();\">
  3115. <br>&nbsp;<br>
  3116. </td></tr></table><br>
  3117. <br>
  3118. ";
  3119. }
  3120. # anpassung durch configeinspielung
  3121. if ( ReadingsVal( $Name, '.change', 'undef') ne "undef")
  3122. {
  3123. # geräteliste
  3124. my $dev;
  3125. for my $name ( sort keys %defs )
  3126. {
  3127. my $devicealias = AttrVal( $name, 'alias', "" );
  3128. my $devicewebcmd =AttrVal( $name, 'webCmd', "noArg" );
  3129. my $devicehash = $defs{$name};
  3130. my $deviceTYPE = $devicehash->{TYPE};
  3131. $dev .="<option selected=\"\" value=\"$name\">". $name." (a: ".$devicealias. ")</option>";
  3132. }
  3133. my $sel="<select id = \"CID\" name=\"trigon\">" . $dev . "</select>";
  3134. my @change = split( "\\|", ReadingsVal( $Name, '.change', 'undef') );
  3135. my $out ='';
  3136. my $count = 0;
  3137. foreach my $changes (@change)
  3138. {
  3139. my @set = split( "#", $changes );
  3140. $out .="<tr class='even'>";
  3141. $out .="<td>";
  3142. $out .= $set[1];
  3143. $out .="</td>";
  3144. $out .="<td>";
  3145. #$out .= $set[0];
  3146. $out .="</td>";
  3147. $out .="<td>";
  3148. $out .="<input type='' id='cdorg".$count."' name='' value ='$set[0]' disabled> ersetzen durch:";
  3149. if ($set[2] eq "device")
  3150. {
  3151. my $newstring = $sel;
  3152. my $newname = "cdnew".$count;
  3153. $newstring =~ s/CID/$newname/g;
  3154. $out .=$newstring;
  3155. }
  3156. else{
  3157. $out .="&nbsp;<input type='' id='cdnew".$count."' name='' size='20' value =''>";
  3158. }
  3159. $out .="</td>";
  3160. $out .="</tr>";
  3161. #$out ="<tr><td>test</td></tr>";
  3162. $count++;
  3163. }
  3164. $ret .="
  3165. <table border='$border' class='block wide' id=''>
  3166. <tr class='even'>
  3167. <td colspan ='3'><center>&nbsp;<br>Eingriff erforderlich !<br>&nbsp;";
  3168. $ret .=ReadingsVal( $Name, '.change_info', '') ;
  3169. $ret .="</td></tr>".$out."
  3170. <tr class='even'>
  3171. <td colspan ='3'><center>&nbsp;<br>
  3172. <input type=\"button\" id=\"\"
  3173. value=\"save changes\" onClick=\"changedevices();\">
  3174. <br>&nbsp;<br>
  3175. </td></tr></table><br>
  3176. <br>
  3177. ";
  3178. $j1 = "<script type=\"text/javascript\">{";
  3179. $j1 .=
  3180. "var t=\$(\"#MSwitchWebTR\"), ip=\$(t).attr(\"ip\"), ts=\$(t).attr(\"ts\");
  3181. FW_replaceWidget(\"[name=aw_ts]\", \"aw_ts\", [\"time\"], \"12:00\");
  3182. \$(\"[name=aw_ts] input[type=text]\").attr(\"id\", \"aw_ts\");";
  3183. $j1 .= "function changedevices(){
  3184. var count = $count;
  3185. var string = '';
  3186. for (i=0; i<count; i++)
  3187. {
  3188. var field1 = 'cdorg'+i;
  3189. var field2 = 'cdnew'+i;
  3190. string += document.getElementById(field1).value + '#' + document.getElementById(field2).value + '|';
  3191. }
  3192. var strneu = string.substr(0, string.length-1);
  3193. strneu = strneu.replace(/ /g,'#[sp]');
  3194. var def = \"".$Name."\"+\" confchange \"+encodeURIComponent(strneu);
  3195. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  3196. }";
  3197. $j1 .= "}</script>";
  3198. return "$ret"."$j1";
  3199. }
  3200. #readingsSingleUpdate( $hash, ".wrong_version", $1, 0 );
  3201. if ( ReadingsVal( $Name, '.wrong_version', 'undef') ne "undef")
  3202. {
  3203. $ret .="<table border='$border' class='block wide' id=''>
  3204. <tr class='even'>
  3205. <td><center>&nbsp;<br>Einspielen des Configfiles nicht möglich !<br>falsche Versionsnummer: ".ReadingsVal( $Name, '.wrong_version', '')."<br>geforderte Versionsnummer $vupdate<br>&nbsp;
  3206. </td></tr></table><br>
  3207. <br>
  3208. ";
  3209. fhem("deletereading $Name .wrong_version");
  3210. }
  3211. if ( ReadingsVal( $Name, '.V_Check', $vupdate ) ne $vupdate )
  3212. {
  3213. my $ver = ReadingsVal( $Name, '.V_Check', '' );
  3214. $ret .="<table border='$border' class='block wide' id=''>
  3215. <tr class='even'>
  3216. <td><center>&nbsp;<br>Versionskonflikt erkannt!<br>Das Device führt derzeit keine Aktionen aus. Bitte ein Update des Devices vornehmen.<br>Erwartete Strukturversionsnummer: $vupdate<br>Vorhandene Strukturversionsnummer: $ver <br>&nbsp;<br>
  3217. <input type=\"button\" id=\"\"
  3218. value=\"try update to $vupdate\" onClick=\"vupdate();\">
  3219. <br>&nbsp;<br>
  3220. </td></tr></table><br>
  3221. <br>
  3222. ";
  3223. $j1 = "<script type=\"text/javascript\">{";
  3224. $j1 .=
  3225. "var t=\$(\"#MSwitchWebTR\"), ip=\$(t).attr(\"ip\"), ts=\$(t).attr(\"ts\");
  3226. FW_replaceWidget(\"[name=aw_ts]\", \"aw_ts\", [\"time\"], \"12:00\");
  3227. \$(\"[name=aw_ts] input[type=text]\").attr(\"id\", \"aw_ts\");";
  3228. $j1 .= "function vupdate(){
  3229. conf='';
  3230. var def = \"".$Name."\"+\" VUpdate \"+encodeURIComponent(conf);
  3231. //alert(def);
  3232. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  3233. }";
  3234. $j1 .= "}</script>";
  3235. return "$ret"."$j1";
  3236. }
  3237. $ret .="<table border='$border' class='block wide' id=''>
  3238. <tr class='even'>
  3239. <td><center>&nbsp;<br>Device is disabled, configuration avaible<br>&nbsp;<br>
  3240. </td></tr></table><br>" if ( IsDisabled($Name));
  3241. ####################
  3242. $ret .="<table border='$border' class='block wide' id='MSwitchWebTR' nm='$hash->{NAME}'>";
  3243. $ret .=" <tr class=\"even\">";
  3244. $ret .="<td colspan=\"3\" id =\"savetrigger\">trigger device/time:&nbsp;&nbsp;&nbsp;";
  3245. $ret = $ret . "</td>
  3246. </tr>
  3247. <tr class=\"even\">
  3248. <td></td>
  3249. <td></td>
  3250. <td></td>
  3251. </tr>
  3252. <tr class=\"even\">
  3253. <td>";
  3254. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3255. {
  3256. $ret = $ret. "<input name='info' type='button' value='?' onclick=\"javascript: info('trigger')\">&nbsp;";
  3257. }
  3258. $ret .="Trigger device: </td>
  3259. <td colspan =\"2\">
  3260. <select id =\"trigdev\" name=\"trigdev\">".$triggerdevices."</select>
  3261. </td>
  3262. </tr>";
  3263. my $visible = 'visible';
  3264. if ( $globalon ne 'on' )
  3265. {
  3266. $visible = 'collapse';
  3267. }
  3268. $ret = $ret . "<tr class=\"even\" id='triggerwhitelist' style=\"visibility:" . $visible . ";\" >
  3269. <td nowrap>";
  3270. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3271. {
  3272. $ret = $ret. "<input name='info' type='button' value='?' onclick=\"javascript: info('whitelist')\">&nbsp;";
  3273. }
  3274. $ret = $ret. "Trigger Device Global Whitelist:
  3275. </td>
  3276. <td></td>
  3277. <td><input type='text' id ='triggerwhite' name='triggerwhitelist' size='30' value ='"
  3278. . ReadingsVal( $Name, '.Trigger_Whitelist', '' )
  3279. . "' onClick=\"javascript:bigwindow(this.id);\" >";
  3280. $ret = $ret . "</td></tr>";
  3281. my $inhalt = "execute 'cmd1' only at :";
  3282. my $inhalt1 = "execute 'cmd2' only at :";
  3283. my $inhalt2 = "execute 'cmd1' only";
  3284. my $inhalt3 = "execute 'cmd2' only";
  3285. my $inhalt4 = "switch MSwitch on + execute 'cmd1' at :";
  3286. my $inhalt5 = "switch $Name on + execute 'cmd1'";
  3287. my $displaynot = '';
  3288. my $displayntog = '';
  3289. my $help ="";
  3290. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3291. {
  3292. $help = "<input name='info' type='button' value='?' onclick=\"javascript: info('execcmd')\">&nbsp;";
  3293. }
  3294. if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Notify" )
  3295. {
  3296. $displaynot = "style='display:none;'";
  3297. $inhalt = "execute 'cmd1' at :";
  3298. $inhalt1 = "execute 'cmd2' at :";
  3299. $inhalt2 = $help."execute 'cmd1'";
  3300. $inhalt3 = $help."execute 'cmd2'";
  3301. }
  3302. if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Toggle" )
  3303. {
  3304. $displayntog = "style='display:none;'";
  3305. $inhalt4 = "toggle $Name + execute 'cmd1/cmd2' at :";
  3306. $inhalt5 = "toggle $Name + execute 'cmd1/cmd2'";
  3307. }
  3308. $ret = $ret . "
  3309. <tr class=\"even\">
  3310. <td>";
  3311. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3312. {
  3313. $ret = $ret. "<input name='info' type='button' value='?' onclick=\"javascript: info('trigger')\">&nbsp;";
  3314. }
  3315. $ret = $ret. "Trigger time: </td>
  3316. <td></td>
  3317. <td>
  3318. </td>
  3319. </tr>
  3320. <tr " . $displaynot . " class=\"even\">
  3321. <td></td>
  3322. <td>" . $inhalt4 . "</td>
  3323. <td><input type='text' id='timeon' name='timeon' size='60' value ='"
  3324. . $timeon . "'></td>
  3325. </tr>
  3326. <tr " . $displaynot . $displayntog . " class=\"even\">
  3327. <td></td>
  3328. <td>switch MSwitch off + execute 'cmd2' at :</td>
  3329. <td><input type='text' id='timeoff' name='timeoff' size='60' value ='"
  3330. . $timeoff . "'></td>
  3331. </tr>
  3332. <tr " . $displayntog . "class=\"even\">
  3333. <td></td>
  3334. <td>" . $inhalt . "</td>
  3335. <td><input type='text' id='timeononly' name='timeononly' size='60' value ='"
  3336. . $timeononly . "'></td>
  3337. </tr>
  3338. <tr " . $displayntog . "class=\"even\">
  3339. <td></td>
  3340. <td>" . $inhalt1 . "</td>
  3341. <td><input type='text' id='timeoffonly' name='timeoffonly' size='60' value ='"
  3342. . $timeoffonly . "'></td>
  3343. </tr>";
  3344. my $triggerinhalt = "Trigger condition (events only): ";
  3345. if ( AttrVal( $Name, 'MSwitch_Condition_Time', "0" ) eq '1' )
  3346. {
  3347. $triggerinhalt ="Trigger condition (time&events): ";
  3348. }
  3349. $ret = $ret . "<tr class=\"even\">
  3350. <td>";
  3351. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3352. {
  3353. $ret = $ret .= "<input name='info' type='button' value='?' onclick=\"javascript: info('triggercondition')\">&nbsp;";
  3354. }
  3355. $ret = $ret . $triggerinhalt."</td>
  3356. <td></td>
  3357. <td><input type='text' id='triggercondition' name='triggercondition' size='60' value ='"
  3358. . $triggercondition . "' onClick=\"javascript:bigwindow(this.id);\" >";
  3359. if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '1' )
  3360. {
  3361. # $ret = $ret. " <input name='info' type='button' value='check condition' onclick=\"javascript: checkcondition('triggercondition',document.querySelector('#triggercondition').value)\">";
  3362. $ret = $ret. " <input name='info' type='button' value='check condition' onclick=\"javascript: checkcondition('triggercondition','$Name:trigger:conditiontest')\">";
  3363. }
  3364. $ret = $ret . "</td></tr>";
  3365. $ret = $ret . "<tr class=\"even\">
  3366. <td colspan=\"3\"><left>
  3367. <input type=\"button\" id=\"aw_trig\" value=\"modify Trigger Device\"$disable>
  3368. </td>
  3369. </tr>
  3370. </table></p>";
  3371. ####################
  3372. # triggerdetails
  3373. my $selectedcheck3 = "";
  3374. my $testlog = ReadingsVal( $Name, 'Trigger_log', 'on' );
  3375. if ( $testlog eq 'on' )
  3376. {
  3377. $selectedcheck3 = "checked=\"checked\"";
  3378. }
  3379. if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) ne 'no_trigger' )
  3380. {
  3381. $ret .="<table border='$border' class='block wide' id='MSwitchWebTRDT' nm='$hash->{NAME}'>
  3382. <tr class=\"even\">
  3383. <td id =\"triggerdetails\">trigger details :</td>
  3384. <td></td>
  3385. <td></td>
  3386. </tr>
  3387. <tr class=\"even\">
  3388. <td></td>
  3389. <td></td>
  3390. <td></td>
  3391. </tr>";
  3392. $ret .= "<tr " . $displaynot . " class=\"even\"><td>";
  3393. $ret .= $inhalt5. "</td><td>
  3394. Trigger " . $Triggerdevice . " :
  3395. </td>
  3396. <td>
  3397. <select id = \"trigon\" name=\"trigon\">" . $optionon . "</select>
  3398. </td>
  3399. </tr>
  3400. <tr " . $displaynot . $displayntog . "class=\"even\">
  3401. <td>
  3402. switch " . $Name . " off + execute 'cmd2'</td>
  3403. <td>
  3404. Trigger " . $Triggerdevice . " :
  3405. </td>
  3406. <td>
  3407. <select id = \"trigoff\" name=\"trigoff\">" . $optionoff . "</select>
  3408. </td>
  3409. </tr>";
  3410. $ret .= "<tr class=\"even\">
  3411. <td colspan=\"3\" >&nbsp</td>
  3412. </tr>
  3413. <tr " . $displayntog . " class=\"even\">
  3414. <td>" . $inhalt2 . "</td>
  3415. <td>
  3416. Trigger " . $Triggerdevice . " :
  3417. </td>
  3418. <td>
  3419. <select id = \"trigcmdon\" name=\"trigcmdon\">" . $optioncmdon . "</select>
  3420. </td>
  3421. </tr>
  3422. <tr " . $displayntog . "class=\"even\">
  3423. <td>" . $inhalt3 . "</td>
  3424. <td>
  3425. Trigger " . $Triggerdevice . " :
  3426. </td>
  3427. <td>
  3428. <select id = \"trigcmdoff\" name=\"trigcmdoff\">"
  3429. . $optioncmdoff . "</select>
  3430. </td>
  3431. </tr>
  3432. <tr class=\"even\">
  3433. <td colspan=\"1\"><left>";
  3434. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3435. {
  3436. $ret = $ret . "<input name='info' type='button' value='?' onclick=\"javascript: info('saveevent')\">&nbsp;";
  3437. }
  3438. $ret = $ret . "Save incomming events :
  3439. </td>
  3440. <td><input $selectedcheck3 name=\"aw_save\" type=\"checkbox\" $disable></td>
  3441. <td></td>
  3442. </tr>
  3443. <tr class=\"even\">
  3444. <td colspan=\"1\"><left>";
  3445. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3446. {
  3447. $ret = $ret . "<input name='info' type='button' value='?' onclick=\"javascript: info('addevent')\">&nbsp;";
  3448. }
  3449. $ret .= "Add event manually :
  3450. </td>
  3451. <td><left>
  3452. <input type='text' id='add_event' name='add_event' size='40' value =''>
  3453. <input type=\"button\" id=\"aw_addevent\" value=\"add event\"$disable>";
  3454. $ret .= "</td>
  3455. <td><left>
  3456. </td>
  3457. </tr>
  3458. <tr class=\"even\">
  3459. <td colspan=\"2\"><left>
  3460. <input type=\"button\" id=\"aw_md\" value=\"modify Trigger\"$disable>
  3461. <input type=\"button\" id=\"aw_md1\" value=\"apply filter to saved events\" $disable>
  3462. <input type=\"button\" id=\"aw_md2\" value=\"clear saved events\"$disable>&nbsp;&nbsp;&nbsp;
  3463. </td>
  3464. <td><left>";
  3465. if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '1' && $optiongeneral ne '' )
  3466. {
  3467. $ret .="<select id = \"eventtest\" name=\"eventtest\">"
  3468. . $optiongeneral
  3469. . "</select><input type=\"button\" id=\"aw_md2\" value=\"test event\"$disable onclick=\"javascript: checkevent(document.querySelector('#eventtest').value)\">";
  3470. }
  3471. $ret .= "</td></tr> </table></p>";
  3472. }
  3473. else
  3474. {
  3475. $ret .= "<p id=\"MSwitchWebTRDT\"></p>";
  3476. }
  3477. # affected devices
  3478. $ret .= "<table border='$border' class='block wide' id='MSwitchWebAF' nm='$hash->{NAME}'>
  3479. <tr class=\"even\">
  3480. <td>affected devices :</td>
  3481. <td></td>
  3482. <td></td>
  3483. </tr>
  3484. <tr class=\"even\">
  3485. <td>
  3486. </td>
  3487. <td>
  3488. </td>
  3489. <td></td>
  3490. </tr>
  3491. <tr class=\"even\">
  3492. <td>";
  3493. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3494. {
  3495. $ret .= "<input name='info' type='button' value='?' onclick=\"javascript: info('affected')\">&nbsp;";
  3496. }
  3497. $ret .="multiple selection with ctrl + mousebutton</td>
  3498. <td><p id =\"textfie\">
  3499. <select id =\"devices\" multiple=\"multiple\" name=\"affected_devices\" size=\"6\" disabled >";
  3500. $ret .= $deviceoption;
  3501. $ret .= "</select>
  3502. </p>
  3503. </td>
  3504. <td><center>
  3505. <input type=\"button\" id=\"aw_great\"
  3506. value=\"edit list\" onClick=\"javascript:deviceselect();\">
  3507. <br>
  3508. <input onChange=\"javascript:switchlock();\" checked=\"checked\" id=\"lockedit\" name=\"lockedit\" type=\"checkbox\" value=\"lockedit\" /> quickedit locked
  3509. <br>
  3510. <br>
  3511. </td>
  3512. </tr>
  3513. <tr class=\"even\">
  3514. <td><leftt>
  3515. <input type=\"button\" id=\"aw_dev\" value=\"modify Devices\"$disable>
  3516. </td>
  3517. <td>&nbsp;</td>
  3518. <td>&nbsp;</td>
  3519. </tr>
  3520. </table>";
  3521. ####################
  3522. #javascript$jsvarset
  3523. my $triggerdevicehtml = $Triggerdevice;
  3524. $triggerdevicehtml =~ s/\(//g;
  3525. $triggerdevicehtml =~ s/\)//g;
  3526. $j1 = "<script type=\"text/javascript\">{";
  3527. if ( AttrVal( $Name, 'MSwitch_Lock_Quickedit', "1" ) eq '0' )
  3528. {
  3529. $j1 .= "
  3530. \$(\"#devices\").prop(\"disabled\", false);
  3531. document.getElementById('aw_great').value='schow greater list';
  3532. document.getElementById('lockedit').checked = false ;
  3533. ";
  3534. }
  3535. if ( $affecteddevices[0] ne 'no_device' )
  3536. {
  3537. $j1 .= "
  3538. var affected = document.getElementById('affected').value
  3539. var devices = affected.split(\",\");
  3540. var i;
  3541. var len = devices.length;
  3542. for (i=0; i<len; i++)
  3543. {
  3544. testname = devices[i].split(\"-\");
  3545. if (testname[0] == \"FreeCmd\") {
  3546. continue;
  3547. }
  3548. sel = devices[i] + '_on';
  3549. sel1 = devices[i] + '_on_sel';
  3550. sel2 = 'cmdonopt' + devices[i] + '1';
  3551. sel3 = 'cmdseton' + devices[i];
  3552. aktcmd = document.getElementById(sel).value;
  3553. aktset = document.getElementById(sel3).value;
  3554. activate(document.getElementById(sel).value,sel1,aktset,sel2);
  3555. sel = devices[i] + '_off';
  3556. sel1 = devices[i] + '_off_sel';
  3557. sel2 = 'cmdoffopt' + devices[i] + '1';
  3558. sel3 = 'cmdsetoff' + devices[i];
  3559. aktcmd = document.getElementById(sel).value;
  3560. aktset = document.getElementById(sel3).value;
  3561. activate(document.getElementById(sel).value,sel1,aktset,sel2);
  3562. };"
  3563. }
  3564. # java wird bei seitenaufruf ausgeführt
  3565. $j1 .= "
  3566. var globallock='';
  3567. var randomdev=[];
  3568. var x = document.getElementsByClassName('randomidclass');
  3569. for (var i = 0; i < x.length; i++)
  3570. {
  3571. var t = x[i].id;
  3572. randomdev.push(t);
  3573. }";
  3574. $j1 .= "
  3575. var globaldetails2='undefined';
  3576. var x = document.getElementsByClassName('devdetails2');
  3577. for (var i = 0; i < x.length; i++)
  3578. {
  3579. var t = x[i].id;
  3580. globaldetails2 +=document.getElementById(t).value;
  3581. }
  3582. var globaldetails='undefined';
  3583. var x = document.getElementsByClassName('devdetails');
  3584. for (var i = 0; i < x.length; i++)
  3585. {
  3586. var t = x[i].id;
  3587. globaldetails +=document.getElementById(t).value;
  3588. document.getElementById(t).onchange = function()
  3589. {
  3590. //alert('changed');
  3591. var changedetails;
  3592. var y = document.getElementsByClassName('devdetails');
  3593. for (var i = 0; i < y.length; i++)
  3594. {
  3595. var t = y[i].id;
  3596. changedetails +=document.getElementById(t).value;
  3597. }
  3598. if( changedetails != globaldetails)
  3599. {
  3600. globallock =' unsaved device actions';
  3601. [ \"aw_trig\",\"aw_md1\",\"aw_md2\",\"aw_addevent\",\"aw_dev\"].forEach (lock,);
  3602. randomdev.forEach (lock);
  3603. }
  3604. if( changedetails == globaldetails)
  3605. {
  3606. [ \"aw_trig\",\"aw_md1\",\"aw_md2\",\"aw_addevent\",\"aw_dev\"].forEach (unlock,);
  3607. randomdev.forEach (unlock);
  3608. }
  3609. }
  3610. }
  3611. ";
  3612. # triggerlock
  3613. $j1 .= "
  3614. var triggerdetails = document.getElementById('MSwitchWebTRDT').innerHTML;
  3615. var saveddevice = '" . $triggerdevicehtml . "';
  3616. var sel = document.getElementById('trigdev');
  3617. sel.onchange = function()
  3618. {
  3619. trigdev = this.value;
  3620. if (trigdev != '";
  3621. $j1 .= $triggerdevicehtml;
  3622. $j1 .= "')
  3623. {
  3624. //document.getElementById('savetrigger').innerHTML = '<font color=#FF0000>trigger device : unsaved!</font> ';
  3625. //document.getElementById('MSwitchWebTRDT').innerHTML = '';
  3626. globallock =' unsaved trigger';
  3627. [\"aw_dev\", \"aw_det\"].forEach (lock);
  3628. randomdev.forEach (lock,);
  3629. }
  3630. else
  3631. {
  3632. //alert (randomdev);
  3633. [\"aw_dev\", \"aw_det\"].forEach (unlock);
  3634. randomdev.forEach (unlock);
  3635. document.getElementById('savetrigger').innerHTML = 'trigger device :';
  3636. document.getElementById('MSwitchWebTRDT').innerHTML = triggerdetails;
  3637. }
  3638. if (trigdev == 'all_events')
  3639. {
  3640. document.getElementById(\"triggerwhitelist\").style.visibility = \"visible\";
  3641. }
  3642. else
  3643. {
  3644. document.getElementById(\"triggerwhitelist\").style.visibility = \"collapse\";
  3645. }
  3646. }
  3647. ";
  3648. #####################
  3649. $j1 .= "
  3650. if (document.getElementById('trigon')){
  3651. var trigonfirst = document.getElementById('trigon').value;
  3652. var sel2 = document.getElementById('trigon');
  3653. sel2.onchange = function()
  3654. {
  3655. if (trigonfirst != document.getElementById('trigon').value)
  3656. {
  3657. closetrigger();
  3658. }
  3659. else{
  3660. opentrigger();
  3661. }
  3662. }
  3663. }
  3664. if (document.getElementById('trigoff')){
  3665. var trigofffirst = document.getElementById('trigoff').value;
  3666. var sel3 = document.getElementById('trigoff');
  3667. sel3.onchange = function()
  3668. {
  3669. if (trigofffirst != document.getElementById('trigoff').value)
  3670. {
  3671. closetrigger();
  3672. }
  3673. else{
  3674. opentrigger();
  3675. }
  3676. }
  3677. }
  3678. if (document.getElementById('trigcmdoff')){
  3679. var trigcmdofffirst = document.getElementById('trigcmdoff').value;
  3680. var sel4 = document.getElementById('trigcmdoff');
  3681. sel4.onchange = function()
  3682. {
  3683. if (trigcmdofffirst != document.getElementById('trigcmdoff').value)
  3684. {
  3685. closetrigger();
  3686. }
  3687. else{
  3688. opentrigger();
  3689. }
  3690. }
  3691. }
  3692. if (document.getElementById('trigcmdon')){
  3693. var trigcmdonfirst = document.getElementById('trigcmdon').value;
  3694. var sel5 = document.getElementById('trigcmdon');
  3695. sel5.onchange = function()
  3696. {
  3697. if (trigcmdonfirst != document.getElementById('trigcmdon').value)
  3698. {
  3699. closetrigger();
  3700. }
  3701. else{
  3702. opentrigger();
  3703. }
  3704. }
  3705. }
  3706. function closetrigger(){
  3707. globallock =' unsaved trigger details';
  3708. [\"aw_dev\", \"aw_det\",\"aw_trig\",\"aw_md1\",\"aw_md2\",\"aw_addevent\"].forEach (lock,);
  3709. randomdev.forEach (lock);
  3710. }
  3711. function opentrigger(){
  3712. //alert('call unlock');
  3713. [ \"aw_dev\",\"aw_det\",\"aw_trig\",\"aw_md1\",\"aw_md2\",\"aw_addevent\"].forEach (unlock,);
  3714. randomdev.forEach (unlock);
  3715. }
  3716. ";
  3717. #####################
  3718. #affected lock
  3719. $j1 .= "
  3720. var globalaffected;
  3721. var auswfirst=document.getElementById('devices');
  3722. for (i=0; i<auswfirst.options.length; i++)
  3723. {
  3724. var pos=auswfirst.options[i];
  3725. if(pos.selected)
  3726. {
  3727. //alert (pos.value);
  3728. globalaffected +=pos.value;
  3729. }
  3730. }
  3731. ///alert (globalaffected);
  3732. var sel1 = document.getElementById('devices');
  3733. sel1.onchange = function()
  3734. {
  3735. var actaffected;
  3736. var auswfirst=document.getElementById('devices');
  3737. for (i=0; i<auswfirst.options.length; i++)
  3738. {
  3739. var pos=auswfirst.options[i];
  3740. if(pos.selected)
  3741. {
  3742. //alert (pos.value);
  3743. actaffected +=pos.value;
  3744. }
  3745. }
  3746. if (actaffected != globalaffected)
  3747. {
  3748. globallock =' unsaved affected device';
  3749. [ \"aw_det\",\"aw_trig\",\"aw_md\",\"aw_md1\",\"aw_md2\",\"aw_addevent\"].forEach (lock,);
  3750. randomdev.forEach (lock);
  3751. }
  3752. else
  3753. {
  3754. [ \"aw_det\",\"aw_trig\",\"aw_md\",\"aw_md1\",\"aw_md2\",\"aw_addevent\"].forEach (unlock,);
  3755. randomdev.forEach (unlock);
  3756. }
  3757. }
  3758. ";
  3759. #function lock unlock
  3760. $j1 .= "function lock (elem, text){
  3761. if (document.getElementById(elem)){
  3762. document.getElementById(elem).style.backgroundColor = \"#ADADAD\"
  3763. document.getElementById(elem).disabled = true;
  3764. if (!document.getElementById(elem).model)
  3765. {
  3766. document.getElementById(elem).model=document.getElementById(elem).value;
  3767. }
  3768. document.getElementById(elem).value = 'N/A'+globallock;
  3769. }
  3770. }";
  3771. $j1 .= "function unlock (elem, index){
  3772. if (document.getElementById(elem)){
  3773. document.getElementById(elem).style.backgroundColor = \"\"
  3774. document.getElementById(elem).disabled = false;
  3775. document.getElementById(elem).value=document.getElementById(elem).model;
  3776. }
  3777. }";
  3778. #####################
  3779. $j1 .= "function saveconfig(conf){
  3780. conf = conf.replace(/\\n/g,'#[EOL]');
  3781. conf = conf.replace(/:/g,'#c[dp]');
  3782. conf = conf.replace(/;/g,'#c[se]');
  3783. conf = conf.replace(/ /g,'#c[sp]');
  3784. var nm = \$(t).attr(\"nm\");
  3785. var def = nm+\" saveconfig \"+encodeURIComponent(conf);
  3786. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  3787. }";
  3788. $j1 .= "function vupdate(){
  3789. conf='';
  3790. var nm = \$(t).attr(\"nm\");
  3791. var def = nm+\" VUpdate \"+encodeURIComponent(conf);
  3792. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  3793. }";
  3794. $j1 .= "function clearlog(){
  3795. conf='';
  3796. var nm = \$(t).attr(\"nm\");
  3797. var def = nm+\" clearlog \"+encodeURIComponent(conf);
  3798. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  3799. }";
  3800. $j1 .= "function savesys(conf){
  3801. conf = conf.replace(/:/g,'#[dp]');
  3802. conf = conf.replace(/;/g,'#[se]');
  3803. conf = conf.replace(/ /g,'#[sp]');
  3804. conf = conf.replace(/'/g,'#[st]');
  3805. var nm = \$(t).attr(\"nm\");
  3806. var def = nm+\" savesys \"+encodeURIComponent(conf);
  3807. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  3808. }";
  3809. $j1 .= "function checkcondition(condition,event){
  3810. //alert(condition,event);
  3811. var selected =document.getElementById(condition).value;
  3812. // event = \"test:test:test\";
  3813. if (selected == '')
  3814. {
  3815. var textfinal = \"<div style ='font-size: medium;'>Es ist keine Bedingung definiert, das Kommando wird immer ausgeführt.</div>\";
  3816. FW_okDialog(textfinal);
  3817. return;
  3818. }
  3819. selected = selected.replace(/\\|/g,'(DAYS)');
  3820. selected = selected.replace(/\\./g,'#[pt]');
  3821. selected = selected.replace(/:/g,'#[dp]');
  3822. selected= selected.replace(/~/g,'#[ti]');
  3823. selected = selected.replace(/ /g,'#[sp]');
  3824. event = event.replace(/~/g,'#[ti]');
  3825. event = event.replace(/ /g,'#[sp]');
  3826. cmd ='get " . $Name . " checkcondition '+selected+'|'+event;
  3827. FW_cmd(FW_root+'?cmd='+encodeURIComponent(cmd)+'&XHR=1', function(resp){FW_okDialog(resp);});
  3828. }
  3829. function checkevent(event){
  3830. event = event.replace(/ /g,'~');
  3831. cmd ='get " . $Name . " checkevent '+event;
  3832. FW_cmd(FW_root+'?cmd='+encodeURIComponent(cmd)+'&XHR=1');
  3833. }
  3834. ";
  3835. if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' )
  3836. {
  3837. $j1 .= "
  3838. function info(from){
  3839. text='Help: ' + from +'<br><br>';
  3840. if (from == 'timer'){
  3841. text = text + 'Hier kann entweder eine direkte Angabe einer Verzögerungszeit (delay with Cond_check) angegeben werden, oder es kann eine Ausführungszeit (at with Cond-check) für den Befehl angegeben werden<br> Bei der Angabe einer Ausführungszeit wird der Schaltbefehl beim nächsten erreichen der angegebenen Zeit ausgeführt. Ist die Zeit am aktuellen Tag bereits überschritten , wird der angegebene Zeitpunkt am Folgetag gesetzt.<br>Die Auswahl \"with Conf-check\" oder \"without Conf-check\" legt fest, ob unmittelbar vor Befehlsausführung nochmals die Condition für den Befehl geprüft wird oder nicht.<br><brAlternativ kann hier auch ein Verweis auf ein beliebiges Reading eines Devices erfolgen, das entsprechenden Wert enthält. Dieser Verweis muss in folgendem Format erfolgen:<br><br>[NAME.reading] des Devices ->z.B. [dummy.state]<br>Das Reading muss in folgendem Format vorliegen: hh:mm:ss ';}
  3842. if (from == 'trigger'){
  3843. text = text + 'Trigger ist das Gerät, oder die Zeit, auf die das Modul reagiert, um andere devices anzusprechen.<br>Das Gerät kann aus der angebotenen Liste ausgewählt werden, sobald dieses ausgewählt ist werden weitere Optionen angeboten.<br>Soll auf mehrereGerät gleichzeitig getriggert werden , so ist dieses ebenfalls möglich. Hierzu muss das Attribut \"MSwitch_Expert\" auf 1 gesetzt sein und als Auswahl \"GLOBAL\" erfolgen.<br><br>Zeitangaben können ebenso als Trigger genutzt werden, das Format muss wie folgt lauten:<br><br> [STUNDEN:MINUTEN|TAGE] - Tage werden von 1-7 gezählt, wobei 1 für Montag steht, 7 für Sonntag.<br /><br>Die Variable \$we ist anstatt der Tagesangabe verwendbar<br> [STUNDEN:MINUTEN|\$we] - Schaltvorgang nur an Wochenenden.<br>[STUNDEN:MINUTEN|!\$we] - Schaltvorgang nur an Werktagen.<br><br>Mehrere Zeitvorgaben können aneinandergereiht werden.<br>[17:00|1][18:30|23] würde den Trigger Montags um 17 Uhr auslösen und Dienstags,Mittwochs um 18 Uhr 30.<br><br>Sunset - Zeitangaben können mit folgender Sytax eingebunden werden: z.B [{sunset()}] , [{sunrise(+1800)}].<br><br>Es ist eine gleichzeitige Nutzung für Trigger durch Zeitangaben und Trigger durch Deviceevents möglich.<br><br>Sonderformate:<br>[?20:00-21:00|5] - Zufälliger Schaltvorgang zwischen 20 Uhr und 21 Uhr am Freitag<br>[00:02*04:10-06:30] - Schaltvorgang alle 2 Minuten zwischen 4.10 Uhr und 6.30 Uhr';}
  3844. if (from == 'triggercondition'){
  3845. text = text + 'Hier kann die Angabe von Bedingungen erfolgen, die zusätzlich zu dem triggernden Device erfuellt sein müssen.<br> Diese Bedingunge sind eng an DOIF- Bedingungen angelehnt .<br>Zeitabhängigkeit: [19.10-23:00] - Trigger des Devices erfolgt nur in angegebenem Zeitraum<br>Readingabhängige Trigger [Devicename:Reading] =/>/< X oder [Devicename:Reading] eq \"x\" - Trigger des Devicec erfolgt nur bei erfüllter Bedingung.<br>Achtung ! Bei der Abfrage von Readings nach Strings ( on,off,etc. ) ist statt \"=\" \"eq\" zu nutzen und der String muss in \"\" gesetzt werden!<br>Die Kombination mehrerer Bedingungen und Zeiten ist durch AND oder OR möglich.<br>[19.10-23:00] AND [Devicename:Reading] = 10 - beide Bedingungen müssen erfüllt sein<br>[19.10-23:00] OR [Devicename:Reading] = 10 - eine der Bedingungen muss erfüllt sein.<br>Es ist auf korrekte Eingabe der Leerzeichen zu achten.<br><br>sunset - Bedingungen werden mit zusätzlichen {} eingefügt z.B. : [{ sunset() }-23:00].<br><br>Variable \$we:<br>Die globlae Variable \$we ist nutzbar und muss in {} gesetzt werden .<br>{ !\$we } löst den Schaltvorgang nur Werktagen an aus<br>{ \$we } löst den Schaltvorgang nur an Wochenenden, Feiertagen aus<br><br>Soll nur an bestimmten Wochentagen geschaltet werden, muss eine Zeitangsbe gemacht werden und durch z.B. |135 ergänzt werden.<br>[10:00-11:00|13] würde den Schaltvorgang z.B nur Montag und Mitwoch zwischen 10 uhr und 11 uhr auslösen. Hierbei zählen die Wochentage von 1-7 für Montag-Sonntag.<br>Achtung: Bei Anwendung der geschweiften Klammern zur einletung eines Perlasdrucks ist unbedingt auf die Leerzeichen hinter und vor der Klammer zu achten !<br> Überschreitet die Zeitangabe die Tagesgrenze (24.00 Uhr ), so gelten die angegebenen Tage noch bis zum ende der angegebenen Schaltzeit,<br> d.H. es würde auch am Mitwoch noch der schaltvorgang erfolgen, obwohl als Tagesvorgabe Dienstag gesetzt wurde.<br><br>Wird in diesem Feld keine Angabe gemacht , so erfolgt der Schaltvorgang nur durch das triggernde Device ohne weitere Bedingungen.<br><br>Achtung: Conditions gelten nur für auslösende Trigger eines Devices und habe keinen Einfluss auf zeitgesteuerte Auslöser. Um Zeitgesteuerte Auslösr ebenfalls an Bedingungen zu Knüpfen muss dieses in den Attributen aktiviert werden.';}
  3846. if (from == 'whitelist'){
  3847. text = text + 'Bei der Auswahl \\\'GLOBAL\\\' als Triggerevent werde alle von Fhem erzeugten Events an dieses Device weitergeleitet. Dieses kann eine erhöhte Systemlast erzeugen.<br>In dem Feld \\\'Trigger Device Global Whitelist:\\\' kann dieses eingeschränkt werden , indem Devices oder Module benannt werden , deren Events Berücksichtigt werden. Sobald hier ein Eintrag erfolgt , werden nur noch Diese berücksichtigt , gibt es keinen Eintrag , werden alle berücksichtigt ( Whitelist ).<br> Format: Die einzelnen Angaben müssen durch Komma getrennt werden .<br><br>Mögliche Angaben :<br>Modultypen: TYPE=CUL_HM<br>Devicenamen: NAME<br><br>';}
  3848. if (from == 'addevent'){
  3849. text = text + 'Hier können manuell Events zugefügt werden , die in den Auswahllisten verfügbar sein sollen und auf die das Modul reagiert.<br>Grundsätzlich ist zu unterscheiden , ob das Device im Normal-, oder Globalmode betrieben wird<br>Im Normalmode bestehen die Events aus 2 Teilen , dem Reading und dem Wert \"state:on\"<br>Wenn sich das Device im GLOBAL Mode befindet müssen die Events aus 3 Teilen bestehen , dem Devicename, dem Reading und dem Wert \"device:state:on\".<br>Wird hier nur ein \"*\" angegeben , reagiert der entsprechende Zweig auf alle eingehenden Events.<br>Weitherhin sind folgende Syntaxmöglichkeiten vorgesehen :<br> device:state:*, device:*:*, *:state:* , etc.<br>Der Wert kann mehrere Auswahlmöglichkeiten haben , durch folgende Syntax: \"device:state:(on/off)\". In diesem Fal reagiert der Zweig sowohl auf den Wert on, als auch auf off.<br><br>Es können mehrere Evebts gleichzeitig angelegt werden . Diese sind durch Komma zu trennen .<br><br>Seit V1.7 kann hier die gängige RegEx-Formulierung erfolgen.';}
  3850. if (from == 'condition'){
  3851. text = text + 'Hier kann die Angabe von Bedingungen erfolgen, die erfüllt sein müssen um den Schaltbefehl auszuführen.<br>Diese Bedingunge sind eng an DOIF- Bedingungen angelehnt.<br><br>Zeitabhängiges schalten: [19.10-23:00] - Schaltbefehl erfolgt nur in angegebenem Zeitraum<br>Readingabhängiges schalten [Devicename:Reading] =/>/< X oder [Devicename:Reading] eq \"x\" - Schaltbefehl erfolgt nur bei erfüllter Bedingung.<br>Achtung! Bei der Abfrage von Readings nach Strings ( on,off,etc. ) ist statt \"=\" \"eq\" zu nutzen und der String muss in \"x\" gesetzt werden!<br> Die Kombination mehrerer Bedingungen und Zeiten ist durch AND oder OR möglich:<br> [19.10-23:00] AND [Devicename:Reading] = 10 - beide Bedingungen müssen erfüllt sein<br>[19.10-23:00] OR [Devicename:Reading] = 10 - eine der Bedingungen muss erfüllt sein.<br>Es ist auf korrekte Eingabe der Leerzeichen zu achten.<br><br>sunset - Bedingungen werden mit zusätzlichen {} eingefügt z.B. : [{ sunset() }-23:00].<br><br>Variable \$we:<br>Die globlae Variable \$we ist nutzbar und muss {} gesetzt werden .<br>{ !\$we } löst den Schaltvorgang nur Werktagen aus<br>{ \$we } löst den Schaltvorgang nur Wochenenden, Feiertagen aus<br><br>Soll nur an bestimmten Wochentagen geschaltet werden, muss eine Zeitangsbe gemacht werden und durch z.B. |135 ergänzt werden.<br>[10:00-11:00|13] würde den Schaltvorgang z.B nur Montag und Mitwoch zwischen 10 uhr und 11 uhr auslösen. Hierbei zählen die Wochentage von 1-7 für Montag-Sonntag.<br>Achtung: Bei Anwendung der geschweiften Klammern zur einletung eines Perlasdrucks ist unbedingt auf die Leerzeichen hinter und vor der Klammer zu achten !<br>Überschreitet die Zeitangabe die Tagesgrenze (24.00 Uhr ), so gelten die angegebenen Tage noch bis zum ende der angegebenen Schaltzeit , d.H. es würde auch am Mitwoch noch der schaltvorgang erfolgen, obwohl als Tagesvorgabe Dienstag gesetzt wurde.<br><br>\$EVENT Variable: Die Variable EVENT enthält den auslösenden Trigger, d.H. es kann eine Reaktion in direkter Abhängigkeit zum auslösenden Trigger erfolgen.<br>[\$EVENT] eq \"state:on\" würde den Kommandozweig nur dann ausführen, wenn der auslösende Trigger \"state:on\" war.<br>Wichtig ist dieses, wenn bei den Triggerdetails nicht schon auf ein bestimmtes Event getriggert wird, sondern hier durch die Nutzung eines wildcards (*) auf alle Events getriggert wird, oder auf alle Events eines Readings z.B. (state:*)<br><br>Bei eingestellter Delayfunktion werden die Bedingungen je nach Einstellung sofort,verzögert oder sowohl-als-auch überprüft, d.H hiermit sind verzögerte Ein-, und Ausschaltbefehle möglich die z.B Nachlauffunktionen oder verzögerte Einschaltfunktionen ermöglichen, die sich selbst überprüfen. z.B. [wenn Licht im Bad an -> schalte Lüfter 2 Min später an -> nur wenn Licht im Bad noch an ist]<br><br>Anstatt einer Verzögerung kann hier auch eine festgelegte Schaltzeit erfolgen.';}
  3852. if (from == 'onoff'){
  3853. text = text + 'Einstellung des auzuführenden Kommandos bei entsprechendem getriggerten Event.<br>Bei angebotenen Zusatzfeldern kann ein Verweis auf ein Reading eines anderen Devices gesetzt werden mit [Device:Reading].<br>\$NAME wird ersetzt durch den Namen des triggernden Devices.<br><br>Bei Nutzung von FreeCmd kann hier entweder reiner FhemCode, oder reiner Perlcode verwendet werden. Perlcode muss mit geschweiften Klammern beginnen und enden. Das Mischen beider Codes ist nicht zulässig.';}
  3854. if (from == 'affected'){
  3855. text = text + 'Einstellung der Geräte, die auf ein Event oder zu einer bestimmten Zeit reagieren sollen.<br>Die Auswahl von FreeCmd ermöglicht eine deviceungebundene Befehlseingabe oder die Eingabe von reinem Perlcode.';}
  3856. if (from == 'repeats'){
  3857. text = text + 'Eingabe von Befehlswiederholungen.<br>Bei Belegung der Felder wird ein Befehl um die Angabe \"Repeats\" mit der jeweiligen Verzögerung \"Repeatdelay in sec\" wiederholt.<br>In dem Feld \"Repeats\" ist eine Angabe im \"setmagic\"-Format möglich.';}
  3858. if (from == 'priority'){
  3859. text = text + 'priority - Auswahl der Reihenfolge der Befehlsabarbeitung. Ein Befehl mit der Nr. 1 wird als erstes ausgeführt , die höchste Nummer zuletzt.<br> Sollte mehrere Befehle die gleiche Nummer haben , so werden diese Befehle in dargestellter Reihenfolge ausgeführt.<br><br>ID - Devices denen eine ID zugewiesen ist , werden in der normalen abarbeitung der Befehle nicht mehr berücksichtigt und somit nicht ausgeführt. Wenn eine ID-Zuweisung erfolgt ist, kann dieser Befehlszweig nur noch über das cmd set DEVICE ID NR on/off erfolgen. Diese Option wird nur in Ausnahmefällen benötigt , wenn die Pipes nicht ausrechend sind um verschiedene Aktionen unter verschiedenen Bedingungen auszuführen. ';}
  3860. if (from == 'saveevent'){
  3861. text = text + 'Bei Anwahl dieser Option werden alle eingehenden Events des ausgewählten Triggerdevices gespeichert und sind in den Auswahlfeldern \"execute cmd1\" und \"execute cmd2\" sowie in allen \"Test-Condition\" zur Auswahl verfügbar.<br>Diese Auswahl sollte zur Resourcenschonung nach der Einrichtung des MSwitchdevices abgewählt werden , da hier je nach Trigger erhebliche Datenmengen anfallen können und gespeichert werden.';}
  3862. if (from == 'execcmd'){
  3863. text = text + 'In diesem Feld wird das Event bestimmt, welches zur Ausführung des cmd Zweiges 1 oder 2 führt. Hier stehen entweder gespeicherte Events zur Verfügung ( wenn \"Save incomming events\" aktiviert ist ) , oder es können mit \"Add event manually\" Events hinzugefügt werden. ';}
  3864. var textfinal =\"<div style ='font-size: small;'>\"+ text +\"</div>\";
  3865. FW_okDialog(textfinal);
  3866. return;
  3867. }";
  3868. }
  3869. $j1 .= "
  3870. function aktvalue(target,cmd){
  3871. document.getElementById(target).value = cmd;
  3872. return;
  3873. }
  3874. function noarg(target,copytofield){
  3875. document.getElementById(copytofield).value = '';
  3876. document.getElementById(target).innerHTML = '';
  3877. return;
  3878. }
  3879. function noaction(target,copytofield){
  3880. document.getElementById(copytofield).value = '';
  3881. document.getElementById(target).innerHTML = '';
  3882. return;}
  3883. function slider(first,step,last,target,copytofield){
  3884. var selected =document.getElementById(copytofield).value;
  3885. var selectfield = \"&nbsp;<br><input type='text' id='\" + target +\"_opt' size='3' value='' readonly>&nbsp;&nbsp;&nbsp;\" + first +\"<input type='range' min='\" + first +\"' max='\" + last + \"' value='\" + selected +\"' step='\" + step + \"' onchange=\\\"javascript: showValue(this.value,'\" + copytofield + \"','\" + target + \"')\\\">\" + last ;
  3886. document.getElementById(target).innerHTML = selectfield + '<br>';
  3887. var opt = target + '_opt';
  3888. document.getElementById(opt).value=selected;
  3889. return;
  3890. }
  3891. function showValue(newValue,copytofield,target){
  3892. var opt = target + '_opt';
  3893. document.getElementById(opt).value=newValue;
  3894. document.getElementById(copytofield).value = newValue;
  3895. }
  3896. function showtextfield(newValue,copytofield,target){
  3897. document.getElementById(copytofield).value = newValue;
  3898. }
  3899. function textfield(copytofield,target){
  3900. //alert(copytofield,target);
  3901. var selected =document.getElementById(copytofield).value;
  3902. if (copytofield.indexOf('cmdonopt') != -1) {
  3903. var selectfield = \"&nbsp;<br><input type='text' size='30' value='\" + selected +\"' onchange=\\\"javascript: showtextfield(this.value,'\" + copytofield + \"','\" + target + \"')\\\">\" ;
  3904. document.getElementById(target).innerHTML = selectfield + '<br>';
  3905. }
  3906. else{
  3907. var selectfield = \"<input type='text' size='30' value='\" + selected +\"' onchange=\\\"javascript: showtextfield(this.value,'\" + copytofield + \"','\" + target + \"')\\\">\" ;
  3908. document.getElementById(target).innerHTML = selectfield + '<br>';
  3909. }
  3910. return;
  3911. }
  3912. function selectfield(args,target,copytofield){
  3913. var cmdsatz = args.split(\",\");
  3914. var selectstart = \"<select id=\\\"\" +target +\"1\\\" name=\\\"\" +target +\"1\\\" onchange=\\\"javascript: aktvalue('\" + copytofield + \"',document.getElementById('\" +target +\"1').value)\\\">\";
  3915. var selectend = '<\\select>';
  3916. var option ='<option value=\"noArg\">noArg</option>';
  3917. var i;
  3918. var len = cmdsatz.length;
  3919. var selected =document.getElementById(copytofield).value;
  3920. for (i=0; i<len; i++){
  3921. if (selected == cmdsatz[i]){
  3922. option += '<option selected value=\"' + cmdsatz[i] + '\">' + cmdsatz[i] + '</option>';
  3923. }
  3924. else{
  3925. option += '<option value=\"' + cmdsatz[i] + '\">' + cmdsatz[i] + '</option>';
  3926. }
  3927. }
  3928. var selectfield = selectstart + option + selectend;
  3929. document.getElementById(target).innerHTML = selectfield + '<br>';
  3930. return;
  3931. }
  3932. function activate(state,target,options,copytofield) ////aufruf durch selctfield
  3933. {
  3934. var globaldetails3='undefined';
  3935. var x = document.getElementsByClassName('devdetails2');
  3936. for (var i = 0; i < x.length; i++)
  3937. {
  3938. var t = x[i].id;
  3939. globaldetails3 +=document.getElementById(t).value;
  3940. }
  3941. if ( globaldetails2 )
  3942. {
  3943. if (globaldetails3 != globaldetails2)
  3944. {
  3945. globallock =' unsaved device actions';
  3946. [ \"aw_trig\",\"aw_md1\",\"aw_md2\",\"aw_addevent\",\"aw_dev\"].forEach (lock,);
  3947. randomdev.forEach (lock);
  3948. }
  3949. else
  3950. {
  3951. [ \"aw_trig\",\"aw_md1\",\"aw_md2\",\"aw_addevent\",\"aw_dev\"].forEach (unlock,);
  3952. randomdev.forEach (unlock);
  3953. }
  3954. }
  3955. var ausgabe = target + '<br>' + state + '<br>' + options;
  3956. if (state == 'no_action'){noaction(target,copytofield);return}
  3957. var optionarray = options.split(\" \");
  3958. var werte = new Array();
  3959. for (var key in optionarray )
  3960. {
  3961. var satz = optionarray[key].split(\":\");
  3962. werte[satz[0]] = satz[1];
  3963. }
  3964. var devicecmd = new Array();
  3965. if (typeof werte[state] === 'undefined') {werte[state]='textField';}
  3966. devicecmd = werte[state].split(\",\");
  3967. if (devicecmd[0] == 'noArg'){noarg(target,copytofield);return;}
  3968. //else if (devicecmd[0] == 'slider'){slider(devicecmd[1],devicecmd[2],devicecmd[3],target,copytofield);return;}
  3969. else if (devicecmd[0] == 'slider'){textfield(copytofield,target);return;}
  3970. else if (devicecmd[0] == 'undefined'){textfield(copytofield,target);return;}
  3971. else if (devicecmd[0] == 'textField'){textfield(copytofield,target);return;}
  3972. else if (devicecmd[0] == 'colorpicker'){textfield(copytofield,target);return;}
  3973. else if (devicecmd[0] == 'RGB'){textfield(copytofield,target);return;}
  3974. else if (devicecmd[0] == 'no_Action'){noaction();return;}
  3975. else {selectfield(werte[state],target,copytofield);return;}
  3976. return;
  3977. }
  3978. function addevice(device){
  3979. var nm = \$(t).attr(\"nm\");
  3980. var def = nm+\" add_device \"+device;
  3981. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  3982. }
  3983. function deletedevice(device){
  3984. var nm = \$(t).attr(\"nm\");
  3985. var def = nm+\" del_device \"+device;
  3986. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  3987. }
  3988. ";
  3989. $j1 .=
  3990. "var t=\$(\"#MSwitchWebTR\"), ip=\$(t).attr(\"ip\"), ts=\$(t).attr(\"ts\");
  3991. FW_replaceWidget(\"[name=aw_ts]\", \"aw_ts\", [\"time\"], \"12:00\");
  3992. \$(\"[name=aw_ts] input[type=text]\").attr(\"id\", \"aw_ts\");
  3993. // modify trigger aw_save
  3994. \$(\"#aw_md\").click(function(){
  3995. var nm = \$(t).attr(\"nm\");
  3996. trigon = \$(\"[name=trigon]\").val();
  3997. trigon = trigon.replace(/ /g,'~');
  3998. trigoff = \$(\"[name=trigoff]\").val();
  3999. trigoff = trigoff.replace(/ /g,'~');
  4000. trigcmdon = \$(\"[name=trigcmdon]\").val();
  4001. trigcmdon = trigcmdon.replace(/ /g,'~');
  4002. trigcmdoff = \$(\"[name=trigcmdoff]\").val();
  4003. trigcmdoff = trigcmdoff.replace(/ /g,'~');
  4004. trigsave = \$(\"[name=aw_save]\").prop(\"checked\") ? \"ja\":\"nein\";
  4005. trigwhite = \$(\"[name=triggerwhitelist]\").val();
  4006. if (trigcmdon == trigon && trigcmdon != 'no_trigger' && trigon != 'no_trigger'){
  4007. FW_okDialog('on triggers for \\'switch Test on + execute on commands\\' and \\'execute on commands only\\' may not be the same !');
  4008. return;
  4009. }
  4010. if (trigcmdoff == trigoff && trigcmdoff != 'no_trigger' && trigoff != 'no_trigger'){
  4011. FW_okDialog('off triggers for \\'switch Test off + execute on commands\\' and \\'execute off commands only\\' may not be the same !');
  4012. return;
  4013. }
  4014. if (trigon == trigoff && trigon != 'no_trigger'){
  4015. FW_okDialog('trigger for \\'switch Test on + execute on commands\\' and \\'switch Test off + execute off commands\\' must not both be \\'*\\'');
  4016. return;
  4017. }
  4018. var def = nm+\" trigger \"+trigon+\" \"+trigoff+\" \"+trigsave+\" \"+trigcmdon+\" \"+trigcmdoff+\" \" ;
  4019. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  4020. });
  4021. //delete trigger
  4022. \$(\"#aw_md2\").click(function(){
  4023. var nm = \$(t).attr(\"nm\");
  4024. var def = nm+\" del_trigger \";
  4025. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  4026. });
  4027. //aplly filter to trigger
  4028. \$(\"#aw_md1\").click(function(){
  4029. var nm = \$(t).attr(\"nm\");
  4030. var def = nm+\" filter_trigger \";
  4031. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  4032. });
  4033. \$(\"#aw_trig\").click(function(){
  4034. var nm = \$(t).attr(\"nm\");
  4035. trigdev = \$(\"[name=trigdev]\").val();
  4036. //trigdev = trigdev.replace(/\:/g,'#[dp]');
  4037. //alert(trigdev);
  4038. timeon = \$(\"[name=timeon]\").val();
  4039. timeoff = \$(\"[name=timeoff]\").val();
  4040. timeononly = \$(\"[name=timeononly]\").val();
  4041. timeoffonly = \$(\"[name=timeoffonly]\").val();
  4042. trigdevcond = \$(\"[name=triggercondition]\").val();
  4043. //trigdevcond = trigdevcond.replace(/:/g,'#[dp]');
  4044. trigdevcond = trigdevcond.replace(/\\./g,'#[pt]');
  4045. trigdevcond = trigdevcond.replace(/:/g,'#[dp]');
  4046. trigdevcond= trigdevcond.replace(/~/g,'#[ti]');
  4047. //trigdevcond = trigdevcond.replace(/ /g,'~');
  4048. trigdevcond = trigdevcond.replace(/ /g,'#[sp]');
  4049. trigdevcond = trigdevcond+':';
  4050. timeon = timeon.replace(/ /g, '');
  4051. timeoff = timeoff.replace(/ /g, '');
  4052. timeononly = timeononly.replace(/ /g, '');
  4053. timeoffonly = timeoffonly.replace(/ /g, '');
  4054. timeon = timeon.replace(/:/g, '#[dp]');
  4055. timeoff = timeoff.replace(/:/g, '#[dp]');
  4056. timeononly = timeononly.replace(/:/g, '#[dp]');
  4057. timeoffonly = timeoffonly.replace(/:/g, '#[dp]');
  4058. timeon = timeon+':';
  4059. timeoff = timeoff+':';
  4060. timeononly = timeononly+':';
  4061. timeoffonly = timeoffonly+':';
  4062. //alert(timeon);
  4063. trigwhite = \$(\"[name=triggerwhitelist]\").val();
  4064. var def = nm+\" set_trigger \"+trigdev+\" \"+timeon+\" \"+timeoff+\" \"+timeononly+\" \"+timeoffonly+\" \"+trigdevcond+\" \"+trigwhite+\" \" ;
  4065. //alert(def);
  4066. def = encodeURIComponent(def);
  4067. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  4068. });
  4069. \$(\"#aw_addevent\").click(function(){
  4070. var nm = \$(t).attr(\"nm\");
  4071. event = \$(\"[name=add_event]\").val();
  4072. event= event.replace(/ /g,'~');
  4073. event= event.replace(/\\|/g,'[bs]');
  4074. if (event == ''){
  4075. //alert('no event specified');
  4076. return;
  4077. }
  4078. var def = nm+\" addevent \"+event+\" \";
  4079. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  4080. });
  4081. \$(\"#aw_dev\").click(function(){
  4082. var nm = \$(t).attr(\"nm\");
  4083. devices = \$(\"[name=affected_devices]\").val();
  4084. var def = nm+\" devices \"+devices+\" \";
  4085. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  4086. });
  4087. \$(\"#aw_det\").click(function(){
  4088. var nm = \$(t).attr(\"nm\");
  4089. devices = '';
  4090. $javaform
  4091. devices = devices.replace(/:/g,'#[dp]');
  4092. devices = devices.replace(/;/g,'#[se]');
  4093. devices = devices.replace(/ /g,'#[sp]');
  4094. devices = devices.replace(/%/g,'#[pr]');
  4095. devices = encodeURIComponent(devices);
  4096. //alert(devices);
  4097. var def = nm+\" details \"+devices+\" \";
  4098. location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def);
  4099. });
  4100. function switchlock(){
  4101. test = document.getElementById('lockedit').checked ;
  4102. if (test){
  4103. \$(\"#devices\").prop(\"disabled\", 'disabled');
  4104. document.getElementById('aw_great').value='edit list';
  4105. }
  4106. else{
  4107. \$(\"#devices\").prop(\"disabled\", false);
  4108. document.getElementById('aw_great').value='schow greater list';
  4109. }
  4110. }
  4111. function deviceselect(){
  4112. sel ='<div style=\"white-space:nowrap;\"><br>';
  4113. var ausw=document.getElementById('devices');
  4114. for (i=0; i<ausw.options.length; i++)
  4115. {
  4116. var pos=ausw.options[i];
  4117. if(pos.selected)
  4118. {
  4119. //targ.options[i].selected = true;
  4120. sel = sel+'<input id =\"Checkbox-'+i+'\" checked=\"checked\" name=\"Checkbox-'+i+'\" type=\"checkbox\" value=\"test\" /> '+pos.value+'<br />';
  4121. }
  4122. else
  4123. {
  4124. sel = sel+'<input id =\"Checkbox-'+i+'\" name=\"Checkbox-'+i+'\" type=\"checkbox\" /> '+pos.value+'<br />';
  4125. }
  4126. }
  4127. sel = sel+'</div>';
  4128. FW_okDialog(sel,'',removeFn) ;
  4129. }
  4130. function bigwindow(targetid){
  4131. targetval =document.getElementById(targetid).value;
  4132. sel ='<div style=\"white-space:nowrap;\"><br>';
  4133. sel = sel+'<textarea id=\"valtrans\" cols=\"80\" name=\"TextArea1\" rows=\"10\" onChange=\" document.getElementById(\\\''+targetid+'\\\').value=this.value; \">'+targetval+'</textarea>';
  4134. sel = sel+'</div>';
  4135. FW_okDialog(sel,'');
  4136. }
  4137. function removeFn() {
  4138. var targ = document.getElementById('devices');
  4139. for (i = 0; i < targ.options.length; i++) {
  4140. test = document.getElementById('Checkbox-' + i).checked;
  4141. targ.options[i].selected = false;
  4142. if (test) {
  4143. targ.options[i].selected = true;
  4144. }
  4145. }
  4146. }
  4147. \$(\"#aw_little\").click(function(){
  4148. var veraenderung = 3; // Textfeld veraendert sich stets um 3 Zeilen
  4149. var sel = document.getElementById('textfie').innerHTML;
  4150. var show = document.getElementById('textfie2');
  4151. var2 = \"size=\\\"6\\\"\";
  4152. var result = sel.replace(/size=\\\"15\\\"/g,var2);
  4153. document.getElementById('textfie').innerHTML = result;
  4154. });
  4155. }
  4156. </script>";
  4157. return "$ret<br>$detailhtml<br>$j1";
  4158. }
  4159. ####################
  4160. sub MSwitch_makeCmdHash($) {
  4161. my $loglevel = 5;
  4162. my ($Name) = @_;
  4163. # detailsatz in scalar laden
  4164. my @devicedatails ;
  4165. @devicedatails = split( /#\[ND\]/, ReadingsVal( $Name, '.Device_Affected_Details', 'no_device' ) ) if defined ReadingsVal( $Name, '.Device_Affected_Details', 'no_device');#inhalt decice und cmds durch komma getrennt
  4166. my %savedetails;
  4167. foreach (@devicedatails)
  4168. {
  4169. # ersetzung
  4170. $_ =~ s/#\[sp\]/ /g;
  4171. $_ =~ s/#\[nl\]/\n/g;
  4172. $_ =~ s/#\[se\]/;/g;
  4173. $_ =~ s/#\[dp\]/:/g;
  4174. $_ =~ s/\(DAYS\)/|/g;
  4175. $_ =~ s/#\[ko\]/,/g; #neu
  4176. $_ =~ s/#\[bs\]/\\/g; #neu
  4177. my @detailarray = split( /#\[NF\]/, $_ ); #enthält daten 0-5 0 - name 1-5 daten 7 und9 sind zeitangaben
  4178. my $key = '';
  4179. my $testtimestroff = $detailarray[7];
  4180. $key = $detailarray[0] . "_delayatonorg";
  4181. $savedetails{$key} = $detailarray[7];
  4182. if ( $testtimestroff ne '[random]' )
  4183. {
  4184. $testtimestroff =~ s/[A-Za-z0-9#\.\-_]//g;
  4185. #Log3( $Name, 0,"testtimestron -> $testtimestroff" . __LINE__ );
  4186. if ( $testtimestroff ne "[:]" && $testtimestroff ne "[\$:]" )
  4187. {
  4188. my $hdel = ( substr( $detailarray[7], 0, 2 ) ) * 3600;
  4189. my $mdel = ( substr( $detailarray[7], 3, 2 ) ) * 60;
  4190. my $sdel = ( substr( $detailarray[7], 6, 2 ) ) * 1;
  4191. $detailarray[7] = $hdel + $mdel + $sdel;
  4192. }
  4193. }
  4194. my $testtimestron = $detailarray[8];
  4195. $key = $detailarray[0] . "_delayatofforg";
  4196. $savedetails{$key} = $detailarray[8];
  4197. if ( $testtimestron ne '[random]' )
  4198. {
  4199. $testtimestron =~ s/[A-Za-z0-9#\.\-_]//g;
  4200. if ( $testtimestron ne "[:]" && $testtimestroff ne "[\$:]" )
  4201. {
  4202. my $hdel = substr( $detailarray[8], 0, 2 ) * 3600;
  4203. my $mdel = substr( $detailarray[8], 3, 2 ) * 60;
  4204. my $sdel = substr( $detailarray[8], 6, 2 ) * 1;
  4205. $detailarray[8] = $hdel + $mdel + $sdel;
  4206. }
  4207. }
  4208. $key = $detailarray[0] . "_on";
  4209. $savedetails{$key} = $detailarray[1];
  4210. $key = $detailarray[0] . "_off";
  4211. $savedetails{$key} = $detailarray[2];
  4212. $key = $detailarray[0] . "_onarg";
  4213. $savedetails{$key} = $detailarray[3];
  4214. $key = $detailarray[0] . "_offarg";
  4215. $savedetails{$key} = $detailarray[4];
  4216. $key = $detailarray[0] . "_delayaton";
  4217. $savedetails{$key} = $detailarray[5];
  4218. $key = $detailarray[0] . "_delayatoff";
  4219. $savedetails{$key} = $detailarray[6];
  4220. $key = $detailarray[0] . "_timeon";
  4221. $savedetails{$key} = $detailarray[7];
  4222. $key = $detailarray[0] . "_timeoff";
  4223. $savedetails{$key} = $detailarray[8];
  4224. $key = $detailarray[0] . "_repeatcount";
  4225. if ( defined $detailarray[11] )
  4226. {
  4227. $savedetails{$key} = $detailarray[11];
  4228. }
  4229. else
  4230. {
  4231. $savedetails{$key} = 0;
  4232. }
  4233. $key = $detailarray[0] . "_repeattime";
  4234. if ( defined $detailarray[12] )
  4235. {
  4236. $savedetails{$key} = $detailarray[12];
  4237. }
  4238. else
  4239. {
  4240. $savedetails{$key} = 0;
  4241. }
  4242. $key = $detailarray[0] . "_priority";
  4243. if ( defined $detailarray[13] )
  4244. {
  4245. $savedetails{$key} = $detailarray[13];
  4246. }
  4247. else
  4248. {
  4249. $savedetails{$key} = 1;
  4250. }
  4251. $key = $detailarray[0] . "_id";
  4252. if ( defined $detailarray[14] )
  4253. {
  4254. $savedetails{$key} = $detailarray[14];
  4255. }
  4256. else
  4257. {
  4258. $savedetails{$key} = 0;
  4259. }
  4260. $key = $detailarray[0] . "_conditionon";
  4261. if ( defined $detailarray[9] )
  4262. {
  4263. $savedetails{$key} = $detailarray[9];
  4264. }
  4265. else
  4266. {
  4267. $savedetails{$key} = '';
  4268. }
  4269. $key = $detailarray[0] . "_conditionoff";
  4270. if ( defined $detailarray[10] )
  4271. {
  4272. $savedetails{$key} = $detailarray[10];
  4273. }
  4274. else
  4275. {
  4276. $savedetails{$key} = '';
  4277. }
  4278. }
  4279. my @pass = %savedetails;
  4280. return @pass;
  4281. }
  4282. ########################################
  4283. sub MSwitch_Delete_Triggermemory($) {
  4284. my ($hash) = @_;
  4285. my $Name = $hash->{NAME};
  4286. my $events = ReadingsVal( $Name, '.Device_Events', '' );
  4287. # my @eventsall = split( /#\[tr\]/, $events );
  4288. my $Triggerdevice = $hash->{Trigger_device};
  4289. my $triggeron = ReadingsVal( $Name, '.Trigger_on', 'no_trigger' );
  4290. if ( !defined $triggeron ) { $triggeron = "" }
  4291. my $triggeroff = ReadingsVal( $Name, '.Trigger_off', 'no_trigger' );
  4292. if ( !defined $triggeroff ) { $triggeroff = "" }
  4293. my $triggercmdon = ReadingsVal( $Name, '.Trigger_cmd_on', 'no_trigger' );
  4294. if ( !defined $triggercmdon ) { $triggercmdon = "" }
  4295. my $triggercmdoff = ReadingsVal( $Name, '.Trigger_cmd_off', 'no_trigger' );
  4296. if ( !defined $triggercmdoff ) { $triggercmdoff = "" }
  4297. my $triggerdevice = ReadingsVal( $Name, 'Trigger_device', '' );
  4298. delete( $hash->{helper}{events} );
  4299. $hash->{helper}{events}{$triggerdevice}{'no_trigger'} = "on";
  4300. $hash->{helper}{events}{$triggerdevice}{$triggeron} = "on";
  4301. $hash->{helper}{events}{$triggerdevice}{$triggeroff} = "on";
  4302. $hash->{helper}{events}{$triggerdevice}{$triggercmdon} = "on";
  4303. $hash->{helper}{events}{$triggerdevice}{$triggercmdoff} = "on";
  4304. readingsSingleUpdate( $hash, ".Device_Events", 'no_trigger', 1 );
  4305. my $eventhash = $hash->{helper}{events}{$triggerdevice};
  4306. $events = "";
  4307. foreach my $name ( keys %{$eventhash} )
  4308. {
  4309. $name =~ s/#\[tr//ig;
  4310. $events = $events . $name . '#[tr]';
  4311. }
  4312. chop($events);
  4313. chop($events);
  4314. chop($events);
  4315. chop($events);
  4316. chop($events);
  4317. readingsSingleUpdate( $hash, ".Device_Events", $events, 0 );
  4318. return;
  4319. }
  4320. ###########################################################################
  4321. sub MSwitch_Exec_Notif($$$$$) {
  4322. #Inhalt Übergabe -> push @cmdarray, $own_hash . ',on,check,' . $eventcopy1
  4323. my ( $hash, $comand, $check, $event,$execids ) = @_;
  4324. my $name = $hash->{NAME};
  4325. my $protokoll = '';
  4326. my $satz;
  4327. $execids = "0";
  4328. MSwitch_LOG( $name, 5,"$name: execnotif -> $hash, $comand, $check, $event,$execids ");
  4329. #### teste auf condition nur wenn nicht von timer
  4330. return "" if ( IsDisabled($name) );# Return without any further action if the module is disabled
  4331. if ( $check ne 'nocheck' )
  4332. {
  4333. my $triggercondition = ReadingsVal( $name, '.Trigger_condition', '' );
  4334. # achtung format change
  4335. $triggercondition =~ s/#\[dp\]/:/g;
  4336. $triggercondition =~ s/#\[pt\]/./g;
  4337. $triggercondition =~ s/#\[ti\]/~/g;
  4338. $triggercondition =~ s/#\[sp\]/ /g;
  4339. if ( $triggercondition ne '' )
  4340. {
  4341. MSwitch_LOG( $name, 5,"$name: check triggercondition -> ");
  4342. my $ret = MSwitch_checkcondition( $triggercondition, $name, '' );
  4343. MSwitch_LOG( $name, 5,"$name: ergebniss triggercondition -> ".$ret);
  4344. if ( $ret eq 'false' )
  4345. {
  4346. MSwitch_LOG( $name, 5,"$name: ergebniss triggercondition false -> abbruch");
  4347. return;
  4348. }
  4349. }
  4350. }
  4351. my %devicedetails = MSwitch_makeCmdHash($name);
  4352. # betroffene geräte suchen
  4353. my @devices = split( /,/, ReadingsVal( $name, '.Device_Affected', 'no_device' ) );
  4354. my $update = '';
  4355. my $testtoggle = '';
  4356. MSwitch_LOG( $name, 5,"$name: zu schaltende devices -> ".@devices);
  4357. # liste nach priorität ändern , falls expert
  4358. @devices = MSwitch_priority($hash,$execids,@devices);
  4359. foreach my $device (@devices)
  4360. {
  4361. if ( AttrVal( $name, 'MSwitch_Delete_Delays', '0' ) eq '1' )
  4362. {
  4363. MSwitch_Delete_Delay( $hash, $device );
  4364. }
  4365. my @devicesplit = split( /-AbsCmd/, $device );
  4366. my $devicenamet = $devicesplit[0];
  4367. # teste auf on kommando
  4368. my $key = $device . "_" . $comand;
  4369. my $timerkey = $device . "_time" . $comand;
  4370. my $testtstate = $devicedetails{$timerkey};
  4371. #MSwitch_LOG( $name, 0,"$name: testtstat1e -> ".$testtstate);
  4372. $testtstate =~ s/[A-Za-z0-9#\.\-_]//g;
  4373. #MSwitch_LOG( $name, 0,"$name:testtstate2 -> ".$testtstate);
  4374. if ( $testtstate eq "[:]" || $testtstate eq "[\$:]")
  4375. {
  4376. $devicedetails{$timerkey} =
  4377. eval MSwitch_Checkcond_state( $devicedetails{$timerkey}, $name );
  4378. if ($devicedetails{$timerkey} =~ m/[0-9]\d:[0-9]\d:[0-9]\d/)
  4379. {
  4380. MSwitch_LOG( $name, 5,"$name: format ok ");
  4381. my $hdel = ( substr( $devicedetails{$timerkey}, 0, 2 ) ) * 3600;
  4382. my $mdel = ( substr( $devicedetails{$timerkey}, 3, 2 ) ) * 60;
  4383. my $sdel = ( substr( $devicedetails{$timerkey}, 6, 2 ) ) * 1;
  4384. $devicedetails{$timerkey} = $hdel + $mdel + $sdel;
  4385. }
  4386. else
  4387. {
  4388. MSwitch_LOG( $name, 1,"$name: ERROR Timerformat ".$devicedetails{$timerkey}." fehlerhaf ");
  4389. $devicedetails{$timerkey} = 0;
  4390. }
  4391. }
  4392. MSwitch_LOG( $name, 5,"$name: timer des devices -> ".$devicedetails{$timerkey});
  4393. # teste auf condition
  4394. # antwort $execute 1 oder 0 ;
  4395. my $conditionkey = $device . "_condition" . $comand;
  4396. if ( $devicedetails{$key} ne "" && $devicedetails{$key} ne "no_action" )
  4397. {
  4398. my $cs = '';
  4399. if ( $devicenamet eq 'FreeCmd' )
  4400. {
  4401. $cs = " $devicedetails{$device.'_'.$comand.'arg'}";
  4402. $cs = MSwitch_makefreecmd($hash,$cs);
  4403. }
  4404. else
  4405. {
  4406. $cs ="set $devicenamet $devicedetails{$device.'_'.$comand} $devicedetails{$device.'_'.$comand.'arg'}";
  4407. }
  4408. #Variabelersetzung
  4409. $cs =~ s/\$NAME/$hash->{helper}{eventfrom}/;
  4410. $cs =~ s/\$SELF/$name/;
  4411. if ( $devicedetails{$timerkey} eq "0" || $devicedetails{$timerkey} eq "" )
  4412. {
  4413. # teste auf condition
  4414. # antwort $execute 1 oder 0 ;
  4415. $conditionkey = $device . "_condition" . $comand;
  4416. my $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $event );
  4417. $testtoggle = 'undef';
  4418. if ( $execute eq 'true' )
  4419. {
  4420. $testtoggle = $cs;
  4421. #############
  4422. Log3( $name, 3,"$name MSwitch_Restartcm: Befehlsausfuehrung -> $cs ". __LINE__ );
  4423. my $toggle = '';
  4424. if ( $cs =~ m/set (.*)(MSwitchtoggle)(.*)/ )
  4425. {
  4426. $toggle = $cs;
  4427. $cs = MSwitch_toggle( $hash, $cs );
  4428. }
  4429. MSwitch_LOG( $name, 5,"$name: auszufuehrender Befehl -> ".$cs);
  4430. # neu
  4431. $devicedetails{ $device . '_repeatcount' } = 0 if !defined $devicedetails{ $device . '_repeatcount' };
  4432. $devicedetails{ $device . '_repeattime' } = 0 if !defined $devicedetails{ $device . '_repeattime' };
  4433. MSwitch_LOG( $name, 5,"$name: teste auf repeasts ");
  4434. my $x =0;
  4435. while ( $devicedetails{ $device . '_repeatcount' } =~ m/\[(.*)\:(.*)\]/ )
  4436. {
  4437. $x++; # exit
  4438. last if $x > 20; # exit
  4439. my $setmagic = ReadingsVal( $1, $2, 0 );
  4440. $devicedetails{ $device . '_repeatcount' } = $setmagic
  4441. }
  4442. $x =0;
  4443. while ( $devicedetails{ $device . '_repeattime' } =~ m/\[(.*)\:(.*)\]/ )
  4444. {
  4445. $x++; # exit
  4446. last if $x > 20; # exit
  4447. my $setmagic = ReadingsVal( $1, $2, 0 );
  4448. $devicedetails{ $device . '_repeattime' } = $setmagic
  4449. }
  4450. if ($devicedetails{ $device . '_repeatcount' } eq "") {$devicedetails{ $device . '_repeatcount' } = 0};
  4451. if ($devicedetails{ $device . '_repeattime' } eq "") {$devicedetails{ $device . '_repeattime' } = 0};
  4452. MSwitch_LOG( $name, 5,"$name: anzahl repeats -> ".$devicedetails{ $device . '_repeatcount' });
  4453. MSwitch_LOG( $name, 5,"$name: delay repeats -> ".$devicedetails{ $device . '_repeattime' });
  4454. if ( AttrVal( $name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeatcount' } > 0 && $devicedetails{ $device . '_repeattime' } > 0 )
  4455. {
  4456. my $i;
  4457. for ( $i = 0 ;$i <= $devicedetails{ $device . '_repeatcount' }; $i++)
  4458. {
  4459. my $msg = $cs . "|" . $name;
  4460. if ( $toggle ne '' )
  4461. {
  4462. $msg = $toggle . "|" . $name;
  4463. }
  4464. my $timecond =gettimeofday() +( ( $i + 1 ) * $devicedetails{ $device . '_repeattime' } );
  4465. $msg = $msg.",".$timecond;
  4466. $hash->{helper}{repeats}{$timecond} = "$msg";
  4467. MSwitch_LOG( $name, 5,"$name: repeat gesetzt -> ".$timecond." ".$msg);
  4468. InternalTimer( $timecond, "MSwitch_repeat", $msg );
  4469. }
  4470. }
  4471. my $todec = $cs;
  4472. $cs = MSwitch_dec($hash,$todec);
  4473. ############################
  4474. if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '2' )
  4475. {
  4476. MSwitch_LOG( $name, 5,"$name: execute -> ".$cs);
  4477. }
  4478. else{
  4479. if ( $cs =~ m/{.*}/ )
  4480. {
  4481. eval($cs);
  4482. if ($@)
  4483. {
  4484. Log3( $name, 1,"$name MSwitch_Set: ERROR $cs: $@ ". __LINE__ );
  4485. }
  4486. }
  4487. else
  4488. {
  4489. my $errors = AnalyzeCommandChain( undef, $cs );
  4490. if ( defined($errors) )
  4491. {
  4492. Log3( $name, 1,"$name Absent_Exec_Notif $comand: ERROR $device: $errors -> Comand: $cs" );
  4493. }
  4494. }
  4495. }
  4496. my $msg = $cs;
  4497. if (length($msg) > 100 ){ $msg = substr($msg,0,100).'....';}
  4498. readingsSingleUpdate( $hash, "Exec_cmd", $msg, 1 ) if $msg ne '';
  4499. }
  4500. }
  4501. else
  4502. {
  4503. # ################### magictimer
  4504. # my $x = 0;
  4505. # while ( $devicedetails{$timerkey} =~ m/(.*?)(\$SELF)(.*)?/)
  4506. # {
  4507. # my $firstpart = $1;
  4508. # my $secondpart = $2;
  4509. # my $lastpart = $3;
  4510. # $devicedetails{$timerkey} = $firstpart.$name.$lastpart;
  4511. # $x++;
  4512. # last if $x > 10; #notausstieg
  4513. # }
  4514. # # setmagic ersetzun
  4515. # MSwitch_LOG( $name, 5, "vor freecmd: ".$cs );
  4516. # $x =0;
  4517. # while ( $devicedetails{$timerkey} =~ m/(.*)\[(.*)\:(.*)\](.*)/ )
  4518. # {
  4519. # $x++; # notausstieg notausstieg
  4520. # last if $x > 20; # notausstieg notausstieg
  4521. # my $setmagic = ReadingsVal( $2, $3, 0 );
  4522. # $devicedetails{$timerkey} = $1.$setmagic.$4;
  4523. # }
  4524. ###################
  4525. if ( AttrVal( $name, 'MSwitch_RandomTime', '' ) ne ''&& $devicedetails{$timerkey} eq '[random]' )
  4526. {
  4527. $devicedetails{$timerkey} =
  4528. MSwitch_Execute_randomtimer($hash);
  4529. # ersetzt $devicedetails{$timerkey} gegen randomtimer
  4530. }
  4531. elsif ( AttrVal( $name, 'MSwitch_RandomTime', '' ) eq '' && $devicedetails{$timerkey} eq '[random]' )
  4532. {
  4533. $devicedetails{$timerkey} = 0;
  4534. }
  4535. my $timecond = gettimeofday() + $devicedetails{$timerkey};
  4536. my $delaykey = $device . "_delayat" . $comand;
  4537. my $delayinhalt = $devicedetails{$delaykey};
  4538. my $delaykey1 = $device . "_delayat" . $comand . "org";
  4539. my $teststateorg = $devicedetails{$delaykey1};
  4540. $conditionkey = $device . "_condition" . $comand;
  4541. my $execute = "true";
  4542. if ($delayinhalt ne "delay2" && $delayinhalt ne "at02")
  4543. {
  4544. $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $event);
  4545. }
  4546. if ($execute eq "true")
  4547. {
  4548. if ( $delayinhalt eq 'at0' || $delayinhalt eq 'at1' )
  4549. {
  4550. $timecond = MSwitch_replace_delay( $hash, $teststateorg );
  4551. }
  4552. if ( $delayinhalt eq 'at1' || $delayinhalt eq 'delay0' )
  4553. {
  4554. $conditionkey = "nocheck";
  4555. }
  4556. $cs =~ s/,/##/g;
  4557. my $msg =
  4558. $cs . "#[tr]"
  4559. . $name . "#[tr]"
  4560. . $conditionkey . "#[tr]"
  4561. . $event . "#[tr]"
  4562. . $timecond . "#[tr]"
  4563. . $device;
  4564. $hash->{helper}{delays}{$msg} = $timecond;
  4565. $testtoggle = 'undef';
  4566. MSwitch_LOG( $name, 5,"$name: timer gesetzt -> ".$cs);
  4567. MSwitch_LOG( $name, 5,"$name: timer gesetzt name -> ".$name);
  4568. MSwitch_LOG( $name, 5,"$name: timer gesetzt conditionkey-> ".$conditionkey);
  4569. MSwitch_LOG( $name, 5,"$name: timer gesetzt event-> ".$event);
  4570. MSwitch_LOG( $name, 5,"$name: timer gesetzt timecond-> ".$timecond);
  4571. MSwitch_LOG( $name, 5,"$name: timer gesetzt -> device ".$device);
  4572. InternalTimer( $timecond, "MSwitch_Restartcmd", $msg );
  4573. }
  4574. }
  4575. }
  4576. if ( $testtoggle ne '' && $testtoggle ne 'undef' )
  4577. {
  4578. $satz .= $testtoggle . ',';
  4579. }
  4580. }
  4581. return $satz;
  4582. }
  4583. ####################
  4584. sub MSwitch_Filter_Trigger($) {
  4585. my ($hash) = @_;
  4586. my $Name = $hash->{NAME};
  4587. if ( !exists $hash->{Trigger_device} ) { return; } #CHANGE
  4588. my $Triggerdevice = $hash->{Trigger_device};
  4589. my $triggeron = ReadingsVal( $Name, '.Trigger_on', 'no_trigger' );
  4590. if ( !defined $triggeron ) { $triggeron = "" }
  4591. my $triggeroff = ReadingsVal( $Name, '.Trigger_off', 'no_trigger' );
  4592. if ( !defined $triggeroff ) { $triggeroff = "" }
  4593. my $triggercmdon = ReadingsVal( $Name, '.Trigger_cmd_on', 'no_trigger' );
  4594. if ( !defined $triggercmdon ) { $triggercmdon = "" }
  4595. my $triggercmdoff = ReadingsVal( $Name, '.Trigger_cmd_off', 'no_trigger' );
  4596. if ( !defined $triggercmdoff ) { $triggercmdoff = "" }
  4597. my $triggerdevice = ReadingsVal( $Name, 'Trigger_device', '' );
  4598. delete( $hash->{helper}{events}{$Triggerdevice} );
  4599. $hash->{helper}{events}{$Triggerdevice}{'no_trigger'} = "on";
  4600. $hash->{helper}{events}{$Triggerdevice}{$triggeron} = "on";
  4601. $hash->{helper}{events}{$Triggerdevice}{$triggeroff} = "on";
  4602. $hash->{helper}{events}{$Triggerdevice}{$triggercmdon} = "on";
  4603. $hash->{helper}{events}{$Triggerdevice}{$triggercmdoff} = "on";
  4604. my $events = ReadingsVal( $Name, '.Device_Events', '' );
  4605. my @eventsall = split( /#\[tr\]/, $events );
  4606. EVENT: foreach my $eventcopy (@eventsall)
  4607. {
  4608. my @filters =split( /,/, AttrVal( $Name, 'MSwitch_Trigger_Filter', '' ) ) ;# beinhaltet filter durch komma getrennt
  4609. foreach my $filter (@filters)
  4610. {
  4611. my $wildcarttest = index( $filter, "*", 0 );
  4612. if ( $wildcarttest > -1 ) ### filter auf wildcart
  4613. {
  4614. $filter = substr( $filter, 0, $wildcarttest );
  4615. my $testwildcart = index( $eventcopy, $filter, 0 );
  4616. if ( $testwildcart eq '0' )
  4617. {
  4618. next EVENT;
  4619. }
  4620. }
  4621. else### filter genauen ausdruck
  4622. {
  4623. if ( $eventcopy eq $filter )
  4624. {
  4625. next EVENT;
  4626. }
  4627. }
  4628. }
  4629. $hash->{helper}{events}{$Triggerdevice}{$eventcopy} = "on";
  4630. }
  4631. my $eventhash = $hash->{helper}{events}{$Triggerdevice};
  4632. $events = "";
  4633. foreach my $name ( keys %{$eventhash} )
  4634. {
  4635. $events = $events . $name . '#[tr]';
  4636. }
  4637. chop($events);
  4638. chop($events);
  4639. chop($events);
  4640. chop($events);
  4641. chop($events);
  4642. readingsSingleUpdate( $hash, ".Device_Events", $events, 0 );
  4643. return;
  4644. }
  4645. ####################
  4646. sub MSwitch_Restartcmd($) {
  4647. my $incomming = $_[0];
  4648. my @msgarray = split( /#\[tr\]/, $incomming );
  4649. my $name = $msgarray[1];
  4650. return "" if ( IsDisabled($name) );
  4651. MSwitch_LOG( $name, 5, "----------------------------------------" );
  4652. MSwitch_LOG( $name, 5, "$name: aufruf restartcmd -> ".$incomming );
  4653. MSwitch_LOG( $name, 5, "----------------------------------------" );
  4654. # checke versionskonflikt der datenstruktur
  4655. if ( ReadingsVal( $name, '.V_Check', $vupdate ) ne $vupdate )
  4656. {
  4657. my $ver = ReadingsVal( $name, '.V_Check', '' );
  4658. MSwitch_LOG( $name, 5, "$name: Versionskonflikt - aktion abgebrochen");
  4659. return;
  4660. }
  4661. my $cs = $msgarray[0];
  4662. #$cs =~ s/##/,/g;
  4663. my $conditionkey = $msgarray[2];
  4664. my $event = $msgarray[2];
  4665. my $device = $msgarray[5];
  4666. my $hash = $modules{MSwitch}{defptr}{$name};
  4667. #MSwitch_LOG( $name, 5, "$name: msga4 -> ".$msgarray[4]);
  4668. #MSwitch_LOG( $name, 5, "$name: msga5 -> ".$msgarray[5]);
  4669. #MSwitch_LOG( $name, 5, "$name: msga6 -> ".$msgarray[6]);
  4670. #MSwitch_LOG( $name, 5, "$name: befehl -> ".$cs);
  4671. #MSwitch_LOG( $name, 5, "$name: event -> ".$event);
  4672. #MSwitch_LOG( $name, 5, "$name: device -> ".$device);
  4673. #MSwitch_LOG( $name, 5, "$name: befehl -> ".$cs);
  4674. MSwitch_LOG( $name, 5, "$name: erstelle cmdhash -> ".$name);
  4675. my %devicedetails = MSwitch_makeCmdHash($name);
  4676. if ( AttrVal( $name, 'MSwitch_RandomNumber', '' ) ne '' )
  4677. {
  4678. MSwitch_Createnumber1($hash);
  4679. }
  4680. ############ teste auf condition
  4681. ### antwort $execute 1 oder 0 ;
  4682. my $execute = "true";
  4683. MSwitch_LOG( $name, 5, "$name: kein aufruf checkcondition - nicht gesetzt ->".$execute) if $devicedetails{$conditionkey} eq '' || $devicedetails{$conditionkey} eq 'nocheck';
  4684. if ( $msgarray[2] ne 'nocheck' )
  4685. {
  4686. MSwitch_LOG( $name, 5, "$name: aufruf checkcondition mit -> ".$devicedetails{$conditionkey});
  4687. $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name,$event );
  4688. MSwitch_LOG( $name, 5, "$name: ergebniss checkcondition -> ".$execute);
  4689. }
  4690. my $toggle = '';
  4691. if ( $execute eq 'true' )
  4692. {
  4693. Log3( $name, 3, "$name MSwitch_Restartcm: Befehlsausfuehrung -> $cs " . __LINE__ );
  4694. if ( $cs =~ m/set (.*)(MSwitchtoggle)(.*)/ )
  4695. {
  4696. $toggle = $cs;
  4697. $cs = MSwitch_toggle( $hash, $cs );
  4698. }
  4699. MSwitch_LOG( $name, 5, "$name: teste repeat -> ".$devicedetails{ $device . '_repeatcount' });
  4700. my $x =0;
  4701. while ( $devicedetails{ $device . '_repeatcount' } =~ m/\[(.*)\:(.*)\]/ )
  4702. {
  4703. $x++; # notausstieg notausstieg
  4704. last if $x > 20; # notausstieg notausstieg
  4705. my $setmagic = ReadingsVal( $1, $2, 0 );
  4706. $devicedetails{ $device . '_repeatcount' } = $setmagic
  4707. }
  4708. $x =0;
  4709. while ( $devicedetails{ $device . '_repeattime' } =~ m/\[(.*)\:(.*)\]/ )
  4710. {
  4711. $x++; # notausstieg notausstieg
  4712. last if $x > 20; # notausstieg notausstieg
  4713. my $setmagic = ReadingsVal( $1, $2, 0 );
  4714. $devicedetails{ $device . '_repeattime' } = $setmagic
  4715. }
  4716. MSwitch_LOG( $name, 5, "$name: repetcount nach test -> ".$devicedetails{ $device . '_repeatcount' });
  4717. MSwitch_LOG( $name, 5, "$name: repeattime nach test -> ".$devicedetails{ $device . '_repeattime' });
  4718. ######################################
  4719. if ( AttrVal( $name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeatcount' } > 0 && $devicedetails{ $device . '_repeattime' } > 0 )
  4720. {
  4721. my $i;
  4722. for ($i = 0 ;$i <= $devicedetails{ $device . '_repeatcount' } ;$i++ )
  4723. {
  4724. my $msg = $cs . "|" . $name;
  4725. if ( $toggle ne '' )
  4726. {
  4727. $msg = $toggle . "|" . $name;
  4728. }
  4729. my $timecond = gettimeofday() +( ( $i + 1 ) * $devicedetails{ $device . '_repeattime' } );
  4730. $msg = $msg."|".$timecond;
  4731. $hash->{helper}{repeats}{$timecond} = "$msg";
  4732. MSwitch_LOG( $name, 5, "$name: repeat gesetzt -> ".$timecond." - ".$msg);
  4733. InternalTimer( $timecond, "MSwitch_repeat", $msg );
  4734. }
  4735. }
  4736. my $todec = $cs;
  4737. $cs = MSwitch_dec($hash,$todec);
  4738. ############################
  4739. if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '2' )
  4740. {
  4741. MSwitch_LOG( $name, 5,"$name: exec comand -> ".$cs );
  4742. }
  4743. else
  4744. {
  4745. if ( $cs =~ m/{.*}/ )
  4746. {
  4747. MSwitch_LOG( $name, 5,"$name: exec als perlcode -> ".$cs );
  4748. eval($cs);
  4749. if ($@)
  4750. {
  4751. MSwitch_LOG( $name, 1,"$name MSwitch_Set: ERROR $cs: $@ " . __LINE__ );
  4752. }
  4753. }
  4754. else
  4755. {
  4756. MSwitch_LOG( $name, 5,"$name: execute als fhemcode -> ".$cs );
  4757. my $errors = AnalyzeCommandChain( undef, $cs );
  4758. if ( defined($errors) )
  4759. {
  4760. MSwitch_LOG( $name, 1,"$name MSwitch_Restartcmd :Fehler bei Befehlsausfuehrung ERROR $errors ". __LINE__ );
  4761. }
  4762. }
  4763. }
  4764. if (length($cs) > 100 ){ $cs = substr($cs,0,100).'....';}
  4765. readingsSingleUpdate( $hash, "Exec_cmd", $cs, 1 ) if $cs ne '';
  4766. }
  4767. RemoveInternalTimer($incomming);
  4768. delete( $hash->{helper}{delays}{$incomming} );
  4769. return;
  4770. }
  4771. ####################
  4772. sub MSwitch_checkcondition($$$) {
  4773. # antwort execute 0 oder 1
  4774. my ( $condition, $name, $event ) = @_;
  4775. my $hash = $modules{MSwitch}{defptr}{$name};
  4776. #$event ="test:test:test" if $event eq "";
  4777. MSwitch_LOG( $name, 5,"$name: Checkcondition - Parameter condition -> ".$condition ) ;
  4778. MSwitch_LOG( $name, 5,"$name: Checkcondition - Parameter event -> ".$event ) ;
  4779. MSwitch_EventBulk($hash,$event ,'0');
  4780. if ( !defined($condition) ) { return 'true'; }
  4781. if ( $condition eq '' ) { return 'true'; }
  4782. if ( AttrVal( $name, 'MSwitch_RandomNumber', '' ) ne '' ) {MSwitch_Createnumber($hash);}
  4783. my $anzahlk1 = $condition =~ tr/{//;
  4784. my $anzahlk2 = $condition =~ tr/}//;
  4785. if ( $anzahlk1 ne $anzahlk2 )
  4786. {
  4787. $hash->{helper}{conditioncheck} = "Klammerfehler";
  4788. return "false";
  4789. }
  4790. $anzahlk1 = $condition =~ tr/(//;
  4791. $anzahlk2 = $condition =~ tr/)//;
  4792. if ( $anzahlk1 ne $anzahlk2 )
  4793. {
  4794. $hash->{helper}{conditioncheck} = "Klammerfehler";
  4795. return "false";
  4796. }
  4797. $anzahlk1 = $condition =~ tr/[//;
  4798. $anzahlk2 = $condition =~ tr/]//;
  4799. if ( $anzahlk1 ne $anzahlk2 )
  4800. {
  4801. $hash->{helper}{conditioncheck} = "Klammerfehler";
  4802. return "false";
  4803. }
  4804. #$event =~ s/ //ig;
  4805. #$event =~ s/~/ /g;
  4806. MSwitch_EventBulk($hash , $event , '0') if $event eq "";;
  4807. my $arraycount = '0';
  4808. my $finalstring;
  4809. my $answer;
  4810. my $i;
  4811. my $pos;
  4812. my $pos1;
  4813. my $part;
  4814. my $part1;
  4815. my $part2;
  4816. my $part3;
  4817. my $lenght;
  4818. # wildcardcheck
  4819. my $we = AnalyzeCommand( 0, '{return $we}' );
  4820. my @perlarray;
  4821. ### perlteile trennen
  4822. $condition =~ s/{!\$we}/ !\$we /ig;
  4823. $condition =~ s/{\$we}/ \$we /ig;
  4824. $condition =~ s/{sunset\(\)}/{ sunset\(\) }/ig;
  4825. $condition =~ s/{sunrise\(\)}/{ sunrise\(\) }/ig;
  4826. $condition =~ s/\$EVENT/$name\:last_event/ig;
  4827. $condition =~ s/\$EVTFULL/$name\:EVTFULL/ig;
  4828. $condition =~ s/\$EVTPART1/$name\:EVTPART1/ig;
  4829. $condition =~ s/\$EVTPART2/$name\:EVTPART2/ig;
  4830. $condition =~ s/\$EVTPART3/$name\:EVTPART3/ig;
  4831. my $x = 0;
  4832. while ( $condition =~ m/(.*?)(\$NAME)(.*)?/)
  4833. {
  4834. my $firstpart = $1;
  4835. my $secondpart = $2;
  4836. my $lastpart = $3;
  4837. $condition = $firstpart.$name.$lastpart;
  4838. $x++;
  4839. last if $x > 10; #notausstieg
  4840. }
  4841. $x = 0;
  4842. while ( $condition =~ m/(.*?)(\$SELF)(.*)?/)
  4843. {
  4844. my $firstpart = $1;
  4845. my $secondpart = $2;
  4846. my $lastpart = $3;
  4847. $condition = $firstpart.$name.$lastpart;
  4848. $x++;
  4849. last if $x > 10; #notausstieg
  4850. }
  4851. my $searchstring;
  4852. $x = 0;
  4853. while ( $condition =~m/(.*?)(\[\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]-\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]\])(.*)?/)
  4854. {
  4855. my $firstpart = $1;
  4856. $searchstring = $2;
  4857. my $lastpart = $3;
  4858. $x++;
  4859. last if $x > 10;#notausstieg
  4860. my $x = 0;
  4861. # Searchstring -> [[t1:state]-[t2:state]]
  4862. while ( $searchstring =~ m/(.*?)(\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\])(.*)?/ )
  4863. {
  4864. my $read1 = '';
  4865. my $firstpart = $1;
  4866. my $secsearchstring = $2;
  4867. my $lastpart = $3;
  4868. if ( $secsearchstring =~ m/\[(.*):(.*)\]/ )
  4869. {
  4870. $read1 = ReadingsVal( $1, $2, 'undef' );
  4871. }
  4872. $searchstring = $firstpart . $read1 . $lastpart;
  4873. $x++;
  4874. last if $x > 10; #notausstieg
  4875. }
  4876. $condition = $firstpart . $searchstring . $lastpart;
  4877. }
  4878. $x = 0;
  4879. while ( $condition =~ m/(.*)({ )(.*)(\$we)( })(.*)/ )
  4880. {
  4881. last if $x > 20; # notausstieg
  4882. $condition = $1 . " " . $3 . $4 . " " . $6;
  4883. }
  4884. ###################################################
  4885. # ersetzte sunset sunrise
  4886. # regex (.*[^~])(~{|{)(sunset\(|sunrise\()(.*\))(~}|})(.*)
  4887. $x = 0;# notausstieg
  4888. while ($condition =~ m/(.*)({ )(sunset\([^}]*\)|sunrise\([^}]*\))( })(.*)/ )
  4889. {
  4890. $x++; # notausstieg
  4891. last if $x > 20; # notausstieg
  4892. if ( defined $2 )
  4893. {
  4894. my $part2 = eval $3;
  4895. chop($part2);
  4896. chop($part2);
  4897. chop($part2);
  4898. my ( $testhour, $testmin ) = split( /:/, $part2 );
  4899. if ( $testhour > 23 )
  4900. {
  4901. $testhour = $testhour - 24;
  4902. $testhour = '0' . $testhour if $testhour < 10;
  4903. $part2 = $testhour . ':' . $testmin;
  4904. }
  4905. $condition = $part2;
  4906. $condition = $1 . $condition if ( defined $1 );
  4907. $condition = $condition . $5 if ( defined $5 );
  4908. }
  4909. }
  4910. my $conditioncopy = $condition;
  4911. my @argarray;
  4912. $arraycount = '0';
  4913. $pos = '';
  4914. $pos1 = '';
  4915. $part = '';
  4916. $part1 = '';
  4917. $part2 = '';
  4918. $part3 = '';
  4919. $lenght = '';
  4920. ARGUMENT: for ( $i = 0 ; $i <= 10 ; $i++ )
  4921. {
  4922. $pos = index( $condition, "[", 0 );
  4923. my $x = $pos;
  4924. if ( $x == '-1' ) { last ARGUMENT; }
  4925. $pos1 = index( $condition, "]", 0 );
  4926. $argarray[$arraycount] =substr( $condition, $pos, ( $pos1 + 1 - $pos ) );
  4927. $lenght = length($condition);
  4928. $part1 = substr( $condition, 0, $pos );
  4929. $part2 = 'ARG' . $arraycount;
  4930. $part3 =substr( $condition, ( $pos1 + 1 ), ( $lenght - ( $pos1 + 1 ) ) );
  4931. $condition = $part1 . $part2 . $part3;
  4932. $arraycount++;
  4933. }
  4934. $condition =~ s/ AND / && /ig;
  4935. $condition =~ s/ OR / || /ig;
  4936. #$condition =~ s/~/ /ig;
  4937. $condition =~ s/ = / == /ig;
  4938. END:
  4939. # teste auf typ
  4940. my $count = 0;
  4941. my $testarg;
  4942. my @newargarray;
  4943. foreach my $args (@argarray)
  4944. {
  4945. $testarg = $args;
  4946. $testarg =~ s/[0-9]+//gs;
  4947. if ( $testarg eq '[:-:|]' || $testarg eq '[:-:]' )
  4948. {
  4949. # timerformatierung erkannt - auswerten über sub
  4950. my $param = $argarray[$count];
  4951. $newargarray[$count] = MSwitch_Checkcond_time( $args, $name );
  4952. }
  4953. else
  4954. {
  4955. my $param = $argarray[$count];
  4956. # stateformatierung erkannt - auswerten über sub
  4957. $newargarray[$count] = MSwitch_Checkcond_state( $args, $name );
  4958. }
  4959. $count++;
  4960. }
  4961. $count = 0;
  4962. my $tmp;
  4963. foreach my $args (@newargarray)
  4964. {
  4965. $tmp = 'ARG' . $count;
  4966. $condition =~ s/$tmp/$args/ig;
  4967. $count++;
  4968. }
  4969. $finalstring ="if (" . $condition . "){\$answer = 'true';} else {\$answer = 'false';} ";
  4970. MSwitch_LOG( $name, 5,"$name: Checkcondition - finalstring -> ".$finalstring ) ;
  4971. my $ret = eval $finalstring;
  4972. MSwitch_LOG( $name, 5,"$name: Checkcondition - return -> ".$ret ) ;
  4973. if ($@)
  4974. {
  4975. MSwitch_LOG( $name, 1, "ERROR: $@ " . __LINE__ );
  4976. MSwitch_LOG( $name, 1, "$finalstring " . __LINE__ );
  4977. $hash->{helper}{conditionerror} = $@;
  4978. return 'false';
  4979. }
  4980. my $test = ReadingsVal( $name, 'last_event', 'undef' );
  4981. $hash->{helper}{conditioncheck} = $finalstring;
  4982. return $ret;
  4983. }
  4984. ####################
  4985. ####################
  4986. sub MSwitch_Checkcond_state($$) {
  4987. my ( $condition, $name ) = @_;
  4988. MSwitch_LOG( $name, 5, "----------------------------------------" );
  4989. MSwitch_LOG( $name, 5, "$name: MSwitch_Checkcond_state -> ".$condition );
  4990. MSwitch_LOG( $name, 5, "----------------------------------------" );
  4991. my $x = 0;
  4992. while ( $condition =~ m/(.*?)(\$SELF)(.*)?/)
  4993. {
  4994. my $firstpart = $1;
  4995. my $secondpart = $2;
  4996. my $lastpart = $3;
  4997. $condition = $firstpart.$name.$lastpart;
  4998. $x++;
  4999. last if $x > 10; #notausstieg
  5000. }
  5001. $condition =~ s/\[//;
  5002. $condition =~ s/\]//;
  5003. my @reading = split( /:/, $condition );
  5004. my $return = "ReadingsVal('$reading[0]', '$reading[1]', '00:00:00')";
  5005. my $test = ReadingsVal( $reading[0], $reading[1], 'undef' );
  5006. MSwitch_LOG( $name, 5, "$name: MSwitch_Checkcond_state OUT -> ".$return );
  5007. return $return;
  5008. }
  5009. ####################
  5010. sub MSwitch_Checkcond_time($$) {
  5011. my ( $condition, $name ) = @_;
  5012. $condition =~ s/\[//;
  5013. $condition =~ s/\]//;
  5014. my $adday = 0;
  5015. my $days = '';
  5016. my $daycondition = '';
  5017. ( $condition, $days ) = split( /\|/, $condition ) if index( $condition, "|", 0 ) > -1;
  5018. my $hour1 = substr( $condition, 0, 2 );
  5019. my $min1 = substr( $condition, 3, 2 );
  5020. my $hour2 = substr( $condition, 6, 2 );
  5021. my $min2 = substr( $condition, 9, 2 );
  5022. if ( $hour1 eq "24" )# test auf 24 zeitangabe
  5023. {
  5024. $hour1 = "00";
  5025. }
  5026. if ( $hour2 eq "24" )
  5027. {
  5028. $hour2 = "00";
  5029. }
  5030. my $time = localtime;
  5031. $time =~ s/\s+/ /g;
  5032. my ( $day, $month, $date, $n, $time1 ) = split( / /, $time );
  5033. my ( $akthour, $aktmin, $aktsec ) = split( /:/, $n );
  5034. ############ timecondition 1
  5035. my $timecondtest;
  5036. my $timecond1;
  5037. #my $time1;
  5038. my ( $tday, $tmonth, $tdate, $tn ); #my ($tday,$tmonth,$tdate,$tn,$time1);
  5039. if ( ( $akthour < $hour1 && $akthour < $hour2 ) && $hour2 < $hour1 ) # und
  5040. {
  5041. use constant SECONDS_PER_DAY => 60 * 60 * 24;
  5042. $timecondtest = localtime( time - SECONDS_PER_DAY );
  5043. $timecondtest =~ s/\s+/ /g;
  5044. ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest );
  5045. $timecond1 = timelocal( '00', $min1, $hour1, $tdate, $tmonth, $time1 );
  5046. $adday = 1;
  5047. }
  5048. else
  5049. {
  5050. $timecondtest = localtime;
  5051. $timecondtest =~ s/\s+/ /g;
  5052. ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest );
  5053. $timecond1 = timelocal( '00', $min1, $hour1, $tdate, $tmonth, $time1 );
  5054. }
  5055. ############# timecondition 2
  5056. my $timecond2;
  5057. $timecondtest = localtime;
  5058. if ( $hour2 < $hour1 )
  5059. {
  5060. if ( $akthour < $hour1 && $akthour < $hour2 )
  5061. {
  5062. $timecondtest = localtime;
  5063. $timecondtest =~ s/\s+/ /g;
  5064. ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest );
  5065. $timecond2 =timelocal( '00', $min2, $hour2, $tdate, $tmonth, $time1 );
  5066. }
  5067. else
  5068. {
  5069. use constant SECONDS_PER_DAY => 60 * 60 * 24;
  5070. $timecondtest = localtime( time + SECONDS_PER_DAY );
  5071. $timecondtest =~ s/\s+/ /g;
  5072. my ( $tday, $tmonth, $tdate, $tn, $time1 ) =split( / /, $timecondtest );
  5073. $timecond2 =timelocal( '00', $min2, $hour2, $tdate, $tmonth, $time1 );
  5074. $adday = 1;
  5075. }
  5076. }
  5077. else
  5078. {
  5079. $timecondtest = localtime;
  5080. $timecondtest =~ s/\s+/ /g;
  5081. ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest );
  5082. $timecond2 = timelocal( '00', $min2, $hour2, $tdate, $tmonth, $time1 );
  5083. }
  5084. my $timeaktuell = timelocal( '00', $aktmin, $akthour, $date, $month, $time1 );
  5085. my $return = "($timecond1 < $timeaktuell && $timeaktuell < $timecond2)";
  5086. if ( $days ne '' )
  5087. {
  5088. $daycondition = MSwitch_Checkcond_day( $days, $name, $adday, $day );
  5089. $return = "($return $daycondition)";
  5090. }
  5091. return $return;
  5092. }
  5093. ####################
  5094. sub MSwitch_Checkcond_day($$$$) {
  5095. my ( $days, $name, $adday, $day ) = @_;
  5096. my %daysforcondition = (
  5097. "Mon" => 1,
  5098. "Tue" => 2,
  5099. "Wed" => 3,
  5100. "Thu" => 4,
  5101. "Fri" => 5,
  5102. "Sat" => 6,
  5103. "Sun" => 7
  5104. );
  5105. $day = $daysforcondition{$day};
  5106. my @daycond = split //, $days;
  5107. my $daycond = '';
  5108. foreach my $args (@daycond)
  5109. {
  5110. if ( $adday == 1 ) { $args++; }
  5111. if ( $args == 8 ) { $args = 1 }
  5112. $daycond = $daycond . "($day == $args) || ";
  5113. }
  5114. chop $daycond;
  5115. chop $daycond;
  5116. chop $daycond;
  5117. chop $daycond;
  5118. $daycond = "&& ($daycond)";
  5119. return $daycond;
  5120. }
  5121. ####################
  5122. sub MSwitch_Createtimer($) {
  5123. my ($hash) = @_;
  5124. my $Name = $hash->{NAME};
  5125. # keine timer vorhenden
  5126. my $condition = ReadingsVal( $Name, '.Trigger_time', '' );
  5127. $condition =~ s/#\[dp\]/:/g;
  5128. #MSwitch_LOG( $Name, 0,"create timer: ".$condition);
  5129. my $x =0;
  5130. # (.*)\[(.*[a-zA-Z].*)\:(.*)\](.*)
  5131. #while ( $condition =~ m/(.*)\[(.*[^0-9]{2})\:(.*[^0-9]{2})\](.*)/ )
  5132. #while ( $condition =~ m/(.*)\[(.*[a-zA-Z].*)\:(.*)\](.*)/ )
  5133. while ( $condition =~ m/(.*)(\[)([0-9]?[a-zA-Z]{1}.*)\:(.*)(\])(.*)/ )
  5134. {
  5135. #MSwitch_LOG( $Name, 0,"create timer1: ".$1);
  5136. #MSwitch_LOG( $Name, 0,"create timer2: ".$2);
  5137. #MSwitch_LOG( $Name, 0,"create timer3: ".$3);
  5138. #MSwitch_LOG( $Name, 0,"create timer4: ".$4);
  5139. $x++; # notausstieg notausstieg
  5140. last if $x > 20; # notausstieg notausstieg
  5141. my $setmagic = ReadingsVal( $3, $4, 0 );
  5142. $condition = $1.'['.$setmagic.']'.$6;
  5143. #MSwitch_LOG( $Name, 0,"create timer: ".$condition);
  5144. }
  5145. my $lenght = length($condition);
  5146. #remove all timers
  5147. MSwitch_Clear_timer($hash);
  5148. if ( $lenght == 0 )
  5149. {
  5150. return;
  5151. }
  5152. # trenne timerfile
  5153. my $key = 'on';
  5154. $condition =~ s/$key//ig;
  5155. $key = 'off';
  5156. $condition =~ s/$key//ig;
  5157. $key = 'ly';
  5158. $condition =~ s/$key//ig;
  5159. $x =0;
  5160. # achtung perl 5.30
  5161. while ($condition =~ m/(.*).\{(.*)\}.(.*)/ )
  5162. {
  5163. $x++; # notausstieg
  5164. last if $x > 20; # notausstieg
  5165. if ( defined $2 )
  5166. {
  5167. my $part2 = "[".substr( (eval $2) , 0, 5 )."]";
  5168. my $test = substr( (eval $2) , 0, 2 ) *1;
  5169. $part2 ="" if $test > 23 ;
  5170. $condition = $1.$part2.$3;
  5171. }
  5172. }
  5173. my @timer = split /~/, $condition;
  5174. $timer[0] = '' if ( !defined $timer[0] );
  5175. $timer[1] = '' if ( !defined $timer[1] );
  5176. $timer[2] = '' if ( !defined $timer[2] );
  5177. $timer[3] = '' if ( !defined $timer[3] );
  5178. #MSwitch_LOG( $Name, 0,"timer0 $timer[0]");
  5179. #MSwitch_LOG( $Name, 0,"timer1 $timer[1]");
  5180. #MSwitch_LOG( $Name, 0,"timer2 $timer[2]");
  5181. #MSwitch_LOG( $Name, 0,"timer3 $timer[3]");
  5182. # lösche bei notify und toggle
  5183. if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Notify" )
  5184. {
  5185. $timer[0] = '';
  5186. $timer[1] = '';
  5187. }
  5188. if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Toggle" )
  5189. {
  5190. $timer[1] = '';
  5191. $timer[2] = '';
  5192. $timer[3] = '';
  5193. }
  5194. my $akttimestamp = TimeNow();
  5195. my ( $aktdate, $akttime ) = split / /, $akttimestamp;
  5196. my ( $aktyear, $aktmonth, $aktmday ) = split /-/, $aktdate;
  5197. $aktmonth = $aktmonth - 1;
  5198. $aktyear = $aktyear - 1900;
  5199. my $jetzt = gettimeofday();
  5200. # aktuelle zeit setzen
  5201. my $time = localtime;
  5202. $time =~ s/\s+/ /g;
  5203. my ( $day, $month, $date, $n, $time1 ) =
  5204. split( / /, $time ); # day enthält aktuellen tag als wochentag
  5205. my $aktday = $day;
  5206. my %daysforcondition = (
  5207. "Mon" => 1,
  5208. "Tue" => 2,
  5209. "Wed" => 3,
  5210. "Thu" => 4,
  5211. "Fri" => 5,
  5212. "Sat" => 6,
  5213. "Sun" => 7
  5214. );
  5215. $day = $daysforcondition{$day}; # enthält aktuellen tag
  5216. ###
  5217. ## für jeden Timerfile ( 0 -4 )
  5218. my $i = 0;
  5219. LOOP2: foreach my $option (@timer)
  5220. {
  5221. $i++;
  5222. #### inhalt array für eine option on , off ...
  5223. $key = '\]\[';
  5224. $option =~ s/$key/ /ig;
  5225. $key = '\[';
  5226. $option =~ s/$key//ig;
  5227. $key = '\]';
  5228. $option =~ s/$key//ig;
  5229. if ( $option =~m/(.*?)([0-9]{2}):([0-9]{2})\*([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2})\|?([0-9]{0,7})(.*)?/ )
  5230. {
  5231. my $part1 = '';
  5232. $part1 = $1 . ' ' if defined $1;
  5233. my $part6 = '';
  5234. if ( defined $6 && $part6 ne '' ) { $part6 = '|' . $6 }
  5235. my $part7 = '';
  5236. $part7 = ' ' . $7 if defined $7;
  5237. my $sectoadd = $2 * 3600 + $3 * 60;
  5238. my $t1 = $4;
  5239. my $t2 = $5;
  5240. my $timecondtest = localtime;
  5241. $timecondtest =~ s/\s+/ /g;
  5242. my ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest );
  5243. my $timecond1 = timelocal( '00', substr( $t1, 3, 2 ),substr( $t1, 0, 2 ),$tdate, $tmonth, $time1 );
  5244. my $timecond2 = timelocal('00',substr( $t2, 3, 2 ), substr( $t2, 0, 2 ), $tdate, $tmonth, $time1);
  5245. my @newarray;
  5246. while ( $timecond1 < $timecond2 )
  5247. {
  5248. #my $timestamp = FmtDateTime($timecond1);
  5249. my $timestamp =substr( FmtDateTime($timecond1), 11, 5 ) . $part6;
  5250. $timecond1 = $timecond1 + $sectoadd;
  5251. push( @newarray, $timestamp );
  5252. }
  5253. my $newopt = join( ' ', @newarray );
  5254. my $newoption = $part1 . $newopt . $part7;
  5255. $newoption =~ s/ / /g;
  5256. $option = $newoption;
  5257. }
  5258. my @optionarray = split / /, $option;
  5259. # für jede angabe eines files
  5260. LOOP3: foreach my $option1 (@optionarray) {
  5261. if ( $option1 =~ m/\?(.*)(-)([0-9]{2}:[0-9]{2})(\|[0-9]{0,7})?(.*)?/ )
  5262. {
  5263. my $testrandom = $1 . $2 . $3;
  5264. my $part4 = '';
  5265. $part4 = $4 if defined $4;
  5266. my $opdays = $part4;
  5267. #testrandomsaved erstellen
  5268. my $newoption1 = MSwitch_Createrandom( $hash, $1, $3 );
  5269. $option1 = $newoption1 . $opdays;
  5270. }
  5271. if ( $option1 =~ m/{/i || $option1 =~ m/}/i )
  5272. {
  5273. my $newoption1 = MSwitch_ChangeCode( $hash, $option1 );
  5274. $option1 = $newoption1;
  5275. }
  5276. my ( $time, $days ) = split /\|/, $option1;
  5277. $time = '' if ( !defined $time );
  5278. $days = '' if ( !defined $days );
  5279. if ( $days eq '!$we' || $days eq '$we' )
  5280. {
  5281. my $we = AnalyzeCommand( 0, '{return $we}' );
  5282. if ( $days eq '$we' && $we == 1 ) { $days = $day; }
  5283. if ( $days eq '!$we' && $we == 0 ) { $days = $day; }
  5284. }
  5285. if ( !defined($days) ) { $days = '' }
  5286. if ( $days eq '' ) { $days = '1234567' }
  5287. if ( index( $days, $day, 0 ) == -1 )
  5288. {
  5289. next LOOP3;
  5290. }
  5291. $time = $time . ':00';
  5292. delete( $hash->{helper}{error} );
  5293. my $timecond = timelocal( substr( $time, 6, 2 ),substr( $time, 3, 2 ),substr( $time, 0, 2 ),$date, $aktmonth, $aktyear);
  5294. my $test = FmtDateTime($timecond);
  5295. my $sectowait = $timecond - $jetzt;
  5296. if ( $timecond > $jetzt )
  5297. {
  5298. my $inhalt = $timecond . "-" . $i;
  5299. $hash->{helper}{timer}{$inhalt} = "$inhalt";
  5300. my $msg = $Name . " " . $timecond . " " . $i;
  5301. my $gettime = gettimeofday();
  5302. InternalTimer( $timecond, "MSwitch_Execute_Timer", $msg );
  5303. }
  5304. }
  5305. }
  5306. # berechne zeit bis 23,59 und setze timer auf create timer
  5307. my $newask = timelocal( '00', '59', '23', $date, $aktmonth, $aktyear );
  5308. $newask = $newask + 70;
  5309. my $newassktest = FmtDateTime($newask);
  5310. my $msg = $Name . " " . $newask . " " . 5;
  5311. my $inhalt = $newask . "-" . 5;
  5312. $hash->{helper}{timer}{$newask} = "$inhalt";
  5313. InternalTimer( $newask, "MSwitch_Execute_Timer", $msg );
  5314. }
  5315. ##############################
  5316. sub MSwitch_Createrandom($$$) {
  5317. my ( $hash, $t1, $t2 ) = @_;
  5318. my $Name = $hash->{NAME};
  5319. my $testrandom = $t1 . "-" . $t2;
  5320. my $testt1 = $t1;
  5321. my $testt2 = $t2;
  5322. $testt1 =~ s/\://g;
  5323. $testt2 =~ s/\://g;
  5324. my $timecondtest = localtime;
  5325. $timecondtest =~ s/\s+/ /g;
  5326. my ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest );
  5327. my $timecond1 = timelocal( '00', substr( $t1, 3, 2 ), substr( $t1, 0, 2 ), $tdate, $tmonth, $time1 );
  5328. my $timecond2 = timelocal( '00', substr( $t2, 3, 2 ), substr( $t2, 0, 2 ), $tdate, $tmonth, $time1 );
  5329. if ( $testt2 < $testt1 ) { $timecond2 = $timecond2 + 86400 }
  5330. my $newtime = int( rand( $timecond2 - $timecond1 ) ) + $timecond1;
  5331. my $timestamp = FmtDateTime($newtime);
  5332. my $timestamp1 = substr( $timestamp, 11, 5 );
  5333. return $timestamp1;
  5334. }
  5335. ###########################
  5336. sub MSwitch_Execute_Timer($) {
  5337. my ($input) = @_;
  5338. my ( $Name, $timecond, $param ) = split( / /, $input );
  5339. my $hash = $defs{$Name};
  5340. return "" if ( IsDisabled($Name) );
  5341. if ( ReadingsVal( $Name, '.V_Check', $vupdate ) ne $vupdate )
  5342. {
  5343. my $ver = ReadingsVal( $Name, '.V_Check', '' );
  5344. Log3( $Name, 1, $Name.' Versionskonflikt, aktion abgebrochen ! erwartet:'.$vupdate.' vorhanden:'.$ver );
  5345. return;
  5346. }
  5347. if ( AttrVal( $Name, 'MSwitch_RandomNumber', '' ) ne '' ) {MSwitch_Createnumber1($hash);}
  5348. if ( $param eq '5' )
  5349. {
  5350. MSwitch_Createtimer($hash);
  5351. return;
  5352. }
  5353. if ( AttrVal( $Name, 'MSwitch_Condition_Time', "0" ) eq '1' )
  5354. {
  5355. my $triggercondition = ReadingsVal( $Name, '.Trigger_condition', '' );
  5356. # $triggercondition =~ s/\./:/g;
  5357. $triggercondition =~ s/#\[dp\]/:/g;
  5358. $triggercondition =~ s/#\[pt\]/./g;
  5359. $triggercondition =~ s/#\[ti\]/~/g;
  5360. $triggercondition =~ s/#\[sp\]/ /g;
  5361. if ( $triggercondition ne '' )
  5362. {
  5363. my $ret = MSwitch_checkcondition( $triggercondition, $Name, '' );
  5364. if ( $ret eq 'false' )
  5365. {
  5366. return;
  5367. }
  5368. }
  5369. }
  5370. my $extime = POSIX::strftime("%H:%M",localtime);
  5371. readingsBeginUpdate($hash);
  5372. readingsBulkUpdate( $hash, "EVENT", $Name.":execute_timer_P".$param.":".$extime );
  5373. readingsBulkUpdate( $hash, "EVTFULL", $Name.":execute_timer_P".$param.":".$extime );
  5374. readingsBulkUpdate( $hash, "EVTPART1", $Name );
  5375. readingsBulkUpdate( $hash, "EVTPART2","execute_timer_P".$param );
  5376. readingsBulkUpdate( $hash, "EVTPART3",$extime );
  5377. readingsEndUpdate( $hash, 1 );
  5378. if ( $param eq '1' )
  5379. {
  5380. my $cs = "set $Name on";
  5381. Log3( $Name, 3, "$Name MSwitch_Execute_Timer: Befehlsausfuehrung -> $cs" . __LINE__ );
  5382. my $errors = AnalyzeCommandChain( undef, $cs );
  5383. if ( defined($errors) )
  5384. {
  5385. Log3( $Name, 1,"$Name MSwitch_Execute_Timer: Fehler bei Befehlsausfuehrung ERROR $Name: $errors ". __LINE__ );
  5386. }
  5387. return;
  5388. }
  5389. if ( $param eq '2' )
  5390. {
  5391. my $cs = "set $Name off";
  5392. Log3( $Name, 3,"$Name MSwitch_Execute_Timer: Befehlsausfuehrung -> $cs" . __LINE__ );
  5393. my $errors = AnalyzeCommandChain( undef, $cs );
  5394. if ( defined($errors) )
  5395. {
  5396. Log3( $Name, 1,"$Name MSwitch_Execute_Timer: Fehler bei Befehlsausfuehrung ERROR $Name: $errors " . __LINE__ );
  5397. }
  5398. return;
  5399. }
  5400. if ( $param eq '3' )
  5401. {
  5402. MSwitch_Exec_Notif( $hash, 'on', 'nocheck', '',0 );
  5403. return;
  5404. }
  5405. if ( $param eq '4' )
  5406. {
  5407. MSwitch_Exec_Notif( $hash, 'off', 'nocheck', '',0 );
  5408. return;
  5409. }
  5410. return;
  5411. }
  5412. ####################
  5413. sub MSwitch_ChangeCode($$) {
  5414. my ( $hash, $option ) = @_;
  5415. my $Name = $hash->{NAME};
  5416. my $x = 0; # exit secure
  5417. #achtung perl5.30
  5418. while ( $option =~ m/(.*)\{(sunset|sunrise)(.*)\}(.*)/ )
  5419. #while ( $option =~ m/(.*){(sunset|sunrise)(.*)}(.*)/ )
  5420. {
  5421. $x++; # exit secure
  5422. last if $x > 20; # exit secure
  5423. if ( defined $2 )
  5424. {
  5425. my $part2 = eval $2 . $3;
  5426. chop($part2);
  5427. chop($part2);
  5428. chop($part2);
  5429. $option = $part2;
  5430. $option = $1 . $option if ( defined $1 );
  5431. $option = $option . $4 if ( defined $4 );
  5432. }
  5433. }
  5434. return $option;
  5435. }
  5436. ####################
  5437. sub MSwitch_Add_Device($$) {
  5438. my ( $hash, $device ) = @_;
  5439. my $Name = $hash->{NAME};
  5440. my @olddevices = split( /,/, ReadingsVal( $Name, '.Device_Affected', '' ) );
  5441. my $count = 1;
  5442. LOOP7: foreach (@olddevices)
  5443. {
  5444. my ( $devicename, $devicecmd ) = split( /-AbsCmd/, $_ );
  5445. if ( $device eq $devicename ) { $count++; }
  5446. }
  5447. my $newdevices .= ',' . $device . '-AbsCmd' . $count;
  5448. my $newset = ReadingsVal( $Name, '.Device_Affected', '' ) . $newdevices;
  5449. $newdevices = join( ',', @olddevices ) . ',' . $newdevices;
  5450. my @sortdevices = split( /,/, $newdevices );
  5451. @sortdevices = sort @sortdevices;
  5452. $newdevices = join( ',', @sortdevices );
  5453. $newdevices = substr( $newdevices, 1 );
  5454. readingsSingleUpdate( $hash, ".Device_Affected", $newdevices, 1 );
  5455. return;
  5456. }
  5457. ###################################
  5458. sub MSwitch_Del_Device($$) {
  5459. my ( $hash, $device ) = @_;
  5460. my $Name = $hash->{NAME};
  5461. my @olddevices = split( /,/, ReadingsVal( $Name, '.Device_Affected', '' ) );
  5462. my @olddevicesset = split( /#\[ND\]/, ReadingsVal( $Name, '.Device_Affected_Details', '' ) );
  5463. #Log3( $Name, 5, "olddevice: @olddevicesset" );
  5464. my @newdevice;
  5465. my @newdevicesset;
  5466. my $count = 0;
  5467. LOOP8: foreach (@olddevices)
  5468. {
  5469. #Log3( $Name, 5, "olddevice: $_" );
  5470. if ( $device eq $_ )
  5471. {
  5472. $count++;
  5473. next LOOP8;
  5474. }
  5475. push( @newdevice, $olddevices[$count] );
  5476. push( @newdevicesset, $olddevicesset[$count] );
  5477. $count++;
  5478. }
  5479. my ( $devicemaster, $devicedeleted ) = split( /-AbsCmd/, $device );
  5480. $count = 1;
  5481. my @newdevice1;
  5482. LOOP9: foreach (@newdevice)
  5483. {
  5484. my ( $devicename, $devicecmd ) = split( /-AbsCmd/, $_ );
  5485. if ( $devicemaster eq $devicename )
  5486. {
  5487. my $newname = $devicename . '-AbsCmd' . $count;
  5488. $count++;
  5489. push( @newdevice1, $newname );
  5490. next LOOP9;
  5491. }
  5492. push( @newdevice1, $_ );
  5493. }
  5494. $count = 1;
  5495. my @newdevicesset1;
  5496. LOOP10: foreach (@newdevicesset)
  5497. {
  5498. # my ( $name, @comands ) = split( /,/, $_ );
  5499. my ( $name, @comands ) = split( /#\[NF\]/, $_ );
  5500. my ( $devicename, $devicecmd ) = split( /-AbsCmd/, $name );
  5501. if ( $devicemaster eq $devicename )
  5502. {
  5503. # my $newname = $devicename . '-AbsCmd' . $count . ',' . join( ',', @comands );
  5504. my $newname = $devicename . '-AbsCmd' . $count . '#[NF]' . join( '#[NF]', @comands );
  5505. push( @newdevicesset1, $newname );
  5506. $count++;
  5507. next LOOP10;
  5508. }
  5509. push( @newdevicesset1, $_ );
  5510. }
  5511. my $newaffected = join( ',', @newdevice1 );
  5512. if ( $newaffected eq '' ) { $newaffected = 'no_device' }
  5513. my $newaffecteddet = join( '#[ND]', @newdevicesset1 );
  5514. #Log3( $Name, 5, "deldevice new: $newaffecteddet" );
  5515. #return;
  5516. readingsBeginUpdate($hash);
  5517. readingsBulkUpdate( $hash, ".Device_Affected", $newaffected );
  5518. readingsBulkUpdate( $hash, ".Device_Affected_Details", $newaffecteddet );
  5519. readingsEndUpdate( $hash, 0 );
  5520. my $devices = MSwitch_makeAffected($hash);
  5521. my $devhash = $hash->{DEF};
  5522. my @dev = split( /#/, $devhash );
  5523. $hash->{DEF} = $dev[0] . ' # ' . $devices;
  5524. }
  5525. ###################################
  5526. sub MSwitch_Debug($) {
  5527. my ($hash) = @_;
  5528. my $Name = $hash->{NAME};
  5529. my $debug1 = ReadingsVal( $Name, '.Device_Affected', 0 );
  5530. my $debug2 = ReadingsVal( $Name, '.Device_Affected_Details', 0 );
  5531. my $debug3 = ReadingsVal( $Name, '.Device_Events', 0 );
  5532. $debug2 =~ s/:/ /ig;
  5533. $debug3 =~ s/,/, /ig;
  5534. readingsBeginUpdate($hash);
  5535. readingsBulkUpdate( $hash, "Device_Affected", $debug1 );
  5536. readingsBulkUpdate( $hash, "Device_Affected_Details", $debug2 );
  5537. readingsBulkUpdate( $hash, "Device_Events", $debug3 );
  5538. readingsEndUpdate( $hash, 0 );
  5539. }
  5540. ###################################
  5541. sub MSwitch_Delete_Delay($$) {
  5542. my ( $hash, $device ) = @_;
  5543. my $Name = $hash->{NAME};
  5544. my $timehash = $hash->{helper}{delays};
  5545. if ($device eq 'all')
  5546. {
  5547. foreach my $a ( keys %{$timehash} )
  5548. {
  5549. my $inhalt = $hash->{helper}{delays}{$a};
  5550. RemoveInternalTimer($a);
  5551. RemoveInternalTimer($inhalt);
  5552. delete( $hash->{helper}{delays}{$a} );
  5553. }
  5554. }
  5555. else
  5556. {
  5557. foreach my $a ( keys %{$timehash} )
  5558. {
  5559. my $pos = index( $a, "$device", 0 );
  5560. if ( $pos != -1 )
  5561. {
  5562. #Log3( $Name, 5,"lösche timer $a". __LINE__ );
  5563. RemoveInternalTimer($a);
  5564. my $inhalt = $hash->{helper}{delays}{$a};
  5565. RemoveInternalTimer($a);
  5566. RemoveInternalTimer($inhalt);
  5567. delete( $hash->{helper}{delays}{$a} );
  5568. }
  5569. }
  5570. }
  5571. }
  5572. ###################################
  5573. sub MSwitch_Clear_timer($) {
  5574. my ( $hash, $device ) = @_;
  5575. my $name = $hash->{NAME};
  5576. my $timehash = $hash->{helper}{timer};
  5577. foreach my $a ( keys %{$timehash} )
  5578. {
  5579. my $inhalt = $hash->{helper}{timer}{$a};
  5580. RemoveInternalTimer($inhalt);
  5581. $inhalt = $hash->{helper}{timer}{$a};
  5582. $inhalt =~ s/-/ /g;
  5583. $inhalt = $name . ' ' . $inhalt;
  5584. RemoveInternalTimer($inhalt);
  5585. }
  5586. delete( $hash->{helper}{timer} );
  5587. }
  5588. ##################################
  5589. # Eventsimulation
  5590. sub MSwitch_Check_Event($$) {
  5591. my ( $hash, $eventin ) = @_;
  5592. my $Name = $hash->{NAME};
  5593. $eventin =~ s/~/ /g;
  5594. my $dev_hash = "";
  5595. if ( ReadingsVal( $Name, 'Trigger_device', '' ) eq "all_events" )
  5596. {
  5597. my @eventin = split( /:/, $eventin );
  5598. $dev_hash = $defs{ $eventin[0] };
  5599. $hash->{helper}{testevent_device} = $eventin[0];
  5600. $hash->{helper}{testevent_event} = $eventin[1] . ":" . $eventin[2];
  5601. $hash->{helper}{testevent_event} = $eventin[1] . ":" . $eventin[2];
  5602. }
  5603. else
  5604. {
  5605. my @eventin = split( /:/, $eventin );
  5606. $dev_hash = $defs{ ReadingsVal( $Name, 'Trigger_device', '' ) };
  5607. $hash->{helper}{testevent_device} =ReadingsVal( $Name, 'Trigger_device', '' );
  5608. $hash->{helper}{testevent_event} = $eventin[0] . ":" . $eventin[1];
  5609. }
  5610. my $we = AnalyzeCommand( 0, '{return $we}' );
  5611. MSwitch_Notify( $hash, $dev_hash );
  5612. delete( $hash->{helper}{testevent_device} );
  5613. delete( $hash->{helper}{testevent_event} );
  5614. delete( $hash->{helper}{testevent_event1} );
  5615. return;
  5616. }
  5617. #########################################
  5618. sub MSwitch_makeAffected($) {
  5619. my ($hash) = @_;
  5620. my $Name = $hash->{NAME};
  5621. my $devices = '';
  5622. my %saveaffected;
  5623. my @affname;
  5624. my $affected = ReadingsVal( $Name, '.Device_Affected', 'nodevices' );
  5625. my @affected = split( /,/, $affected );
  5626. LOOP30: foreach (@affected)
  5627. {
  5628. @affname = split( /-/, $_ );
  5629. $saveaffected{ $affname[0] } = 'on';
  5630. }
  5631. foreach my $a ( keys %saveaffected )
  5632. {
  5633. $devices = $devices . $a . ' ';
  5634. }
  5635. chop($devices);
  5636. return $devices;
  5637. }
  5638. #############################
  5639. sub MSwitch_checktrigger(@) {
  5640. my ( $own_hash, $ownName, $eventstellen, $triggerfield, $device, $zweig,$eventcopy, @eventsplit )= @_;
  5641. my $triggeron = ReadingsVal( $ownName, '.Trigger_on', '' );
  5642. my $triggeroff = ReadingsVal( $ownName, '.Trigger_off', '' );
  5643. my $triggercmdon = ReadingsVal( $ownName, '.Trigger_cmd_on', '' );
  5644. my $triggercmdoff = ReadingsVal( $ownName, '.Trigger_cmd_off', '' );
  5645. my $answer="";
  5646. #$triggerfield =~ s/\(//g;
  5647. #$triggerfield =~ s/\)//g;
  5648. unshift( @eventsplit, $device ) if ReadingsVal( $ownName, 'Trigger_device', '' ) eq "all_events";
  5649. if (ReadingsVal( $ownName, 'Trigger_device', '' ) eq "all_events" )
  5650. {
  5651. $eventcopy =$device.":".$eventcopy;
  5652. if ($triggerfield eq "*")
  5653. {
  5654. $triggerfield = "*:*:*";
  5655. }
  5656. }
  5657. if ( $triggerfield eq "*" && ReadingsVal( $ownName, 'Trigger_device', '' ) ne "all_events" )
  5658. {
  5659. $triggerfield = "*:*";
  5660. }
  5661. $triggerfield =~ s/\*/.*/g;
  5662. # erkennunhg der formartierung bis v1.66 ( <1.67)
  5663. my $x =0;
  5664. while ( $triggerfield =~ m/(.*)(\()(.*)(\/)(.*)(\))(.*)/ )
  5665. {
  5666. $x++; # exit secure
  5667. last if $x > 20; # exit secure
  5668. $triggerfield = $1 . $3 ."|" . $5 . $7;
  5669. }
  5670. ################
  5671. if ( $eventcopy =~m/^$triggerfield/)
  5672. {
  5673. $answer = "wahr";
  5674. }
  5675. return 'on'
  5676. if $zweig eq 'on'
  5677. && $answer eq 'wahr'
  5678. && $eventcopy ne $triggercmdoff
  5679. && $eventcopy ne $triggercmdon
  5680. && $eventcopy ne $triggeroff;
  5681. return 'off'
  5682. if $zweig eq 'off'
  5683. && $answer eq 'wahr'
  5684. && $eventcopy ne $triggercmdoff
  5685. && $eventcopy ne $triggercmdon
  5686. && $eventcopy ne $triggeron;
  5687. return 'offonly' if $zweig eq 'offonly' && $answer eq 'wahr';
  5688. return 'ononly' if $zweig eq 'ononly' && $answer eq 'wahr';
  5689. return 'undef';
  5690. }
  5691. ###############################
  5692. sub MSwitch_VUpdate($) {
  5693. my ($hash) = @_;
  5694. my $Name = $hash->{NAME};
  5695. readingsSingleUpdate( $hash, ".V_Check", $vupdate, 0 );
  5696. my $devs = ReadingsVal( $Name, '.Device_Affected_Details', '' ) ;
  5697. # encode from old format
  5698. $devs =~ s/,/#[NF]/g;
  5699. $devs =~ s/\|/#[ND]/g;
  5700. $devs =~ s/~/ /g;
  5701. $devs =~ s/\[cnl\]/\n/g;
  5702. $devs =~ s/\[se\]/;/g;
  5703. $devs =~ s/#\[ko\]/,/g;
  5704. $devs =~ s/#\[sp\]/ /g;
  5705. # decode to new format
  5706. $devs =~ s/#\[wa\]/|/g;
  5707. $devs =~ s/\n/#[nl]/g;
  5708. $devs =~ s/;/#[se]/g;
  5709. $devs =~ s/\:/#[dp]/g;
  5710. $devs =~ s/\t/ /g;
  5711. $devs =~ s/ /#[sp]/g;
  5712. $devs =~ s/\\/#[bs]/g;
  5713. $devs =~ s/,/#[ko]/g;
  5714. $devs =~ s/^#\[/#[eo]/g;
  5715. $devs =~ s/^#\]/#[ec]/g;
  5716. $devs =~ s/\|/#[wa]/g;
  5717. # change timerkey to new format
  5718. my $x =0;
  5719. while ( $devs =~ m/(.*#\[NF\])([0-9]{2})([0-9]{2})([0-9]{2})(#\[NF\].*)/ )
  5720. {
  5721. $x++; # exit
  5722. last if $x > 20; # exit
  5723. $devs = $1.$2."#[dp]".$3."#[dp]".$4.$5 ;
  5724. }
  5725. readingsSingleUpdate( $hash, ".Device_Affected_Details", $devs, 0 );
  5726. return;
  5727. }
  5728. ################################
  5729. sub MSwitch_backup($) {
  5730. my ($hash) = @_;
  5731. my $Name = $hash->{NAME};
  5732. my @areadings =
  5733. qw(.Device_Affected .Device_Affected_Details .Device_Events .First_init .Trigger_Whitelist .Trigger_cmd_off .Trigger_cmd_on .Trigger_condition .Trigger_off .Trigger_on .Trigger_time .V_Check Exec_cmd Trigger_device Trigger_log last_event state .sysconf Sys_Extension) ; #alle readings
  5734. my %keys;
  5735. open( BACKUPDATEI, ">MSwitch_backup_$vupdate.cfg" ); # Datei zum Schreiben öffnen
  5736. print BACKUPDATEI "# Mswitch Devices\n"; #
  5737. foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) #
  5738. {
  5739. print BACKUPDATEI "$testdevice\n";
  5740. }
  5741. print BACKUPDATEI "# Mswitch Devices END\n"; #
  5742. print BACKUPDATEI "\n"; # HTML-Datei schreiben
  5743. foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) #
  5744. {
  5745. print BACKUPDATEI "#N -> $testdevice\n"; #
  5746. foreach my $key (@areadings)
  5747. {
  5748. my $tmp = ReadingsVal( $testdevice, $key, 'undef' );
  5749. print BACKUPDATEI "#S $key -> $tmp\n";
  5750. }
  5751. my %keys;
  5752. foreach my $attrdevice ( keys %{ $attr{$testdevice} } ) #geht
  5753. {
  5754. print BACKUPDATEI "#A $attrdevice -> ". AttrVal( $testdevice, $attrdevice, '' ) . "\n";
  5755. }
  5756. print BACKUPDATEI "#E -> $testdevice\n";
  5757. print BACKUPDATEI "\n";
  5758. }
  5759. close(BACKUPDATEI);
  5760. }
  5761. ################################
  5762. sub MSwitch_backup_this($) {
  5763. my ($hash) = @_;
  5764. my $Name = $hash->{NAME};
  5765. my $Zeilen = ("");
  5766. my $Zeilen1 ="";
  5767. open( BACKUPDATEI, "<MSwitch_backup_$vupdate.cfg" ) || return "no Backupfile found!\n";
  5768. while (<BACKUPDATEI>)
  5769. {
  5770. $Zeilen = $Zeilen . $_;
  5771. }
  5772. close(BACKUPDATEI);
  5773. $Zeilen =~ s/\n/[NL]/g;
  5774. if ( $Zeilen !~ m/#N -> $Name\[NL\](.*)#E -> $Name\[NL\]/ )
  5775. {
  5776. return "no Backupfile found\n";
  5777. }
  5778. my @found = split( /\[NL\]/, $1 );
  5779. foreach (@found)
  5780. {
  5781. if ( $_ =~ m/#S (.*) -> (.*)/ ) # setreading
  5782. {
  5783. # Log3( $Name, 0, "s1 $1" );
  5784. # Log3( $Name, 0, "s2 $2" );
  5785. if ( $2 eq 'undef' || $2 eq '' || $2 eq ' ' )
  5786. {
  5787. }
  5788. else
  5789. {
  5790. $Zeilen1 = $2;
  5791. readingsSingleUpdate( $hash, "$1", $Zeilen1, 0 );
  5792. }
  5793. }
  5794. if ( $_ =~ m/#A (.*) -> (.*)/ ) # setattr
  5795. {
  5796. my $cs = "attr $Name $1 $2";
  5797. my $errors = AnalyzeCommandChain( undef, $cs );
  5798. if ( defined($errors) )
  5799. {
  5800. Log3( $Name, 1, "ERROR $cs" );
  5801. }
  5802. }
  5803. }
  5804. MSwitch_LoadHelper($hash);
  5805. return "MSwitch $Name restored.\nPlease refresh device.";
  5806. }
  5807. # ################################
  5808. sub MSwitch_Getsupport($){
  5809. my ($hash) = @_;
  5810. my $Name = $hash->{NAME};
  5811. my $out='';
  5812. $out .="Modulversion: $version\\n";
  5813. $out .="Datenstruktur: $vupdate\\n";
  5814. $out .="\\n----- Devicename -----\\n";
  5815. $out .="$Name\\n";
  5816. $out .="\\n----- Attribute -----\\n";
  5817. my %keys;
  5818. foreach my $attrdevice ( keys %{ $attr{$Name} } ) #geht
  5819. {
  5820. $out .="Attribut $attrdevice: ". AttrVal( $Name, $attrdevice, '' )."\\n";
  5821. }
  5822. $out .="\\n----- Trigger -----\\n";
  5823. $out .="Trigger device: ";
  5824. my $tmp = ReadingsVal( $Name, 'Trigger_device', 'undef' );
  5825. $out .="$tmp\\n";
  5826. $out .="Trigger time: ";
  5827. $tmp = ReadingsVal( $Name, '.Trigger_time', 'undef' );
  5828. $tmp =~ s/~/ /g;
  5829. $out .="$tmp\\n";
  5830. $out .="Trigger condition: ";
  5831. $tmp = ReadingsVal( $Name, '.Trigger_condition', 'undef' );
  5832. $out .="$tmp\\n";
  5833. $out .="Trigger Device Global Whitelist: ";
  5834. $tmp = ReadingsVal( $Name, '.Trigger_Whitelist', 'undef' );
  5835. $out .="$tmp\\n";
  5836. $out .="\\n----- Trigger Details -----\\n";
  5837. $out .="Trigger cmd1: ";
  5838. $tmp = ReadingsVal( $Name, '.Trigger_on', 'undef' );
  5839. $out .="$tmp\\n";
  5840. $out .="Trigger cmd2: ";
  5841. $tmp = ReadingsVal( $Name, '.Trigger_off', 'undef' );
  5842. $out .="$tmp\\n";
  5843. $out .="Trigger cmd3: ";
  5844. $tmp = ReadingsVal( $Name, '.Trigger_cmd_on', 'undef' );
  5845. $out .="$tmp\\n";
  5846. $out .="Trigger cmd4: ";
  5847. $tmp = ReadingsVal( $Name, '.Trigger_cmd_off', 'undef' );
  5848. $out .="$tmp\\n";
  5849. my %savedetails = MSwitch_makeCmdHash($hash);
  5850. $out .="\\n----- Device Actions -----\\n";
  5851. my @affecteddevices = split( /#\[ND\]/, ReadingsVal( $Name, '.Device_Affected_Details', 'no_device' ) );
  5852. foreach (@affecteddevices)
  5853. {
  5854. my @devicesplit = split( /#\[NF\]/, $_ );
  5855. $out .="\\nDevice: ".$devicesplit[0]."\\n";
  5856. $out .="cmd1: ".$devicesplit[1]." ".$devicesplit[3]."\\n";
  5857. $out .="cmd2: ".$devicesplit[2]." ".$devicesplit[4]."\\n";
  5858. $out .="cmd1 condition: ".$devicesplit[9]."\\n";
  5859. $out .="cmd2 condition: ".$devicesplit[10]."\\n";
  5860. $out .="cmd1 delay: ".$devicesplit[7]."\\n";
  5861. $out .="cmd2 delay: ".$devicesplit[8]."\\n";
  5862. $out .="repeats: ".$devicesplit[11]."\\n";
  5863. $out .="repeats delay: ".$devicesplit[12]."\\n";
  5864. $out .="priority: ".$devicesplit[13]."\\n";
  5865. $out .="id: ".$devicesplit[14]."\\n";
  5866. }
  5867. $out =~ s/#\[dp\]/:/g;
  5868. $out =~ s/#\[pt\]/./g;
  5869. $out =~ s/#\[ti\]/~/g;
  5870. $out =~ s/#\[sp\]/ /g;
  5871. $out =~ s/#\[nl\]/\n/g;
  5872. $out =~ s/#\[se\]/;/g;
  5873. $out =~ s/#\[dp\]/:/g;
  5874. $out =~ s/\(DAYS\)/|/g;
  5875. $out =~ s/#\[ko\]/,/g; #neu
  5876. $out =~ s/#\[bs\]/\\/g; #neu
  5877. asyncOutput( $hash->{CL},
  5878. "<html><center>Supportanfragen bitte im Forum stellen:<a href=\"https://forum.fhem.de/index.php/topic,86199.0.html\">Fhem-Forum</a><br>Bei Devicespezifischen Fragen bitte untenstehene Datei anhängen, das erleichtert Anfragen erheblich.<br>&nbsp;<br><textarea name=\"edit1\" id=\"edit1\" rows=\""
  5879. . "40\" cols=\"180\" STYLE=\"font-family:Arial;font-size:9pt;\">"
  5880. . $out
  5881. . "</textarea><br></html>"
  5882. );
  5883. return;
  5884. }
  5885. ##################
  5886. sub MSwitch_Getconfig($) {
  5887. my ($hash) = @_;
  5888. my $Name = $hash->{NAME};
  5889. my @areadings = qw(.Device_Affected .Device_Affected_Details .Device_Events .First_init .Trigger_Whitelist .Trigger_cmd_off .Trigger_cmd_on .Trigger_condition .Trigger_off .Trigger_on .Trigger_time .V_Check Trigger_device Trigger_log last_event .sysconf state Sys_Extension);
  5890. #.sysconf
  5891. #alle readings
  5892. # my %keys; $vupdate
  5893. my $count = 0;
  5894. my $out = "#V $version\\n";
  5895. $out .= "#VS $vupdate\\n";
  5896. my $testdevice = $Name;
  5897. foreach my $key (@areadings)
  5898. {
  5899. my $tmp = ReadingsVal( $testdevice, $key, 'undef' );
  5900. if ($key eq ".Device_Affected_Details")
  5901. {
  5902. $tmp =~ s/#\[nl\]/;;/g;
  5903. $tmp =~ s/#\[sp\]/ /g;
  5904. $tmp =~ s/#\[nl\]/\\n/g;
  5905. $tmp =~ s/#\[se\]/;/g;
  5906. $tmp =~ s/#\[dp\]/:/g;
  5907. $tmp =~ s/\(DAYS\)/|/g;
  5908. $tmp =~ s/#\[ko\]/,/g; #neu
  5909. $tmp =~ s/#\[wa\]/|/g;
  5910. $tmp =~ s/#\[st\]/\\'/g;
  5911. $tmp =~ s/'/\\'/g;
  5912. $tmp =~ s/#\[bs\]/\\\\/g;
  5913. #Log3( $Name, 0, $tmp );
  5914. }
  5915. if ($key eq ".sysconf")
  5916. {
  5917. }
  5918. if ($key eq ".Device_Events")
  5919. {
  5920. $tmp =~ s/#\[tr\]/ /g;
  5921. }
  5922. $out .= "#S $key -> $tmp\\n";
  5923. $count++;
  5924. }
  5925. # my %keys;
  5926. foreach my $attrdevice ( keys %{ $attr{$testdevice} } ) #geht
  5927. {
  5928. $out .= "#A $attrdevice -> ". AttrVal( $testdevice, $attrdevice, '' ) . "\\n";
  5929. $count++;
  5930. }
  5931. $count++;
  5932. $count++;
  5933. my $client_hash = $hash->{CL};
  5934. asyncOutput( $hash->{CL},
  5935. "<html>Änderungen sollten hier nur von erfahrenen Usern durchgeführt werden.<textarea name=\"edit1\" id=\"edit1\" rows=\""
  5936. . $count
  5937. . "\" cols=\"160\" STYLE=\"font-family:Arial;font-size:9pt;\">"
  5938. . $out
  5939. . "</textarea><br><input name\"edit\" type=\"button\" value=\"save changes\" onclick=\" javascript: saveconfig(document.querySelector(\\\'#edit1\\\').value) \"></html>"
  5940. );
  5941. return;
  5942. }
  5943. #######################################################
  5944. sub MSwitch_Sysextension($) {
  5945. my ($hash) = @_;
  5946. my $Name = $hash->{NAME};
  5947. my $count = 30;
  5948. my $out = ReadingsVal( $Name,'.sysconf', '' );
  5949. $out =~ s/#\[sp\]/ /g;
  5950. $out =~ s/#\[nl\]/\\n/g;
  5951. $out =~ s/#\[se\]/;/g;
  5952. $out =~ s/#\[dp\]/:/g;
  5953. $out =~ s/#\[st\]/\\'/g;
  5954. $out =~ s/#\[dst\]/\"/g;
  5955. $out =~ s/#\[tab\]/ /g;
  5956. $out =~ s/#\[ko\]/,/g;
  5957. $out =~ s/#\[wa\]/|/g;
  5958. $out =~ s/#\[bs\]/\\\\/g;
  5959. my $client_hash = $hash->{CL};
  5960. asyncOutput( $hash->{CL},
  5961. "<html><center>Achtung! Hier angegebener Code greift direkt in das Programm 98_MSwitch ein und wird unmittelbar zu beginn der Routine X_Set ausgeführt<br><textarea name=\"sys\" id=\"sys\" rows=\""
  5962. . $count
  5963. . "\" cols=\"160\" STYLE=\"font-family:Arial;font-size:9pt;\">"
  5964. . $out
  5965. . "</textarea><br><input type=\"button\" value=\"save changes\" onclick=\" javascript: savesys(document.querySelector(\\\'#sys\\\').value) \"></html>"
  5966. );
  5967. return;
  5968. }
  5969. ################################
  5970. sub MSwitch_backup_all($) {
  5971. my ($hash) = @_;
  5972. my $Name = $hash->{NAME};
  5973. my $answer = '';
  5974. my $Zeilen = ("");
  5975. open( BACKUPDATEI, "<MSwitch_backup_$vupdate.cfg" )|| return "$Name|no Backupfile MSwitch_backup_$vupdate.cfg found\n";
  5976. while (<BACKUPDATEI>)
  5977. {
  5978. $Zeilen = $Zeilen . $_;
  5979. }
  5980. close(BACKUPDATEI);
  5981. foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) #
  5982. {
  5983. Log3( $testdevice, 0, "MSWITCH-RESTORE: ".$testdevice );
  5984. my $devhash = $defs{$testdevice};
  5985. $Zeilen =~ s/\n/[NL]/g;
  5986. if ( $Zeilen !~ m/#N -> $testdevice\[NL\](.*)#E -> $testdevice\[NL\]/ )
  5987. {
  5988. $answer = $answer . "no Backupfile found for $testdevice\n";
  5989. }
  5990. my @found = split( /\[NL\]/, $1 );
  5991. foreach (@found) {
  5992. if ( $_ =~ m/#S (.*) -> (.*)/ ) # setreading
  5993. {
  5994. if ( $2 eq 'undef' || $2 eq '' || $2 eq ' ' )
  5995. {
  5996. }
  5997. else
  5998. {
  5999. readingsSingleUpdate( $devhash, "$1", $2, 0 );
  6000. }
  6001. }
  6002. if ( $_ =~ m/#A (.*) -> (.*)/ ) # setattr
  6003. {
  6004. my $cs = "attr $testdevice $1 $2";
  6005. my $errors = AnalyzeCommandChain( undef, $cs );
  6006. if ( defined($errors) )
  6007. {
  6008. Log3( $testdevice, 1, "ERROR $cs" );
  6009. }
  6010. }
  6011. }
  6012. my $cs = "attr $testdevice verbose 0";
  6013. my $errors = AnalyzeCommandChain( undef, $cs );
  6014. if ( defined($errors) )
  6015. {
  6016. Log3( $testdevice, 1, "ERROR $cs" );
  6017. }
  6018. MSwitch_LoadHelper($devhash);
  6019. Log3( $testdevice, 0, "MSWITCH-RESTORE ready -> ".$testdevice );
  6020. $answer = $answer . "MSwitch $testdevice restored.\n";
  6021. }
  6022. return $answer;
  6023. }
  6024. ################################################
  6025. sub MSwitch_savesys($$) {
  6026. my ( $hash, $cont ) = @_;
  6027. my $name = $hash->{NAME};
  6028. $cont = urlDecode( $cont );
  6029. $cont =~ s/\n/#[nl]/g;
  6030. $cont =~ s/\t/ /g;
  6031. $cont =~ s/ /#[sp]/g;
  6032. $cont =~ s/\\/#[bs]/g;
  6033. $cont =~ s/,/#[ko]/g;
  6034. $cont =~ s/^#\[/#[eo]/g;
  6035. $cont =~ s/^#\]/#[ec]/g;
  6036. $cont =~ s/\|/#[wa]/g;
  6037. if (!defined $cont){$cont ="";};
  6038. if ($cont ne '')
  6039. {
  6040. readingsSingleUpdate( $hash, ".sysconf", $cont, 0 );
  6041. }
  6042. else
  6043. {
  6044. fhem("deletereading $name .sysconf");
  6045. }
  6046. return;
  6047. }
  6048. ################################################
  6049. sub MSwitch_saveconf($$) {
  6050. my ( $hash, $cont ) = @_;
  6051. my $name = $hash->{NAME};
  6052. my $contcopy = $cont;
  6053. $cont =~ s/#c\[sp\]/ /g;
  6054. $cont =~ s/#c\[se\]/;/g;
  6055. $cont =~ s/#c\[dp\]/:/g;
  6056. my @changes;
  6057. my $info ="";
  6058. my @found = split( /#\[EOL\]/, $cont );
  6059. foreach (@found)
  6060. {
  6061. if ( $_ =~ m/#Q (.*)/ ) # setattr
  6062. {
  6063. push(@changes,$1);
  6064. }
  6065. if ( $_ =~ m/#I (.*)/ ) # setattr
  6066. {
  6067. $info =$1;
  6068. }
  6069. if ( $_ =~ m/#VS (.*)/ ) # setattr
  6070. {
  6071. if ( $1 ne $vupdate )
  6072. {
  6073. readingsSingleUpdate( $hash, ".wrong_version", $1, 0 );
  6074. return ;
  6075. }
  6076. }
  6077. if ( $_ =~ m/#S (.*) -> (.*)/ ) # setreading
  6078. {
  6079. if ( $2 eq 'undef' || $2 eq '' || $2 eq ' ' )
  6080. {
  6081. }
  6082. else
  6083. {
  6084. my $newstring =$2;
  6085. if ($1 eq ".Device_Affected_Details")
  6086. {
  6087. $newstring =~ s/;/#[se]/g;
  6088. $newstring =~ s/:/#[dp]/g;
  6089. $newstring =~ s/\t/ /g;
  6090. $newstring =~ s/ /#[sp]/g;
  6091. $newstring =~ s/\\/#[bs]/g;
  6092. $newstring =~ s/,/#[ko]/g;
  6093. $newstring =~ s/^#\[/#[eo]/g;
  6094. $newstring =~ s/^#\]/#[ec]/g;
  6095. $newstring =~ s/\|/#[wa]/g;
  6096. $newstring =~ s/#\[se\]#\[se\]#\[se\]/#[se]#[nl]/g;
  6097. $newstring =~ s/#\[se\]#\[se\]/#[nl]/g;
  6098. }
  6099. if ($1 eq ".sysconf")
  6100. {
  6101. }
  6102. if ($1 eq ".Device_Events")
  6103. {
  6104. $newstring =~ s/ /#[tr]/g;
  6105. }
  6106. readingsSingleUpdate( $hash, "$1", $newstring, 0 );
  6107. }
  6108. }
  6109. if ( $_ =~ m/#A (.*) -> (.*)/ ) # setattr
  6110. {
  6111. $attr{$name}{$1} = $2;
  6112. }
  6113. }
  6114. MSwitch_set_dev($hash);
  6115. if (@changes > 0)
  6116. {
  6117. my $save = join( '|', @changes );
  6118. readingsSingleUpdate( $hash, ".change", $save, 0 );
  6119. }
  6120. if ($info ne "")
  6121. {
  6122. readingsSingleUpdate( $hash, ".change_info", $info, 0 );
  6123. }
  6124. return;
  6125. }
  6126. ################################################
  6127. sub MSwitch_backup_done($) {
  6128. my ($string) = @_;
  6129. return unless ( defined($string) );
  6130. my @a = split( "\\|", $string );
  6131. my $Name = $a[0];
  6132. my $answer = $a[1];
  6133. my $hash = $defs{$Name};
  6134. delete( $hash->{helper}{RUNNING_PID} );
  6135. my $client_hash = $hash->{helper}{RESTORE_ANSWER};
  6136. $answer =~ s/\[nl\]/\n/g;
  6137. foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) #
  6138. {
  6139. my $devhash = $defs{$testdevice};
  6140. MSwitch_Createtimer($devhash);
  6141. }
  6142. asyncOutput( $client_hash, $answer );
  6143. return;
  6144. }
  6145. ###########################################
  6146. sub MSwitch_Execute_randomtimer($) {
  6147. my ($hash) = @_;
  6148. my $Name = $hash->{NAME};
  6149. my $param = AttrVal( $Name, 'MSwitch_RandomTime', '0' );
  6150. my $min = substr( $param, 0, 2 ) * 3600;
  6151. $min = $min + substr( $param, 3, 2 ) * 60;
  6152. $min = $min + substr( $param, 6, 2 );
  6153. my $max = substr( $param, 9, 2 ) * 3600;
  6154. $max = $max + substr( $param, 12, 2 ) * 60;
  6155. $max = $max + substr( $param, 15, 2 );
  6156. my $sekmax = $max - $min;
  6157. my $ret = $min + int( rand $sekmax );
  6158. return $ret;
  6159. }
  6160. ############################################
  6161. sub MSwitch_replace_delay($$) {
  6162. my ( $hash, $timerkey ) = @_;
  6163. my $name = $hash->{NAME};
  6164. my $time = time;
  6165. my $ltime = TimeNow();
  6166. MSwitch_LOG( $name, 5, "----------------------------------------" );
  6167. MSwitch_LOG( $name, 5, "$name: MSwitch_replace_delay-> $timerkey" );
  6168. MSwitch_LOG( $name, 5, "----------------------------------------" );
  6169. my ( $aktdate, $akttime ) = split / /, $ltime;
  6170. my $hh = ( substr( $timerkey, 0, 2 ) );
  6171. my $mm = ( substr( $timerkey, 2, 2 ) );
  6172. my $ss = ( substr( $timerkey, 4, 2 ) );
  6173. my $referenz = time_str2num("$aktdate $hh:$mm:$ss");
  6174. if ( $referenz < $time )
  6175. {
  6176. $referenz = $referenz + 86400;
  6177. }
  6178. if ( $referenz >= $time )
  6179. {
  6180. }
  6181. $referenz = $referenz - $time;
  6182. my $timestampGMT = FmtDateTimeRFC1123($referenz);
  6183. return $referenz;
  6184. }
  6185. ############################################################
  6186. sub MSwitch_repeat($) {
  6187. my ( $msg, $name ) = @_;
  6188. my $incomming = $_[0];
  6189. my @msgarray = split( /\|/, $incomming );
  6190. $name = $msgarray[1];
  6191. my $time = $msgarray[2];
  6192. my $cs = $msgarray[0];
  6193. my $hash = $defs{$name};
  6194. $cs =~ s/\n//g;
  6195. MSwitch_LOG( $name, 5, "----------------------------------------" );
  6196. MSwitch_LOG( $name, 5, "$name: Repeat -> ".$cs );
  6197. MSwitch_LOG( $name, 5, "----------------------------------------" );
  6198. if ( $cs =~ m/set (.*)(MSwitchtoggle)(.*)/ )
  6199. {
  6200. $cs = MSwitch_toggle( $hash, $cs );
  6201. MSwitch_LOG( $name, 5, "$name: fround toggle -> ".$cs );
  6202. }
  6203. MSwitch_LOG( $name, 5, "$name: execute repeat $time -> ".$cs );
  6204. if ( AttrVal( $name, 'MSwitch_Debug', "0" ) ne '2' )
  6205. {
  6206. if ( $cs =~ m/{.*}/ )
  6207. {
  6208. eval($cs);
  6209. if ($@)
  6210. {
  6211. MSwitch_LOG( $name, 1,"$name MSwitch_repeat: ERROR $cs: $@ " . __LINE__ );
  6212. }
  6213. }
  6214. else
  6215. {
  6216. my $errors = AnalyzeCommandChain( undef, $cs );
  6217. if ( defined($errors) )
  6218. {
  6219. MSwitch_LOG( $name, 1, "$name Absent_repeat $cs: ERROR : $errors -> Comand: $cs" );
  6220. }
  6221. }
  6222. }
  6223. delete( $hash->{helper}{repeats}{$time} );
  6224. }
  6225. #########################
  6226. sub MSwitch_Createnumber($) {
  6227. my ($hash) = @_;
  6228. my $Name = $hash->{NAME};
  6229. my $number = AttrVal( $Name, 'MSwitch_RandomNumber', '' )+1;
  6230. my $number1 = int (rand ($number));
  6231. readingsSingleUpdate( $hash, "RandomNr", $number1, 1 );
  6232. return;
  6233. }
  6234. ################################
  6235. sub MSwitch_Createnumber1($) {
  6236. my ($hash) = @_;
  6237. my $Name = $hash->{NAME};
  6238. my $number = AttrVal( $Name, 'MSwitch_RandomNumber', '' )+1;
  6239. my $number1 = int (rand ($number));
  6240. readingsSingleUpdate( $hash, "RandomNr1", $number1, 1 );
  6241. return;
  6242. }
  6243. ###############################
  6244. sub MSwitch_Safemode($) {
  6245. my ($hash) = @_;
  6246. my $Name = $hash->{NAME};
  6247. if (AttrVal( $Name, 'MSwitch_Safemode', '0' ) == 0){ return;}
  6248. my $time = gettimeofday();
  6249. $time =~ s/\.//g;
  6250. my $time1 =int ($time);
  6251. my $count =0;
  6252. my $timehash = $hash->{helper}{savemode};
  6253. foreach my $a ( keys %{$timehash} )
  6254. {
  6255. $count++;
  6256. if ($a < $time1-1000000) # für 10 sekunden
  6257. {
  6258. delete( $hash->{helper}{savemode}{$a} );
  6259. $count = $count-1;
  6260. }
  6261. }
  6262. $hash->{helper}{savemode}{$time1} =$time1;
  6263. if ($count > $savecount)
  6264. {
  6265. Log3( $Name, 1, "Das Device ".$Name." wurde automatisch deaktiviert ( Safemode )" );
  6266. $hash->{helper}{savemodeblock}{blocking} ='on';
  6267. readingsSingleUpdate( $hash, "Safemode", 'on', 1 );
  6268. foreach my $a ( keys %{$timehash} )
  6269. {
  6270. delete( $hash->{helper}{savemode}{$a} );
  6271. }
  6272. $attr{$Name}{disable} = '1';
  6273. }
  6274. return;
  6275. }
  6276. ###############################################################
  6277. sub MSwitch_EventBulk($$$){
  6278. my ( $hash, $event, $update ) = @_;
  6279. my $name = $hash->{NAME};
  6280. return if !defined $event;
  6281. return if !defined $hash;
  6282. if ($hash eq ""){return;}
  6283. my @evtparts = split( /:/, $event );
  6284. $update ='1';
  6285. my $evtsanzahl = @evtparts;
  6286. if ( $evtsanzahl < 3 )
  6287. {
  6288. my $eventfrom = $hash->{helper}{eventfrom};
  6289. unshift( @evtparts, $eventfrom );
  6290. $evtsanzahl = @evtparts;
  6291. }
  6292. my $evtfull = join( ':', @evtparts );
  6293. $evtparts[2] ='' if !defined $evtparts[2];
  6294. if (ReadingsVal( $name, 'last_event', '' ) ne $event && $event ne '')
  6295. {
  6296. readingsBeginUpdate($hash);
  6297. readingsBulkUpdate( $hash, "EVENT", $event ) if $event ne '';
  6298. readingsBulkUpdate( $hash, "EVTFULL", $evtfull ) if $evtfull ne '';
  6299. readingsBulkUpdate( $hash, "EVTPART1", $evtparts[0] ) if $evtparts[0] ne '';
  6300. readingsBulkUpdate( $hash, "EVTPART2", $evtparts[1] ) if $evtparts[1] ne '';
  6301. readingsBulkUpdate( $hash, "EVTPART3", $evtparts[2] ) if $evtparts[2] ne '';
  6302. readingsBulkUpdate( $hash, "last_event", $event ) if $event ne '';
  6303. readingsEndUpdate( $hash, $update );
  6304. }
  6305. return;
  6306. }
  6307. ##########################################################
  6308. # setzt reihenfolge und testet ID
  6309. sub MSwitch_priority(@)
  6310. {
  6311. my ( $hash,$execids, @devices ) = @_;
  6312. my $name = $hash->{NAME};
  6313. MSwitch_LOG( $name, 5, "$name: zuweisung der reihenfolge und der id" );
  6314. if ( AttrVal( $name, 'MSwitch_Expert', "0" ) ne'1' )
  6315. {
  6316. return @devices;
  6317. }
  6318. my %devicedetails = MSwitch_makeCmdHash($name);
  6319. # my $execids = "0" if !defined $execids;
  6320. my %new;
  6321. foreach my $device (@devices)
  6322. {
  6323. # $execids beinhaltet auszuführende ids gesetzt bei init
  6324. my $key1 = $device . "_id";
  6325. Log3( $name, 5, "$name: device hat die ID $device - $devicedetails{$key1}" );
  6326. next if $devicedetails{$key1} ne $execids;
  6327. my $key = $device . "_priority";
  6328. my $prio = $devicedetails{$key};
  6329. MSwitch_LOG( $name, 5, "$name: device hat die priority $device - $devicedetails{$key1}" );
  6330. $new{$device}=$prio;
  6331. }
  6332. my @new = %new;
  6333. my @newlist;
  6334. for my $key (sort { $new{ $a } <=> $new{ $b } } keys %new)
  6335. {
  6336. if ($key ne "" && $key ne " "){
  6337. push(@newlist,$key);
  6338. }
  6339. }
  6340. @devices=@newlist;
  6341. my $test = join( '|', @devices );
  6342. return @devices;
  6343. }
  6344. ##########################################################
  6345. sub MSwitch_set_dev($) {
  6346. # setzt NOTIFYDEF
  6347. my ($hash) = @_;
  6348. my $name = $hash->{NAME};
  6349. my $not = ReadingsVal( $name, 'Trigger_device', '' );
  6350. if ( $not ne 'no_trigger' )
  6351. {
  6352. if ( $not eq "all_events" )
  6353. {
  6354. delete( $hash->{NOTIFYDEV} );
  6355. if ( ReadingsVal( $name, '.Trigger_Whitelist', '' ) ne '' )
  6356. {
  6357. $hash->{NOTIFYDEV} =
  6358. ReadingsVal( $name, '.Trigger_Whitelist', '' );
  6359. }
  6360. }
  6361. else
  6362. {
  6363. $hash->{NOTIFYDEV} = $not;
  6364. my $devices = MSwitch_makeAffected($hash);
  6365. $hash->{DEF} = $not . ' # ' . $devices;
  6366. }
  6367. }
  6368. else
  6369. {
  6370. $hash->{NOTIFYDEV} = 'no_trigger';
  6371. delete $hash->{DEF};
  6372. }
  6373. }
  6374. ##############################################################
  6375. sub MSwitch_dec($$) {
  6376. # ersetzungen direkt vor befehlsausführung
  6377. my ( $hash, $todec) = @_;
  6378. my $name = $hash->{NAME};
  6379. $todec =~ s/\n//g;
  6380. $todec =~ s/#\[wa\]/|/g;
  6381. $todec =~ s/\$NAME/$hash->{helper}{eventfrom}/;
  6382. $todec =~ s/MSwitch_Self/$name/;
  6383. my $x = 0;
  6384. while ( $todec =~ m/(.*?)(\$SELF)(.*)?/)
  6385. {
  6386. my $firstpart = $1;
  6387. my $secondpart = $2;
  6388. my $lastpart = $3;
  6389. $todec = $firstpart.$name.$lastpart;
  6390. $x++;
  6391. last if $x > 10; #notausstieg
  6392. }
  6393. # setmagic ersetzun
  6394. $x =0;
  6395. while ( $todec =~ m/(.*)\[(.*)\:(.*)\](.*)/ )
  6396. {
  6397. $x++; # notausstieg notausstieg
  6398. last if $x > 20; # notausstieg notausstieg
  6399. my $setmagic = ReadingsVal( $2, $3, 0 );
  6400. $todec = $1.$setmagic.$4;
  6401. }
  6402. return $todec;
  6403. }
  6404. ################################################################
  6405. sub MSwitch_clearlog($){
  6406. my ( $hash, $cs) = @_;
  6407. my $name = $hash->{NAME};
  6408. open( BACKUPDATEI, ">./log/MSwitch_debug_$name.log" );
  6409. print BACKUPDATEI localtime()." Starte Log\n"; #
  6410. close(BACKUPDATEI);
  6411. }
  6412. ################################################################
  6413. sub MSwitch_debug2($$) {
  6414. my ( $hash, $cs) = @_;
  6415. my $name = $hash->{NAME};
  6416. return if $cs eq '';
  6417. open( BACKUPDATEI, ">>./log/MSwitch_debug_$name.log" ); # Datei zum Schreiben öffnen
  6418. print BACKUPDATEI localtime().": -> $cs\n"; #
  6419. close(BACKUPDATEI);
  6420. }
  6421. ##################################
  6422. ##################################
  6423. sub MSwitch_LOG($$$)
  6424. {
  6425. my ( $name,$level, $cs) = @_;
  6426. my $hash = $defs{$name};
  6427. if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '2' || AttrVal( $name, 'MSwitch_Debug', "0" ) eq '3' )
  6428. {
  6429. MSwitch_debug2($hash, $cs);
  6430. }
  6431. Log3( $name, $level, $cs );
  6432. }
  6433. #########################
  6434. sub MSwitch_confchange($$)
  6435. {
  6436. # change wenn folgende einträge vorhanden
  6437. #I testinfo
  6438. #Q dummy1#zu schaltendes geraet#device
  6439. my ( $hash, $cs) = @_;
  6440. my $name = $hash->{NAME};
  6441. MSwitch_clearlog($hash);
  6442. $cs = urlDecode( $cs );
  6443. $cs =~ s/#\[sp\]/ /g;
  6444. my @changes = split( /\|/, $cs );
  6445. foreach my $change (@changes)
  6446. {
  6447. #MSwitch_LOG( $name, 5, "zu ersetzen: ".$change );
  6448. my @names = split( /#/, $change );
  6449. # afected devices
  6450. my $tochange1 = ReadingsVal( $name, ".Device_Affected", "" );
  6451. my $oldname = $names[0]."-";
  6452. my $newname = $names[1]."-";
  6453. my @devices = split( /,/,$tochange1 );
  6454. my $x =0;
  6455. foreach (@devices)
  6456. {
  6457. $_ =~ s/$oldname/$newname/g;
  6458. $devices[$x] = $_;
  6459. $x++;
  6460. }
  6461. my $newdevices = join( ',', @devices );
  6462. readingsSingleUpdate( $hash, ".Device_Affected", $newdevices, 0 );
  6463. #details
  6464. my $tochange2 = ReadingsVal( $name, ".Device_Affected_Details", "" );
  6465. #Log3( $name, 0, "vor change: ".$tochange2 );
  6466. my @devicesdetails = split( /#\[ND\]/,$tochange2 );
  6467. $x =0;
  6468. foreach (@devicesdetails)
  6469. {
  6470. $_ =~ s/$oldname/$newname/g;
  6471. $devicesdetails[$x] = $_;
  6472. $x++;
  6473. }
  6474. $tochange2 = join( '#[ND]', @devicesdetails );
  6475. #Log3( $name, 0, "oldname: ".$oldname );
  6476. #Log3( $name, 0, "newname: ".$newname );
  6477. #Log3( $name, 0, "navh change: ".$tochange2 );
  6478. $x = 0;
  6479. while ( $tochange2 =~ m/(.*?)($names[0])(.*)?/)
  6480. {
  6481. my $firstpart = $1;
  6482. my $secondpart = $2;
  6483. my $lastpart = $3;
  6484. $tochange2 = $firstpart.$names[1].$lastpart;
  6485. $x++;
  6486. last if $x > 10; #notausstieg
  6487. }
  6488. # Log3( $name, 0, "navh 2 change: ".$tochange2 );
  6489. readingsSingleUpdate( $hash, ".Device_Affected_Details", $tochange2, 0 );
  6490. }
  6491. fhem("deletereading $name .change");
  6492. fhem("deletereading $name .change_info");
  6493. }
  6494. #########################
  6495. sub MSwitch_makefreecmd($$) {
  6496. #ersetzungen und variablen für freecmd
  6497. my ( $hash, $cs) = @_;
  6498. my $name = $hash->{NAME};
  6499. my $ersetzung ="";
  6500. # entferne kommntarzeilen
  6501. $cs =~ s/#.*\n//g;
  6502. # entferne zeilenumbruch
  6503. $cs =~ s/\n//g;
  6504. # ersetze Eventvariablen
  6505. $ersetzung = ReadingsVal( $name, "EVTPART3", "" );
  6506. $cs =~ s/\$EVTPART3/$ersetzung/g;
  6507. $ersetzung = ReadingsVal( $name, "EVTPART2", "" );
  6508. $cs =~ s/\$EVTPART2/$ersetzung/g;
  6509. $ersetzung = ReadingsVal( $name, "EVTPART1", "" );
  6510. $cs =~ s/\$EVTPART1/$ersetzung/g;
  6511. $ersetzung = ReadingsVal( $name, "EVENT", "" );
  6512. $cs =~ s/\$EVENT/$ersetzung/g;
  6513. $ersetzung = ReadingsVal( $name, "EVENTFULL", "" );
  6514. $cs =~ s/\$EVENTFULL/$ersetzung/g;
  6515. $cs =~ s/\$NAME/$hash->{helper}{eventfrom}/;
  6516. #$cs =~ s/\$SELF/$name/;
  6517. my $x = 0;
  6518. while ( $cs =~ m/(.*?)(\$SELF)(.*)?/)
  6519. {
  6520. my $firstpart = $1;
  6521. my $secondpart = $2;
  6522. my $lastpart = $3;
  6523. $cs = $firstpart.$name.$lastpart;
  6524. $x++;
  6525. last if $x > 10; #notausstieg
  6526. }
  6527. # setmagic ersetzun
  6528. MSwitch_LOG( $name, 5, "vor freecmd: ".$cs );
  6529. $x =0;
  6530. while ( $cs =~ m/(.*)\[(.*)\:(.*)\](.*)/ )
  6531. {
  6532. $x++; # notausstieg notausstieg
  6533. last if $x > 20; # notausstieg notausstieg
  6534. my $setmagic = ReadingsVal( $2, $3, 0 );
  6535. $cs = $1.$setmagic.$4;
  6536. }
  6537. MSwitch_LOG( $name, 5, "after freecmd: ".$cs );
  6538. return $cs;
  6539. }
  6540. #################################
  6541. # devices = devices.replace(/:/g,'#[dp]');
  6542. # devices = devices.replace(/;/g,'#[se]');
  6543. # devices = devices.replace(/ /g,'#[sp]');
  6544. # auskommentierte wurden bereits dur jscript ersetzt
  6545. # $savedetails =~ s/#\[wa\]/|/g;
  6546. # $savedetails =~ s/\n/#[nl]/g;
  6547. # $savedetails =~ s/;/#[se]/g;
  6548. # $savedetails =~ s/\:/#[dp]/g;
  6549. # $savedetails =~ s/\t/ /g;
  6550. # $savedetails =~ s/ /#[sp]/g;
  6551. # $savedetails =~ s/\\/#[bs]/g;
  6552. # $savedetails =~ s/,/#[ko]/g;
  6553. # $savedetails =~ s/^#\[/#[eo]/g;
  6554. # $savedetails =~ s/^#\]/#[ec]/g;
  6555. # $savedetails =~ s/\|/#[wa]/g;
  6556. 1;
  6557. =pod
  6558. =item helper
  6559. =item summary MultiswitchModul
  6560. =item summary_DE Modul zum event und zeitgesteuerten Schalten von Devices etc.
  6561. =begin html
  6562. <a name="MSwitch"></a>
  6563. <h3>MSwitch</h3>
  6564. <ul>
  6565. <u><b>MSwitch</b></u>
  6566. <br />
  6567. MSwitch is an auxiliary module that works both event- and time-controlled. <br />
  6568. For a detailed description see Wiki
  6569. <br /><br />
  6570. <a name="MSwitchdefine"></a>
  6571. <b>Define</b>
  6572. <ul><br />
  6573. <code>define &lt; Name &gt; MSwitch;</code>
  6574. <br /><br />
  6575. Beispiel:
  6576. <ul><br />
  6577. <code>define Schalter MSwitch</code><br />
  6578. </ul>
  6579. <br />
  6580. The command creates a device of type MSwitch named Switch. <br />
  6581. All further configuration takes place at a later time and can be modified and adjusted within the device at any time
  6582. </ul>
  6583. <br /><br />
  6584. <a name="MSwitch set"></a>
  6585. <b>Set</b>
  6586. <ul>
  6587. <li> inactive - sets the device inactive </li>
  6588. <li> active - sets the device active </li>
  6589. <li> backup MSwitch - creates a backup file with the configuration of all MSwitch devices </li>
  6590. <li> del_delays - deletes all pending timed commands </li>
  6591. <li> exec_cmd1 - immediate execution of the command branch1 </li>
  6592. <li> exec_cmd2 - immediate execution of command branch2 </li>
  6593. <li> fakeevent [event] - simulation of an incoming event </li>
  6594. <li> wait [sec] - no acceptance of events for given period </li>
  6595. <br />
  6596. </ul>
  6597. <br /><br />
  6598. <a name="MSwitch get"></a>
  6599. <b>Get</b>
  6600. <ul>
  6601. <li> active_timer show - displays a list of all pending timers and delays </li>
  6602. <li> active_timer delete - deletes all pending timers and delays. Timers are recalculated </li>
  6603. <li> get_config - shows the config set associated with the device</li>
  6604. <li> restore_Mswitch_date this_device - restore the device from the backupfile </li>
  6605. <li> restore_Mswitch_date all_devices - restore all MSwitchdevices from the backupfile </li>
  6606. <br />
  6607. </ul>
  6608. <br /><br />
  6609. <a name="MSwitch attribut"></a>
  6610. <b>Attribute</b>
  6611. <ul>
  6612. <li> MSwitch_Help: 0.1 - displays help buttons for all relevant fields </li>
  6613. <li> MSwitch_Debug: 0,1,2,3 - 1. switches test fields to Conditions etc. / 2. Testmode, no active cmds / 3. pure development mode </li>
  6614. <li> MSwitch_Expert: 0.1 - 1. enables additional options such as global triggering, priority selection, command repetition, etc. </li>
  6615. <li> MSwitch_Delete_Delays: 0.1 - 1. deletes all pending delays when another suitable event arrives</li>
  6616. <li> MSwitch_Include_Devicecmds: 0,1 - 1. all devices with own command set (set?) are included in affected devices </li>
  6617. <li> MSwitch_Include_Webcmds: 0.1 - 1. all devices with existing WbCmds are included in affected devices </li>
  6618. <li> MSwitch_Include_MSwitchcmds: 0.1 - 1. all devices with existing MSwitchcmds are included in affected devices </li>
  6619. <li> MSwitch_Activate_MSwitchcmds: 0.1 - 1. activates the attribute MSwitchcmds in all devices </li>
  6620. <li> MSwitch_Lock_Quickedit: 0,1 - 1. activates the lock of the selection field 'affected devices' </li>
  6621. <li> MSwitch_Ignore_Types: - List of all device types that are not displayed in the 'affected devices' </li>
  6622. <li> MSwitch_Trigger_Filter - List of events to ignore </li>
  6623. <li> MSwitch_Extensions: 0.1 - 1. Enables additional option Devicetogggle </li>
  6624. <li>MSwitch_Startdelay - delays the start of MSwitch after Fhemstart by the specified time in seconds. Recommended: 30 seconds</li>
  6625. <li> MSwitch_Inforoom - contains a room name where MSwitches are displayed in detail </li>
  6626. <li> MSwitch_Mode: Full, Notify, Toggle - Device Operation Mode </li>
  6627. <li> MSwitch_Condition_Time: 0.1 - activation of the trigger conditions for timed triggering </li>
  6628. <li> MSwitch_Safemode: 0.1 - 1. aborts all actions of the device if more than 20 calls per second take place </li>
  6629. <li> MSwitch_RandomTime - see Wiki </li>
  6630. <li> MSwitch_RandomNumber - see Wiki </li>
  6631. </ul>
  6632. </ul>
  6633. =end html
  6634. =begin html_DE
  6635. <a name="MSwitch"></a>
  6636. <h3>MSwitch</h3>
  6637. <ul>
  6638. <u><b>MSwitch</b></u>
  6639. <br />
  6640. MSwitch ist ein Hilfsmodul , das sowohl event-, als auch zeitgesteuert arbeitet.<br />
  6641. Für eine umfangreche Beschreibung siehe Wiki: https://wiki.fhem.de/wiki/MSwitch
  6642. <br /><br />
  6643. <a name="MSwitchdefine"></a>
  6644. <b>Define</b>
  6645. <ul><br />
  6646. <code>define &lt; Name &gt; MSwitch;</code>
  6647. <br /><br />
  6648. Beispiel:
  6649. <ul><br />
  6650. <code>define Schalter MSwitch</code><br />
  6651. </ul>
  6652. <br />
  6653. Der Befehl legt ein Device vom Typ MSwitch an mit dem Namen Schalter.<br />
  6654. sämtliche weitere Konfiguration erfolgt zu einem späteren Zeitpunkt und kann innerhalb des Devices jerderzeit verändert und angepasst werden
  6655. </ul>
  6656. <br /><br />
  6657. <a name="MSwitch set"></a>
  6658. <b>Set</b>
  6659. <ul>
  6660. <li>inactive - setzt das Device inaktiv</li>
  6661. <li>active - setzt das Device aktiv</li>
  6662. <li>backup MSwitch - legt eine Backupdatei mit der Konfiguration aller MSwitchdevices an</li>
  6663. <li>del_delays - löscht alle anstehenden timer für zeitversetzte Befehle</li>
  6664. <li>exec_cmd1 - sofortiges Ausführen des Kommandozweiges1</li>
  6665. <li>exec_cmd2 - sofortiges Ausführen des Kommandozweiges2</li>
  6666. <li>fakeevent [event] - simulation eines eingehenden Events</li>
  6667. <li>wait [sek] - keine annahme von Events für vorgegebenen Zeitraum</li>
  6668. <br />
  6669. </ul>
  6670. <br /><br />
  6671. <a name="MSwitch get"></a>
  6672. <b>Get</b>
  6673. <ul>
  6674. <li>active_timer show - zeigt eine Liste aller anstehenden Timer und Delays</li>
  6675. <li>active_timer delete - löscht alle anstehenden Timer und Delays. Timer werden neu berechnet</li>
  6676. <li>get_config - zeigt den dem Device zugeordneten Configsatz</li>
  6677. <li>restore_Mswitch_date this_device - restore des Devices aus dem Backupfile</li>
  6678. <li>restore_Mswitch_date all_devices - restore aller MSwitchdevices aus dem Backupfile</li>
  6679. <br />
  6680. </ul>
  6681. <br /><br />
  6682. <a name="MSwitch attribut"></a>
  6683. <b>Attribute</b>
  6684. <ul>
  6685. <li>MSwitch_Help:0,1 - zeigt Hilfebuttons zu allen relevanten Feldern</li>
  6686. <li>MSwitch_Debug:0,1,2 - 1. schaltet Prüffelder zu Conditions etc. an / 2. Testmode shreibt alle Aktionen in ein seperates Log, führt diese aber nicht aus / 3. reiner Entwicklungsmode</li>
  6687. <li>MSwitch_Expert:0,1 - 1. aktiviert Zusatzoptionenv wi z.B globales triggern, prioritätsauswahl, Befehlswiederholungesn etc. </li>
  6688. <li>MSwitch_Delete_Delays:0,1 - 1. löscht alle anstehenden Delays bei erneutem eintreffen eines passenden Events</li>
  6689. <li>MSwitch_Include_Devicecmds:0,1 - 1. alles Devices mit eigenem Befehlssatz (set ?) werden in affected Devices einbezogen</li>
  6690. <li>MSwitch_Include_Webcmds:0,1 - 1. alles Devices mit vorhandenen WbCmds werden in affected Devices einbezogen</li>
  6691. <li>MSwitch_Include_MSwitchcmds:0,1 - 1. alles Devices mit vorhandenen MSwitchcmds werden in affected Devices einbezogen</li>
  6692. <li>MSwitch_Activate_MSwitchcmds:0,1 - 1. aktiviert in allen Devices das Attribut MSwitchcmds</li>
  6693. <li>MSwitch_Lock_Quickedit:0,1 - 1. aktiviert die sperre des Auswahlfeldes 'affected devices'</li>
  6694. <li>MSwitch_Ignore_Types: - Liste aller DeviceTypen , die nicht in den 'affected devices' dargestellt werden'</li>
  6695. <li>MSwitch_Trigger_Filter - Liste aller zu ignorierenden Events</li>
  6696. <li>MSwitch_Extensions:0,1 - 1. aktiviert zusatzoption Devicetogggle</li>
  6697. <li>MSwitch_Startdelay - verzögert den Start von MSwitch nach Fhemstart um die angegebene Zeit in Sekunden . Empfohlen:30 sekunden</li>
  6698. <li>MSwitch_Inforoom - beinhalttet einen Raumnamen , in dem MSwitches detailiert dargestellt werden</li>
  6699. <li>MSwitch_Mode:Full,Notify,Toggle - Betriebsmodus des Devices</li>
  6700. <li>MSwitch_Condition_Time:0,1 - zuschaltung der Triggerconditions für zeitgesteuertes Auslösen</li>
  6701. <li>MSwitch_Safemode:0,1 - 1. bricht alle Aktionen des Devices ab, wenn mehr als 20 Aufrufe pro Sekunde erfolgen</li>
  6702. <li>MSwitch_RandomTime - siehe Wiki</li>
  6703. <li>MSwitch_RandomNumber - siehe Wiki</li>
  6704. </ul>
  6705. </ul>
  6706. =end html_DE
  6707. =cut