98_MSwitch.pm 284 KB

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