├── admin └── timertut1.png ├── .vscode └── launch.json ├── LICENSE ├── tsconfig.json ├── README.md ├── TimerView.txt └── Timerscript.js /admin/timertut1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pittini/iobroker-Timer/HEAD/admin/timertut1.png -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "skipFiles": [ 12 | "/**" 13 | ], 14 | "program": "${workspaceRoot}/Timerscript.js" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2020 Pittini 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": true, 3 | "compilerOptions": { 4 | // do not compile anything, this file is just to configure type checking 5 | "noEmit": true, 6 | 7 | // check JS files 8 | "allowJs": true, 9 | "checkJs": true, 10 | 11 | "module": "commonjs", 12 | "moduleResolution": "node", 13 | // this is necessary for the automatic typing of the adapter config 14 | "resolveJsonModule": true, 15 | 16 | // Set this to false if you want to disable the very strict rules (not recommended) 17 | "strict": true, 18 | // Or enable some of those features for more fine-grained control 19 | // "strictNullChecks": true, 20 | // "strictPropertyInitialization": true, 21 | // "strictBindCallApply": true, 22 | "noImplicitAny": false, 23 | "noUnusedLocals": true, 24 | "noUnusedParameters": true, 25 | 26 | // Consider targetting es2017 or higher if you require the new NodeJS 8+ features 27 | "target": "es2017", 28 | 29 | }, 30 | "include": [ 31 | "**/*.js", 32 | "**/*.d.ts" 33 | ], 34 | "exclude": [ 35 | "node_modules/**", 36 | "admin/**" 37 | ] 38 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Legt eine beliebige Anzahl von Timern an mit folgenden Features: 2 | 3 | **If you like it, please consider a donation:** 4 | 5 | [![paypal](https://www.paypalobjects.com/en_US/DK/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=GGF786JBJNYRN&source=url) 6 | 7 | ## Features 8 | 1. Alle benötigten Datenpunkte werden automatisch erstellt. 9 | 2. Jeder Timer steuert genau einen Schaltvorgang. Für einen kompletten ein/aus Zyklus müssen also 2 Timer genutzt werden. 10 | 3. Es kann ein/aus-geschaltet werden, aber auch Werte gesendet werden (Z.b. Rollo um 13:00 auf 40% fahren). 11 | 4. Timer bietet die Option "Nur bei Anwesenheit" bzw. "Nur bei Abwesenheit" und greift hierfür auf einen schon vorhandenen Anwesenheitsdatenpunkt zu. 12 | 5. Timer ist ein Wochentimer, jeder Tag kann separat an/ab -gewählt werden. 13 | 6. Timer hat Astrofunktion, bei Auswahl einer Astrofunktion kann hier zusätzlich ein +- Offset angegeben werden. 14 | 7. Timer wird komplett via Vis gesteuert, keinerlei Skriptänderungen nötig um Timer anzulegen, zu löschen oder zu ändern. 15 | 8. Vis zeigt Status der Schaltziele durch Farbwechsel. 16 | 17 | 18 | ## WICHTIG!!! 19 | ### Vorraussetzungen: Den zu schaltenden Geräten/Datenpunkten muss eine Funktion, z.B. "TimerTarget" zugewiesen sein. 20 | ### **Aber nur für den Datenpunkt, nicht den gesamten Channel!!!** 21 | 22 | ![timertut1.png](/admin/timertut1.png) 23 | 24 | # Installation 25 | 1. Wenn noch nicht geschehen, allen gewünschten Zieldatenpunkten eine Funktion zuweisen. Die Funktion muss vorher in den Aufzählungen hinzugefügt werden und könnte z.B. "TimerTarget" lauten. Soll ein anderer Begriff verwendet werden, muss dies dann auch im Script geändert werden. **Nach der Zuweisung, bzw. dem anlegen neuer Aufzählungspunkte ist es empfehlenswert die JS Instanz neu zu starten da diese bei Aufzählungsänderungen gerne mal "zickt" was dann zu Skriptfehlern führt**. 26 | 2. Das Skript in ein neues JS Projekt kopieren. 27 | 3. Als nächstes (Zeile 9) gebt Ihr den Datenpunkt für An/Abwesenheit an. 28 | Dieser darf numerische oder boolsche Werte beinhalten. Habt Ihr keinen entsprechenden Datenpunkt tragt "" ein. 29 | 4. Das Script starten. 30 | Im Hintergrund werden nun alle benötigten Channels und Datenpunkte unter dem Channel der in Zeile 7 angegeben wurde, angelegt. Als default ist das: "javascript.0.Timer". 31 | 5. Ab hier habt Ihr mit dem Skript und der Objektliste nichts mehr zu tun, alles weitere wird via Vis erledigt, ihr solltet nun die beigefügte Vorlage (TimerView.txt) via "Widgets importieren" in Euer Vis Projekt integrieren und die Vis RUNTIME aufrufen. Im Vis Editor habt Ihr nach dem Import nichts mehr zu tun. 32 | 33 | ## Bedienung und Anzeigen des Vis Views 34 | Vorab der Hinweis, dass alle in der Tabelle verwendeten Icons und Farben in den Skript/Tabelleneinstellungen verändert werden können. Wie in all meinen Skripten wird für die Icons der Iconsatz "icons-mfd-svg" verwendet. Ist dieser Satz installiert, so seht Ihr dies in der Liste der installierten Instanzen. Ist er dort nicht aufzufinden solltet Ihr ihn installieren (als Adapter). 35 | Der View besteht im wesentlichen aus zwei Bereichen. Der erste, obere, Bereich mit den Einstellfeldern und den Kontrollelementen für speichern/hinzufügen/löschen von Timern, sowie der Übersichtstabelle unten, in der Ihr alle angelegten Timer und deren Status seht. 36 | ### Nun zur Funktion der einzelnen Elemente: 37 | 1. **Das Listenfeld "Timer"** - Hier wählt Ihr aus welchen Timer Ihr mit den nachfolgenden Elementen bearbeiten möchtet. Der gewählte Timer wird zur optischen Bestätigung in der Übersichtstabelle dunkelgelb (ocker) dargestellt. 38 | 2. **Der Button "on/off"** - Hiermit könnt Ihr den jeweiligen Timer aktivieren oder deaktivieren ohne ihn gleich zu löschen. 39 | 3. **Das Listenfeld "Aktion"** - hier legt Ihr fest was dieser Timer tun soll. anschalten (true), ausschalten (false) oder umschalten. Die Variante "umschalten" dreht den jeweils aktuellen Status des Datenpunktes um, ist dieser true, wird er auf false gesetzt und umgekehrt. Bitte beachtet das ein kompletter Schaltzyklus von an- und ausschalten aus zwei Timereinträgen besteht! 40 | Wählt Ihr die Option "Wert senden", erscheint ein neues Eingabefeld, in dem Ihr den zu sendenden Wert (egal ob Zahl, Text oder Bool) eingebt. 41 | 4. **Das Listenfeld "Modus"** - Hier wird festgelegt ob der Timer zu einer (im nachfolgenden Feld) eingegebenen Zeit schalten soll, oder ob eine der verfügbaren Astroschaltzeiten (Sonnenaufgang, Sonnenuntergang usw.) verwendet werden soll. 42 | 5. **Das Eingabe/Anzeige Feld "Zeit"** - Dieses Feld hat zwei unterschiedliche Funktionen/Verhalten, je nachdem was unter Modus eingestellt wurde. Wurde dort als Modus "Zeit" gewählt, so dient dieses Feld zur Eingabe der Schaltzeit. Wurde eine Astrofunktion gewählt wird es zu einem reinen Anzeigefeld in das Ihr nichts eingeben könnt und zeigt Euch die durch die Astrofunktion vorgegebene Schaltzeit an. 43 | 6. **Das Eingabefeld "Offset"** - Wurde unter Modus eine Astrofunktion gewählt, so könnt Ihr hier eine Offsetzeit ,sowohl positiv als auch negativ, in Minuten angeben. Wurde Modus "Zeit" gewählt ist diese Option nicht verfügbar. 44 | 7. **Das Listenfeld "Ziel"** - Hier wählt Ihr aus welches Ziel geschaltet werden soll. Die hier vorhandenen Einträge, sind die Namen jener Id's, welche Ihr der Funktion "TimerTarget" zugewiesen habt. Schaltbar ist grundsätzlich alles was mit true/false gesteuert wird, egal ob Lampen, Steckdosen oder auch Skripte, Datenpunkte usw. 45 | 8. **Die Buttons der "Tage"** - Hiermit legt Ihr fest an welchen Tagen der Timer schaltet (Grün=aktiv, grau=inaktiv). 46 | 9. **Der Button "Haus mit Person"** - Legt fest das nur bei Anwesenheit geschaltet wird (Grün=aktiv, grau=inaktiv). 47 | Solltet Ihr keinen Anwesenheitsdatenpunkt eingetragen haben, so ist dieser Button, sowie die zugehörige Spalte in der Übersichtstabelle nicht sichtbar. Skriptintern wird die Anwesenheit auf true gesetzt. 48 | 10. **Der Button "Haus leer"** - Legt fest das bei nur Abwesenheit geschaltet wird (Grün=aktiv, grau=inaktiv). 49 | Solltet Ihr keinen Anwesenheitsdatenpunkt eingetragen haben, so ist dieser Button, sowie die zugehörige Spalte in der Übersichtstabelle nicht sichtbar. Skriptintern wird die Anwesenheit auf true gesetzt. 50 | 11. **Der Button "Briefumschlag"** - Hiermit kannst Du festlegen ob Du über die Aktivitäten dieses Timers benachrichtigt werden möchtest oder nicht. Default ist: benachrichtigen. Setzt voraus dass eine Benachrichtigungvariante grundsätzlich in den Skripteinstellungen aktiviert ist. 51 | 52 | Aus Sicherheits/Fehlbedienungs-gründen und um Schreibzugriffe zu minimieren werden geänderte Einstellungen erst gespeichert wenn Ihr dies explizit veranlasst. Hierzu dient: 53 | 54 | 12. **Der Button "Diskette"** - Durch Klick auf diesen werden die getroffenen Einstellungen gespeichert. Dieses wird optisch bestätigt durch kurzen Farbwechsel zu grün und zurück zu grau. 55 | 56 | Um einen neuen Timereintrag anzulegen verwendest Du: 57 | 58 | 13. **Den Button "+"** - Ein klick auf diesen Button erzeugt einen neuen Eintrag und setzt den Fokus auf diesen so das Du sofort im Editbereich die gewünschten Werte eintragen kannst. Speichern nicht vergessen! 59 | 60 | Zuguterletzt gibt es noch die Möglichkeit den Timer mit dem aktuellen Fokus zu löschen, hierzu dient: 61 | 62 | 14. **Der Button "Papierkorb"** - Um versehentliches Löschen zu erschweren hat dieser Button eine **Sicherheitsabfrage**. Der erste Klick auf den Button "Papierkorb" läßt dessen Farbe zu rot wechseln, das Symbol wandelt sich zu einem Fragezeichen. Erst ein weiterer Klick, nunmehr auf das Fragezeichen, innerhalb 3 Sekunden, löscht den Eintrag tatsächlich und unwiederbringlich. Läßt Du die 3 Sekunden ohne Klick verstreichen, wandelt sich der Button zurück zum Papierkorb, der Löschmodus wird abgebrochen. 63 | 64 | ### Farben der Übersichtstabelle 65 | **Weisser** Rahmen zeigt Dir den Eintrag mit aktuellem Fokus. Änderungen im Editbereich würden sich auf genau diese Zeile auswirken. Sobald Du im Editbereich eine erste Änderung vornimmst, wandelt sich der Hintergrund in: 66 | 67 | **gelb** und zeigt Dir damit an das Du bereits eine Änderung vorgenommen hast. Gespeichert wird diese aber, wie oben beschrieben, erst, wenn Du das Diskettensymbol anklickst. 68 | 69 | **grün** dargestellt werden alle Einträge welche einstellungsgemäß **eingeschaltet** wurden. Wird manuell oder durch einen anderen Timer der Status verändert, wechselt die Zeile wieder zu grau. 70 | 71 | **rot** dargestellt werden alle Einträge welche einstellungsgemäß **ausgeschaltet** wurden. Wird manuell oder durch einen anderen Timer der Status verändert, wechselt die Zeile wieder zu grau. 72 | 73 | **schwarz** dargestellt werden alle Einträge welche neu bzw. ungültig sind. Dies ist der Fall wenn kein Ziel zugeordnet wurde. 74 | 75 | 76 | 77 | Das wars, viel Spaß. 78 | 79 | 80 | 81 | ## Changelog 82 | ### V2.2.0 (18.07.2021) 83 | * Add: Möglichkeit bedingter Ausführung hinzugefügt. Z.B. Bewässerung um 6.00 starten, aber nur wenn Bodenfeuchte kleiner x. 84 | ### V2.1.10 (03.05.2021) 85 | * Fix: Fehlermeldung "...has been written without ack-flag" bei Verwendung des Js Controllers 3.3.x oder höher. Issue: https://github.com/Pittini/iobroker-Timer/issues/8 86 | ### V2.1.9 (08.12.2020) 87 | * Fix: Beim setzen von Werten wird nun der Datentyp des Zieldatenpunktes vorab geprüft und der Wert nötigenfalls entsprechend konvertiert. Issue: https://github.com/Pittini/iobroker-Timer/issues/6 88 | ### V2.1.8 (22.09.2020) 89 | * Fix: Problem beim löschen von Timern behoben. (fastfood) 90 | ### V2.1.7 (26.07.2020) 91 | * Fix: Problem bei Verwendung des Alias.0 Ordners (keine Namensanzeige) behoben. 92 | * Add: Möglichkeit in den Einstellungen hinzugefügt statt Channelnamen, Id-Namen zu verwenden. 93 | ### V2.1.5 (19.07.2020) 94 | * Add: Option "Wert senden" zu Aktionen, sowie entsprechendes Eingabefeld und Spalte in der Tabelle hinzugefügt. 95 | ### V2.1.4 (30.06.2020) 96 | * Fix: Fehler bei noch leeren Timern behoben. 97 | ### V2.1.2 (20.06.2020) 98 | * Fix: Fehler abgefangen der auftrat wenn Timerzeit ohne Sekunden angegeben wurde. 99 | ### V2.1.1 (18.06.2020) 100 | * Add: Namen der Schaltziele können nun geändert werden. Änderungen werden automatisch mit anderen Timern synchronisiert welche das gleiche Ziel haben, Auswahlliste wird automatisch angepasst. Zusätzliches Eingabefeld (über "Ziel") und Button (rechts neben "Ziel") in Vis Vorlage hinzugefügt. 101 | ### V2.1.0 (14.06.2020) 102 | * Fix: Diverse Aktualisierungs und Anzeigefehler für Astro behoben. 103 | * Fix: Mehrfachaufrufe bestimmter Funktionen korrigiert. 104 | * Fix: Führende Nullen bei Stundenangabe in Astrofunktionen hinzugefügt. 105 | * Fix: Korrektur der Astrofunktionen wenn nur bestimmte Tage gewählt wurden. 106 | * Fix: Doppelauslösungen (nur durch Log oder Nachricht bemerkbar) im Sommerhalbjahr bei Astro korrigiert. 107 | * Fix: Auflaufen von Schedules korrigiert. 108 | ### V2.0.7 (02.06.2020) 109 | * Change: Auswahl der Astrofunktionen auf alle verfügbaren erweitert. 110 | * Change: Kleine interne Codeänderungen. 111 | ### V2.0.6 (31.05.2020) 112 | * Fix: Ausnahmeregel für Namensauflösung von Datenpunkten ohne übergeordnetem Channel hinzugefügt. 113 | * Fix: Anzeigefehler bei Wechsel von Zeit zu Astrofunktion behoben. 114 | ### V2.0.5 (30.05.2020) 115 | * Add: Datenpunkt hinzugefügt der die Zahl der aktivierten Timer zeigt. 116 | * Add: Abfrage hinzugefügt welche verhindert das Timer ohne Ziel aktiviert werden können, hier wird das speichern verweigert. 117 | * Add: Timer ohne Ziel werden farblich schwarz markiert. 118 | * Fix: Farbwechsel in der Tabelle korrigiert. 119 | ### V2.0.4 (25.05.2020) 120 | * Add: Schriftgrößen der Tabelle nun im Einstellungsbereich konfigurierbar. 121 | * Add: Benachrichtigung nun zusätzlich pro Timer aktivier/deaktivier-bar, hierzu zusätzliche Spalte + Button ins Vis eingefügt. 122 | * Change: Triggerhandling geändert. Farbwechsel in der Tabelle erfolgt nun bei schalten des Timers (rot/grün) und zurückschalten (grau) wodurch auch immer. Alle weiteren Schaltvorgänge von außerhalb werden ignoriert. 123 | ### V2.0.3 Beta (24.05.2020) 124 | * Fix: Problem welches zur Warnmeldung: 125 | "Object javascript.0.Timer.x is invalid: obj.common.type has an invalid value (channel) but has to be one of number, string, boolean, array, object, mixed, file, json" führte behoben. 126 | * Fix: Async Problem beim hinzufügen neuer Timer behoben welche zur Fehlermeldung: 127 | "Error in callback: TypeError: Cannot read property '0' of undefined" führten. 128 | * Fix: Problem mit verbleibenden subscriptions behoben welche zur Fehlermeldung: 129 | "Error in callback: TypeError: Cannot set property '18' of undefined" führten. 130 | ### V2.0.2 Beta (23.05.2020) 131 | * Add: Es ist nun nicht mehr möglich die Schaltung gleichzeitig bei Anwesenheit als auch bei Abwesenheit zu deaktivieren da dies zu "nie" führen würde. 132 | ### V2.0.2 Beta (23.05.2020) 133 | * Fix: Trigger für TimerTargets wird jetzt beim speichern korrekt gesetzt/aktualisiert. 134 | * Add: Meldungen können via Datenpunkt gemutet/deaktiviert werden. Weist Ihr diesem Datenpunkt die Funktion TimerTarget zu, kann dies auch zeitgesteuert geschehen. 135 | * Add: Meldungen hinzugefügt. Ausgeführte Schaltungen können jetzt via Mail/Telegram/Alexa gemeldet werden. 136 | * Change: Der fokusierte Timer im Vis hat nun farbigen Rahmen statt Hintergrund. 137 | * Fix: Presence Datenpunkt defaults geändert. 138 | ### V2.0.1 Beta (22.05.2020) 139 | * Add: einige Logpunkte hinzugefügt. 140 | ### V2.0.0 Beta (22.05.2020) 141 | * Release V2 Beta 142 | ### V1.1.2 (07.02.2020) 143 | * Bugfix: Presence Trigger hinzugefügt. 144 | 145 | ### V1.1.1 (26.01.2020) 146 | * Add: Readme erstellt 147 | 148 | ### V1.1.0 (18.12.2019) 149 | * Add: Schaltoptionen "Nur bei Anwesenheit" und "Nur bei Abwesenheit" hinzugefügt. 150 | 151 | ### V1.0.0 (2019-10-28) 152 | * Initial Release -------------------------------------------------------------------------------- /TimerView.txt: -------------------------------------------------------------------------------- 1 | [{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.TimerSonntag","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
So:","html_true":"
So:","class":"","html_prepend":""},"style":{"left":"717px","top":"25px","width":"30px","height":"19px","text-align":"center","cursor":"pointer","font-size":"14px","color":"white"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.TimerMontag","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
Mo:","html_true":"
Mo:","class":""},"style":{"left":"750px","top":"25px","width":"30px","height":"19px","text-align":"center","cursor":"pointer","font-size":"14px","color":"white"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.TimerDienstag","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
Di:","html_true":"
Di:","class":""},"style":{"left":"783px","top":"25px","width":"30px","height":"19px","text-align":"center","cursor":"pointer","font-size":"14px","color":"white"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.TimerMittwoch","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
Mi:","html_true":"
Mi:","class":""},"style":{"left":"684px","top":"54px","width":"30px","height":"19px","text-align":"center","cursor":"pointer","font-size":"14px","color":"white"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.TimerDonnerstag","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
Do:","html_true":"
Do:","class":""},"style":{"left":"717px","top":"54px","width":"30px","height":"19px","text-align":"center","cursor":"pointer","font-size":"14px","color":"white"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.TimerFreitag","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
Fr:","html_true":"
Fr:","class":""},"style":{"left":"750px","top":"54px","width":"30px","height":"19px","text-align":"center","cursor":"pointer","font-size":"14px","color":"white"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.TimerSamstag","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
Sa:","html_true":"
Sa:","class":""},"style":{"left":"783px","top":"54px","width":"30px","height":"19px","text-align":"center","cursor":"pointer","font-size":"14px","color":"white"},"widgetSet":"basic"},{"tpl":"tplJquiSelectList","data":{"oid":"javascript.0.Timer.Template.SwitchTarget","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","values":"{javascript.0.Timer.TimerTargetValues}","texts":"{javascript.0.Timer.TimerTargetText}","height":"150","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"class":"","no_style":true},"style":{"left":"540px","top":"54px","width":"140px","z-index":10,"height":"22px","font-size":"small","cursor":"pointer"},"widgetSet":"jqui"},{"tpl":"tplValueStringRaw","data":{"oid":"javascript.0.Timer.Template.TimerAstroTimestamp","g_fixed":true,"g_visibility":true,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":true,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"!=","visibility-val":"time","visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"visibility-oid":"javascript.0.Timer.Template.TimerChoice","views":null,"class":""},"style":{"left":"372px","top":"54px","width":"100px","height":"19px","z-index":3,"background-color":"white","color":"","text-align":"center","font-weight":"","font-size":"14px","border-color":"","border-width":"","border-style":"","padding-top":"2px","cursor":"not-allowed"},"widgetSet":"basic"},{"tpl":"tplJquiSelectList","data":{"oid":"javascript.0.Timer.Template.Rolle","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","values":"{javascript.0.Timer.AktionValues}","texts":"{javascript.0.Timer.AktionText}","height":"120","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"no_style":true,"views":null,"class":""},"style":{"left":"124px","top":"54px","width":"100px","height":"20px","z-index":8,"font-size":"small","cursor":"pointer"},"widgetSet":"jqui"},{"tpl":"tplJquiInput","data":{"oid":"javascript.0.Timer.Template.TimerAstroShift","g_fixed":true,"g_visibility":true,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"label":"","digits":"0","size":"10","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"visibility-cond":"!=","visibility-val":"time","visibility-groups-action":"hide","visibility-oid":"javascript.0.Timer.Template.TimerChoice","views":null,"class":""},"style":{"left":"476px","top":"54px","width":"60px","height":"19px","font-size":"","z-index":9,"font-weight":"","color":"","text-align":"center","background-color":"white"},"widgetSet":"jqui"},{"tpl":"tplJquiSelectList","data":{"oid":"javascript.0.Timer.Template.TimerChoice","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","values":"{javascript.0.Timer.ModeValues}","texts":"{javascript.0.Timer.ModeText}","height":"200","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"no_style":true,"views":null,"class":""},"style":{"left":"228px","top":"54px","width":"140px","height":"22px","font-size":"medium","font-weight":"","z-index":9,"cursor":"pointer"},"widgetSet":"jqui"},{"tpl":"tplJquiInputDatetime","data":{"oid":"javascript.0.Timer.Template.TimerTimestamp","g_fixed":true,"g_visibility":true,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":"time","visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"size":"5","timeOnly":true,"hideSeconds":false,"visibility-oid":"javascript.0.Timer.Template.TimerChoice","views":null,"class":"","showGrid":true},"style":{"left":"372px","top":"54px","width":"100px","height":"19px","font-weight":"","z-index":9,"font-size":"14px","text-align":"right","background-color":"white"},"widgetSet":"jqui"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Aktion","class":""},"style":{"left":"124px","top":"25px","width":"100px","height":"20px","color":"white","padding-left":"2px","padding-top":"2px","background-color":"grey","text-align":"center","z-index":"0"},"widgetSet":"basic"},{"tpl":"tplJquiSelectList","data":{"oid":"javascript.0.Timer.SwitchToTimer","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","values":"{javascript.0.Timer.TimerCountValues}","texts":"{javascript.0.Timer.TimerCountText}","height":"120","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"no_style":true,"views":null,"class":""},"style":{"left":"16px","top":"54px","width":"50px","height":"20px","z-index":8,"font-size":"small","cursor":"pointer","text-align":"center"},"widgetSet":"jqui"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Ziel"},"style":{"left":"540px","top":"25px","height":"20px","color":"white","padding-left":"2px","padding-top":"2px","background-color":"grey","width":"140px","text-align":"center"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Modus"},"style":{"left":"228px","top":"25px","height":"20px","width":"140px","color":"white","padding-left":"2px","padding-top":"2px","background-color":"grey","text-align":"center"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":true,"g_css_border":true,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"{javascript.0.Timer.TimerOverviewTable}"},"style":{"left":"16px","top":"80px","width":"97.88%","height":"540px","border-width":"1px","border-style":"solid","overflow-y":"auto","padding":"0px","margin-left":"0px","margin-top":"0px","margin-right":"0px","margin-bottom":"0px"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Zeit"},"style":{"left":"372px","top":"25px","height":"20px","width":"100px","color":"white","padding-left":"2px","padding-top":"2px","background-color":"grey","text-align":"center","z-index":"1"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Offset"},"style":{"left":"476px","top":"25px","height":"20px","width":"60px","color":"white","padding-left":"2px","padding-top":"2px","background-color":"grey","text-align":"center"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.OnlyIfPresence","g_fixed":false,"g_visibility":true,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":"true","visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_true":"
","html_prepend":"","html_false":"
","html_append":"","visibility-oid":"javascript.0.Timer.PresenceFuncAvailable"},"style":{"left":"816px","top":"25px","width":"40px","height":"43px","cursor":"pointer"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.OnlyIfNoPresence","g_fixed":false,"g_visibility":true,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":"true","visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_true":"
","html_prepend":"","html_false":"
","html_append":"","visibility-oid":"javascript.0.Timer.PresenceFuncAvailable"},"style":{"left":"860px","top":"25px","width":"40px","height":"43px","cursor":"pointer"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.Aktiv","g_fixed":false,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_true":"
on","html_prepend":"","html_false":"
off","html_append":""},"style":{"left":"70px","top":"54px","width":"50px","height":"18px","cursor":"pointer","text-align":"center","color":"white","font-size":"14px"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.SaveEdit","g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_true":"
","html_prepend":"","html_false":"
","html_append":""},"style":{"left":"1314px","top":"25px","width":"40px","height":"43px","cursor":"pointer"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.AddTimer","g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_true":"
","html_prepend":"","html_false":"
","html_append":""},"style":{"left":"1360px","top":"25px","width":"40px","height":"43px","cursor":"pointer"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.DelTimer","g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_true":"
","html_prepend":"","html_false":"
","html_append":""},"style":{"left":"1404px","top":"25px","width":"40px","height":"43px","cursor":"pointer"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":true,"g_css_font_text":true,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":"time","visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"n/a","visibility-oid":"javascript.0.Timer.Template.TimerChoice"},"style":{"left":"476px","top":"54px","width":"60px","height":"19px","font-size":"14px","background-color":"white","text-align":"center","padding-top":"2px","cursor":"not-allowed"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
Tage","html_true":"
Tage","class":"","html_prepend":""},"style":{"left":"684px","top":"25px","width":"30px","height":"19px","text-align":"center","cursor":"","font-size":"12px","color":"white"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Timer","class":""},"style":{"left":"16px","top":"25px","width":"50px","height":"20px","color":"white","padding-left":"2px","padding-top":"2px","background-color":"grey","text-align":"center"},"widgetSet":"basic"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"on/off","class":""},"style":{"left":"70px","top":"25px","width":"50px","height":"20px","color":"white","padding-left":"2px","padding-top":"2px","background-color":"grey","text-align":"center"},"widgetSet":"basic"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.Template.ActivityMessage","g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_true":"
","html_prepend":"","html_false":"
","html_append":"","visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide"},"style":{"left":"904px","top":"25px","width":"40px","height":"43px","cursor":"pointer"},"widgetSet":"basic"},{"tpl":"tplJquiInput","data":{"oid":"javascript.0.Timer.Template.SwitchTargetSmartName","g_fixed":false,"g_visibility":true,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","label":"","digits":"0","size":"10","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"asString":true,"visibility-oid":"javascript.0.Timer.ShowNameEdit"},"style":{"left":"542px","top":"25px","height":"20px","width":"120px","z-index":"1"},"widgetSet":"jqui"},{"tpl":"tplValueBoolCtrl","data":{"oid":"javascript.0.Timer.ShowNameEdit","g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html_false":"
","html_true":"
"},"style":{"left":"660px","top":"25px","width":"20px","z-index":"1","height":"20px","cursor":"pointer"},"widgetSet":"basic"},{"tpl":"tplJquiInput","data":{"oid":"javascript.0.Timer.Template.SendValue","g_fixed":false,"g_visibility":true,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":"3","visibility-groups-action":"hide","label":"","digits":"0","size":"10","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"asString":true,"visibility-oid":"javascript.0.Timer.Template.Rolle"},"style":{"left":"126px","top":"23px","height":"20px","width":"100px","z-index":"1"},"widgetSet":"jqui"},{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":true,"g_css_shadow_padding":true,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"html":"Nur wenn"},"style":{"left":"948px","top":"25px","height":"20px","width":"360px","color":"white","padding-left":"2px","padding-top":"2px","background-color":"grey","text-align":"center"},"widgetSet":"basic"},{"tpl":"tplJquiInput","data":{"oid":"javascript.0.Timer.Template.RuleVal1","g_fixed":false,"g_visibility":true,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":"","visibility-groups-action":"hide","label":"","digits":"0","size":"16","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"asString":true,"visibility-oid":""},"style":{"left":"948px","top":"55px","height":"22px","width":"200px","z-index":"1"},"widgetSet":"jqui"},{"tpl":"tplJquiSelectList","data":{"oid":"javascript.0.Timer.Template.RuleOperator","g_fixed":true,"g_visibility":false,"g_css_font_text":true,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","values":"<;<=;>;>=;=;!=","texts":"<;<=;>;>=;=;!=","height":"200","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"no_style":true,"views":null,"class":""},"style":{"left":"1148px","top":"55px","width":"40px","height":"20px","font-size":"medium","font-weight":"","z-index":9,"cursor":"pointer"},"widgetSet":"jqui"},{"tpl":"tplJquiInput","data":{"oid":"javascript.0.Timer.Template.RuleVal2","g_fixed":false,"g_visibility":true,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"g_last_change":false,"visibility-cond":"==","visibility-val":"","visibility-groups-action":"hide","label":"","digits":"0","size":"6","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0,"asString":true,"visibility-oid":""},"style":{"left":"1194px","top":"55px","height":"20px","width":"116px","z-index":"1"},"widgetSet":"jqui"}] -------------------------------------------------------------------------------- /Timerscript.js: -------------------------------------------------------------------------------- 1 | const SkriptVersion = "2.2.0"; //Stand 18.07.2021 - Github: https://github.com/Pittini/iobroker-Timer Forum: https://forum.iobroker.net/topic/33228/vorlage-flexibles-timerskript-vis 2 | 3 | //Timerskript 4 | 5 | //Wichtige Einstellungen 6 | const logging = false; //Logmeldungen an/aus 7 | const praefix = "javascript.0.Timer."; //Grundpfad 8 | const PresenceDp = "radar2.0._nHere"; //Pfad zum Anwesenheitsdatenpunkt - Leer lassen wenn nicht vorhanden! 9 | const WelcheFunktionVerwenden = "TimerTarget"; 10 | const UseChannelNames = true; //Namen aus ID oder Channel extrahieren? 11 | 12 | //Benachrichtigungseinstellungen 13 | const UseTelegram = false; // Sollen Nachrichten via Telegram gesendet werden? 14 | const UseAlexa = false; // Sollen Nachrichten via Alexa ausgegeben werden? 15 | const AlexaId = ""; // Die Alexa Seriennummer. 16 | const UseMail = false; //Nachricht via Mail versenden? 17 | const UseSay = false; // Sollen Nachrichten via Say ausgegeben werden? Autorenfunktion, muß deaktiviert werden. 18 | const UseEventLog = false; // Sollen Nachrichten ins Eventlog geschreiben werden? Autorenfunktion, muß deaktiviert werden. 19 | 20 | //Tabellen Einstellungen 21 | const TblOnBgColor = "#4caf50"; //Hintergrundfarbe für Timer hat angeschaltet 22 | const TblOffBgColor = "#f44336"; //Hintergrundfarbe für Timer hat ausgeschaltet 23 | const TblIdleBgColor = ""; //Hintergrundfarbe für Timer ist inaktiv 24 | const TblDisabledBgColor = "black"; //Hintergrundfarbe für Timer ist inaktiv 25 | const TblEditBgColor = "#ffc107"; //Hintergrundfarbe für Timer welcher gerade bearbeitet wird 26 | const TblChoosenColor = "white"; //Rahmenfarbe für gewählten Timer, noch nicht im Edit Mode 27 | const HeadBgColor = "dimgrey"; //Hintergrundfarbe des Tabellenkopfes 28 | const FontColor = "white"; //Textfarbe für Tabelleninhalt 29 | const HeadFontColor = "white"; //Textfarbe für Tabellenkopf 30 | const FontSize = "12px";//Textgröße für Tabelleninhalt 31 | const HeadFontSize = "16px";//Textgröße für Tabellenlopf 32 | const TblShowTimerLfdCol = true; //Tabellenspalte mit laufender Nummer anzeigen? 33 | const TblShowTimerActiveCol = true; //Tabellenspalte ob Timer aktiv anzeigen? 34 | const TblShowTimerActionCol = true; //Tabellenspalte mit Timer Aktion anzeigen? 35 | const TblShowTimerSendValueCol = true; //Tabellenspalte mit Sendewerten anzeigen? 36 | const TblShowTimerModeCol = true; //Tabellenspalte mit Timermodus anzeigen? 37 | const TblShowTimerTimeCol = true; //Tabellenspalte mit Schaltzeit anzeigen? 38 | const TblShowTimerAstroOffsetCol = true; //Tabellenspalte mit Astro Offset anzeigen? 39 | const TblShowTimerTargetCol = true; //Tabellenspalte mit Timer Ziel anzeigen? 40 | const TblShowTimerTargetNameCol = true; //Tabellenspalte mit Namen des Timer Ziels anzeigen? 41 | const TblShowTimerDaysCol = true; //Tabellenspalte mit aktiven Tagen anzeigen? 42 | const TblShowTimerIfPresenceCol = true; //Tabellenspalte Schaltung nur bei Anwesenheit ausgeben? 43 | const TblShowTimerIfNoPresenceCol = true; //Tabellenspalte Schaltung nur bei Abwesenheit ausgeben? 44 | const TblShowTimerMessageCol = true; //Tabellenspalte für separate Benachrichtigungseinstellung ausgeben? 45 | const TblShowTimerRuleCol = true; //Tabellenspalte für Rules ausgeben? 46 | const ImgInvert = 0; // Bildfarben invertieren? Erlaubte Werte von 0 bis 1 47 | const TblLfdImg = "/icons-mfd-svg/time_timer.svg"; //Bild für "Timer aktiv" 48 | const TblActiveImg = "/icons-mfd-svg/control_on_off.svg"; //Bild für "Timer aktiv" 49 | const TblIfPresenceImg = "/icons-mfd-svg/status_available.svg"; //Bild für "Nur wenn anwesend" 50 | const TblIfNoPresenceImg = "/icons-mfd-svg/control_building_empty.svg"; //Bild für "Nur wenn abwesend" 51 | const TblMessageImg = "/icons-mfd-svg/message_mail.svg"; //Bild für "Nachricht senden" 52 | 53 | //Ab hier nix mehr ändern 54 | let TimerCount = 2; //Wieviele Timer bei SkriptERSTstart anlegen? 55 | let ActiveTimerCount = 0; //Timer welche aktiv sind 56 | let MsgMute = false; 57 | let Funktionen = getEnums('functions'); //Array mit Aufzählung der Funktionen 58 | const Targets = []; 59 | let TargetNames = []; 60 | /* 61 | "sunrise": sunrise (top edge of the sun appears on the horizon) 62 | "sunriseEnd": sunrise ends (bottom edge of the sun touches the horizon) 63 | "goldenHourEnd": morning golden hour (soft light, best time for photography) ends 64 | "solarNoon": solar noon (sun is in the highest position) 65 | "goldenHour": evening golden hour starts 66 | "sunsetStart": sunset starts (bottom edge of the sun touches the horizon) 67 | "sunset": sunset (sun disappears below the horizon, evening civil twilight starts) 68 | "dusk": dusk (evening nautical twilight starts) 69 | "nauticalDusk": nautical dusk (evening astronomical twilight starts) 70 | "night": night starts (dark enough for astronomical observations) 71 | "nightEnd": night ends (morning astronomical twilight starts) 72 | "nauticalDawn": nautical dawn (morning nautical twilight starts) 73 | "dawn": dawn (morning nautical twilight ends, morning civil twilight starts) 74 | "nadir": nadir (darkest moment of the night, sun is in the lowest position) 75 | */ 76 | 77 | const Wochentage = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]; //Array für createStateschleife zum anlegen der Wochentage 78 | const WeekdaysShort = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"]; //Array zur Bestimmung des aktuellen und morgigen Tages für Astro 79 | const ModeValues = ["time", "dawn", "sunrise", "sunriseEnd", "goldenHourEnd", "solarNoon", "goldenHour", "sunsetStart", "sunset", "dusk", "night", "nadir", "nightEnd"]; //Array für Astrobezeichnungen 80 | const ModeText = ["Zeit", "Morgendämmerung", "Sonnenaufgang", "Ende Sonnenaufgang", "Ende Blaue Stunde", "Sonnenmittag", "Goldene Stunde", "Beginn Sonnenuntergang", "Sonnenuntergang", "Abenddämmerung", "Nacht", "Nadir", "Nachtende"]; //Array für Astrobezeichnungen in Deutsch 81 | const AktionValues = [0, 1, 2, 3]; 82 | const AktionText = ["Ausschalten", "Einschalten", "Umschalten", "Wert senden"]; 83 | const Dps = ["Aktiv", "Rolle", "TimerTimestamp", "TimerAstroTimestamp", "TimerAstroShift", "TimerChoice", "TimerSonntag", "TimerMontag", "TimerDienstag", "TimerMittwoch", "TimerDonnerstag", "TimerFreitag", "TimerSamstag", "SwitchTarget", "OnlyIfPresence", "OnlyIfNoPresence", "ActivityMessage", "SwitchTargetSmartName", "SendValue", "RuleVal1", "RuleOperator", "RuleVal2"]; 84 | const DpDefaults = [false, 1, "00:00:00", "00:00:00", 0, "time", true, true, true, true, true, true, true, "", true, true, true, "", "-", "", "", ""]; 85 | 86 | let MyTimer = []; //Datenarray aller Timer, darf nicht const sein weil bei Timerlöschung komplette Neuzuweisung erfolgt 87 | const MyTimerTemplate = []; 88 | const TriggerArray = []; //Sammelt die Schaltdatenpunkte der Timer ohne Duplikate 89 | 90 | let Presence = true; //Voreinstellung Anwesenheit ist wahr, für den Fall das kein PresenceDp angegeben 91 | let DpCount = 0; //Counter 92 | 93 | let TargetSwitchingInProgress = false; 94 | let SwitchingInProgress = false; //Steuervariable um ungewolltes Triggern (und aktivieren des Edit Modes) während Template-umschaltung zu vermeiden 95 | let DeletionInProgress = false; 96 | let ChoosenTimer = 0; //Aktuell (in Vis) gewählter Timer 97 | 98 | log("Starting TimerSkript V" + SkriptVersion); 99 | PrepareDps(); //Datenpunkte Initial erstellen 100 | 101 | function Meldung(msg) { 102 | if (logging) log("Reaching Meldung, msg= " + msg); 103 | 104 | if (!MsgMute) { 105 | if (UseSay) Say(msg); 106 | 107 | if (UseAlexa) { 108 | if (AlexaId != "") setState("alexa2.0.Echo-Devices." + AlexaId + ".Commands.announcement"/*announcement*/, msg); 109 | }; 110 | 111 | if (UseEventLog) { 112 | WriteEventLog(msg); 113 | }; 114 | 115 | if (UseTelegram) { 116 | sendTo("telegram.0", "send", { 117 | text: msg 118 | }); 119 | }; 120 | 121 | if (UseMail) { 122 | sendTo("email", { 123 | html: msg 124 | }); 125 | }; 126 | }; 127 | } 128 | 129 | function PrepareDps() { 130 | const States = []; // 131 | 132 | //Dps für ValueLists 133 | States[DpCount] = { id: praefix + "TimerTargetValues", initial: "", forceCreation: false, common: { read: true, write: false, name: "Ziele welche geschaltet werden", type: "string", def: "" } }; //Zentrale Source für die Anzeige in vis, Erstellung in der TimerRoot 134 | DpCount++; 135 | States[DpCount] = { id: praefix + "TimerTargetText", initial: "", forceCreation: false, common: { read: true, write: false, name: "Smartnames für die Ziele", type: "string", def: "" } }; 136 | DpCount++; 137 | States[DpCount] = { id: praefix + "ModeValues", initial: "", forceCreation: false, common: { read: true, write: false, name: "Werte für ModeListenfeld", type: "string", def: "" } }; 138 | DpCount++; 139 | States[DpCount] = { id: praefix + "ModeText", initial: "", forceCreation: false, common: { read: true, write: false, name: "Bezeichnungen für ModeListenfeld", type: "string", def: "" } }; 140 | DpCount++; 141 | States[DpCount] = { id: praefix + "AktionValues", initial: "", forceCreation: false, common: { read: true, write: false, name: "Werte für AktionListenfeld", type: "string", def: "" } }; 142 | DpCount++; 143 | States[DpCount] = { id: praefix + "AktionText", initial: "", forceCreation: false, common: { read: true, write: false, name: "Bezeichnungen für AktionListenfeld", type: "string", def: "" } }; 144 | DpCount++; 145 | States[DpCount] = { id: praefix + "TimerCountValues", initial: "", forceCreation: false, common: { read: true, write: false, name: "Werte für TimerCountListenfeld?", type: "string", def: "" } }; 146 | DpCount++; 147 | States[DpCount] = { id: praefix + "TimerCountText", initial: "", forceCreation: false, common: { read: true, write: false, name: "Bezeichnungen für TimerCountListenfeld", type: "string", def: "" } }; 148 | DpCount++; 149 | 150 | //Diverse Root Dps 151 | States[DpCount] = { id: praefix + "TimerOverviewTable", initial: "", forceCreation: false, common: { read: true, write: false, name: "HTML Übersichtstabelle aller Timer", type: "string", def: "" } }; 152 | DpCount++; 153 | States[DpCount] = { id: praefix + "SwitchToTimer", initial: 0, forceCreation: false, common: { read: true, write: true, name: "Welchen Timer anzeigen/bearbeiten?", type: "number", def: 0 } }; 154 | DpCount++; 155 | States[DpCount] = { id: praefix + "SaveEdit", initial: false, forceCreation: false, common: { read: true, write: true, name: "Einstellungen speichern", type: "boolean", def: false } }; 156 | DpCount++; 157 | States[DpCount] = { id: praefix + "AddTimer", initial: false, forceCreation: false, common: { read: true, write: true, name: "Timer hinzufügen", type: "boolean", def: false } }; 158 | DpCount++; 159 | States[DpCount] = { id: praefix + "DelTimerSecCheck", initial: false, forceCreation: false, common: { read: true, write: true, name: "Sicherheitsabfrage Timer löschen", type: "boolean", def: false } }; 160 | DpCount++; 161 | States[DpCount] = { id: praefix + "DelTimer", initial: false, forceCreation: false, common: { read: true, write: true, name: "Timer löschen", type: "boolean", def: false } }; 162 | DpCount++; 163 | States[DpCount] = { id: praefix + "TimerCount", initial: TimerCount, forceCreation: false, common: { read: true, write: true, name: "Anzahl der Timer", type: "number", def: TimerCount } }; 164 | DpCount++; 165 | States[DpCount] = { id: praefix + "PresenceFuncAvailable", initial: false, forceCreation: false, common: { read: true, write: false, name: "Anwesenheitsdatenpunkt vorhanden?", type: "boolean", def: false } }; 166 | DpCount++; 167 | States[DpCount] = { id: praefix + "MsgMute", initial: false, forceCreation: false, common: { read: true, write: true, name: "Meldungen stummschalten?", type: "boolean", def: false } }; 168 | DpCount++; 169 | States[DpCount] = { id: praefix + "ActiveTimerCount", initial: 0, forceCreation: false, common: { read: true, write: true, name: "Anzahl der aktiven Timer", type: "number", def: 0 } }; 170 | DpCount++; 171 | States[DpCount] = { id: praefix + "ShowNameEdit", initial: false, forceCreation: false, common: { read: true, write: true, name: "Feld für Smartnameänderung einblenden?", type: "boolean", def: false } }; 172 | DpCount++; 173 | 174 | //Template Dps 175 | States[DpCount] = { id: praefix + "Template" + ".Aktiv", initial: DpDefaults[0], forceCreation: false, common: { read: true, write: true, name: "Timer aktiv", type: "boolean", role: "switch", def: DpDefaults[0] } }; //Legt fest ob der Timer aktiv ist 176 | DpCount++; 177 | States[DpCount] = { id: praefix + "Template" + ".Rolle", initial: DpDefaults[1], forceCreation: false, common: { read: true, write: true, name: "Rolle", type: "number", role: "value", def: DpDefaults[1] } }; //Legt fest ob der Timer für An oder Aus zuständig ist 178 | DpCount++; 179 | States[DpCount] = { id: praefix + "Template" + ".TimerTimestamp", initial: DpDefaults[2], forceCreation: false, common: { read: true, write: true, name: "Zeitstempel für schaltzeit", type: "string", def: DpDefaults[2] } }; 180 | DpCount++; 181 | States[DpCount] = { id: praefix + "Template" + ".TimerAstroTimestamp", initial: DpDefaults[3], forceCreation: false, common: { read: true, write: true, name: "Zeitstempel für Astroschaltzeit", type: "string", def: DpDefaults[3] } }; 182 | DpCount++; 183 | States[DpCount] = { id: praefix + "Template" + ".TimerAstroShift", initial: DpDefaults[4], forceCreation: false, common: { read: true, write: true, name: "Zeitverschiebung für Astroschaltzeit", type: "number", def: DpDefaults[4] } }; 184 | DpCount++; 185 | States[DpCount] = { id: praefix + "Template" + ".TimerChoice", initial: DpDefaults[5], forceCreation: false, common: { read: true, write: true, name: "Funktionswahl für Timer/Astro", type: "string", def: DpDefaults[5] } }; //Gewählte Funktion, Timer oder Astro 186 | DpCount++; 187 | 188 | for (let y = 0; y < 7; y++) { //Einträge für jeden Wochentag anlegen 189 | States[DpCount] = { id: praefix + "Template" + ".Timer" + Wochentage[y], initial: DpDefaults[(y + 6)], forceCreation: false, common: { read: true, write: true, name: Wochentage[y], type: "boolean", role: "switch", def: DpDefaults[(y + 6)] } }; 190 | DpCount++; 191 | }; 192 | States[DpCount] = { id: praefix + "Template" + ".SwitchTarget", initial: DpDefaults[13], forceCreation: false, common: { read: true, write: true, name: "Ziel für Schaltvorgang", type: "string", def: DpDefaults[13] } }; 193 | DpCount++; 194 | States[DpCount] = { id: praefix + "Template" + ".OnlyIfPresence", initial: DpDefaults[14], forceCreation: false, common: { read: true, write: true, name: "Nur ausführen falls jemand anwesend", type: "boolean", role: "switch", def: DpDefaults[14] } }; //Legt fest ob der Timer aktiv ist 195 | DpCount++; 196 | States[DpCount] = { id: praefix + "Template" + ".OnlyIfNoPresence", initial: DpDefaults[15], forceCreation: false, common: { read: true, write: true, name: "Nur ausführen falls niemand anwesend", type: "boolean", role: "switch", def: DpDefaults[15] } }; //Legt fest ob der Timer aktiv ist 197 | DpCount++; 198 | States[DpCount] = { id: praefix + "Template" + ".ActivityMessage", initial: DpDefaults[16], forceCreation: false, common: { read: true, write: true, name: "Benachrichtigen bei Schaltung?", type: "boolean", role: "switch", def: DpDefaults[16] } }; //Legt fest ob der Timer aktiv ist 199 | DpCount++; 200 | States[DpCount] = { id: praefix + "Template" + ".SwitchTargetSmartName", initial: DpDefaults[17], forceCreation: false, common: { read: true, write: true, name: "Name für Ziel", type: "string", def: DpDefaults[17] } }; 201 | DpCount++; 202 | States[DpCount] = { id: praefix + "Template" + ".SendValue", initial: DpDefaults[18], forceCreation: false, common: { read: true, write: true, name: "Zu sendender Wert", type: "string", def: DpDefaults[18] } }; 203 | DpCount++; 204 | States[DpCount] = { id: praefix + "Template" + ".RuleVal1", initial: DpDefaults[19], forceCreation: false, common: { read: true, write: true, name: "Vergleichswert1", type: "string", def: DpDefaults[19] } }; 205 | DpCount++; 206 | States[DpCount] = { id: praefix + "Template" + ".RuleOperator", initial: DpDefaults[20], forceCreation: false, common: { read: true, write: true, name: "Zu sendender Wert", type: "string", def: DpDefaults[20] } }; 207 | DpCount++; 208 | States[DpCount] = { id: praefix + "Template" + ".RuleVal2", initial: DpDefaults[21], forceCreation: false, common: { read: true, write: true, name: "Vergleichswert2", type: "string", def: DpDefaults[21] } }; 209 | DpCount++; 210 | 211 | //Alle States anlegen, Main aufrufen wenn fertig 212 | let numStates = States.length; 213 | States.forEach(function (state) { 214 | createState(state.id, state.initial, state.forceCreation, state.common, function () { 215 | numStates--; 216 | if (numStates === 0) { 217 | if (logging) log("Initial CreateStates finished!"); 218 | main(); 219 | }; 220 | }); 221 | }); 222 | } 223 | 224 | function CreateTimer(x) { //Erzeugt Timerchannel und Dps. Aufruf bei Start und AddTimer 225 | //if (logging) log("Reaching CreateTimer, x=" + x) 226 | 227 | const States = []; 228 | DpCount = 0; 229 | //Datenpunkte anlegen 230 | States[DpCount] = { id: praefix + x + ".Aktiv", initial: DpDefaults[0], forceCreation: false, common: { read: true, write: true, name: "Timer aktiv", type: "boolean", role: "switch", def: DpDefaults[0] } }; //Legt fest ob der Timer aktiv ist 231 | DpCount++; 232 | States[DpCount] = { id: praefix + x + ".Rolle", initial: DpDefaults[1], forceCreation: false, common: { read: true, write: false, name: "Rolle", type: "number", role: "value", def: DpDefaults[1] } }; //Legt fest ob der Timer für An oder Aus zuständig ist 233 | DpCount++; 234 | States[DpCount] = { id: praefix + x + ".TimerTimestamp", initial: DpDefaults[2], forceCreation: false, common: { read: true, write: false, name: "Zeitstempel für schaltzeit", type: "string", def: DpDefaults[2] } }; 235 | DpCount++; 236 | States[DpCount] = { id: praefix + x + ".TimerAstroTimestamp", initial: DpDefaults[3], forceCreation: false, common: { read: true, write: false, name: "Zeitstempel für Astroschaltzeit", type: "string", def: DpDefaults[3] } }; 237 | DpCount++; 238 | States[DpCount] = { id: praefix + x + ".TimerAstroShift", initial: DpDefaults[4], forceCreation: false, common: { read: true, write: false, name: "Zeitverschiebung für Astroschaltzeit", type: "number", def: DpDefaults[4] } }; 239 | DpCount++; 240 | States[DpCount] = { id: praefix + x + ".TimerChoice", initial: DpDefaults[5], forceCreation: false, common: { read: true, write: false, name: "Funktionswahl für Timer/Astro", type: "string", def: DpDefaults[5] } }; //Gewählte Funktion, Timer oder Astro 241 | DpCount++; 242 | 243 | for (let y = 0; y < 7; y++) { //Einträge für jeden Wochentag anlegen 244 | States[DpCount] = { id: praefix + x + ".Timer" + Wochentage[y], initial: DpDefaults[(y + 6)], forceCreation: false, common: { read: true, write: false, name: Wochentage[y], type: "boolean", role: "switch", def: DpDefaults[(y + 6)] } }; 245 | DpCount++; 246 | }; 247 | States[DpCount] = { id: praefix + x + ".SwitchTarget", initial: DpDefaults[13], forceCreation: false, common: { read: true, write: false, name: "Ziel für Schaltvorgang", type: "string", def: DpDefaults[13] } }; 248 | DpCount++; 249 | States[DpCount] = { id: praefix + x + ".OnlyIfPresence", initial: DpDefaults[14], forceCreation: false, common: { read: true, write: false, name: "Nur ausführen falls jemand anwesend", type: "boolean", role: "switch", def: DpDefaults[14] } }; //Legt fest ob der Timer aktiv ist 250 | DpCount++; 251 | States[DpCount] = { id: praefix + x + ".OnlyIfNoPresence", initial: DpDefaults[15], forceCreation: false, common: { read: true, write: false, name: "Nur ausführen falls niemand anwesend", type: "boolean", role: "switch", def: DpDefaults[15] } }; //Legt fest ob der Timer aktiv ist 252 | DpCount++; 253 | States[DpCount] = { id: praefix + x + ".ActivityMessage", initial: DpDefaults[16], forceCreation: false, common: { read: true, write: false, name: "Nur ausführen falls niemand anwesend", type: "boolean", role: "switch", def: DpDefaults[16] } }; //Legt fest ob der Timer aktiv ist 254 | DpCount++; 255 | States[DpCount] = { id: praefix + x + ".SwitchTargetSmartName", initial: DpDefaults[17], forceCreation: false, common: { read: true, write: true, name: "Name für Ziel", type: "string", def: DpDefaults[17] } }; 256 | DpCount++; 257 | States[DpCount] = { id: praefix + x + ".SendValue", initial: DpDefaults[18], forceCreation: false, common: { read: true, write: true, name: "Zu sendender Wert", type: "string", def: DpDefaults[18] } }; 258 | DpCount++; 259 | States[DpCount] = { id: praefix + x + ".RuleVal1", initial: DpDefaults[19], forceCreation: false, common: { read: true, write: true, name: "Vergleichswert1", type: "string", def: DpDefaults[19] } }; 260 | DpCount++; 261 | States[DpCount] = { id: praefix + x + ".RuleOperator", initial: DpDefaults[20], forceCreation: false, common: { read: true, write: true, name: "Zu sendender Wert", type: "string", def: DpDefaults[20] } }; 262 | DpCount++; 263 | States[DpCount] = { id: praefix + x + ".RuleVal2", initial: DpDefaults[21], forceCreation: false, common: { read: true, write: true, name: "Vergleichswert2", type: "string", def: DpDefaults[21] } }; 264 | DpCount++; 265 | 266 | //Alle States anlegen, aufrufen wenn fertig 267 | let numStates = States.length; 268 | States.forEach(function (state) { 269 | createState(state.id, state.initial, state.forceCreation, state.common, function () { 270 | numStates--; 271 | if (numStates === 0) { //Sicherstellen das alle Dps erzeugt wurden bevor eingelesen wird 272 | if (logging) log("Timer CreateState(s) finished!"); 273 | FillTimerArray(x); 274 | FillTimerTemplateArray(); 275 | }; 276 | }); 277 | }); 278 | } 279 | 280 | 281 | function FillTimerArray(x) { //Erzeugt TimerArray. Aufruf bei Start und AddTimer 282 | //if (logging) log("Reaching FillTimerArray, x=" + x) 283 | MyTimer[x] = []; 284 | let temp; 285 | for (let y = 0; y < Dps.length; y++) { 286 | MyTimer[x][y] = getState(praefix + x + "." + Dps[y]).val; 287 | if (y == 4) MyTimer[x][y] = parseInt(MyTimer[x][y]); //Sicherstellen das Offset Zahl ist 288 | if (y == 0 && MyTimer[x][y]) ActiveTimerCount++; 289 | }; 290 | 291 | setState(praefix + "ActiveTimerCount", ActiveTimerCount); //Zähler der aktiven Timer in Dp schreiben 292 | 293 | if (MyTimer[x][13] != "" && TriggerArray.indexOf(MyTimer[x][13]) == -1) { //Wenn Ziel nicht leer und Ziel ist noch nicht in Triggerarray 294 | CreateDeviceTrigger(TriggerArray.push(MyTimer[x][13]) - 1); //Ziel zu Triggerarray hinzufügen und mit Rückgemeldeten Index Trigger erstellen 295 | }; 296 | 297 | if (MyTimer[x][17] == "" && MyTimer[x][13] != "") { //Wenn Smartname nicht vorhanden und Ziel nicht leer, auf default setzen 298 | temp = GetParentId(MyTimer[x][13]) 299 | if (temp != "" && typeof temp != "undefined") { 300 | MyTimer[x][17] = getObject(temp, "common").common.name; 301 | } else { 302 | MyTimer[x][17] = ""; 303 | }; 304 | setState(praefix + x + ".SwitchTargetSmartName", MyTimer[x][17]); 305 | }; 306 | 307 | if (MyTimer[x][13] == "") { 308 | MyTimer[x][Dps.length] = "disabled"; //Zusätzlichen internen Eintrag [18] für Tabellenstatus anhängen - disabled wenn Timer inaktiv 309 | } 310 | else { 311 | MyTimer[x][Dps.length] = "idle"; //Idle wenn Timer aktiv 312 | }; 313 | 314 | MyTimer[x][Dps.length + 1] = false; //Weiteren Status [19] für IsEdit anhängen 315 | //20 aktuell unbenutzt 316 | MyTimer[x][Dps.length + 3] = null; //Weiteren Status [21] für TimerAction (TimerobjektArray für Schedule) anhängen 317 | 318 | SetTimer(x, false); //Timer setzen 319 | 320 | if (x == TimerCount - 1) { //Erst bei letztem Eintrag Tabelle refreshen (bei Skriptstart relevant) 321 | CreateTimerTargetsNameList(); 322 | 323 | MakeTable(); 324 | }; 325 | } 326 | 327 | function FillTimerTemplateArray() { //Liest die gepeicherten Templatedaten ein 328 | for (let x = 0; x < Dps.length; x++) { 329 | MyTimerTemplate[x] = getState(praefix + "Template" + "." + Dps[x]).val; 330 | if (x == 4) MyTimerTemplate[x] = parseInt(MyTimerTemplate[x]); //Sicherstellen das Offset Zahl ist 331 | }; 332 | } 333 | 334 | function ConvertPresence(TempPresence = true) {//Wert vom Anwesenheitsdatenpunkt konvertieren falls Nummer, true als default. 335 | if (logging) log("Reaching ConvertPresence. TempPresence=" + TempPresence) 336 | if (PresenceDp != "") { 337 | setState(praefix + "PresenceFuncAvailable", true, true); //Anwesenheitsfunktion vorhanden Datenpunkt aktivieren um Buttons in Vis anzuzeigen 338 | TempPresence = getState(PresenceDp).val; 339 | switch (typeof (TempPresence)) { 340 | case "number": 341 | if (TempPresence == 0) Presence = false; 342 | break; 343 | case "boolean": 344 | Presence = TempPresence; 345 | break; 346 | }; 347 | } else { 348 | setState(praefix + "PresenceFuncAvailable", false, true);//Anwesenheitsfunktion vorhanden Datenpunkt deaktivieren um Buttons in Vis anzuzeigen 349 | }; 350 | } 351 | 352 | function CreateTimerCountList() { //Erzeugt Werte für Timer Valuelists (Vis) 353 | if (logging) log("Reaching CreateTimerCountList()") 354 | 355 | //Timerauswahl ValueList 356 | let ValueDummy = ""; 357 | let ValueTextDummy = ""; 358 | 359 | for (let x = 0; x < TimerCount; x++) { 360 | ValueDummy += x + ";"; 361 | ValueTextDummy += (x + 1) + ";"; 362 | }; 363 | 364 | ValueDummy = ValueDummy.substr(0, ValueDummy.length - 1); 365 | ValueTextDummy = ValueTextDummy.substr(0, ValueTextDummy.length - 1); 366 | 367 | //Timer ValueList 368 | setState(praefix + "TimerCountValues", ValueDummy, true); 369 | setState(praefix + "TimerCountText", ValueTextDummy, true); 370 | } 371 | 372 | function SetValueListPairs() { //Erzeugt Werte und Texte für Timer Value Listenfeld (Vis) 373 | if (logging) log("Reaching SetValueListPairs()"); 374 | 375 | //Mode ValueList 376 | setState(praefix + "ModeValues", ModeValues.join(";"), true); 377 | setState(praefix + "ModeText", ModeText.join(";"), true); 378 | 379 | //Aktion ValueList 380 | setState(praefix + "AktionValues", AktionValues.join(";"), true); 381 | setState(praefix + "AktionText", AktionText.join(";"), true); 382 | } 383 | 384 | function CreateTimerTargetsNameList() { //Ermittelt Channelnamen, oder Smartnamen wenn vorhanden 385 | if (logging) log("Reaching CreateTimerTargetsNameList()") 386 | 387 | let NewTargetNames = TargetNames.join(";").split(";"); 388 | //log(TargetNames.join(";").split(";")); 389 | 390 | for (let x = 0; x < Targets.length; x++) { //Alle Ziele durchgehen, im ersten Durchlauf Liste erzeugen 391 | for (let y = 0; y < TimerCount; y++) { //Alle Timer 392 | if (MyTimer[y][13] == Targets[x]) { //Wenn Switchtarget entspricht einem Eintrag in der Targetslist 393 | if (MyTimer[y][17] != TargetNames[x] && MyTimer[y][17] != "") { // und Smartname entspricht nicht dem Orig. Namen 394 | NewTargetNames[x] = MyTimer[y][17]; //NewTargetNames korrigieren 395 | //log("NewTargetNames[" + x + "] " + TargetNames[x] + " corrected to " + MyTimer[y][17] + " y=" + y) 396 | } 397 | }; 398 | }; 399 | }; 400 | 401 | for (let x = 0; x < Targets.length; x++) { //Alle Ziele und Timer durchgehen, im 2. Durchlauf alle TimerSmartnames anpassen wenn nötig 402 | for (let y = 0; y < TimerCount; y++) { 403 | if (MyTimer[y][13] == Targets[x]) { //Wenn Switchtarget entspricht einem Eintrag in der Targetslist 404 | if (MyTimer[y][17] != NewTargetNames[x]) { //Aktueller Smartname entspricht nicht der Liste 405 | log("Smartname synchronisiert x=" + x + " y=" + y + " AlterSmartname=" + MyTimer[y][17] + " neuer Smartname=" + NewTargetNames[x]) 406 | MyTimer[y][17] = NewTargetNames[x]; 407 | setState(praefix + y + ".SwitchTargetSmartName", MyTimer[y][17]); 408 | }; 409 | }; 410 | }; 411 | }; 412 | 413 | if (logging) log("Original TargetNames are:" + TargetNames); 414 | 415 | TargetNames = NewTargetNames; 416 | 417 | setState(praefix + "TimerTargetValues", Targets.join(";"), true); //Datenpunkt für Vis Listenfeld füllen 418 | setState(praefix + "TimerTargetText", NewTargetNames.join(";"), true); //Datenpunkt für Vis Listenfeld füllen 419 | 420 | if (logging) log("Possible Target are:" + Targets); 421 | if (logging) log("New TargetNames are:" + NewTargetNames); 422 | } 423 | 424 | function init() { 425 | if (logging) log("Reaching Init()"); 426 | // 0 1 2 3 4 5 6 7 8 9 427 | //"Aktiv", "Rolle", "TimerTimestamp", "TimerAstroTimestamp", "TimerAstroShift", "TimerChoice", "TimerSonntag", "TimerMontag", "TimerDienstag", "TimerMittwoch", 428 | 429 | // 10 11 12 13 14 15 16 17 18 19 (+0) 20 (+1) 21 (+2) 22 (+3) 430 | // "TimerDonnerstag", "TimerFreitag", "TimerSamstag", "SwitchTarget", "OnlyIfPresence", "OnlyIfNoPresence","ActivityMessage","SmartName", "SendValue", "TabellenStatus", "IsEdit","unused","TimerAktion" 431 | 432 | TimerCount = getState(praefix + "TimerCount").val; // Initialen Timercount mit im Dp gespeicherten Wert korrigieren 433 | ChoosenTimer = getState(praefix + "SwitchToTimer").val; //Aktuell (in Vis) gewählter Timer 434 | MsgMute = getState(praefix + "MsgMute").val; 435 | 436 | for (let x in Funktionen) { // loop ueber alle Functions - Erzeugt Listen mit TimerTargets und deren Namen 437 | let Funktion = Funktionen[x].name; 438 | if (Funktion == undefined) { 439 | log("Keine Funktion gefunden!", "error"); 440 | } 441 | else { 442 | if (typeof Funktion == 'object') Funktion = Funktion.de; 443 | let members = Funktionen[x].members; 444 | if (Funktion == WelcheFunktionVerwenden) { //Wenn Function ist z.B. TimerTarget 445 | for (let y in members) { // Loop über alle TimerTarget Members 446 | Targets[y] = members[y]; 447 | log("GetParentId(Targets[y])=" + GetParentId(Targets[y])) 448 | if (UseChannelNames) { 449 | TargetNames[y] = getObject(GetParentId(Targets[y]), "common").common.name; 450 | if (typeof getObject(GetParentId(Targets[y]), "common").common.name == 'object') TargetNames[y] = getObject(GetParentId(Targets[y]), "common").common.name.de 451 | } else { 452 | TargetNames[y] = getObject(Targets[y], "common").common.name; 453 | } 454 | }; 455 | log(Targets.length + " Targets found - Targets are: " + Targets); 456 | log("Names are: " + TargetNames); 457 | 458 | setState(praefix + "TimerTargetValues", Targets.join(";"), true); //Datenpunkt für Vis Listenfeld füllen 459 | setState(praefix + "TimerTargetText", TargetNames.join(";"), true); //Datenpunkt für Vis Listenfeld füllen 460 | }; 461 | }; 462 | }; 463 | 464 | //Alle Daten in MyTimer Array einlesen 465 | for (let x = 0; x < TimerCount; x++) { 466 | CreateTimer(x); //Erzeugt alle Timerchannels und Dps und liest diese in Array ein 467 | }; 468 | } 469 | 470 | //**************************** 471 | function main() { 472 | if (logging) log("Reaching Main"); 473 | init(); 474 | CreateTimerCountList(); 475 | SetValueListPairs(); 476 | ConvertPresence(); 477 | CreateTrigger(); 478 | } 479 | 480 | function GetParentId(DpId) { //Liest Id des dem DP übergeordnetem Channel 481 | //if (logging) log("Reaching GetParentId, Id=" + DpId); 482 | if (DpId == "") return ""; //Wenn Id leer, Abbruch (neuer Timer) 483 | let parentDevicelId; 484 | if (DpId.indexOf("scene.") != -1) { //Wenn scene in Objektlistenroot keine Ebene zurück 485 | parentDevicelId = DpId; 486 | } 487 | else if (DpId.indexOf("hm-rpc.") != -1 || DpId.indexOf("shelly.") != -1 || DpId.indexOf("yeelight-2.") != -1) { //Wenn HM, shelly oder yeelight, 2 Ebenen zurück 488 | parentDevicelId = DpId.split(".").slice(0, -2).join(".");// Id an den Punkten in Array schreiben (split), die 2 letzten Elemente von hinten entfernen (slice) und den Rest wieder zu String zusammensetzen (join) 489 | } 490 | else { //Ansonsten 1 Ebene zurück 491 | parentDevicelId = DpId.split(".").slice(0, -1).join("."); // Id an den Punkten in Array schreiben (split), das letzte Element von hinten entfernen (slice) und den Rest wieder zu String zusammensetzen (join) 492 | }; 493 | //if (logging) log("DpId= " + DpId + " ParentDeviceId=" + parentDevicelId); 494 | return parentDevicelId; 495 | } 496 | 497 | function GetDeviceName(DeviceId) { //Liest Namen des zum Schaltdatenpunkt gehörenden Devices 498 | //if (logging) log("Reaching GetDeviceName, DeviceId=" + DeviceId + " Typeof=" + typeof (DeviceId)); 499 | if (DeviceId == "") return ""; ///Wenn DeviceId leer (neuer Timer) 500 | return getObject(DeviceId, "common").common.name; 501 | } 502 | 503 | //*********************** Core Functions ********************************* */ 504 | 505 | function CreateTimeDaysString(whichone) { //Erzeugt Teilstring für Cron mit gewählten Tagen für reine Zeittimer 506 | if (logging) log("Reaching CreateTimeDaysString(whichone=" + whichone + ")"); 507 | 508 | let DaysSubString = ""; 509 | for (let x = 0; x < 7; x++) { 510 | if (MyTimer[whichone][x + 6] == true) { //Beginnend mit dem 6ten Eintrag (TimerSonntag) die 7 Wochentage durchzählen und Werte anhängen 511 | DaysSubString += x + ","; 512 | }; 513 | }; 514 | DaysSubString = DaysSubString.substr(0, DaysSubString.length - 1); //Komma am Ende entfernen 515 | 516 | if (DaysSubString == "0,1,2,3,4,5,6") { DaysSubString = "*"; }; // Sternchen wenn alle Tage gewählt 517 | return DaysSubString; 518 | } 519 | 520 | function DetermineNextActiveAstroDay(whichone, GoToTommorrow) {//Erzeugt Teilstring für Cron mit nächstem aktiven Astrotag, sowie die Anzahl der Tage bis nächsten aktiven Astrotag 521 | if (logging) log("Reaching DetermineNextActiveAstroDay(whichone=" + whichone + " GoToTommorrow=" + GoToTommorrow + ")"); 522 | 523 | let TodayDay = formatDate(new Date(), "W"); //Aktuellen Wochentag ermitteln 524 | let TodayDayIndex = WeekdaysShort.indexOf(TodayDay); //Index des aktuellen Wochentags ermitteln 525 | let TodayAstroIsOver; 526 | 527 | if (GoToTommorrow) { 528 | log("GoToTommorrow requested, TodayAstroIsOver automatically set to true, skipping check") 529 | TodayAstroIsOver = true; 530 | } 531 | else { 532 | if (whichone == -1) { //Wenn Aufruf durch Template 533 | TodayAstroIsOver = CheckTodayAstroIsOver(MyTimerTemplate[5], MyTimerTemplate[4]); //Prüfen ob Astroereignis heute schon vorüber 534 | } else { 535 | TodayAstroIsOver = CheckTodayAstroIsOver(MyTimer[whichone][5], MyTimer[whichone][4]); 536 | }; 537 | }; 538 | 539 | let NextActiveDayIndex = TodayDayIndex; // Auswertung bei heutigem Tag beginnen 540 | 541 | if (logging) log("Initial NextActiveDay=" + Wochentage[NextActiveDayIndex] + " =" + NextActiveDayIndex + " TodayAstroIsOver=" + TodayAstroIsOver); 542 | 543 | let FoundNextActiveDay = false; //Marker um nach Schleifendurchlauf noch zu wissen wo der erste Treffer war 544 | let FoundIndex = 0; 545 | let FoundDiff = 0; 546 | for (let x = 0; x < 7; x++) {// 7 Tage durchgehen 547 | if (whichone == -1) { //Aufruf durch Template 548 | if (MyTimerTemplate[NextActiveDayIndex + 6] == true && !FoundNextActiveDay) { //Wenn counter Tag ist aktiv und nächster aktiver Tag noch nicht gefunden 549 | //if (logging) log("Called from Template, NextActiveDay=" + Wochentage[NextActiveDayIndex] + " =" + NextActiveDayIndex + " DayDiff=" + x); 550 | if (x == 0 && (TodayAstroIsOver)) { //Wenn Treffer ist heute, und Event bereits vorüber 551 | FoundIndex = NextActiveDayIndex + 1; 552 | FoundDiff = x + 1; 553 | if (logging) log("NextActiveDay=today and TodayAstroIsOver=" + TodayAstroIsOver + " and GoToTommorrow=" + GoToTommorrow); 554 | } else { 555 | FoundIndex = NextActiveDayIndex; 556 | FoundDiff = x; 557 | if (logging) log("NextActiveDayIndex=" + NextActiveDayIndex + " and x=" + x + " and TodayAstroIsOver=" + TodayAstroIsOver + " and GoToTommorrow=" + GoToTommorrow); 558 | } 559 | FoundNextActiveDay = true; 560 | }; 561 | } 562 | else { //Aufruf durch Timer 563 | if (MyTimer[whichone][NextActiveDayIndex + 6] == true && !FoundNextActiveDay) { //Wenn counter Tag ist aktiv 564 | //if (logging) log("Called from Timer, NextActiveDay=" + Wochentage[NextActiveDayIndex] + " =" + NextActiveDayIndex + " DayDiff=" + x); 565 | if (x == 0 && (TodayAstroIsOver)) { //Wenn Treffer ist heute, dann prüfen ob Event bereits vorüber 566 | FoundIndex = NextActiveDayIndex + 1; 567 | FoundDiff = x + 1; 568 | if (logging) log("NextActiveDay=today and TodayAstroIsOver=" + TodayAstroIsOver + " and GoToTommorrow=" + GoToTommorrow); 569 | } else { 570 | FoundIndex = NextActiveDayIndex; 571 | FoundDiff = x; 572 | if (logging) log("NextActiveDayIndex=" + NextActiveDayIndex + " and x=" + x + " and TodayAstroIsOver=" + TodayAstroIsOver + " and GoToTommorrow=" + GoToTommorrow); 573 | } 574 | FoundNextActiveDay = true; 575 | }; 576 | }; 577 | 578 | if (NextActiveDayIndex > 6) { //Bei Wochensprung 579 | NextActiveDayIndex = 0; 580 | } else { 581 | NextActiveDayIndex++; 582 | }; 583 | }; 584 | 585 | if (FoundIndex > 6) FoundIndex = 0; 586 | if (logging) log("Returning FoundIndex=" + FoundIndex + " FoundDiff=" + FoundDiff); 587 | return [String(FoundIndex), FoundDiff]; //Index und Tagesdifferenz als Array zurückgeben 588 | } 589 | 590 | function MakeCronString(whichone, NextActiveDayIndex) { //String nach Cronsyntax zusammenbauen für Schedule. 591 | if (logging) log("Reaching MakeCronString(whichone=" + whichone + ")"); 592 | let CronString = ""; 593 | if (MyTimer[whichone][5] == "time") { //Wenn Zeit gewählt 594 | CronString = SplitTime(MyTimer[whichone][2])[2] + " " + SplitTime(MyTimer[whichone][2])[1] + " " + SplitTime(MyTimer[whichone][2])[0] + " * * " + NextActiveDayIndex; 595 | if (logging) log("CronString for Timer " + (whichone + 1) + " created " + CronString); 596 | } 597 | else if (MyTimer[whichone][5] != "time") { //Wenn Astro gewählt 598 | CronString = SplitTime(MyTimer[whichone][3])[2] + " " + SplitTime(MyTimer[whichone][3])[1] + " " + SplitTime(MyTimer[whichone][3])[0] + " * * " + NextActiveDayIndex; 599 | if (logging) log("Cronstring for Timer " + (whichone + 1) + " Astro created " + CronString); 600 | }; 601 | return CronString; 602 | } 603 | 604 | 605 | function SetTimer(whichone, GoToTommorrow) { //spezifischen Timer setzen 606 | if (logging) log("Reaching SetTimer(whichone=," + whichone + " GoToTommorrow=" + GoToTommorrow + ")"); 607 | 608 | if (MyTimer[whichone][0] == true) { //Wenn Timer aktiv 609 | if (logging) log("Timer " + (whichone + 1) + " will be set, GoToTommorrow=" + GoToTommorrow); 610 | let NextActiveDay; 611 | if (MyTimer[whichone][5] != "time") { //Wenn Astro gewählt 612 | NextActiveDay = DetermineNextActiveAstroDay(whichone, GoToTommorrow); //Array mit nächstem Astrotag als Index und Differenz zu heute 0=Index 1=Diff 613 | let NewAstroTime = DetermineChoosenAstroTime(MyTimer[whichone][5].trim(), NextActiveDay[1], MyTimer[whichone][4]); //Neue Astrozeit generieren nach Ausführung 614 | setState(praefix + whichone + "." + Dps[3], NewAstroTime, true); 615 | MyTimer[whichone][3] = NewAstroTime; 616 | } else { 617 | NextActiveDay = [CreateTimeDaysString(whichone)]; 618 | }; 619 | 620 | MyTimer[whichone][(Dps.length + 3)] = schedule(MakeCronString(whichone, NextActiveDay[0]), function () { //Cronstring erzeugen und Schedule setzen sowie Objektvariablen TimerAktion zuweisen 621 | DoAction(whichone); //Geplante Aktion ausführen 622 | if (MyTimer[whichone][5] != "time") { //Wenn Astro gewählt 623 | if (KillTimer(whichone)) SetTimer(whichone, true); //Neuen Schedule anlegen (selbstaufruf der Funktion) für nächsten aktiven Tag und vorher alten Timer löschen 624 | }; 625 | }); 626 | }; 627 | } 628 | 629 | function KillTimer(whichone) { //spezifischen Timer löschen 630 | if (typeof (MyTimer[whichone][(Dps.length + 3)]) == "object") { 631 | clearSchedule(MyTimer[whichone][(Dps.length + 3)]); 632 | if (logging) log("Timer Schedule " + (whichone + 1) + " killed"); 633 | }; 634 | return true; // 635 | } 636 | 637 | function CheckTodayAstroIsOver(AstroChoice, Shift) { //Berücksichtigen ob Event schon vorbei ist und dann für morgen setzen 638 | if (logging) log("Reaching CheckTodayAstroIsOver(AstroChoice=" + AstroChoice + " Shift=" + Shift + ")"); 639 | Shift = parseInt(Shift); //Sicherstellen dass Shift eine Zahl ist 640 | //let today = new Date(); 641 | let jetzt = new Date(); 642 | 643 | let AstroTime = getAstroDate(AstroChoice); //Heutige Astrotime einlesen 644 | AstroTime.setMinutes(AstroTime.getMinutes() + Shift);//zammrechna 645 | 646 | //log("Astrotime=" + AstroTime.getTime() + " jetzt=" + jetzt.getTime()) 647 | if (AstroTime.getTime() <= jetzt.getTime()) { //Wenn Astrozeit vor aktueller Zeit, ist Event vorüber 648 | if (logging) log("Es ist " + jetzt.toLocaleTimeString('de-DE', { hour12: false }) + ", Astroevent today passed by at: " + getAstroDate(AstroChoice).toLocaleTimeString('de-DE', { hour12: false })); 649 | return true; 650 | } 651 | else { //Wenn Astrozeit nach aktueller Zeit dann Astrozeit von heute verwenden 652 | if (logging) log("Es ist " + jetzt.toLocaleTimeString('de-DE', { hour12: false }) + ", Astroevent today is still upcoming at: " + getAstroDate(AstroChoice).toLocaleTimeString('de-DE', { hour12: false })); 653 | return false; 654 | }; 655 | } 656 | 657 | function DetermineChoosenAstroTime(AstroChoice, AddDays, Shift) { //Zeit für gewählte Astrozeit ermitteln 658 | if (logging) log("Reaching DetermineChoosenAstroTime( AstroChoice=" + AstroChoice + " AddDays=" + AddDays + " Shift=" + Shift + ")"); 659 | //Berücksichtigen ob Event schon vorbei ist und dann für morgen setzen 660 | Shift = parseInt(Shift); //Sicherstellen dass Shift eine Zahl ist 661 | let today = new Date(); 662 | //let jetzt = new Date(); 663 | let NextActiveDay = today.setDate(today.getDate() + AddDays); 664 | let NextActiveDayAstroTime = getAstroDate(AstroChoice, NextActiveDay); 665 | NextActiveDayAstroTime.setMinutes(NextActiveDayAstroTime.getMinutes() + Shift);//zammrechna 666 | if (logging) log(AstroChoice + " today starts at:" + getAstroDate(AstroChoice).toLocaleTimeString('de-DE', { hour12: false }) + " and starts next active day at " + NextActiveDayAstroTime.toLocaleTimeString('de-DE', { hour12: false })); 667 | 668 | if (logging) log("Returning next active Astrotime=" + NextActiveDayAstroTime.toLocaleTimeString('de-DE', { hour12: false })); 669 | if (NextActiveDayAstroTime.toLocaleTimeString('de-DE', { hour12: false }).length == 7) { //Einstellige Stundenzahl korrigieren 670 | return "0" + NextActiveDayAstroTime.toLocaleTimeString('de-DE', { hour12: false }); 671 | } 672 | else { 673 | return NextActiveDayAstroTime.toLocaleTimeString('de-DE', { hour12: false }); 674 | }; 675 | } 676 | 677 | function CheckRule(whichone) { 678 | if (logging) log("Reaching CheckRule, Val1=" + MyTimer[whichone][19] + " Operator=" + MyTimer[whichone][20] + " Val2=" + MyTimer[whichone][21]); 679 | let tempVal1; 680 | let tempVal2; 681 | if (MyTimer[whichone][19] == "" || MyTimer[whichone][20] == "" || MyTimer[whichone][21] == "") { //Wenn auch nur eins der Vergleichsfelder leer, Abbruch 682 | return true; 683 | }; 684 | 685 | if (existsState(MyTimer[whichone][19])) { 686 | tempVal1 = getState(MyTimer[whichone][19]).val; //Wenn der Wert im Feld 1 eine ID ist, Wert lesen, ansonsten Abbruch (erster Wert MUSS ID sein) 687 | } else { 688 | return true; 689 | }; 690 | 691 | if (existsState(MyTimer[whichone][21])) { 692 | tempVal2 = getState(MyTimer[whichone][21]).val;//Wenn der Wert im Feld 2 eine ID ist, Wert lesen, ansonsten Inhalt=Wert 693 | } else { 694 | tempVal2 = MyTimer[whichone][21]; 695 | 696 | if (parseFloat(tempVal2) != NaN) { //Datentypen konvertieren wenn möglich 697 | tempVal2 = parseFloat(tempVal2); 698 | } else if (tempVal2 == "true") { 699 | tempVal2 = true; 700 | } else if (tempVal2 == "false") { 701 | tempVal2 = false; 702 | }; 703 | }; 704 | 705 | switch (MyTimer[whichone][20]) { 706 | case "<": 707 | if (tempVal1 < tempVal2) { 708 | return true; 709 | } else { 710 | return false; 711 | }; 712 | break; 713 | case "<=": 714 | if (tempVal1 <= tempVal2) { 715 | return true; 716 | } else { 717 | return false; 718 | }; 719 | break; 720 | case ">": 721 | if (tempVal1 > tempVal2) { 722 | return true; 723 | } else { 724 | return false; 725 | }; 726 | break; 727 | case ">=": 728 | if (tempVal1 >= tempVal2) { 729 | return true; 730 | } else { 731 | return false; 732 | }; 733 | break; 734 | case "=": 735 | if (tempVal1 == tempVal2) { 736 | return true; 737 | } else { 738 | return false; 739 | }; 740 | break; 741 | case "!=": 742 | if (tempVal1 != tempVal2) { 743 | return true; 744 | } else { 745 | return false; 746 | }; 747 | break; 748 | default: 749 | return true; 750 | }; 751 | 752 | 753 | } 754 | 755 | function DoAction(whichone) { //Hier wird geschaltet, Zentralfunktion 756 | if (logging) log("Reaching DoAction(), aktiv=" + MyTimer[whichone][0] + " Rolle=" + MyTimer[whichone][1] + " whichone=" + whichone + " Presence=" + Presence + " MyTimer[whichone][13]=" + MyTimer[whichone][13] + " MyTimer[whichone][14]=" + MyTimer[whichone][14]); 757 | if (MyTimer[whichone][0] == true && CheckRule(whichone)) { //Wenn Timer aktiv und Rule erfüllt (oder keine Rule eingetragen) 758 | if ((MyTimer[whichone][14] == true && Presence == true) || (MyTimer[whichone][15] == true && Presence == false) || (MyTimer[whichone][15] == true && MyTimer[whichone][14] == true)) { //Wenn "bei Anwesenheit" aktiv 759 | TargetSwitchingInProgress = true; 760 | let OldState = getState(MyTimer[whichone][13]).val; 761 | let StateType = typeof OldState; 762 | if (logging) log("StateType from " + MyTimer[whichone][13] + " = " + StateType + " value=" + OldState) 763 | switch (MyTimer[whichone][1]) { 764 | case 0://Wenns die Rolle Ausschalter ist 765 | if (StateType == "string") { 766 | setState(MyTimer[whichone][13], "false");//Switchtarget deaktivieren 767 | } else { 768 | setState(MyTimer[whichone][13], false);//Switchtarget deaktivieren 769 | }; 770 | MyTimer[whichone][(Dps.length + 0)] = "off"; 771 | log("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", switched off"); 772 | if (MyTimer[whichone][16]) Meldung("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", hat ausgeschaltet"); 773 | break; 774 | case 1:// Wenn die Rolle Anschalter ist 775 | if (StateType == "string") { 776 | setState(MyTimer[whichone][13], "true");//Switchtarget deaktivieren 777 | } else { 778 | setState(MyTimer[whichone][13], true);//Switchtarget deaktivieren 779 | }; 780 | MyTimer[whichone][(Dps.length + 0)] = "on"; 781 | log("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", switched on"); 782 | if (MyTimer[whichone][16]) Meldung("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", hat eingeschaltet"); 783 | break; 784 | case 2:// Wenn die Rolle Umschalter ist 785 | if (OldState) { //Aktuellen Targetstatus lesen 786 | if (StateType == "string") { 787 | setState(MyTimer[whichone][13], "false");//Switchtarget deaktivieren 788 | } else { 789 | setState(MyTimer[whichone][13], false);//Switchtarget deaktivieren 790 | }; 791 | MyTimer[whichone][(Dps.length + 0)] = "off"; 792 | log("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", changed over to off"); 793 | if (MyTimer[whichone][16]) Meldung("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", hat (um)-ausgeschaltet"); 794 | } else { 795 | if (StateType == "string") { 796 | setState(MyTimer[whichone][13], "true");//Switchtarget deaktivieren 797 | } else { 798 | setState(MyTimer[whichone][13], true);//Switchtarget deaktivieren 799 | }; 800 | MyTimer[whichone][(Dps.length + 0)] = "on"; 801 | log("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", changed over to on"); 802 | if (MyTimer[whichone][16]) Meldung("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", hat (um)-angeschaltet"); 803 | }; 804 | break; 805 | case 3:// Wenn Rolle ist "Wert senden" 806 | log("MyTimer[whichone][18]=" + MyTimer[whichone][18]) 807 | if (MyTimer[whichone][18] != "" && MyTimer[whichone][18] != "-" && typeof MyTimer[whichone][18] != "undefined") { 808 | setState(MyTimer[whichone][13], ConvertSendValue(MyTimer[whichone][18], StateType)); //Switchtarget Wert senden 809 | MyTimer[whichone][(Dps.length + 0)] = "on"; 810 | log("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", send value " + MyTimer[whichone][18] + " as " + typeof ConvertSendValue(MyTimer[whichone][18], StateType)); 811 | if (MyTimer[whichone][16]) Meldung("Timer " + (whichone + 1) + ", " + GetDeviceName(GetParentId(MyTimer[whichone][13])) + ", send value " + MyTimer[whichone][18] + " as " + typeof ConvertSendValue(MyTimer[whichone][18], StateType)); 812 | 813 | }; 814 | break; 815 | default: 816 | }; 817 | SetLockStates(-1, whichone); //Interne States setzen für Tabellenfarbmarkierungen 818 | }; 819 | }; 820 | } 821 | 822 | function ConvertSendValue(SendValue, StateType) { //Formatiert Wert passend zum Datentyp des Datenpunktes welcher als Target eingestellt ist. 823 | log("Reaching ConvertSendValue") 824 | switch (StateType) { 825 | case "string": 826 | SendValue = String(SendValue) 827 | break; 828 | case "number": 829 | if (parseInt(SendValue) != NaN) SendValue = parseInt(SendValue); 830 | break; 831 | case "boolean": 832 | if (SendValue == "true") SendValue = true; 833 | if (SendValue == "false") SendValue = false; 834 | break; 835 | default: 836 | }; 837 | return SendValue; 838 | } 839 | 840 | function SplitTime(Time) { //Zeit in Stunden und Minuten teilen für Cronstring 841 | let timesplit = Time.split(":"); 842 | //h = timesplit[0] / m = timesplit[1 / s = timesplit[2]]; 843 | if (typeof (timesplit[2]) == "undefined") timesplit[2] = "00"; 844 | return timesplit; 845 | } 846 | 847 | function MakeTable() { 848 | //Bearbeite - Aktiv - Aktion - Mode - Zeit - Offset - Ziel - Tage - wenn anwesend - wenn abwesend 849 | if (logging) log("Reaching MakeTable"); 850 | 851 | let BgColor = ""; 852 | let style0 = "style='border: 1px solid black; padding: 5px 3px; font-size:" + FontSize + "; font-weight: normal; text-align: center; color:" + FontColor + "; background-color:" 853 | let style1 = "style='border: 1px solid black; width: 40px; padding: 5px 3px; font-size:" + FontSize + "; font-weight: normal; text-align: right; color:" + FontColor + "; background-color:" 854 | let ImgColstyle = "style='border: 1px solid black; width: 40px; padding: 0px 5px; font-size:" + FontSize + "; font-weight: normal; text-align: center; color:" + FontColor + "; background-color:" 855 | 856 | let headstyle0 = "style='border: 1px solid black; padding: 0px 5px; height: 30px; font-size:" + HeadFontSize + "; font-weight: bold; text-align: center; color:" + HeadFontColor + "; background-color:" 857 | let ImgColheadstyle = "style='border: 1px solid black; height: 40px; width: 40px; text-align: center; color:" + HeadFontColor + "; background-color:" 858 | 859 | let MyTableHead = ""; 860 | let MyTable; 861 | 862 | if (TblShowTimerLfdCol) { 863 | MyTableHead = MyTableHead + ""; 864 | }; 865 | if (TblShowTimerActiveCol) { 866 | MyTableHead = MyTableHead + ""; 867 | }; 868 | if (TblShowTimerActionCol) { 869 | MyTableHead = MyTableHead + ""; 870 | }; 871 | if (TblShowTimerSendValueCol) { 872 | MyTableHead = MyTableHead + ""; 873 | }; 874 | if (TblShowTimerModeCol) { 875 | MyTableHead = MyTableHead + ""; 876 | }; 877 | 878 | if (TblShowTimerTimeCol) { 879 | MyTableHead = MyTableHead + ""; 880 | }; 881 | if (TblShowTimerAstroOffsetCol) { 882 | MyTableHead = MyTableHead + ""; 883 | }; 884 | if (TblShowTimerTargetCol) { 885 | MyTableHead = MyTableHead + ""; 886 | }; 887 | if (TblShowTimerTargetNameCol) { 888 | MyTableHead = MyTableHead + ""; 889 | }; 890 | if (TblShowTimerDaysCol) { 891 | MyTableHead = MyTableHead + ""; 892 | }; 893 | if (TblShowTimerIfPresenceCol && PresenceDp != "") { 894 | MyTableHead = MyTableHead + ""; 895 | }; 896 | if (TblShowTimerIfPresenceCol && PresenceDp != "") { 897 | MyTableHead = MyTableHead + ""; 898 | }; 899 | if (TblShowTimerMessageCol) { 900 | MyTableHead = MyTableHead + ""; 901 | }; 902 | if (TblShowTimerRuleCol) { 903 | MyTableHead = MyTableHead + ""; 904 | }; 905 | 906 | MyTableHead = MyTableHead + ""; 907 | MyTable = MyTableHead + ""; 908 | 909 | for (let x = 0; x < MyTimer.length; x++) { //Alle Timer durchlaufen 910 | //if (logging) log("MyTimer[" + x + "][17]=" + MyTimer[x][(Dps.length + 0)] + " - TriggerArrayIndex=" + TriggerArray.indexOf(MyTimer[x][13])) 911 | switch (MyTimer[x][(Dps.length + 0)]) { 912 | case "on": 913 | BgColor = TblOnBgColor; 914 | break; 915 | case "off": 916 | BgColor = TblOffBgColor; 917 | break; 918 | case "idle": 919 | BgColor = TblIdleBgColor; 920 | break; 921 | case "disabled": 922 | BgColor = TblDisabledBgColor; 923 | break; 924 | 925 | default: 926 | BgColor = "blue"; 927 | }; 928 | if (ChoosenTimer == x) { 929 | MyTable += "" 930 | } 931 | else { 932 | MyTable += "" 933 | } 934 | if (MyTimer[x][(Dps.length + 1)]) { //Edit in Progress 935 | //log(MyTimer[x][(Dps.length+1)]) 936 | BgColor = TblEditBgColor; 937 | }; 938 | 939 | if (TblShowTimerLfdCol) { 940 | MyTable += ""; 941 | }; 942 | if (TblShowTimerActiveCol) { 943 | if (MyTimer[x][0]) { //Wenn timer aktiv 944 | MyTable += ""; 945 | } 946 | else { 947 | MyTable += ""; 948 | }; 949 | }; 950 | if (TblShowTimerActionCol) { 951 | MyTable += ""; 952 | }; 953 | if (TblShowTimerSendValueCol) { 954 | switch (MyTimer[x][1]) { 955 | case 0: //aus 956 | MyTable += ""; 957 | break; 958 | case 1: //ein 959 | MyTable += ""; 960 | break; 961 | case 2: 962 | MyTable += ""; 963 | break; 964 | case 3: 965 | MyTable += ""; 966 | break; 967 | default: 968 | MyTable += ""; 969 | 970 | }; 971 | }; 972 | 973 | if (TblShowTimerModeCol) { 974 | MyTable += ""; 975 | }; 976 | if (TblShowTimerTimeCol) { 977 | if (MyTimer[x][5] == "time") { 978 | MyTable += ""; 979 | } 980 | else { 981 | MyTable += ""; 982 | } 983 | }; 984 | if (TblShowTimerAstroOffsetCol) { 985 | MyTable += ""; 986 | }; 987 | if (TblShowTimerTargetCol) { 988 | MyTable += ""; 989 | }; 990 | if (TblShowTimerTargetNameCol) { 991 | //log("MyTimer[x][13]=" + MyTimer[x][13] + " x=" + x) 992 | //MyTable += ""; 993 | MyTable += ""; 994 | 995 | }; 996 | if (TblShowTimerDaysCol) { 997 | let TempDaysString = ""; 998 | let DaysCounter = 0; 999 | for (let y = 0; y < Wochentage.length; y++) { 1000 | if (MyTimer[x][y + 6]) { 1001 | TempDaysString += Wochentage[y].substr(0, 2) + "./ "; 1002 | DaysCounter++; 1003 | }; 1004 | }; 1005 | if (DaysCounter == 7) TempDaysString = "Alle Tage"; 1006 | MyTable += ""; 1007 | }; 1008 | if (TblShowTimerIfPresenceCol && PresenceDp != "") { 1009 | if (MyTimer[x][14]) { 1010 | MyTable += ""; 1011 | } else { 1012 | MyTable += ""; 1013 | }; 1014 | }; 1015 | if (TblShowTimerIfPresenceCol && PresenceDp != "") { 1016 | if (MyTimer[x][15]) { 1017 | MyTable += ""; 1018 | } else { 1019 | MyTable += ""; 1020 | }; 1021 | }; 1022 | if (TblShowTimerMessageCol) { 1023 | if (MyTimer[x][16]) { 1024 | MyTable += ""; 1025 | } else { 1026 | MyTable += ""; 1027 | }; 1028 | }; 1029 | if (TblShowTimerRuleCol) { 1030 | if (MyTimer[x][19] != "" && MyTimer[x][20] != "" && MyTimer[x][21] != "") { 1031 | MyTable += ""; 1032 | } else { 1033 | MyTable += ""; 1034 | }; 1035 | }; 1036 | 1037 | MyTable += ""; 1038 | }; 1039 | 1040 | MyTable += "
AktionSendeModusZeit+/-SchaltzielZielnameTageRegel
" + (x + 1) + "" + "X" + "" + " " + "" + AktionText[MyTimer[x][1]] + "" + "false" + "" + "true" + "" + "" + "" + MyTimer[x][18] + "" + "" + "" + ModeText[ModeValues.indexOf(MyTimer[x][5])] + "" + MyTimer[x][2] + "" + MyTimer[x][3] + "" + MyTimer[x][4] + " Min." + MyTimer[x][13] + "" + GetDeviceName(GetParentId(MyTimer[x][13])) + "" + MyTimer[x][17] + "" + TempDaysString + "" + "X" + "" + " " + "" + "X" + "" + " " + "" + "X" + "" + " " + "" + MyTimer[x][19] + " " + MyTimer[x][20] + " " + MyTimer[x][21] + "" + "
"; 1041 | setState(praefix + "TimerOverviewTable", MyTable, true); 1042 | //if (logging) log(MyTable); 1043 | } 1044 | 1045 | function WriteToTimer(whichone) { //Schreibt Daten vom Template in bestimmten Timer 1046 | if (logging) log("Reaching WriteToTimer, whichone=" + whichone); 1047 | let TempVal; 1048 | let OldActiveTimer = MyTimer[whichone][0]; //Alten TimerActive Wert speichern für Vergleich beim erstellen des ActiveTimerCount 1049 | 1050 | if (getState(praefix + "Template" + "." + Dps[0]).val && getState(praefix + "Template" + "." + Dps[13]).val == "") { //Timer wurde aktiviert, aber kein Ziel eingetragen 1051 | return false; //Abbruch 1052 | }; 1053 | 1054 | for (let y = 0; y < Dps.length; y++) { 1055 | TempVal = getState(praefix + "Template" + "." + Dps[y]).val 1056 | if (y == 4) TempVal = parseInt(TempVal); //Workaround für jqui Input welches immer Strings liefert 1057 | setState(praefix + whichone + "." + Dps[y], TempVal, true); 1058 | MyTimer[whichone][y] = TempVal; 1059 | }; 1060 | 1061 | if (OldActiveTimer != MyTimer[whichone][0]) { //Wenn sich an Timer aktiv was geändert hat 1062 | if (MyTimer[whichone][0]) { //Zähler der aktiven Timer aktualisieren 1063 | ActiveTimerCount++; 1064 | } else { 1065 | ActiveTimerCount--; 1066 | }; 1067 | setState(praefix + "ActiveTimerCount", ActiveTimerCount); //Zähler der aktiven Timer in Dp schreiben 1068 | }; 1069 | 1070 | if (MyTimer[whichone][13] != "") { //Sobald ein Ziel eingetragen von disabled auf idle stellen 1071 | MyTimer[whichone][Dps.length + 0] = "idle"; 1072 | }; 1073 | 1074 | if (MyTimerTemplate[17].indexOf(TargetNames) == -1) { // 1075 | CreateTimerTargetsNameList(); 1076 | if (logging) log("CreateTimerTargetsNameList() refresh done, MyTimerTemplate[17].indexOf(TargetNames)=" + MyTimerTemplate[17].indexOf(TargetNames)); 1077 | }; 1078 | 1079 | 1080 | KillTimer(whichone); //Vorhandenen Timer/Schedule löschen 1081 | SetTimer(whichone, false); // Timer/Schedule aktualisieren 1082 | SwitchEditMode(whichone, false); //Editmode deaktivieren 1083 | MakeTable(); //Tabelle refreshen 1084 | } 1085 | 1086 | function AddNewTimer() { 1087 | if (logging) log("Reaching AddNewTimer"); 1088 | TimerCount++; 1089 | setState(praefix + "TimerCount", TimerCount); 1090 | if (logging) log("Timercount=" + TimerCount); 1091 | let x = TimerCount - 1; 1092 | CreateTimer(x) 1093 | CreateTimerCountList();//Timer Value List aktualisieren 1094 | 1095 | setTimeout(function () { //Warten bis neuer Timer angelegt 1096 | setState(praefix + "SwitchToTimer", TimerCount - 1); //Dann zu neuem Timer wechseln 1097 | }, 50); 1098 | } 1099 | 1100 | 1101 | function DeleteTimer(whichone = ChoosenTimer) { 1102 | if (logging) log("Reaching DeleteTimer(whichone), whichone=" + whichone); 1103 | if (TimerCount == 1) return; //Letzten Timer nie löschen, Funktion verlassen 1104 | let TempArray = []; 1105 | let NewArray = []; 1106 | 1107 | KillTimer(whichone); //Vorhandenen Timer/Schedule löschen 1108 | 1109 | NewArray = TempArray.concat(MyTimer.slice(0, whichone), MyTimer.slice(whichone + 1)); 1110 | 1111 | TimerCount--; //Nach löschen im Array, Timerzähler -1 1112 | setState(praefix + "TimerCount", TimerCount); //TimerCount in Objektliste aktualisieren 1113 | 1114 | if (MyTimer[whichone][0]) { //Wenn Timer aktiv war ActiveTimercount Variable und Dp aktualisieren 1115 | ActiveTimerCount--; 1116 | setState(praefix + "ActiveTimerCount", ActiveTimerCount); //Zähler der aktiven Timer in Dp schreiben 1117 | }; 1118 | 1119 | if (MyTimer[whichone][13] != "" && NewArray.indexOf(MyTimer[whichone][13]) == -1) {//Subscription löschen wenn ein Ziel vorhanden war und kein weiterer Timer dieses Ziel verwendet 1120 | //unsubscribe(MyTimer[whichone][13]); 1121 | }; 1122 | 1123 | CreateTimerCountList();//Timer Value List aktualisieren 1124 | MyTimer = NewArray; 1125 | 1126 | //if (logging) log("whichone=" + whichone + " TimerCount=" + TimerCount) 1127 | //if (logging) log("MyTimer.length=" + MyTimer.length + " NewArray.length=" + NewArray.length + " NewArray=" + NewArray); 1128 | 1129 | //Alle Channels neu schreiben, dann letzten Channel komplett rekursiv löschen 1130 | for (let x = 0; x < TimerCount; x++) { 1131 | for (let y = 0; y < Dps.length; y++) { 1132 | //log("setState(" + praefix + x + "." + Dps[y] + " , " + MyTimer[x][y]); 1133 | setState(praefix + x + "." + Dps[y], MyTimer[x][y], true); 1134 | }; 1135 | }; 1136 | setState(praefix + "SwitchToTimer", TimerCount - 1); //Dann zu vorherigem Timer wechseln 1137 | if (logging) log("Now Delete last channel=" + praefix + (TimerCount)); 1138 | deleteObject(praefix + (TimerCount), true); //Löscht gesamten Channel 1139 | 1140 | MakeTable(); 1141 | } 1142 | 1143 | function WriteToTemplate(whichone) { //Schreibt Werte von bestimmten Timer ins Template 1144 | if (logging) log("Reaching WriteToTemplate(whichone), whichone=" + whichone); 1145 | if (logging) log("Typeof MyTimer[" + whichone + "]=" + typeof MyTimer[whichone]) 1146 | if (typeof MyTimer[whichone] == "undefined") { //Wenn bei neuem Timer Eintrag noch nicht gesetzt (async Problem) 1147 | for (let y = 0; y < Dps.length; y++) { 1148 | setState(praefix + "Template" + "." + Dps[y], DpDefaults[y]); //Defaults setzen 1149 | MyTimerTemplate[y] = DpDefaults[y]; 1150 | }; 1151 | } 1152 | else { 1153 | for (let y = 0; y < Dps.length; y++) { 1154 | setState(praefix + "Template" + "." + Dps[y], MyTimer[whichone][y]); //Normale Werte aus Array setzen 1155 | MyTimerTemplate[y] = MyTimer[whichone][y]; 1156 | if (MyTimerTemplate[5] != "time") { //und Astro aktiv ist 1157 | if (logging) log("Astro choosen and weekday changed"); 1158 | //Astrozeit neuberechnen und eintragen 1159 | // Nächsten aktiven Tag ermitteln und in der nächsten Zeile die Zeit dafür berechnen 1160 | setState(praefix + "Template." + Dps[3], DetermineChoosenAstroTime(MyTimerTemplate[5], DetermineNextActiveAstroDay(-1, false)[1], MyTimerTemplate[4])); //Zu gewählter Astrofunktion passende Zeit anzeigen unter Berücksichtigung welcher Tag der nächste aktive ist 1161 | }; 1162 | 1163 | }; 1164 | }; 1165 | } 1166 | 1167 | function SwitchEditMode(whichone, onoff) { //Aktiviert/deaktiviert Edit Modus für bestimmten Timer 1168 | if (logging) log("Reaching SwitchEditMode(whichone, onoff), whichonex=" + whichone + " TimerCount=" + TimerCount + " onoff=" + onoff); 1169 | if (whichone < TimerCount) MyTimer[whichone][(Dps.length + 1)] = onoff; //Sicherstellen das Timereintrag noch existiert (ist nach Löschung nicht der Fall) und Wert setzen 1170 | MakeTable(); 1171 | } 1172 | 1173 | function SetLockStates(TriggerIndex, SwitchingTimerIndex) { //Setzt interne States für Tabellenfarbkennzeichnungen. 1174 | if (logging) log("Reaching SetLockStates() TriggerIndex=" + TriggerIndex + " SwitchingTimerIndex=" + SwitchingTimerIndex); 1175 | 1176 | if (TriggerIndex != -1) { //Aufruf durch Trigger 1177 | for (let x = 0; x < MyTimer.length; x++) { //Alle Timer durchlaufen 1178 | if (TriggerArray[TriggerIndex] == MyTimer[x][13]) { 1179 | MyTimer[x][(Dps.length + 0)] = "idle"; 1180 | if (logging) log("Device " + MyTimer[x][13] + " switched from outside, setting TargetDeviceTimer " + (x + 1) + " to idle") 1181 | }; 1182 | 1183 | }; 1184 | } 1185 | else if (SwitchingTimerIndex != -1) { //Aufruf durch Schaltung (DoAction) 1186 | for (let x = 0; x < MyTimer.length; x++) { //Alle Timer durchlaufen 1187 | if (x != SwitchingTimerIndex && MyTimer[SwitchingTimerIndex][13] == MyTimer[x][13]) { //Alle Timer außer aktuellem berücksichtigen welche gleichen Zieldatenpunkt wie aktueller Timer haben 1188 | MyTimer[x][(Dps.length + 0)] = "idle"; //Diese auf idle setzen 1189 | }; 1190 | }; 1191 | }; 1192 | setTimeout(function () { 1193 | TargetSwitchingInProgress = false; 1194 | }, 500); 1195 | 1196 | MakeTable(); 1197 | } 1198 | 1199 | function CreateDeviceTrigger(whichone) { //TargetDeviceTrigger 1200 | if (logging) log("Reaching CreateDeviceTrigger() Trigger added for " + TriggerArray[whichone] + " whichone= " + whichone); 1201 | 1202 | on(TriggerArray[whichone], function (dp) { //Timer Zieldatenpunkt 1203 | if (logging) log("TargetDevice " + TriggerArray[whichone] + " state changed to " + dp.state.val + ", refreshing table"); 1204 | if (logging) log("MyTimer[" + whichone + "][(Dps.length + 0)]=" + MyTimer[whichone][(Dps.length + 0)]) 1205 | if (logging) log("TargetSwitchingInProgress=" + TargetSwitchingInProgress) 1206 | 1207 | if (!TargetSwitchingInProgress) { 1208 | SetLockStates(whichone, -1); 1209 | }; 1210 | }); 1211 | } 1212 | 1213 | function CreateTrigger() { 1214 | if (logging) log("Reaching CreateTrigger()"); 1215 | 1216 | // Template Trigger 1217 | for (let x = 0; x < Dps.length; x++) { //Alle Template Dps durchgehen und Trigger setzen 1218 | on(praefix + "Template." + Dps[x], function (dp) { 1219 | //if (logging) log("SwitchingInProgress =" + SwitchingInProgress) 1220 | MyTimerTemplate[x] = dp.state.val; 1221 | 1222 | if (!SwitchingInProgress) { //Anzeige aktivieren das Werte geändert wurden 1223 | SwitchEditMode(ChoosenTimer, true); 1224 | }; 1225 | 1226 | if (x == 4 && getState(praefix + "Template." + Dps[5]).val != "time") { //AstroShift geändert 1227 | if (logging) log("AstroShift edited"); 1228 | setState(praefix + "Template." + Dps[3], DetermineChoosenAstroTime(getState(praefix + "Template." + Dps[5]).val, DetermineNextActiveAstroDay(-1, false)[1], dp.state.val)); //Neuberechnete Zeit im Template anzeigen 1229 | }; 1230 | 1231 | if (x == 5 && dp.state.val != "time" && typeof dp.state.val != "undefined") { //TimerChoice geändert und Astro gewählt 1232 | if (logging) log("Astro choosen"); 1233 | setState(praefix + "Template." + Dps[3], DetermineChoosenAstroTime(dp.state.val, DetermineNextActiveAstroDay(-1, false)[1], getState(praefix + "Template." + Dps[4]).val)); //Zu gewählter Astrofunktion passende Zeit anzeigen 1234 | }; 1235 | 1236 | if (x == 13) { //Änderung TimerTarget 1237 | if (logging) log("Template TimerTarget changed, typeof=" + typeof dp.state.val + " Wert=" + dp.state.val); 1238 | if (typeof dp.state.val != "undefined" && dp.state.val != "") { 1239 | MyTimerTemplate[17] = TargetNames[Targets.indexOf(dp.state.val)]; //Smartname ermitteln und setzen 1240 | setState(praefix + "Template." + Dps[17], MyTimerTemplate[17]); //Smartname schreiben 1241 | }; 1242 | //log("MyTimerTemplate[17]=" + MyTimerTemplate[17]) 1243 | }; 1244 | 1245 | 1246 | if (x == 14) { //OnlyIfPresence - Block verhinder dass sowohl bei Anwesenheit als auch bei Abwesenheit abgewählt werden können was zu "nie" führen würde 1247 | if (!dp.state.val && !getState(praefix + "Template." + Dps[15]).val) { 1248 | setState(praefix + "Template." + Dps[15], true); 1249 | }; 1250 | } 1251 | else if (x == 15) { //OnlyIfNoPresence 1252 | if (!dp.state.val && !getState(praefix + "Template." + Dps[14]).val) { 1253 | setState(praefix + "Template." + Dps[14], true); 1254 | }; 1255 | }; 1256 | 1257 | if (x == 6 || x == 7 || x == 8 || x == 9 || x == 10 || x == 11 || x == 12) { //Wenn ein Wochentag geändert wurde 1258 | if (MyTimerTemplate[5] != "time") { //und Astro aktiv ist 1259 | if (logging) log("Astro choosen and weekday changed"); 1260 | //Astrozeit neuberechnen und eintragen 1261 | // Nächsten aktiven Tag ermitteln und in der nächsten Zeile die Zeit dafür berechnen 1262 | setState(praefix + "Template." + Dps[3], DetermineChoosenAstroTime(MyTimerTemplate[5], DetermineNextActiveAstroDay(-1, false)[1], MyTimerTemplate[4])); //Zu gewählter Astrofunktion passende Zeit anzeigen unter Berücksichtigung welcher Tag der nächste aktive ist 1263 | }; 1264 | }; 1265 | }); 1266 | }; 1267 | 1268 | //Trigger für Root Dps 1269 | on(praefix + "SwitchToTimer", function (dp) { //Bei Änderung Timer (Valuelist in Vis) 1270 | ChoosenTimer = dp.state.val; 1271 | SwitchingInProgress = true; //Steuervariable setzen um ungewolltes Triggern und aktivieren des Edit Modes zu vermeiden 1272 | WriteToTemplate(dp.state.val); //Nach Änderung Werte ins Template schreiben 1273 | SwitchEditMode(dp.oldState.val, false); //Editmode bei Timerwechsel verwerfen 1274 | setTimeout(function () { 1275 | SwitchingInProgress = false //Steuervariable nach Zeit x zurücksetzen 1276 | }, 500); 1277 | if (logging) log("Timertemplate changed to " + dp.state.val); 1278 | }); 1279 | 1280 | on(praefix + "SaveEdit", function (dp) { //Bei Änderung SaveEdit (Save Button in Vis) 1281 | if (dp.state.val) { 1282 | WriteToTimer(ChoosenTimer); 1283 | setTimeout(function () { 1284 | if (logging) log("Settings saved") 1285 | setState(praefix + "SaveEdit", false); //State wieder zurücksetzen nach einer Sek. (erzeugt kurze Farbbestätigung in Vis) um erneut definiert auf true triggern zu können 1286 | }, 1000); 1287 | }; 1288 | }); 1289 | 1290 | on(praefix + "AddTimer", function (dp) { //Bei Änderung AddTimer (Button in Vis) 1291 | if (logging) log("AddTimer triggered, val=" + dp.state.val) 1292 | 1293 | if (dp.state.val) { 1294 | AddNewTimer(); 1295 | setTimeout(function () { 1296 | setState(praefix + "AddTimer", false); 1297 | }, 500); 1298 | }; 1299 | }); 1300 | 1301 | on(praefix + "DelTimer", function (dp) { //Bei Änderung DeleteTimer (Button in Vis) 1302 | if (dp.state.val) { 1303 | DeletionInProgress = true 1304 | setTimeout(function () { 1305 | DeletionInProgress = false 1306 | setState(praefix + "DelTimer", false); 1307 | }, 3000); 1308 | } 1309 | else if (!dp.state.val && DeletionInProgress) { 1310 | DeleteTimer(); 1311 | DeletionInProgress = false 1312 | }; 1313 | }); 1314 | 1315 | on(praefix + "MsgMute", function (dp) { //Bei Änderung AddTimer (Button in Vis) 1316 | if (logging) log("MsgMute triggered, val=" + dp.state.val) 1317 | MsgMute = dp.state.val; 1318 | }); 1319 | 1320 | 1321 | //Sondertrigger 1322 | if (PresenceDp != "") { //Trigger nur erstellen wenn Anwesenheitsdatenpunkt vorhanden 1323 | on(PresenceDp, function (dp) { //Bei Änderung Anwesenheitsdatenpunkt 1324 | ConvertPresence(dp.state.val); 1325 | }); 1326 | }; 1327 | 1328 | onStop(function () { //Bei Scriptende alle Timer löschen 1329 | for (let x = 0; x < TimerCount; x++) { 1330 | KillTimer(x); 1331 | }; 1332 | }, 100); 1333 | } 1334 | 1335 | 1336 | 1337 | 1338 | --------------------------------------------------------------------------------