├── admin ├── fensteroffentut3.jpg ├── fensteroffentut4.jpg ├── fensteroffentut5.jpg ├── fensteroffentut1a.jpg └── fensteroffentut2c.png ├── .vscode └── launch.json ├── LICENSE ├── tsconfig.json ├── readme.md └── Fensterauswertung.js /admin/fensteroffentut3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pittini/iobroker-Fensterauswertung/HEAD/admin/fensteroffentut3.jpg -------------------------------------------------------------------------------- /admin/fensteroffentut4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pittini/iobroker-Fensterauswertung/HEAD/admin/fensteroffentut4.jpg -------------------------------------------------------------------------------- /admin/fensteroffentut5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pittini/iobroker-Fensterauswertung/HEAD/admin/fensteroffentut5.jpg -------------------------------------------------------------------------------- /admin/fensteroffentut1a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pittini/iobroker-Fensterauswertung/HEAD/admin/fensteroffentut1a.jpg -------------------------------------------------------------------------------- /admin/fensteroffentut2c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pittini/iobroker-Fensterauswertung/HEAD/admin/fensteroffentut2c.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}/Fensterauswertung.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 | ## (Version 1.6.14) 2 | ## Script um offene Türen und Fenster pro Raum und insgesamt zu zählen sowie offen/zu/gekippt States anzulegen und eine pro Raum konfigurierbare Lüftungsempfehlung (zeitbezogen) zu geben. Direkte Ausgabe aller Stati via HTML Tabelle und/oder Alexa/Telegram/Mail. Flexibel konfigurierbar. 3 | 4 | **If you like it, please consider a donation:** 5 | 6 | [![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) 7 | 8 | ### Features 9 | - #### Kann beliebige Tür/Fenster Kontakte verwenden. Noch nicht erfasste Varianten können über die Einstellungen hinzugefügt werden. 10 | - #### Berücksichtigt mehrflügelige Fenster bzw. mehrere Fenster pro Raum. 11 | - #### Legt pro Raum 13 Datenpunkte an (Raumfensteroffenzähler, Raumfenstergekipptzähler, Raumtürzähler ,Raumfensterstatus und die Einstellfelder für die Lüftungsempfehlung und welche Nachrichten Ihr haben möchtet, sowie das Feld in dem Ihr eine Benutzdefinierte Reihenfolge für die Ausgabe festlegen könnt), sowie 14 Datenpunkte fürs gesamte. (Siehe Beschreibung der Datenpunkte weiter unten) 12 | - #### Möglichkeit eine Meldung/Ansage via Mail/Telegram/Alexa nach x Minuten einmalig oder zyklisch bis Fensterschließung auszugeben. 13 | - #### Meldungen können bei Bedarf über einen Mute Datenpunkt entweder gesamt oder nur für Sprachnachrichten stummgeschaltet werden. 14 | - #### Gibt dynamische HTML Tabelle mit Übersicht aller Räume und farblicher Kennzeichnug der jeweiligen Stati aus. Verwendete Bilder und Farben sind frei konfigurierbar. 15 | - #### Möglichkeit die Tabelle nicht/alphabetisch/benutzerdefiniert zu sortieren 16 | - #### Gibt zeitbezogene Lüftungswarnung aus wenn Fenster für Zeit x (pro Raum einstellbar) nicht geöffnet wurden. 17 | - #### Gibt Liste mit Räumen für welche aktuell eine Fensteroffen Warnung besteht aus und zählt diese. 18 | - #### Gibt Liste mit Räumen in denen gekippte Fenster sind aus und zählt diese. 19 | - #### Gibt Liste mit Räumen in denen offfene Türen sind aus und zählt diese. 20 | - #### Gibt Liste mit Räumen für welche aktuell eine Lüftungs Warnung besteht aus. 21 | - #### Kann kurze auf/zu Änderungen innerhalb Zeit x (einstellbar) ignorieren. 22 | 23 | # WICHTIG!!! 24 | ### Vorraussetzungen: Den Geräten müssen Räume (für den gesamten Channel) zugewiesen sein, sowie eine Funktion, z.B. "Fenster", bzw. "Tuer" für jeden entsprechenden Datenpunkt. 25 | ### **Hier aber nur für den Datenpunkt, nicht den gesamten Channel!!!** 26 | 27 | ![fensteroffentut1a.jpg](/admin/fensteroffentut1a.jpg) 28 | 29 | 30 | 31 | 32 | # Installation 33 | 1. Wenn noch nicht geschehen, allen gewünschten Sensoren einen Raum und eine Funktion zuweisen. Die Funktion muss vorher in den Aufzählungen hinzugefügt werden und könnte z.B. "Fenster", bzw. "Tuer" lauten. Sollen andere Begriffe verwendet werden, muss dies dann auch im Script, Zeile 12 und 13 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**. 34 | 2. Das Skript in ein neues JS Projekt kopieren. 35 | ![fensteroffentut4.jpg](/admin/fensteroffentut4.jpg) 36 | ![fensteroffentut5.jpg](/admin/fensteroffentut5.jpg) 37 | 3. Zeile 9-53 kontrollieren und bei Bedarf anpassen, siehe Beschreibungen direkt neben den Variablen. 38 | 4. Zeile 18-27 wäre der richtige Ort falls Telegram, Alexa etc. die Meldungen ausgeben sollen. 39 | 5. Skript starten 40 | 6. In den Objekten, unter Javascript.0.FensterUeberwachung sollte es jetzt für jeden definierten Raum einen Channel mit 13 Datenpunkten geben: 41 | 1. RoomIsOpen (readonly): Sind in diesem Raum ein oder mehrere Fenster und/oder eine Tür geöffnet? 42 | 2. DoorIsOpen (readonly): Sind in diesem Raum ein oder mehrere Türen geöffnet? 43 | 3. WindowIsOpen (readonly): Sind in diesem Raum ein oder mehrere Fenster geöffnet? 44 | 5. RoomOpenCount (readonly): Summe der in diesem Raum geöffneten (inkl. der gekippten!) Fenster und Türen, 0 wenn alle geschlossen. 45 | 5. RoomOpenWindowCount (readonly): Anzahl der in diesem Raum geöffneten (inkl. der gekippten!) Fenster, 0 wenn alle geschlossen. 46 | 6. RoomOpenDoorCount (readonly): Anzahl der in diesem Raum geöffneten Türen, 0 wenn alle geschlossen. 47 | 7. RoomTiltedWindowCount (readonly): Anzahl der in diesem Raum gekippten Fenster, 0 wenn alle geschlossen. 48 | 8. VentWarnTime: Einstellfeld für die Anzahl Tage nach denen eine Lüftungsempfehlung ausgegeben wird. Lüftungsempfehlung ist bei 0 für diesen Raum deaktiviert. 49 | 9. SendVentMsg: Einstellfeld ob Ihr für diesen Raum eine Lüftungswarnung haben möchtet. 50 | 10. SendWindowOpenCloseMsg: Einstellfeld ob Ihr für diesen Raum eine Benachrichtigung für das erste Öffnen und das letzte Schließen der/des Fensters haben möchtet. 51 | 10. SendDoorOpenCloseMsg: Einstellfeld ob Ihr für diesen Raum eine Benachrichtigung für das erste Öffnen und das letzte Schließen einer Tür haben möchtet. 52 | 12. SendWindowWarnMsg: Einstellfeld ob Ihr für diesen Raum eine Offenwarnung haben möchtet. 53 | 13. RoomOrderPriority: Einstellfeld für die benutzerdefinierte Sortierung der Raumliste (wichtige Räume an den Listenanfang um nicht scrollen zu müssen). Keine doppelten Zahlen verwenden! Änderungen hier treten erst nach Skriptneustart in Kraft. 54 | 55 | 7. Zusätzlich werden 15 weitere Datenpunkte in der Skript Root ("javascript.0.FensterUeberwachung") angelegt: 56 | 1. AllWindowsClosed (Ersetzt ab V.1.6.0 die Bezeichnung "AlleFensterZu"): Gesamtstatus aller Fenster 57 | 2. AllDoorsClosed: Gesamtstatus aller Türen 58 | 3. DoorsOpen: Anzahl der offenen Türen über alle Räume summiert. 59 | 4. WindowsOpen: Anzahl der offenen Fenster über alle Räume summiert (inkl. der gekippten Fenster!). 60 | 5. WindowsTilted: Anzahl der gekippten Fenster über alle Räume summiert. 61 | 7. RoomsWithOpenDoors: Eine Textliste von Räumen mit geöffneten Türen und deren Anzahl. Sinnvoll für Kurzfassungsanzeigen in Vis. 62 | 7. RoomsWithOpenWindows: Eine Textliste von Räumen mit geöffneten Fenstern und deren Anzahl, sowie die Untermenge der davon gekippten Fenster (Funktioniert natürlich nur wenn entsprechende Sensoren verwendet werden die gekippt als Status melden). Sinnvoll für Kurzfassungsanzeigen in Vis. 63 | 8. RoomsWithTiltedWindows: Eine Textliste von Räumen mit gekippten Fenstern und deren Anzahl. Sinnvoll für Kurzfassungsanzeigen in Vis (Funktioniert natürlich nur wenn entsprechende Sensoren verwendet werden die gekippt als Status melden). 64 | 7. RoomsWithOpenings: Eine Textliste von Räumen mit geöffneten Fenstern und Türen sowie deren Anzahl, sowie die Untermenge der davon gekippten Fenster (Funktioniert natürlich nur wenn entsprechende Sensoren verwendet werden die gekippt als Status melden). Sinnvoll für Kurzfassungsanzeigen in Vis. 65 | 10. RoomsWithVentWarning: Eine Textliste von Räumen bei denen eine Lüftungswarnung besteht. 66 | 11. LastMessage: Die zuletzt ausgegebene Nachricht. Ermöglicht es die Meldungen mit History zu erfassen oder mit Vis auszugeben. 67 | 12. MessageLog: Ein kleines Log der ausgegebenen Meldungen mit Zeitstempel. Zeitstempel Format und max. Anzahl der Logeinträge in den Einstellungen konfigurierbar. Default Trennzeichen ist ">br>", somit kann die Liste direkt in einem HTML Widget via Binding (**{javascript.0.FensterUeberwachung.MessageLog}**) in Vis ausgegeben werden. 68 | 13. OverviewTable: Dynamisch erzeugte HTML Tabelle mit allen Räumen und den jeweiligen Fensterstati. Verwendung in Vis als Binding: **{javascript.0.FensterUeberwachung.OverviewTable}** in einem HTML Widget, optimale Breite 310px, Hintergrundfarbe, Schriftfarbe und Schriftart nach Wahl. 69 | 14. MuteMode: Bietet die Möglichkeit via Datenpunkt z.B. nachts Nachrichtenausgaben zu verhindern. 70 | - 0 = Alle Ansagen werden ausgegeben. 71 | - 1 = "Stumme" Nachrichten via Telegram/Mail etc. werden ausgegeben, Sprachausgaben geblockt. 72 | - 2 = Alle Nachrichten werden geblockt. 73 | 15. SendRoomsWithOpeningsMsg: Legt fest ob bei Statusänderungen eine Übersichtsmeldung gesendet wird. 74 | 75 | ![fensteroffentut3.jpg](/admin/fensteroffentut3.jpg) 76 | 77 | Es werden drei Icons aus dem Satz: *"icons-mfd-svg"* verwendet. Solltet Ihr diese nicht installiert haben, so könnt Ihr dies nachholen (wird als Adapter installiert) oder beliebige eigene Icons verwenden, hierzu muß dann jedoch der Name und Pfad im Skript, Zeile 30 - 36 angepasst werden. Sieht dann z.B. so aus: 78 | 79 | ![fensteroffentut2c.png](/admin/fensteroffentut2c.png) 80 | 81 | Diese Datenpunkte könnt Ihr jetzt z.B. in Vis verwenden um offene Türen/Fenster pro Raum anzuzeigen. Es wird dabei berücksichtigt dass es mehrere Türen/Fenster pro Raum, bzw. mehrflügelige Fenster geben kann. 82 | # Changelog 83 | #### 22.11.21 (1.6.15) 84 | * Add: Zu verwendende Funktionsaufzählung nun konfigurierbar gemacht. 85 | #### 09.10.21 (1.6.14) 86 | * Add: SendRoomsWithOpeningsMsg: Legt fest ob bei Statusänderungen eine Übersichtsmeldung gesendet wird. 87 | #### 06.05.21 (1.6.13) 88 | * Fix: Unbenutzte PushOver Instanz wird jetzt verwendet. 89 | * Add: PushOver Sound Option zu Einstellungen hinzugefügt. https://github.com/Pittini/iobroker-Fensterauswertung/issues/38 90 | #### 03.05.21 (1.6.12) 91 | * Fix: Fehlermeldung "Read-only state ... has been written without ack-flag with value ..." nach update des Js Controller auf Version 3.3.x oder höher behoben. Issue: https://github.com/Pittini/iobroker-Fensterauswertung/issues/34 92 | #### 18.03.21 (V1.6.11) 93 | - Fix: Anzeigefehler für Pluralvariante von RoomsWithOpenings behoben. 94 | #### 16.03.21 (V1.6.10) 95 | - Fix: Fehler im Trigger des AnwesenheitsDp korrigiert. 96 | #### 11.02.21 (V1.6.9) 97 | - Add: Alexa Lautstärke und Instanz nun einstellbar. 98 | #### 08.02.21 (V1.6.8) 99 | - Add: PushOver Option zu Nachrichten hinzugefügt. (https://github.com/Pittini/iobroker-Fensterauswertung/issues/28) 100 | #### 15.10.20 (V1.6.7) 101 | - Add: Zeit bis Benachrichtigung kann nun für Fenster und Türen separat gesetzt werden. 102 | #### 29.07.20 (V1.6.6) 103 | - Fix: Dp "RoomIsOpen" wird nun korrekt gesetzt. 104 | #### 04.07.20 (V1.6.5) 105 | - Add: Türenbenachrichtigung hinzugefügt. 106 | #### 02.07.20 (V1.6.4) 107 | - Fix: Problem bei HM Instanzen ungleich 0 behoben. 108 | - Fix: Fehlende Implementierung von NoMsgAtPresence behoben. 109 | - Change: Layout der ersten Tabellenspalte geändert. Wenn ein Raum nur Fenster oder Tür -> eine Spalte. Wenn Raum Fenster und Tür -> zwei Spalten. 110 | - Add: Türen können nun auch "gekippt" Status haben. 111 | #### 29.06.20 (V1.6.3) 112 | - Fix: Problem mit zusätzlicher Tabellenspalte behoben wenn sowohl Fenster als auch Türsensoren vorhanden waren und beides geschlossen. 113 | #### 24.06.20 (V1.6.2) 114 | - Change: Tabellendetails hinzugefügt/geändert. 115 | - Change: Zahlenspalte angepasst. 116 | #### 24.06.20 (V1.6.0) 117 | - Add: Raumliste kann jetzt alphabetisch oder benutzerdefiniert sortiert werden, wodurch es möglich wird gewünschte Räume für die Tabellemausgabe in der Reihenfolge nach oben zu schieben. 118 | - Add: Es ist jetzt möglich auch Türen separat mitzuzählen, hierfür muß eine zweite Funktion, z.B. "Tuer" festgelegt und den entsprechenden Türkontakten zugewiesen werden. Bei der Tabellenausgabe gibt es eine weitere Spalte für Türen mit eigenem Icon und eigener Farbe. Die gesamte Textausgabe wurde angepasst und nennt nun pro geöffneten Raum, sowohl Fenster als auch Türöffnungsstatusänderungen. 119 | - Change: der bisherige Defaultwert für die Funktionsbezeichnung der Fenster wurde geändert von "Verschluss" zu "Fenster". 120 | #### 03.05.20 (V1.5.3) 121 | - Fix: Zeitversatz bei Lüftungsmeldungen behoben welcher zu 23 Stunden, 59 Minuten Meldungen (statt 1 Tag) führte. 122 | - Fix: Mail Messaging auf Html umgestellt damit Umbrüche korrekt angezeigt werden. 123 | - Change: Einige default Werte geändert, kleine interne Codeänderungen. 124 | #### 27.4.20 (V1.5.2) 125 | - Add/Fix: Da sich HM Geräte nicht einig sind welcher Wert welchen Zustand bedeutet (bei einfachen Fensterkontakten 0=zu / 1=offen, bei Drehgriffkontakten 0=zu / 1=gekippt / 2=offen) wird jetzt zusätzlich der Text der Werteliste, wenn vorhanden, verwendet. 126 | - Fix: Timingproblem behoben welches bei Verwendung von HM Drehgriffkontakten und Statusänderung von gekippt nach zu auftrat. 127 | #### 24.4.20 (V 1.5.0) 128 | - Add: Nachrichtenausgabe kann nun in den Raumdatenpunkten pro Raum konfiguriert werden. Hierzu die Datenpunkte: SendOpenCloseMsg, SendVentMsg und SendWarnMsg angelegt. 129 | - Add: In den Skripteinstellungen, MaxMsg hinzugefügt. Hier kann festgelegt werden wieviele Nachrichten Ihr maximal pro Raum erhalten möchtet. Wegfall der Option RepeatInfoMsg, da dies durch MaxMsg=1 konfiguriert werden kann. 130 | - Add: Zusätzlicher Status "gekippt". Ausgabe der entsprechenden Werte sowohl als Gesamtzählung, als Liste, als auch pro Raum. Entsprechende Änderung der Texte (Wenn Fenster im Raum nur gekippt, Ausgabe Fenster gekippt, wenn nur offen, Ausgabe Fenster offen, wenn Fenster im Raum sowohl gekippt als auch offen, Ausgabe x Fenster offen, davon x Fenster gekippt). Zusätzliche Farbe und Bild für HTML Tabelle. 131 | - Fix: Problem mit inkorrekten Lüftungswarnungen nach öffnen/schliessen innerhalb Berechnungstimeout. 132 | - Add: Kurzzeitige (Zeit einstellbar) öffnen/schliessen Aktionen werden nun ignoriert (z.B. mal schnell aus dem Fenster guggen) 133 | #### 17.4.20 (V 1.4.3) 134 | - Add: Zusätzliche Logpunkte. 135 | - Fix: Problem mit inkorrekten Lüftungswarnungen nach Initphase. 136 | #### 13.4.20 (V 1.4.2) 137 | - Add: Zusätzlicher Datenpunkt "MuteMode" in der Skript Root eingefügt. 138 | - Add: Zusätzlicher Datenpunkt "RoomsWithVentWarning" in der Skript Root eingefügt. 139 | #### 12.4.20 (V 1.4.0) 140 | - Add: Zusätzlicher Datenpunkt "LastMessage" in der Skript Root eingefügt. 141 | - Add: Zusätzlicher Datenpunkt "MessageLog" in der Skript Root eingefügt. 142 | - Change: Tabelle, Defaultfarben an MaterialDesign2 Farben angepasst. Schriftgrößenfestlegung von em auf px und Tabellenaufbau geändert um bessere Kompatibilität mit MD2 zu erreichen. 143 | - Add: Tabelle, Überschrift, Zusammenfassung und Detailbereich können nun in den Einstellungen deaktiviert werden. 144 | - Add: Bilder können in Einstellungen invertiert werden. 145 | - Change: Tabelle, Bilder horizontal zentriert. 146 | - Change: Zur besseren Verständlichkeit einige Einstellungskonstanten umbenannt. 147 | #### 9.4.20 (V 1.3.0) 148 | - Add: Unterstriche werden in Meldungen nun als Leerzeichen ausgegeben. Ae, ue, oe, wird in Meldungen nun als ä, ü, ö ausgegeben. 149 | - Change: offen/geschlossen Zeiten werden nicht mehr als Zeitstempel angezeigt sondern die jeweilige Dauer berechnet und minütlich aktualisiert. 150 | - Add: Pro Raum konfigurierbare Lüftungsempfehlung integriert. Bei Skriptneustarts wird bereits vorhandene geschlossen Zeit berücksichtigt. 151 | - Change: Tabellenfarben jetzt heller / freundlicher. 152 | - Fix: Ignorieren von geöffneten Fenstern bei Skriptstart behoben, wenn diese in einem Raum mit mehreren/zweiflügeligen Fenstern waren und das geöffnete Fenster in der Aufzählung vor dem geschlossenen gelistet war. 153 | #### 1.4.20 (V 1.2.3) Add: Tabellendatumsformatierung ist jetzt in Einstellungen konfigurierbar. 154 | #### 31.3.20 (V1.2.2) 155 | - Add: Benachrichtigung via Mail hinzugefügt. 156 | - Add: Option hinzugefügt um auch erstmaliges öffnen sowie schliessen zu melden. 157 | - Change: Zeitausgaben werden nun auf eine Nachkommastelle gerundet. 158 | #### 29.3.20 (V1.2.1)Add: Möglichkeit integriert die Tabelle ohne Kopf darzustellen 159 | #### 28.3.20 (V1.2.0)Add: Dynamisch erstellte HTML Übersichtstabelle über alle Räume/Fenster 160 | #### 25.3.20 (V1.1.7) Add: HMIP Drehgriffe integriert; Statebezeichnungen für auf/zu jetzt User-konfigurierbar -erweiterbar 161 | #### 23.3.20 (V1.1.6)Add: Neuer Datenpunkt mit Textübersicht ausschliesslich der Räume mit geöffneten Fenstern 162 | #### 22.3.20 (V1.1.5) Bugfix für HM Drehgriff Sensoren, Logging erweitert 163 | #### 5.2.20 (V1.1.4)Add: Fehlerabfangroutinen integriert 164 | #### 3.2.20 (V1.1.3) Kleinere Bugfixes und upload zu git 165 | #### 1.2.20 (V1.1.2) Add: Möglichkeit eine Ansage nach x Minuten einmalig oder zyklisch bis Fensterschließung anzugeben. 166 | #### 14.1.20 (V1.1.1) Add: "Offen" erweitert um "Open", "Tilted", "Gekippt" 167 | #### 9.8.19 (V1.1.0) Zählung der Fenster gesamt ausgeweitet auf Fenster pro Raum 168 | #### 4.8.19 Init (V1.0.0) 169 | 170 | -------------------------------------------------------------------------------- /Fensterauswertung.js: -------------------------------------------------------------------------------- 1 | const Skriptversion = "1.6.15" //vom 22.11.2021 - https://github.com/Pittini/iobroker-Fensterauswertung - https://forum.iobroker.net/topic/31674/vorlage-generisches-fensteroffenskript-vis 2 | //Script um offene Fenster/Türen pro Raum und insgesamt zu zählen. 3 | //Möglichkeit eine Ansage nach x Minuten einmalig oder zyklisch bis Fensterschließung anzugeben 4 | //Dynamische erzeugung einer HTML Übersichtstabelle 5 | //WICHTIG!!! 6 | //Vorraussetzungen: Den Geräten müssen Räume zugewiesen sein, sowie die Funktion "Fenster" bzw "Tuer" für jeden entsprechenden Datenpunkt. 7 | 8 | //Grundeinstellungen 9 | const logging = false; //Erweiterte Logs ausgeben? 10 | const praefix = "javascript.0.FensterUeberwachung."; //Grundpfad für Script DPs - Muß innerhalb javascript.x sein. 11 | const PresenceDp = "" //Pfad zum Anwesenheitsdatenpunkt, leer lassen wenn nicht vorhanden 12 | const WhichWindowFunctionToUse = "Fenster"; // Legt fest nach welchem Begriff in Funktionen gesucht wird. Diese Funktion nur dem Datenpunkt zuweisen, NICHT dem ganzen Channel! 13 | const WhichDoorFunctionToUse = "Tuer"; // Legt fest nach welchem Begriff in Funktionen gesucht wird. Diese Funktion nur dem Datenpunkt zuweisen, NICHT dem ganzen Channel! 14 | const WindowIgnoreTime = 10000; // 10000 ms = 10 Sekunden - Zeit in ms für die kurzzeitiges öffnen/schliessen ignoriert wird 15 | const DoorIgnoreTime = 1000; // 1000 ms = 1 Sekunden - Zeit in ms für die kurzzeitiges öffnen/schliessen ignoriert wird 16 | const WhichEnumCategoryToUse = "functions"; // Legt fest in welcher Kategorie sich die Aufzählungen befinden! Nur ändern wer weis was er tut! 17 | 18 | //Nachrichteneinstellungen 19 | const TimeToWindowMsg = 900000 // 300000 ms = 5 Minuten - Zyklus- bzw. Ablaufzeit für Fenster-offenwarnung/en 20 | const TimeToDoorMsg = 300000 // 300000 ms = 5 Minuten - Zyklus- bzw. Ablaufzeit für Tür-offenwarnung/en 21 | 22 | const MaxMessages = 1; //Maximale Anzahl der Nachrichten pro Raum 23 | 24 | //Telegram 25 | const UseTelegram = false; // Sollen Nachrichten via Telegram gesendet werden? 26 | 27 | //Pushover 28 | const UsePushOver = false; // Sollen Nachrichten via PushOver gesendet werden? 29 | const PushOverInstance = "pushover.0"; //Pushoverinstanz welche genutzt werden soll angeben 30 | const PushOverDevice = "All"; //Welches Gerät soll die Nachricht bekommen 31 | const PushOverTitle = "Fensterüberwachung"; 32 | const PushOverSound = "none"; //Welcher Sound soll abgespielt werden? "none" für kein Sound, "" für Standartsound, ansonsten Namen angeben z.B. "magic" 33 | 34 | //Alexa 35 | const UseAlexa = false; // Sollen Nachrichten via Alexa ausgegeben werden? 36 | const AlexaInstance = "alexa2.0"; 37 | const AlexaId = ""; // Die Alexa Seriennummer. 38 | const AlexaVolume = "50"; // Lautstärke der Nachrichten. Wert von 1 bis 100 39 | 40 | //Other 41 | const UseMail = false; //Nachricht via Mail versenden? 42 | const UseSay = true; // Sollen Nachrichten via Say ausgegeben werden? Autorenfunktion, muß deaktiviert werden. 43 | const UseEventLog = true; // Sollen Nachrichten ins Eventlog geschreiben werden? Autorenfunktion, muß deaktiviert werden. 44 | 45 | const NoMsgAtPresence = false; //Sollen Nachrichten bei Anwesenheit unterdrückt werden? 46 | 47 | //Tabelleneinstellungen 48 | const DoorOpenImg = "/icons-mfd-svg/fts_door_open.svg"; //Icon für Tür offen 49 | const DoorCloseImg = "/icons-mfd-svg/fts_door.svg"; // Icon für Tür geschlossen 50 | const DoorTiltedImg = "/icons-mfd-svg/fts_door_tilt.svg" // Icon für Tür gekippt 51 | const WindowOpenImg = "/icons-mfd-svg/fts_window_1w_open.svg"; //Icon für Fenster offen 52 | const WindowCloseImg = "/icons-mfd-svg/fts_window_1w.svg"; // Icon für Fenster geschlossen 53 | const WindowTiltedImg = "/icons-mfd-svg/fts_window_1w_tilt.svg" //Icon für Fenster gekippt 54 | const WindowOpenTiltedImg = "/icons-mfd-svg/fts_window_2w_open_l_tilt_r.svg" //Icon für offen und gekippt in einem Raum gleichzeitig 55 | const VentImg = "/icons-mfd-svg/vent_ventilation.svg"; //Icon für Lüftungsinfo 56 | const ImgInvert = 1; // Bildfarben invertieren? Erlaubte Werte von 0 bis 1 57 | const OpenWindowColor = "#f44336"; // Farbe für Fenster offen 58 | const OpenDoorColor = "darkorange"; //Farbe für Tür offen 59 | const TiltedWindowColor = "#F56C62"; //Farbe für gekippte Fenster o. Tür/en 60 | const ClosedWindowColor = "#4caf50"; // Farbe für geschlossene Fenster o. Tür/en 61 | const VentWarnColor = "#ffc107"; // Farbe für Lüftungswarnung 62 | const ShowCaptionTbl = false; // Überschrift anzeigen? 63 | const ShowSummaryTbl = true; // Zusammenfassung anzeigen? 64 | const ShowDetailTbl = true; // Details anzeigen? 65 | const RoomSortMode = 1; //0= Raumliste unsortiert, 1= alpabetisch sortiert, 2= Benutzerdefinierte Sortierung 66 | 67 | //Logeinstellungen 68 | const MaxLogEntrys = 20; //Maximale Anzahl der zu speichernden Logeinträge 69 | const AutoAddTimestamp = true; //Soll den geloggten Nachrichten automatisch ein Zeitsempel zugeordnet werden? 70 | const LogTimeStampFormat = "TT.MM.JJJJ SS:mm:ss"; //Zeitformatierung für Log Zeitstempel 71 | const LogEntrySeparator = "
"; //Trennzeichen für Logeinträge 72 | 73 | //Ab hier nix mehr ändern! 74 | const SendVentMsg = []; 75 | const SendDoorOpenCloseMsg = []; 76 | const SendWindowOpenCloseMsg = []; 77 | const SendWindowWarnMsg = []; 78 | const SendDoorWarnMsg = []; 79 | const OpenWindowListSeparator = "
"; //Trennzeichen für die Textausgabe der offenen Fenster pro Raum 80 | 81 | const WindowIsOpenWhen = ["true", "offen", "open", "opened", "2"]; // Hier können eigene States für offen angegeben werden, immer !!! in Kleinschreibung 82 | const WindowIsClosedWhen = ["false", "geschlossen", "closed", "0"]; // Hier können eigene States für geschlossen angegeben werden, immer !!! in Kleinschreibung 83 | const WindowIsTiltedWhen = ["tilted", "gekippt", "1"]; // Hier können eigene States für gekippt angegeben werden, immer !!! in Kleinschreibung 84 | 85 | let OpenDoorCount = 0; // Gesamtzahl der geöffneten Türen 86 | let TiltedDoorCount = 0; // Gesamtzahl der gekippten Türen 87 | let OpenWindowCount = 0; // Gesamtzahl der geöffneten Fenster 88 | let TiltedWindowCount = 0; // Davon Anzahl der gekippten Fenster 89 | 90 | const RoomOpenCount = []; // Array für Summe geöffneter Verschlüsse pro Raum 91 | const RoomOpenDoorCount = []; // Array für Zähler offene Türen pro Raum 92 | const RoomTiltedDoorCount = []; // Array für Zähler gekippte Türen pro Raum 93 | const RoomOpenWindowCount = []; // Array für Zähler offene Fenster pro Raum 94 | const RoomTiltedWindowCount = []; // Array für Zähler gekippte Fenster pro Raum 95 | const RoomWindowMsgCount = []; //Zähler für bereits ausgegebene Fenster Warnmeldungen 96 | const RoomDoorMsgCount = []; //Zähler für bereits ausgegebene Tür Warnmeldungen 97 | let RoomHas = [] // 0=Weder Tür noch Fenster, 1 Tür, 2 Fenster, 3 Tür und Fenster 98 | const RoomsWithCombinedOpenings = []; 99 | let RoomsWithOpenings = ""; // Kombinierte Liste mit offenen Türen und Fenstern 100 | let RoomsWithOpenDoors = ""; //Liste der Räume mit offenen Türen 101 | let RoomsWithTiltedDoors = ""; //Liste der Räume mit offenen Türen 102 | let RoomsWithOpenWindows = ""; //Liste der Räume mit offenen Fenstern 103 | let RoomsWithTiltedWindows = ""; //Liste der Räume mit gekippten Fenstern 104 | let RoomsWithVentWarnings = []; //Räume mit Lüftungswarnung 105 | let RoomListOrderPriority = ""; //Sortierreihenfolge der Raumliste 106 | 107 | const OpenWindowMsgHandler = []; // Objektarray für timeouts pro Raum/Fenster 108 | const OpenDoorMsgHandler = []; // Objektarray für timeouts pro Raum/Tür 109 | const IgnoreValue = []; //Vergleichswert für IgnoreTimeout 110 | const VentMsgHandler = []; //Timeout/Intervall Objekt 111 | const VentMsg = []; //Lüftungsnachricht 112 | const Sensor = []; //Sensoren als Array anlegen 113 | let SensorType = []; //Unterscheidung zwischen Tür und Fenstersensor 114 | const SensorVal = [];//Sensorwerte als Array anlegen 115 | const SensorOldVal = []; //Alte Sensorwerte als Array ablegen 116 | const WindowWarnRuntime = []; //Timer WindowWarnRuntime pro Fenster 117 | const DoorWarnRuntime = []; //Timer DoorWarnRuntime pro Tür 118 | const VentWarnTime = []; // Array mit Zeiten nach dem eine Lüftungsempfehlung ausgegeben wird 119 | let RoomList = []; // Raumlisten Array 120 | const RoomStateTimeStamp = []; //Letzte Änderung des Fenster-Raumstatus 121 | const RoomStateTimeCount = []; // Zeitspanne seit letzter Änderung 122 | const RoomDoorStateTimeStamp = []; //Letzte Änderung des Tür-Raumstatus 123 | const RoomDoorStateTimeCount = []; // Zeitspanne seit letzter Änderung 124 | let z = 0; //Zähler 125 | let DpCount = 0; //Zähler 126 | let IsInit = true // Marker - Wird nach initialisierung auf false gesetzt 127 | // /** @type {{ id: string, initial: any, forceCreation: boolean, common: iobJS.StateCommon }[]} */ 128 | const States = []; // Array mit anzulegenden Datenpunkten 129 | let Funktionen = getEnums(WhichEnumCategoryToUse); //Array mit Aufzählung der Funktionen 130 | let MessageLog = ""; //Log der ausgegebenen Meldungen 131 | let MuteMode = 0; //Stummschaltungsmodus für Nachrichten. 0=Alles erlaubt, 1=Sprachnachrichten deaktivieren, 2=Alles deaktivieren 132 | let Presence = true; //Anwesenheit als gegeben initialisieren 133 | const IgnoreInProcess = []; //Läuft gerade eine Überprüfung ob eine Statusänderung ignoriert werden muß? 134 | let SensorCount = 0; //Hilfszähler weil y bei mehreren Funktionen mehrmals bei 0 beginnt 135 | let SendRoomsWithOpeningsMsg = false; 136 | let SendRoomsWithOpeningsMsgRefresh = 0; 137 | let RoomsWithOpeningsMsgRefreshTickerObj; 138 | 139 | log("starting Fensterskript, Version " + Skriptversion); 140 | 141 | for (let x in Funktionen) { // loop ueber alle Functions 142 | 143 | let Funktion = Funktionen[x].name; 144 | if (typeof Funktion == "undefined") { 145 | log("Keine Funktion gefunden", "error"); 146 | } 147 | else { 148 | if (typeof Funktion == 'object') Funktion = Funktion.de; 149 | let members = Funktionen[x].members; 150 | if (Funktion == WhichWindowFunctionToUse || Funktion == WhichDoorFunctionToUse) { //Wenn Function ist Fenster oder Tür 151 | for (let y in members) { // Loop über alle Fenster/Tür Members 152 | Sensor[SensorCount] = members[y]; 153 | let room = getObject(Sensor[SensorCount], 'rooms').enumNames[0]; 154 | if (typeof room == 'object') room = room.de; 155 | if (RoomList.indexOf(room) == -1) { //Raumliste ohne Raumduplikate und zugehörige Dps erzeugen 156 | //Datenpunkte pro Raum vorbereiten 157 | States[DpCount] = { id: praefix + room + ".RoomOrderPriority", initial: z, forceCreation: false, common: { read: true, write: true, name: "Raumpriorität für Tabelle", role: "state", type: "number", def: z } }; 158 | DpCount++; 159 | States[DpCount] = { id: praefix + room + ".RoomOpenCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Summe der geöffneten Fenster und Türen im Raum", role: "state", type: "number", def: 0 } }; 160 | DpCount++; 161 | States[DpCount] = { id: praefix + room + ".RoomOpenDoorCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Anzahl der geöffneten Türen im Raum", role: "state", type: "number", def: 0 } }; 162 | DpCount++; 163 | States[DpCount] = { id: praefix + room + ".RoomTiltedDoorCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Anzahl der gekippten Türen im Raum", role: "state", type: "number", def: 0 } }; 164 | DpCount++; 165 | States[DpCount] = { id: praefix + room + ".RoomOpenWindowCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Anzahl der geöffneten Fenster im Raum", role: "state", type: "number", def: 0 } }; 166 | DpCount++; 167 | States[DpCount] = { id: praefix + room + ".RoomTiltedWindowCount", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Anzahl der gekippten Fenster im Raum", role: "state", type: "number", def: 0 } }; 168 | DpCount++; 169 | States[DpCount] = { id: praefix + room + ".SendVentMsg", initial: true, forceCreation: false, common: { read: true, write: true, name: "Sollen für diesen Raum Lüftungsnachrichten ausgegeben werden?", type: "boolean", role: "state", def: true } }; // 170 | DpCount++; 171 | States[DpCount] = { id: praefix + room + ".SendDoorOpenCloseMsg", initial: true, forceCreation: false, common: { read: true, write: true, name: "Sollen für diesen Raum Nachrichten bei öffnen/schliessen von Türen ausgegeben werden?", type: "boolean", role: "state", def: true } }; // 172 | DpCount++; 173 | States[DpCount] = { id: praefix + room + ".SendWindowOpenCloseMsg", initial: true, forceCreation: false, common: { read: true, write: true, name: "Sollen für diesen Raum Nachrichten bei öffnen/schliessen von Fenstern ausgegeben werden?", type: "boolean", role: "state", def: true } }; // 174 | DpCount++; 175 | States[DpCount] = { id: praefix + room + ".SendWindowWarnMsg", initial: true, forceCreation: false, common: { read: true, write: true, name: "Sollen für diesen Raum Nachrichten für überschrittene Fenster Öffnungszeit ausgegeben werden?", type: "boolean", role: "state", def: true } }; // 176 | DpCount++; 177 | States[DpCount] = { id: praefix + room + ".SendDoorWarnMsg", initial: true, forceCreation: false, common: { read: true, write: true, name: "Sollen für diesen Raum Nachrichten für überschrittene Tür Öffnungszeit ausgegeben werden?", type: "boolean", role: "state", def: true } }; // 178 | DpCount++; 179 | States[DpCount] = { id: praefix + room + ".WindowIsOpen", initial: false, forceCreation: false, common: { read: true, write: false, name: "Fenster im Raum offen oder gekippt?", type: "boolean", role: "state", def: false } }; // 180 | DpCount++; 181 | States[DpCount] = { id: praefix + room + ".DoorIsOpen", initial: false, forceCreation: false, common: { read: true, write: false, name: "Türen im Raum offen?", type: "boolean", role: "state", def: false } }; // 182 | DpCount++; 183 | States[DpCount] = { id: praefix + room + ".RoomIsOpen", initial: false, forceCreation: false, common: { read: true, write: false, name: "Raum offen?", type: "boolean", role: "state", def: false } }; // 184 | DpCount++; 185 | States[DpCount] = { id: praefix + room + ".VentWarnTime", initial: 0, forceCreation: false, common: { read: true, write: true, name: "Anzahl der Tage nach der eine Lüftungsempfehlung erzeugt wird", unit: "Tage", type: "number", role: "state", def: 0 } }; 186 | DpCount++; 187 | //log(Funktion + ': ' + room); 188 | RoomList[z] = room; 189 | RoomOpenCount[z] = 0; // Array mit 0 initialisieren 190 | RoomOpenDoorCount[z] = 0; // Array mit 0 initialisieren 191 | RoomTiltedDoorCount[z] = 0; // Array mit 0 initialisieren 192 | RoomOpenWindowCount[z] = 0; // Array mit 0 initialisieren 193 | RoomTiltedWindowCount[z] = 0; // Array mit 0 initialisieren 194 | RoomWindowMsgCount[z] = 0; 195 | RoomDoorMsgCount[z] = 0; 196 | WindowWarnRuntime[z] = 0; // Array mit 0 initialisieren 197 | DoorWarnRuntime[z] = 0; // Array mit 0 initialisieren 198 | RoomsWithCombinedOpenings[z] = []; //Zweite Dimension für jeden Raum initialisieren 199 | z++; 200 | }; 201 | 202 | let TempIndex = RoomList.indexOf(room); 203 | if (Funktion == WhichWindowFunctionToUse) { //Fenster 204 | if (typeof RoomHas[TempIndex] == "undefined") { //Für Raum festlegen ob Türen und/oder Fenster überwacht werden. Steuert ein/aus-blenden der Tabellenbilder 205 | RoomHas[TempIndex] = 2; // 0=Weder Tür noch Fenster, 1 Tür, 2 Fenster, 3 Tür und Fenster 206 | } 207 | else if (RoomHas[TempIndex] == 1) { 208 | RoomHas[TempIndex] = 3; 209 | }; 210 | SensorType[SensorCount] = "Window"; 211 | } else if (Funktion == WhichDoorFunctionToUse) { //Tür 212 | if (typeof RoomHas[TempIndex] == "undefined") { //Für Raum festlegen ob Türen und/oder Fenster überwacht werden. Steuert ein/aus-blenden der Tabellenbilder 213 | RoomHas[TempIndex] = 1; // 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 214 | } 215 | else if (RoomHas[TempIndex] == 2) { 216 | RoomHas[TempIndex] = 3; 217 | }; 218 | SensorType[SensorCount] = "Door"; 219 | }; 220 | if (logging) { 221 | if (RoomHas[TempIndex] == 1) log("Raum- " + TempIndex + " = " + RoomList[TempIndex] + " hat Türsensor/en"); 222 | if (RoomHas[TempIndex] == 2) log("Raum- " + TempIndex + " = " + RoomList[TempIndex] + " hat Fenstersensor/en"); 223 | if (RoomHas[TempIndex] == 3) log("Raum- " + TempIndex + " = " + RoomList[TempIndex] + " hat Tür- und Fenstersensor/en"); 224 | }; 225 | 226 | //log("Sensor " + SensorCount + " in " + room + " =" + Sensor[SensorCount] + " SensorType[y]=" + SensorType[SensorCount] + " x=" + x + " Funktion=" + Funktion); 227 | SensorCount++; 228 | }; 229 | }; 230 | }; 231 | }; 232 | 233 | //Struktur anlegen in js.0 um Sollwert und Summenergebniss zu speichern 234 | //Generische Datenpunkte vorbereiten 235 | States[DpCount] = { id: praefix + "AllWindowsClosed", initial: true, forceCreation: false, common: { read: true, write: false, name: "Sind aktuell alle Fenster geschlossen?", type: "boolean", role: "state", def: true } }; // 236 | DpCount++; 237 | States[DpCount] = { id: praefix + "AllDoorsClosed", initial: true, forceCreation: false, common: { read: true, write: false, name: "Sind aktuell alle Türen geschlossen?", type: "boolean", role: "state", def: true } }; // 238 | DpCount++; 239 | States[DpCount] = { id: praefix + "WindowsOpen", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Anzahl der geöffneten Fenster", type: "number", def: 0 } }; 240 | DpCount++; 241 | States[DpCount] = { id: praefix + "DoorsOpen", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Anzahl der geöffneten Türen", type: "number", def: 0 } }; 242 | DpCount++; 243 | States[DpCount] = { id: praefix + "WindowsTilted", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Anzahl der gekippten Fenster", type: "number", def: 0 } }; 244 | DpCount++; 245 | States[DpCount] = { id: praefix + "DoorsTilted", initial: 0, forceCreation: false, common: { read: true, write: false, name: "Anzahl der gekippten Türen", type: "number", def: 0 } }; 246 | DpCount++; 247 | States[DpCount] = { id: praefix + "RoomsWithOpenings", initial: "", forceCreation: false, common: { read: true, write: false, name: "In welchen Räumen sind Türen/Fenster geöffnet?", type: "string", def: "" } }; 248 | DpCount++; 249 | States[DpCount] = { id: praefix + "RoomsWithOpenDoors", initial: "", forceCreation: false, common: { read: true, write: false, name: "In welchen Räumen sind Türen geöffnet?", type: "string", def: "" } }; 250 | DpCount++; 251 | States[DpCount] = { id: praefix + "RoomsWithTiltedDoors", initial: "", forceCreation: false, common: { read: true, write: false, name: "In welchen Räumen sind Türen gekippt?", type: "string", def: "" } }; 252 | DpCount++; 253 | States[DpCount] = { id: praefix + "RoomsWithOpenWindows", initial: "", forceCreation: false, common: { read: true, write: false, name: "In welchen Räumen sind Fenster geöffnet?", type: "string", def: "" } }; 254 | DpCount++; 255 | States[DpCount] = { id: praefix + "RoomsWithTiltedWindows", initial: "", forceCreation: false, common: { read: true, write: false, name: "In welchen Räumen sind Fenster gekippt?", type: "string", def: "" } }; 256 | DpCount++; 257 | States[DpCount] = { id: praefix + "RoomsWithVentWarnings", initial: "", forceCreation: false, common: { read: true, write: false, name: "In welchen Räumen ist eine Lüftungswarnung aktiv?", type: "string", def: "" } }; 258 | DpCount++; 259 | States[DpCount] = { id: praefix + "LastMessage", initial: "", forceCreation: false, common: { read: true, write: false, name: "Die zuletzt ausgegebene Meldung?", type: "string", def: "" } }; 260 | DpCount++; 261 | States[DpCount] = { id: praefix + "MessageLog", initial: "", forceCreation: false, common: { read: true, write: false, name: "Liste der letzten x ausgebenen Meldungen", type: "string", def: "" } }; 262 | DpCount++; 263 | States[DpCount] = { id: praefix + "OverviewTable", initial: "", forceCreation: false, common: { read: true, write: false, name: "Übersicht aller Räume und geöffneten Fenster", type: "string", def: "" } }; 264 | DpCount++; 265 | States[DpCount] = { id: praefix + "SendRoomsWithOpeningsMsg", initial: false, forceCreation: false, common: { read: true, write: true, name: "Übersicht der offenen Türen und Fenster senden?", type: "boolean", role: "state", def: false } }; // 266 | DpCount++; 267 | States[DpCount] = { id: praefix + "SendRoomsWithOpeningsMsgRefresh", initial: 60, forceCreation: false, common: { read: true, write: true, name: "Refreshzeit der Übersicht der offenen Türen und Fenster", type: "number", unit: "Min.", role: "state", min: 0, def: 60 } }; // 268 | DpCount++; 269 | States[DpCount] = { id: praefix + "MuteMode", initial: 0, forceCreation: false, common: { read: true, write: true, name: "Stummschalten?", type: "number", min: 0, max: 2, def: 0 } }; 270 | 271 | //Alle States anlegen, Main aufrufen wenn fertig 272 | let numStates = States.length; 273 | States.forEach(function (state) { 274 | createState(state.id, state.initial, state.forceCreation, state.common, function () { 275 | numStates--; 276 | if (numStates === 0) { 277 | if (logging) log("CreateStates fertig!"); 278 | InitialSort(); 279 | }; 280 | }); 281 | }); 282 | 283 | function InitialSort() { 284 | let TempRoomHas = []; 285 | let TempRoomList = []; 286 | let AlphabeticalSortedRoomList = RoomList.join(","); //Raumliste zu kommaseparierten String wandeln 287 | let OrderPriority; 288 | TempRoomList = AlphabeticalSortedRoomList.split(","); //String wieder zurück zu Array wandeln 289 | AlphabeticalSortedRoomList = TempRoomList.sort(); //Array sortieren 290 | 291 | if (RoomSortMode == 1) { //Raumliste sortieren //alphabetisch 292 | for (let x = 0; x < RoomList.length; x++) { //Raum Dps durchlaufen 293 | OrderPriority = AlphabeticalSortedRoomList.indexOf(RoomList[x]); 294 | TempRoomList[OrderPriority] = RoomList[x]; 295 | TempRoomHas[OrderPriority] = RoomHas[x]; 296 | }; 297 | RoomList = TempRoomList; 298 | RoomHas = TempRoomHas; 299 | } 300 | else if (RoomSortMode == 2) {//benutzerdefiniert 301 | for (let x = 0; x < RoomList.length; x++) { //Raum Dps durchlaufen 302 | OrderPriority = getState(praefix + RoomList[x] + ".RoomOrderPriority").val; //benutzdefinierte Reihenfolge lesen 303 | TempRoomList[OrderPriority] = RoomList[x]; //und an entsprechende Stelle schreiben 304 | TempRoomHas[OrderPriority] = RoomHas[x]; //RoomHas synchron halten 305 | }; 306 | RoomList = TempRoomList; 307 | RoomHas = TempRoomHas; 308 | }; 309 | //log(RoomList); 310 | //log(TempRoomList); 311 | //log(RoomHas); 312 | //log(TempRoomHas); 313 | //log(AlphabeticalSortedRoomList); 314 | main(); 315 | } 316 | 317 | function init() { 318 | MessageLog = getState(praefix + "MessageLog").val; 319 | MuteMode = getState(praefix + "MuteMode").val; 320 | SendRoomsWithOpeningsMsg = getState(praefix + "SendRoomsWithOpeningsMsg").val; 321 | SendRoomsWithOpeningsMsgRefresh = getState(praefix + "SendRoomsWithOpeningsMsgRefresh").val; 322 | if (PresenceDp != "") Presence = getState(PresenceDp).val; 323 | 324 | for (let x = 0; x < RoomList.length; x++) { //Messaging DPs einlesen 325 | SendVentMsg[x] = getState(praefix + RoomList[x] + ".SendVentMsg").val; 326 | SendDoorOpenCloseMsg[x] = getState(praefix + RoomList[x] + ".SendDoorOpenCloseMsg").val; 327 | SendWindowOpenCloseMsg[x] = getState(praefix + RoomList[x] + ".SendWindowOpenCloseMsg").val; 328 | SendWindowWarnMsg[x] = getState(praefix + RoomList[x] + ".SendWindowWarnMsg").val; 329 | SendDoorWarnMsg[x] = getState(praefix + RoomList[x] + ".SendDoorWarnMsg").val; 330 | if (logging) log("x=" + x + "=" + RoomList[x] + " SendWindowWarnMsg=" + SendWindowWarnMsg[x] + " SendDoorWarnMsg=" + SendDoorWarnMsg[x] + " SendVentMsg=" + SendVentMsg[x] + " SendWindowOpenCloseMsg=" + SendWindowOpenCloseMsg[x] + " SendDoorOpenCloseMsg=" + SendDoorOpenCloseMsg[x]); 331 | }; 332 | 333 | for (let x = 0; x < Sensor.length; x++) { //Sensor Dps einlesen 334 | SensorVal[x] = SimplyfyWindowStates(getState(Sensor[x]).val, x); // Wert von Sensor in Schleife einlesen 335 | SensorOldVal[x] = ""; 336 | CheckWindow(x); 337 | }; 338 | 339 | for (let x = 0; x < RoomList.length; x++) { //Raum Dps einlesen 340 | RoomsWithVentWarnings[x] = ""; 341 | VentWarnTime[x] = getState(praefix + RoomList[x] + ".VentWarnTime").val; //Lüftungswarnzeiten einlesen 342 | VentMsg[x] = ""; // Lüftungsnachricht mit Leerstring initialisieren 343 | VentCheck(x); 344 | }; 345 | IsInit = false; 346 | } 347 | 348 | function main() { 349 | init(); //Bei Scriptstart alle Sensoren und Räume einlesen 350 | CreateTrigger(); //Trigger erstellen 351 | CreateRoomsWithOpenDoorsList(); //Übersichtsliste mit Räumen mit offenen Türen erstellen 352 | CreateRoomsWithTiltedDoorsList(); //Übersichtsliste mit Räumen mit offenen Türen erstellen 353 | CreateRoomsWithOpenWindowsList(); //Übersichtsliste mit Räumen mit offenen Fenstern erstellen 354 | CreateRoomsWithTiltedWindowsList(); //Übersichtsliste mit Räumen mit gekippten Fenstern erstellen 355 | CreateRoomsWithOpeningsList();//Übersichtsliste mit Räumen mit offenen Fenstern und Türen erstellen 356 | CreateRoomsWithVentWarnings();//Übersichtsliste mit Räumen mit Lüftungswarnung erstellen 357 | CreateOverviewTable(); //HTML Tabelle erstellen 358 | Ticker(); //Minutenticker für Tabellenrefresh starten 359 | RoomsWithOpeningsMsgRefresh(SendRoomsWithOpeningsMsgRefresh); 360 | } 361 | 362 | function RoomsWithOpeningsMsgRefresh(refresh) { 363 | if (typeof RoomsWithOpeningsMsgRefreshTickerObj == "object") clearInterval(RoomsWithOpeningsMsgRefreshTickerObj); 364 | 365 | RoomsWithOpeningsMsgRefreshTickerObj = setInterval(function () { // Wenn 366 | // log("RoomsWithOpeningsMsgRefresh working, refreshtime=" + refresh) 367 | if (SendRoomsWithOpeningsMsg && RoomsWithOpenings != "") { 368 | if (RoomsWithOpenings.substr(RoomsWithOpenings.length - LogEntrySeparator.length, RoomsWithOpenings.length) == LogEntrySeparator) {//Wenn Umbruch am Ende 369 | // log("A " + RoomsWithOpenings.substr(0, RoomsWithOpenings.length - LogEntrySeparator.length)); 370 | Meldung(RoomsWithOpenings.substr(0, RoomsWithOpenings.length - LogEntrySeparator.length)); //Umbruch am Ende entfernen 371 | } else { 372 | // log("B" + RoomsWithOpenings) 373 | Meldung(RoomsWithOpenings); 374 | }; 375 | }; 376 | }, refresh * 1000 * 60); 377 | } 378 | 379 | function Meldung(msg) { 380 | if (logging) log("Reaching Meldung, msg= " + msg + " NoMsgAtPresence= " + NoMsgAtPresence + " Presence= " + Presence); 381 | 382 | if (NoMsgAtPresence && Presence) { 383 | if (logging) log("Meldung blocked cause, NoMsgAtPresence= " + NoMsgAtPresence + " Presence= " + Presence); 384 | } 385 | else { 386 | if (MuteMode != 1 && MuteMode != 2) { 387 | if (UseSay) Say(msg); 388 | 389 | if (UseAlexa) { 390 | if (AlexaId != "") setState(AlexaInstance + ".Echo-Devices." + AlexaId + ".Commands.announcement"/*announcement*/, AlexaVolume + "; " + msg); 391 | }; 392 | }; 393 | if (MuteMode != 2) { 394 | if (UseEventLog) { 395 | WriteEventLog(msg); 396 | }; 397 | 398 | if (UseTelegram) { 399 | sendTo("telegram.0", "send", { 400 | text: msg 401 | }); 402 | }; 403 | 404 | if (UsePushOver) { 405 | sendTo(PushOverInstance, "send", { 406 | device: PushOverDevice, message: msg, title: PushOverTitle, sound: PushOverSound 407 | }); 408 | }; 409 | 410 | if (UseMail) { 411 | sendTo("email", { 412 | html: msg 413 | }); 414 | }; 415 | } 416 | setState(praefix + "LastMessage", msg, true); 417 | WriteMessageLog(msg); 418 | }; 419 | } 420 | 421 | function WriteMessageLog(msg) { 422 | if (logging) log("Reaching WriteMessageLog, Message=" + msg); 423 | let LogEntrys = 0; //Arrayeinträge zählen 424 | 425 | let TempMessageLog = []; 426 | if (MessageLog == null) { //Fehler "Cannot read property 'split' of null" abfangen 427 | if (logging) log("MessageLog=null skiping split"); 428 | } 429 | else { 430 | TempMessageLog = MessageLog.split(LogEntrySeparator); //Logstring in Array wandeln (Entfernt den Separator, deswegen am Funktionsende wieder anhängen) 431 | }; 432 | 433 | if (AutoAddTimestamp) { 434 | LogEntrys = TempMessageLog.unshift(formatDate(new Date(), LogTimeStampFormat) + ": " + msg); //neuen Eintrag am Anfang des Array einfügen, Rückgabewert setzt Zähler 435 | } else { 436 | LogEntrys = TempMessageLog.unshift(msg); //neuen Eintrag am Anfang des Array einfügen, Rückgabewert setzt Zähler 437 | }; 438 | 439 | if (LogEntrys > MaxLogEntrys) { //Wenn durchs anfügen MaxLogEntrys überschritten, einen Eintrag am Ende entfernen 440 | TempMessageLog.splice(MaxLogEntrys - LogEntrys); //Vom Ende des Arrays benötigte Anzahl Einträge löschen. Berücksichtig auch Einstellungsänderung auf niedrigere Zahl. 441 | LogEntrys = TempMessageLog.length; 442 | }; 443 | // log("TempMessageLog=" + TempMessageLog + " Logentrys=" + LogEntrys); 444 | MessageLog = TempMessageLog.join(LogEntrySeparator); //Array zu String wandeln und Separator anhängen 445 | setState(praefix + "MessageLog", MessageLog, true); //Logstring schreiben 446 | } 447 | 448 | function CreateOverviewTable() { // Erzeugt tabellarische Übersicht als HTML Tabelle 449 | let OverviewTable = ""; 450 | let TableSubString = []; 451 | TableSubString[0] = ""; 465 | }; 466 | 467 | // Details / Head 468 | if (ShowDetailTbl) { 469 | OverviewTable += ""; 470 | OverviewTable += ""; 471 | OverviewTable += ""; 474 | //Tabelle der Raumdetails 475 | for (let x = 0; x < RoomList.length; x++) { //Alle Räume durchgehen 476 | OverviewTable += ""; 477 | RoomStateTimeCount[x] = CalcTimeDiff("now", RoomStateTimeStamp[x]); 478 | RoomDoorStateTimeCount[x] = CalcTimeDiff("now", RoomDoorStateTimeStamp[x]); 479 | //log("x=" + x + " Raum = "+RoomList[x] + " RoomStateTimeCount[x] = "+CreateTimeString(RoomStateTimeCount[x]) +" RoomDoorStateTimeCount[x] = "+CreateTimeString(RoomDoorStateTimeCount[x])) 480 | if (RoomOpenWindowCount[x] > 0 || RoomOpenDoorCount[x] > 0) { // Räume mit offenen Fenstern oder Türen 481 | 482 | if (RoomTiltedWindowCount[x] == 0 && RoomOpenWindowCount[x] > 0 && RoomOpenDoorCount[x] == 0) { //Fenster ist offen, keines ist gekippt, Tür/en sind geschlossen 483 | if (RoomHas[x] == 2) { //RoomHas[] 1=Tür, 2=Fenster, 3=Tür+Fenster 484 | OverviewTable += TableSubString[3] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenImg + "'>"; 485 | } else if (RoomHas[x] == 1) { 486 | OverviewTable += TableSubString[3] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorCloseImg + "'>"; 487 | 488 | } else { 489 | OverviewTable += TableSubString[0] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenImg + "'>"; 490 | OverviewTable += TableSubString[0] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorCloseImg + "'>"; 491 | }; 492 | 493 | OverviewTable += TableSubString[5] + OpenWindowColor + ";'>"; 494 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 495 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 496 | OverviewTable += ""; 497 | 498 | OverviewTable += TableSubString[6] + OpenWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 499 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster geöffnet: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 500 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür geschlossen: " + CreateTimeString(RoomDoorStateTimeCount[x]); 501 | 502 | } 503 | else if (RoomTiltedWindowCount[x] > 0 && RoomTiltedWindowCount[x] == RoomOpenWindowCount[x] && RoomOpenDoorCount[x] == 0) { //Fenster ist gekippt, Tür/en sind geschlossen 504 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 505 | OverviewTable += TableSubString[3] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowTiltedImg + "'>"; 506 | } else if (RoomHas[x] == 1) { 507 | OverviewTable += TableSubString[3] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorCloseImg + "'>"; 508 | } else { 509 | OverviewTable += TableSubString[0] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowTiltedImg + "'>"; 510 | OverviewTable += TableSubString[0] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorCloseImg + "'>"; 511 | }; 512 | 513 | OverviewTable += TableSubString[5] + TiltedWindowColor + ";'>"; 514 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 515 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 516 | OverviewTable += ""; 517 | 518 | OverviewTable += TableSubString[6] + TiltedWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 519 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster gekippt:" + CreateTimeString(RoomStateTimeCount[x]) + "
"; 520 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür geschlossen:" + CreateTimeString(RoomDoorStateTimeCount[x]); 521 | } 522 | else if (RoomTiltedWindowCount[x] < RoomOpenWindowCount[x] && RoomOpenDoorCount[x] == 0) { // Fenster sind offen und gekippt, Tür/en sind geschlossen 523 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 524 | OverviewTable += TableSubString[3] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenTiltedImg + "'>"; 525 | } else if (RoomHas[x] == 1) { 526 | OverviewTable += TableSubString[3] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorCloseImg + "'>"; 527 | } else { 528 | OverviewTable += TableSubString[0] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenTiltedImg + "'>"; 529 | OverviewTable += TableSubString[0] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorCloseImg + "'>"; 530 | }; 531 | 532 | OverviewTable += TableSubString[5] + OpenWindowColor + ";'>"; 533 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 534 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 535 | OverviewTable += ""; 536 | 537 | OverviewTable += TableSubString[6] + OpenWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 538 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster geöffnet/gekippt:" + CreateTimeString(RoomStateTimeCount[x]) + "
"; 539 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür geschlossen: " + CreateTimeString(RoomDoorStateTimeCount[x]); 540 | } 541 | 542 | //***************** 543 | 544 | if (RoomTiltedDoorCount[x] > 0 && RoomOpenWindowCount[x] == 0) { // Tür/en gekippt, kein Fenster ist geöffnet 545 | if (RoomHas[x] == 2) { //RoomHas[] 1=Tür, 2=Fenster, 3=Tür+Fenster 546 | OverviewTable += TableSubString[3] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowCloseImg + "'>"; 547 | } else if (RoomHas[x] == 1) { 548 | OverviewTable += TableSubString[3] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorTiltedImg + "'>"; 549 | } else { 550 | OverviewTable += TableSubString[0] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowCloseImg + "'>"; 551 | OverviewTable += TableSubString[0] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorTiltedImg + "'>"; 552 | }; 553 | 554 | OverviewTable += TableSubString[5] + OpenDoorColor + ";'>"; 555 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 556 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 557 | OverviewTable += ""; 558 | 559 | OverviewTable += TableSubString[6] + OpenDoorColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 560 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster geschlossen: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 561 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür gekippt: " + CreateTimeString(RoomDoorStateTimeCount[x]); 562 | } 563 | else if (RoomOpenWindowCount[x] > 0 && RoomTiltedWindowCount[x] == 0 && RoomTiltedDoorCount[x] > 0) { //Fenster ist offen, keines ist gekippt, Tür/en sind gekippt 564 | if (RoomHas[x] == 2) { //RoomHas[] 1=Tür, 2=Fenster, 3=Tür+Fenster 565 | OverviewTable += TableSubString[3] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenImg + "'>"; 566 | } else if (RoomHas[x] == 1) { 567 | OverviewTable += TableSubString[3] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorTiltedImg + "'>"; 568 | } else { 569 | OverviewTable += TableSubString[0] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenImg + "'>"; 570 | OverviewTable += TableSubString[0] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorTiltedImg + "'>"; 571 | }; 572 | 573 | OverviewTable += TableSubString[5] + OpenWindowColor + ";'>"; 574 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 575 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 576 | OverviewTable += ""; 577 | 578 | OverviewTable += TableSubString[6] + OpenWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 579 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster geöffnet: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 580 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür gekippt: " + CreateTimeString(RoomDoorStateTimeCount[x]); 581 | } 582 | else if (RoomTiltedWindowCount[x] > 0 && RoomTiltedWindowCount[x] == RoomOpenWindowCount[x] && RoomTiltedDoorCount[x] > 0) { //Fenster ist gekippt, Tür/en sind gekippt 583 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 584 | OverviewTable += TableSubString[3] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowTiltedImg + "'>"; 585 | } else if (RoomHas[x] == 1) { 586 | OverviewTable += TableSubString[3] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorTiltedImg + "'>"; 587 | } else { 588 | OverviewTable += TableSubString[0] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowTiltedImg + "'>"; 589 | OverviewTable += TableSubString[0] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorTiltedImg + "'>"; 590 | }; 591 | 592 | OverviewTable += TableSubString[5] + TiltedWindowColor + ";'>"; 593 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 594 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 595 | OverviewTable += ""; 596 | 597 | OverviewTable += TableSubString[6] + TiltedWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 598 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster gekippt: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 599 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür gekippt: " + CreateTimeString(RoomDoorStateTimeCount[x]); 600 | } 601 | else if (RoomOpenWindowCount[x] > 0 && RoomTiltedWindowCount[x] < RoomOpenWindowCount[x] && RoomTiltedDoorCount[x] > 0) { // Fenster sind offen und gekippt, Tür/en sind gekippt 602 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 603 | OverviewTable += TableSubString[3] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenTiltedImg + "'>"; 604 | } else if (RoomHas[x] == 1) { 605 | OverviewTable += TableSubString[3] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorTiltedImg + "'>"; 606 | } else { 607 | OverviewTable += TableSubString[0] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenTiltedImg + "'>"; 608 | OverviewTable += TableSubString[0] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorTiltedImg + "'>"; 609 | }; 610 | 611 | OverviewTable += TableSubString[5] + OpenWindowColor + ";'>"; 612 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 613 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 614 | OverviewTable += ""; 615 | 616 | OverviewTable += TableSubString[6] + OpenWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 617 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster geöffnet/gekippt: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 618 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür gekippt: " + CreateTimeString(RoomDoorStateTimeCount[x]); 619 | } 620 | 621 | //*******************/ 622 | else if (RoomOpenDoorCount[x] > 0 && RoomOpenWindowCount[x] == 0) { // Tür/en geöffnet, kein Fenster ist geöffnet 623 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 624 | OverviewTable += TableSubString[3] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowCloseImg + "'>"; 625 | } else if (RoomHas[x] == 1) { 626 | OverviewTable += TableSubString[3] + OpenDoorColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 627 | } else { 628 | OverviewTable += TableSubString[0] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowCloseImg + "'>"; 629 | OverviewTable += TableSubString[0] + OpenDoorColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 630 | }; 631 | 632 | OverviewTable += TableSubString[5] + OpenDoorColor + ";'>"; 633 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 634 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 635 | OverviewTable += ""; 636 | 637 | OverviewTable += TableSubString[6] + OpenDoorColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 638 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster geschlossen: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 639 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür geöffnet: " + CreateTimeString(RoomDoorStateTimeCount[x]); 640 | } 641 | else if (RoomOpenWindowCount[x] > 0 && RoomTiltedWindowCount[x] == 0 && RoomOpenDoorCount[x] > 0) { //Fenster ist offen, keines ist gekippt, Tür/en sind geöffnet 642 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 643 | OverviewTable += TableSubString[3] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenImg + "'>"; 644 | } else if (RoomHas[x] == 1) { 645 | OverviewTable += TableSubString[3] + OpenDoorColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 646 | } else { 647 | OverviewTable += TableSubString[0] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenImg + "'>"; 648 | OverviewTable += TableSubString[0] + OpenDoorColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 649 | }; 650 | 651 | OverviewTable += TableSubString[5] + OpenWindowColor + ";'>"; 652 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 653 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 654 | OverviewTable += ""; 655 | 656 | OverviewTable += TableSubString[6] + OpenWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 657 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster geöffnet: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 658 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür geöffnet: " + CreateTimeString(RoomDoorStateTimeCount[x]); 659 | } 660 | else if (RoomTiltedWindowCount[x] > 0 && RoomTiltedWindowCount[x] == RoomOpenWindowCount[x] && RoomOpenDoorCount[x] > 0) { //Fenster ist gekippt, Tür/en sind geöffnet 661 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 662 | OverviewTable += TableSubString[3] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowTiltedImg + "'>"; 663 | } else if (RoomHas[x] == 1) { 664 | OverviewTable += TableSubString[3] + OpenDoorColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 665 | } else { 666 | OverviewTable += TableSubString[0] + TiltedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowTiltedImg + "'>"; 667 | OverviewTable += TableSubString[0] + OpenDoorColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 668 | }; 669 | 670 | OverviewTable += TableSubString[5] + TiltedWindowColor + ";'>"; 671 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 672 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 673 | OverviewTable += ""; 674 | 675 | OverviewTable += TableSubString[6] + TiltedWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 676 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster gekippt: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 677 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür geöffnet: " + CreateTimeString(RoomDoorStateTimeCount[x]); 678 | } 679 | else if (RoomOpenWindowCount[x] > 0 && RoomTiltedWindowCount[x] < RoomOpenWindowCount[x] && RoomOpenDoorCount[x] > 0) { // Fenster sind offen und gekippt, Tür/en sind geöffnet 680 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 681 | OverviewTable += TableSubString[3] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenTiltedImg + "'>"; 682 | } else if (RoomHas[x] == 1) { 683 | OverviewTable += TableSubString[3] + OpenDoorColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 684 | } else { 685 | OverviewTable += TableSubString[0] + OpenWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + WindowOpenTiltedImg + "'>"; 686 | OverviewTable += TableSubString[0] + OpenDoorColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 687 | }; 688 | 689 | OverviewTable += TableSubString[5] + OpenWindowColor + ";'>"; 690 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 691 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 692 | OverviewTable += ""; 693 | 694 | OverviewTable += TableSubString[6] + OpenWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
"; 695 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += "Fenster geöffnet/gekippt: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 696 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += "Tür geöffnet: " + CreateTimeString(RoomDoorStateTimeCount[x]); 697 | } 698 | 699 | OverviewTable += "
"; 700 | } 701 | else { // Geschlossene Räume 702 | 703 | if (VentMsg[x] == "") { //geschlossen + keine Lüftungswarnung 704 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 705 | OverviewTable += TableSubString[3] + ClosedWindowColor + ";'>"; 706 | } else if (RoomHas[x] == 1) { 707 | OverviewTable += TableSubString[3] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorCloseImg + "'>"; 708 | } else { 709 | OverviewTable += TableSubString[0] + ClosedWindowColor + ";'>"; 710 | OverviewTable += TableSubString[0] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorCloseImg + "'>"; 711 | }; 712 | 713 | OverviewTable += ""; 717 | 718 | 719 | if (RoomHas[x] == 2) OverviewTable += TableSubString[6] + ClosedWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
Fenster geschlossen: " + CreateTimeString(RoomStateTimeCount[x]) + "
"; 720 | if (RoomHas[x] == 1) OverviewTable += TableSubString[6] + ClosedWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
Tür geschlossen: " + CreateTimeString(RoomDoorStateTimeCount[x]); 721 | if (RoomHas[x] == 3) OverviewTable += TableSubString[6] + ClosedWindowColor + ";'>" + ReplaceChars(RoomList[x]) + "
Fenster geschlossen: " + CreateTimeString(RoomStateTimeCount[x]) + "
Tür geschlossen: " + CreateTimeString(RoomDoorStateTimeCount[x]); 722 | 723 | OverviewTable += "
" 724 | } 725 | else { //geschlossen + Lüftungswarnung 726 | if (RoomHas[x] == 2) { //RoomHas[] 0=Weder Tür noch Fenster, 1=Tür, 2=Fenster, 3=Tür+Fenster 727 | OverviewTable += TableSubString[3] + VentWarnColor + ";'>"; 728 | } else if (RoomHas[x] == 1) { 729 | OverviewTable += TableSubString[3] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 730 | } else { 731 | OverviewTable += TableSubString[0] + VentWarnColor + ";'>"; 732 | OverviewTable += TableSubString[0] + ClosedWindowColor + TableSubString[1] + ImgInvert + "); height: 40px;' src='" + DoorOpenImg + "'>"; 733 | }; 734 | 735 | OverviewTable += ""; 739 | 740 | OverviewTable += TableSubString[6] + VentWarnColor + ";'>" + ReplaceChars(RoomList[x]) + "
Raum nicht gelüftet: " + CreateTimeString(RoomStateTimeCount[x]); 741 | OverviewTable += "
"; 742 | }; 743 | }; 744 | }; 745 | OverviewTable += "
"; 472 | OverviewTable += ""; 473 | OverviewTable += "
"; 714 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 715 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 716 | OverviewTable += "
"; 736 | if (RoomHas[x] == 2 || RoomHas[x] == 3) OverviewTable += RoomOpenWindowCount[x] + "
"; 737 | if (RoomHas[x] == 1 || RoomHas[x] == 3) OverviewTable += RoomOpenDoorCount[x]; 738 | OverviewTable += "
"; 746 | }; 747 | setState(praefix + "OverviewTable", OverviewTable, true); 748 | } 749 | 750 | function CalcTimeDiff(time1, time2) { 751 | if (time1 == "now") { 752 | time1 = new Date().getTime(); 753 | }; 754 | //if (logging) log("Reaching CalcTimeDiff, time1=" + time1 + ", time2=" + time2 + ", result= " + CreateTimeString(time1 - time2)); 755 | return (time1 - time2); 756 | } 757 | 758 | function Ticker() { 759 | setInterval(function () { // Wenn 760 | //if (logging) log("Refreshing OverviewTable") 761 | CreateOverviewTable(); 762 | }, 60000); 763 | } 764 | 765 | function ReplaceChars(OrigString) { 766 | //log(typeof OrigString) 767 | if (typeof OrigString == "undefined") OrigString = ""; 768 | let NewString = OrigString.replace("_", " "); 769 | NewString = NewString.replace("ae", "ä"); 770 | NewString = NewString.replace("ue", "ü"); 771 | NewString = NewString.replace("oe", "ö"); 772 | return NewString; 773 | } 774 | 775 | function CreateRoomsWithOpenWindowsList() { //Erzeugt Textliste mit Räumen welche geöffnete Fenster haben 776 | if (logging) log("Reaching CreateRoomsWithOpenWindowsList"); 777 | RoomsWithOpenWindows = ""; //Liste Initialisieren 778 | for (let x = 0; x < RoomList.length; x++) { //Alle Räume durchgehen 779 | //RoomsWithCombinedOpenings[x] = []; 780 | 781 | if (RoomOpenWindowCount[x] > 0) { // Nur Räume mit offenen Fenstern berücksichtigen 782 | if (RoomOpenWindowCount[x] == 1) { //Wenn 1 Fenster offen, Singular Schreibweise 783 | if (RoomTiltedWindowCount[x] == 1) { //Wenn das eine Fenster gekippt ist 784 | RoomsWithOpenWindows += ReplaceChars(RoomList[x]) + " " + RoomOpenWindowCount[x] + " gekipptes Fenster" + OpenWindowListSeparator; 785 | RoomsWithCombinedOpenings[x][0] = RoomOpenWindowCount[x] + " gekipptes Fenster"; 786 | } 787 | else { 788 | RoomsWithOpenWindows += ReplaceChars(RoomList[x]) + " " + RoomOpenWindowCount[x] + " offenes Fenster" + OpenWindowListSeparator; 789 | RoomsWithCombinedOpenings[x][0] = RoomOpenWindowCount[x] + " offenes Fenster"; 790 | }; 791 | } 792 | else { //ansonsten Plural Schreibweise 793 | if (RoomTiltedWindowCount[x] == RoomOpenWindowCount[x]) { //Wenn gekippte Fenster = offene Fenster 794 | RoomsWithOpenWindows += RoomTiltedWindowCount[x] + " gekippte Fenster" + OpenWindowListSeparator; 795 | RoomsWithCombinedOpenings[x][0] = RoomOpenWindowCount[x] + " gekippte Fenster"; 796 | } 797 | else { 798 | RoomsWithOpenWindows += ReplaceChars(RoomList[x]) + " " + RoomOpenWindowCount[x] + " offene Fenster" + OpenWindowListSeparator; 799 | RoomList[x][0] = RoomOpenWindowCount[x] + " offene Fenster"; 800 | RoomsWithCombinedOpenings[x][0] = RoomOpenWindowCount[x] + " offene Fenster"; 801 | if (RoomTiltedWindowCount[x] == 1) { //Wenn 1 Fenster gekippt Singular schreibweise 802 | RoomsWithOpenWindows += " davon " + RoomTiltedWindowCount[x] + " gekipptes Fenster" + OpenWindowListSeparator; 803 | RoomsWithCombinedOpenings[x][0] = RoomOpenWindowCount[x] + " offene Fenster," + " davon " + RoomTiltedWindowCount[x] + " gekipptes Fenster"; 804 | 805 | } 806 | else if (RoomTiltedWindowCount[x] > 1) { //ansonsten Plural Schreibweise 807 | RoomsWithOpenWindows += " davon " + RoomTiltedWindowCount[x] + " gekippte Fenster" + OpenWindowListSeparator; 808 | RoomsWithCombinedOpenings[x][0] = RoomOpenWindowCount[x] + " offene Fenster," + " davon " + RoomTiltedWindowCount[x] + " gekippte Fenster"; 809 | }; 810 | }; 811 | }; 812 | } else { 813 | RoomsWithCombinedOpenings[x][0] = "Alle Fenster sind geschlossen"; 814 | }; 815 | }; 816 | RoomsWithOpenWindows = RoomsWithOpenWindows.substr(0, RoomsWithOpenWindows.length - OpenWindowListSeparator.length); //letzten
Umbruch wieder entfernen 817 | 818 | if (RoomsWithOpenWindows == "") { 819 | RoomsWithOpenWindows = "Alle Fenster sind geschlossen"; 820 | 821 | }; 822 | setState(praefix + "RoomsWithOpenWindows", RoomsWithOpenWindows, true); 823 | if (logging) log("RoomsWithOpenWindows: " + RoomsWithOpenWindows); 824 | } 825 | 826 | function CreateRoomsWithTiltedWindowsList() { //Erzeugt Textliste mit Räumen welche gekippte Fenster haben 827 | if (logging) log("Reaching CreateRoomsWithTiltedWindowsList"); 828 | RoomsWithTiltedWindows = ""; //Liste Initialisieren 829 | for (let x = 0; x < RoomList.length; x++) { //Alle Räume durchgehen 830 | if (RoomTiltedWindowCount[x] > 0) { // Nur Räume mit gekippten Fenstern berücksichtigen 831 | if (RoomTiltedWindowCount[x] == 1) { //Wenn 1 Fenster gekippt, Singular Schreibweise 832 | RoomsWithTiltedWindows += ReplaceChars(RoomList[x]) + " " + RoomTiltedWindowCount[x] + " gekipptes Fenster" + OpenWindowListSeparator; 833 | } 834 | else { //ansonsten Plural Schreibweise 835 | RoomsWithTiltedWindows += ReplaceChars(RoomList[x]) + " " + RoomOpenWindowCount[x] + " gekippte Fenster" + OpenWindowListSeparator; 836 | }; 837 | }; 838 | }; 839 | RoomsWithTiltedWindows = RoomsWithTiltedWindows.substr(0, RoomsWithTiltedWindows.length - OpenWindowListSeparator.length); //letzten
Umbruch wieder entfernen 840 | 841 | if (RoomsWithTiltedWindows == "") { 842 | RoomsWithTiltedWindows = "Keine Fenster gekippt"; 843 | }; 844 | setState(praefix + "RoomsWithTiltedWindows", RoomsWithTiltedWindows, true); 845 | if (logging) log("RoomsWithTiltedWindows: " + RoomsWithTiltedWindows); 846 | } 847 | 848 | function CreateRoomsWithOpenDoorsList() { //Erzeugt Textliste mit Räumen welche offene Türen haben 849 | if (logging) log("Reaching CreateRoomsWithOpenDoorsList"); 850 | RoomsWithOpenDoors = ""; //Liste Initialisieren 851 | for (let x = 0; x < RoomList.length; x++) { //Alle Räume durchgehen 852 | //RoomsWithCombinedOpenings[x] = []; 853 | 854 | if (RoomOpenDoorCount[x] > 0) { // Nur Räume mit offenen Türen berücksichtigen 855 | 856 | if (RoomOpenDoorCount[x] == 1) { //Wenn 1 Tür offen, Singular Schreibweise 857 | RoomsWithOpenDoors += ReplaceChars(RoomList[x]) + " " + RoomOpenDoorCount[x] + " offene Tür" + OpenWindowListSeparator; 858 | RoomsWithCombinedOpenings[x][1] = RoomOpenDoorCount[x] + " offene Tür"; 859 | 860 | } 861 | else { //ansonsten Plural Schreibweise 862 | RoomsWithOpenDoors += ReplaceChars(RoomList[x]) + " " + RoomOpenDoorCount[x] + " offene Türen" + OpenWindowListSeparator; 863 | RoomsWithCombinedOpenings[x][1] = RoomOpenDoorCount[x] + " offene Türen"; 864 | }; 865 | } else { 866 | RoomsWithCombinedOpenings[x][1] = "Keine Tür/en geöffnet"; 867 | }; 868 | }; 869 | RoomsWithOpenDoors = RoomsWithOpenDoors.substr(0, RoomsWithOpenDoors.length - OpenWindowListSeparator.length); //letzten
Umbruch wieder entfernen 870 | 871 | if (RoomsWithOpenDoors == "") { 872 | RoomsWithOpenDoors = "Keine Tür/en geöffnet"; 873 | }; 874 | setState(praefix + "RoomsWithOpenDoors", RoomsWithOpenDoors, true); 875 | if (logging) log("RoomsWithOpenDoors: " + RoomsWithOpenDoors); 876 | } 877 | 878 | function CreateRoomsWithTiltedDoorsList() { //Erzeugt Textliste mit Räumen welche gekippte Türen haben 879 | if (logging) log("Reaching CreateRoomsWithTiltedDoorsList"); 880 | RoomsWithTiltedDoors = ""; //Liste Initialisieren 881 | for (let x = 0; x < RoomList.length; x++) { //Alle Räume durchgehen 882 | if (RoomTiltedDoorCount[x] > 0) { // Nur Räume mit gekippten Türen berücksichtigen 883 | if (RoomTiltedDoorCount[x] == 1) { //Wenn 1 Tür gekippt, Singular Schreibweise 884 | RoomsWithTiltedDoors += ReplaceChars(RoomList[x]) + " " + RoomTiltedDoorCount[x] + " gekippte Tür" + OpenWindowListSeparator; 885 | } 886 | else { //ansonsten Plural Schreibweise 887 | RoomsWithTiltedDoors += ReplaceChars(RoomList[x]) + " " + RoomTiltedDoorCount[x] + " gekippte Türen" + OpenWindowListSeparator; 888 | }; 889 | }; 890 | }; 891 | RoomsWithTiltedDoors = RoomsWithTiltedDoors.substr(0, RoomsWithTiltedDoors.length - OpenWindowListSeparator.length); //letzten
Umbruch wieder entfernen 892 | 893 | if (RoomsWithTiltedDoors == "") { 894 | RoomsWithTiltedDoors = "Keine Tür gekippt"; 895 | }; 896 | setState(praefix + "RoomsWithTiltedDoors", RoomsWithTiltedDoors, true); 897 | if (logging) log("RoomsWithTiltedDoors: " + RoomsWithTiltedDoors); 898 | } 899 | 900 | function CreateRoomsWithOpeningsList() { //Erzeugt Textliste mit Räumen welche offene Türen und/oder Fenster haben 901 | if (logging) log("CreateOpenRoomsList()"); 902 | RoomsWithOpenings = ""; 903 | for (let x = 0; x < RoomList.length; x++) { //Alle Räume durchgehen 904 | if (RoomOpenWindowCount[x] == 0 && RoomOpenDoorCount[x] > 0) { 905 | RoomsWithOpenings += ReplaceChars(RoomList[x]) + " " + RoomsWithCombinedOpenings[x][1] + OpenWindowListSeparator; 906 | } 907 | else if (RoomOpenWindowCount[x] > 0 && RoomOpenDoorCount[x] == 0) { 908 | RoomsWithOpenings += ReplaceChars(RoomList[x]) + " " + RoomsWithCombinedOpenings[x][0] + OpenWindowListSeparator; 909 | } 910 | else if (RoomOpenWindowCount[x] > 0 && RoomOpenDoorCount[x] > 0) { 911 | RoomsWithOpenings += ReplaceChars(RoomList[x]) + " " + RoomsWithCombinedOpenings[x].join(", ") + OpenWindowListSeparator; 912 | } 913 | }; 914 | setState(praefix + "RoomsWithOpenings", RoomsWithOpenings, true); 915 | if (logging) log("RoomsWithOpenings: " + RoomsWithOpenings); 916 | } 917 | 918 | function CreateRoomsWithVentWarnings(x, Warning) { //Erzeugt Liste mit Räumen für die eine Lüftungswarnung besteht 919 | let Tempstring = ""; 920 | if (logging) log("Reaching CreateRoomsWithVentWarnings"); 921 | RoomsWithVentWarnings[x] = Warning; 922 | 923 | for (let y = 0; y < RoomsWithVentWarnings.length; y++) { 924 | if (RoomsWithVentWarnings[y] != "") 925 | Tempstring += RoomList[y] + " nicht gelüftet seit: " + RoomsWithVentWarnings[y] + OpenWindowListSeparator; 926 | }; 927 | Tempstring = Tempstring.substr(0, Tempstring.length - OpenWindowListSeparator.length); 928 | setState(praefix + "RoomsWithVentWarnings", Tempstring, true); 929 | } 930 | 931 | function VentCheck(x) { //Überprüft wie lange Räume geschlossen sind und gibt Lüftungswarnung aus 932 | if (logging) log("Reaching VentCheck x=" + x + " Init=" + IsInit + " VentwarnTime[x]=" + VentWarnTime[x] + " RoomStateTimeStamp[x]=" + RoomStateTimeStamp[x]); 933 | if (RoomOpenWindowCount[x] == 0 && VentWarnTime[x] != 0) { //VentTimeout starten wenn alle Fenster im Raum geschlossen und Warnzeit nicht 0 (= deaktiviert) 934 | if (logging) log("Starting VentInterval for Room " + RoomList[x] + " Time set to: " + VentWarnTime[x] + " days"); 935 | if (IsInit) { //Bei Skriptstart 936 | if (CalcTimeDiff("now", RoomStateTimeStamp[x]) >= getDateObject(VentWarnTime[x] * 24 * 60 * 60 * 1000).getTime()) { //Wenn Ventwarnzeit bei Skriptstart schon überschritten, sofortige Meldung 937 | VentMsg[x] = CreateTimeString(RoomStateTimeCount[x]); 938 | CreateRoomsWithVentWarnings(x, VentMsg[x]); 939 | if (SendVentMsg[x]) Meldung(ReplaceChars(RoomList[x]) + " nicht gelüftet " + VentMsg[x]); 940 | } else { //Wenn Ventwarnzeit bei Skriptstart noch nicht überschritten, Restzeit berechnen und einmaligen Timeout starten welcher bei Ablauf den regulären Interval startet 941 | 942 | if (logging) log("Remaining Vent Warn DiffTime at startup= " + CreateTimeString(CalcTimeDiff(VentWarnTime[x] * 24 * 60 * 60 * 1000, RoomStateTimeCount[x]))) 943 | VentMsgHandler[x] = setTimeout(function () { 944 | RoomStateTimeCount[x] = CalcTimeDiff("now", RoomStateTimeStamp[x]); //RoomstateTimeCount aktualisieren um exakten Wert bei Ausgabe zu haben und 23 Stunden 59 Minuten Meldungen zu vermeiden 945 | 946 | VentMsg[x] = CreateTimeString(RoomStateTimeCount[x]); 947 | CreateRoomsWithVentWarnings(x, VentMsg[x]); 948 | if (SendVentMsg[x]) { 949 | Meldung(ReplaceChars(RoomList[x]) + " nicht gelüftet " + VentMsg[x]); 950 | CreateOverviewTable(); 951 | }; 952 | if (logging) log("Init Vent Timeout exceeded now calling regular Interval for x=" + x); 953 | VentCheck(x); 954 | }, CalcTimeDiff(VentWarnTime[x] * 24 * 60 * 60 * 1000, RoomStateTimeCount[x])); 955 | }; 956 | 957 | } else { //Normalbetrieb, kein Init 958 | VentMsgHandler[x] = setInterval(function () { // Neuen Timeout setzen, volle Warnzeit 959 | RoomStateTimeCount[x] = CalcTimeDiff("now", RoomStateTimeStamp[x]); //RoomstateTimeCount aktualisieren um exakten Wert bei Ausgabe zu haben und 23 Stunden 59 Minuten Meldungen zu vermeiden 960 | VentMsg[x] = CreateTimeString(RoomStateTimeCount[x]); //Watch!! 961 | CreateRoomsWithVentWarnings(x, VentMsg[x]) 962 | if (SendVentMsg[x]) { 963 | Meldung(ReplaceChars(RoomList[x]) + " nicht gelüftet " + VentMsg[x]); 964 | CreateOverviewTable(); 965 | }; 966 | }, VentWarnTime[x] * 24 * 60 * 60 * 1000); 967 | }; 968 | if (logging) log("VentMsg=" + VentMsg[x]); 969 | } 970 | else if (RoomOpenWindowCount[x] != 0 || VentWarnTime[x] == 0) { 971 | if (logging) log("Room " + x + " = " + RoomList[x] + " is open or disabled, no vent warning set"); 972 | CreateRoomsWithVentWarnings(x, ""); 973 | ClearVentTime(x); 974 | VentMsg[x] = ""; 975 | }; 976 | } 977 | 978 | 979 | function GetRoom(x) { // Liefert den Raum von Sensor x 980 | if (logging) log("Reaching GetRoom x=" + x) 981 | let room = getObject(Sensor[x], 'rooms').enumNames[0]; 982 | if (typeof room == "undefined") { 983 | log("Kein Raum definiert bei Sensor " + Sensor[x], 'error'); 984 | return "Kein Raum definiert"; 985 | }; 986 | if (typeof room == 'object') room = room.de; 987 | return room; 988 | } 989 | 990 | function CheckWindow(x) { //Für einzelnes Fenster/Tür. Via Trigger angesteuert. Eigentliche Primärauswertefunktion des Skriptes 991 | let TempRoom = GetRoom(x); //Raum des aktuellen Sensors bestimmen 992 | let TempRoomIndex = RoomList.indexOf(TempRoom); // Raumlistenindex für aktuellen Raum bestimmen 993 | if (logging) log("reaching CheckWindow, SensorVal[" + x + "]=" + SensorVal[x] + " SensorOldVal=" + SensorOldVal[x] + " TempRoom=" + TempRoom + " SensorType[x]=" + SensorType[x] + " TempRoomIndex=" + TempRoomIndex) 994 | 995 | if (((SensorVal[x] == "open") && (SensorOldVal[x] == "closed" || SensorOldVal[x] == "" || SensorOldVal[x] != "tilted")) || ((SensorVal[x] == "tilted") && (SensorOldVal[x] == "closed" || SensorOldVal[x] == "" || SensorOldVal[x] != "open"))) { //Fenster war geschlossen und wurde geöffnet oder gekippt - Wechsel von open auf tilted nicht berücksichtigt!!! 996 | 997 | if (SensorType[x] == "Window") { 998 | if (RoomOpenWindowCount[TempRoomIndex] == 0) setState(praefix + TempRoom + ".WindowIsOpen", true, true); 999 | if (RoomOpenWindowCount[TempRoomIndex] == 0) setState(praefix + TempRoom + ".RoomIsOpen", true, true); 1000 | 1001 | OpenWindowCount++; //Gesamtfensterzähler erhöhen 1002 | RoomOpenWindowCount[TempRoomIndex]++; //Raumfensterzähler erhöhen 1003 | 1004 | if (logging) log("RoomOpenWindowCount für " + TempRoom + "=" + RoomOpenWindowCount[TempRoomIndex]); 1005 | setState(praefix + TempRoom + ".RoomOpenWindowCount", RoomOpenWindowCount[TempRoomIndex], true); 1006 | 1007 | if (!IsInit) { 1008 | if (RoomOpenWindowCount[TempRoomIndex] == 1) { 1009 | RoomStateTimeStamp[TempRoomIndex] = new Date().getTime(); //Bei Erstöffnung Zeitstempel für Raum auf jetzt setzen 1010 | }; 1011 | 1012 | if (SensorVal[x] == "open") { 1013 | if (logging) log(TempRoom + " Fenster geöffnet"); 1014 | if (SendWindowOpenCloseMsg[TempRoomIndex]) Meldung(ReplaceChars(TempRoom) + " Fenster geöffnet!"); 1015 | if (UseEventLog) WriteEventLog(ReplaceChars(TempRoom) + " Fenster geöffnet!"); 1016 | } 1017 | else if (SensorVal[x] == "tilted") { 1018 | if (logging) log(TempRoom + " Fenster gekippt"); 1019 | if (SendWindowOpenCloseMsg[TempRoomIndex]) Meldung(ReplaceChars(TempRoom) + " Fenster gekippt!"); 1020 | if (UseEventLog) WriteEventLog(ReplaceChars(TempRoom) + " Fenster gekippt!"); 1021 | }; 1022 | 1023 | }; 1024 | 1025 | if (RoomOpenWindowCount[TempRoomIndex] == 1) { 1026 | if (logging) log("SendWindowWarnMsg=" + SendWindowWarnMsg[TempRoomIndex] + " TempRoomIndex=" + TempRoomIndex) 1027 | WindowWarnRuntime[TempRoomIndex] = 0; 1028 | if (SendWindowWarnMsg[TempRoomIndex]) { 1029 | if (logging) log("Setting Interval to Room:" + TempRoom); 1030 | OpenWindowMsgHandler[TempRoomIndex] = setInterval(function () {// Interval starten und Dauer bei Ansage aufaddieren 1031 | WindowWarnRuntime[TempRoomIndex] = WindowWarnRuntime[TempRoomIndex] + TimeToWindowMsg; 1032 | if (RoomWindowMsgCount[TempRoomIndex] <= MaxMessages - 1) Meldung(ReplaceChars(TempRoom) + "fenster seit " + CreateTimeString(CalcTimeDiff("now", RoomStateTimeStamp[TempRoomIndex])) + " geöffnet!"); 1033 | RoomWindowMsgCount[TempRoomIndex]++; 1034 | }, TimeToWindowMsg); 1035 | }; 1036 | }; 1037 | } else if (SensorType[x] == "Door") { 1038 | if (RoomOpenDoorCount[TempRoomIndex] == 0) setState(praefix + TempRoom + ".DoorIsOpen", true, true); 1039 | if (RoomOpenDoorCount[TempRoomIndex] == 0) setState(praefix + TempRoom + ".RoomIsOpen", true, true); 1040 | 1041 | OpenDoorCount++; //Gesamttürzähler erhöhen 1042 | RoomOpenDoorCount[TempRoomIndex]++; //Raumtürzähler erhöhen 1043 | 1044 | if (logging) log("RoomOpenDoorCount für " + TempRoom + "=" + RoomOpenDoorCount[TempRoomIndex]); 1045 | setState(praefix + TempRoom + ".RoomOpenDoorCount", RoomOpenDoorCount[TempRoomIndex], true); 1046 | 1047 | if (!IsInit) { 1048 | if (RoomOpenDoorCount[TempRoomIndex] == 1) { 1049 | RoomDoorStateTimeStamp[TempRoomIndex] = new Date().getTime(); //Bei Erstöffnung Zeitstempel für Raum auf jetzt setzen 1050 | }; 1051 | if (SensorVal[x] == "open") { 1052 | if (logging) log(TempRoom + " Tür geöffnet"); 1053 | if (SendDoorOpenCloseMsg[TempRoomIndex]) Meldung(ReplaceChars(TempRoom) + " Tür geöffnet!"); 1054 | if (UseEventLog) WriteEventLog(ReplaceChars(TempRoom) + " Tür geöffnet!"); 1055 | } 1056 | else if (SensorVal[x] == "tilted") { 1057 | if (logging) log(TempRoom + " Tür gekippt"); 1058 | if (SendDoorOpenCloseMsg[TempRoomIndex]) Meldung(ReplaceChars(TempRoom) + " Tür gekippt!"); 1059 | if (UseEventLog) WriteEventLog(ReplaceChars(TempRoom) + " Tür gekippt!"); 1060 | }; 1061 | }; 1062 | 1063 | if (RoomOpenDoorCount[TempRoomIndex] == 1) { 1064 | if (logging) log("SendDoorWarnMsg=" + SendDoorWarnMsg[TempRoomIndex] + " TempRoomIndex=" + TempRoomIndex) 1065 | DoorWarnRuntime[TempRoomIndex] = 0; 1066 | if (SendDoorWarnMsg[TempRoomIndex]) { 1067 | if (logging) log("Setting Interval to Room:" + TempRoom); 1068 | OpenDoorMsgHandler[TempRoomIndex] = setInterval(function () {// Interval starten und Dauer bei Ansage aufaddieren 1069 | DoorWarnRuntime[TempRoomIndex] = DoorWarnRuntime[TempRoomIndex] + TimeToDoorMsg; 1070 | if (RoomDoorMsgCount[TempRoomIndex] <= MaxMessages - 1) Meldung(ReplaceChars(TempRoom) + "tür seit " + CreateTimeString(CalcTimeDiff("now", RoomDoorStateTimeStamp[TempRoomIndex])) + " geöffnet!"); 1071 | RoomDoorMsgCount[TempRoomIndex]++; 1072 | }, TimeToDoorMsg); 1073 | }; 1074 | }; 1075 | 1076 | } 1077 | } 1078 | else if (SensorVal[x] == "closed") { 1079 | if (SensorType[x] == "Window") { 1080 | if (!IsInit) { // Wenn nicht in Initialisierungsphase (Skriptstart) 1081 | if (OpenWindowCount > 0) OpenWindowCount--; 1082 | if (RoomOpenWindowCount[TempRoomIndex] > 0) RoomOpenWindowCount[TempRoomIndex]--; 1083 | if (RoomOpenWindowCount[TempRoomIndex] == 0) { // Wenn letztes Fenster geschlossen 1084 | RoomStateTimeStamp[TempRoomIndex] = new Date().getTime(); //Bei schliessen Zeitstempel für Raum setzen 1085 | if (logging) log(TempRoom + " Fenster geschlossen."); 1086 | if (SendWindowOpenCloseMsg[TempRoomIndex]) Meldung(ReplaceChars(TempRoom) + " Fenster geschlossen!"); 1087 | if (UseEventLog) WriteEventLog(ReplaceChars(TempRoom) + " Fenster geschlossen!"); 1088 | }; 1089 | }; 1090 | setState(praefix + TempRoom + ".RoomOpenWindowCount", RoomOpenWindowCount[TempRoomIndex], true); 1091 | } 1092 | else if (SensorType[x] == "Door") { 1093 | if (!IsInit) { // Wenn nicht in Initialisierungsphase (Skriptstart) 1094 | if (OpenDoorCount > 0) OpenDoorCount--; 1095 | if (RoomOpenDoorCount[TempRoomIndex] > 0) RoomOpenDoorCount[TempRoomIndex]--; 1096 | if (RoomOpenDoorCount[TempRoomIndex] == 0) { // Wenn letzte Tür geschlossen 1097 | RoomDoorStateTimeStamp[TempRoomIndex] = new Date().getTime(); //Bei schliessen Zeitstempel für Raum setzen 1098 | if (logging) log(TempRoom + " Tür geschlossen."); 1099 | if (SendDoorOpenCloseMsg[TempRoomIndex]) Meldung(ReplaceChars(TempRoom) + " Tür geschlossen!"); 1100 | if (UseEventLog) WriteEventLog(ReplaceChars(TempRoom) + " Tür geschlossen!"); 1101 | }; 1102 | }; 1103 | if (logging) log("RoomOpenDoorCount[TempRoomIndex]=" + RoomOpenDoorCount[TempRoomIndex] + " TempRoom=" + TempRoom + " TempRoomIndex=" + TempRoomIndex) 1104 | setState(praefix + TempRoom + ".RoomOpenDoorCount", RoomOpenDoorCount[TempRoomIndex], true); 1105 | }; 1106 | 1107 | if (RoomOpenWindowCount[TempRoomIndex] == 0) { //Wenn alle Fenster im Raum geschlossen, Dp aktualisieren und Intervall/Timeout löschen 1108 | setState(praefix + TempRoom + ".WindowIsOpen", false, true); 1109 | ClearWindowWarnTime(TempRoomIndex); 1110 | }; 1111 | 1112 | if (RoomOpenDoorCount[TempRoomIndex] == 0) { //Wenn alle Türen im Raum geschlossen, Dp aktualisieren 1113 | setState(praefix + TempRoom + ".DoorIsOpen", false, true); 1114 | ClearDoorWarnTime(TempRoomIndex); 1115 | }; 1116 | 1117 | if (RoomOpenDoorCount[TempRoomIndex] == 0 && RoomOpenWindowCount[TempRoomIndex] == 0) { //Wenn alle Türen und Fenster im Raum geschlossen, Dp aktualisieren 1118 | setState(praefix + TempRoom + ".RoomIsOpen", false, true); 1119 | }; 1120 | }; 1121 | 1122 | //*************Bereich gekippte Fenster */ 1123 | if (SensorType[x] == "Window") { 1124 | if (SensorVal[x] == "tilted") { 1125 | if (logging) log("Reaching tilted+ in checkWindow"); 1126 | TiltedWindowCount++; //Gekippte Fenster Zähler erhöhen 1127 | RoomTiltedWindowCount[TempRoomIndex]++; 1128 | setState(praefix + TempRoom + ".RoomTiltedWindowCount", RoomTiltedWindowCount[TempRoomIndex], true); 1129 | if (logging) log("TiltedWindowCount=" + TiltedWindowCount + " RoomTiltedWindowCount=" + RoomTiltedWindowCount[TempRoomIndex] + " TempRoomIndex=" + TempRoomIndex) 1130 | } 1131 | else if ((SensorVal[x] != "tilted" && SensorOldVal[x] == "tilted") && IsInit == false) { //Bei Wechsel von gekippt auf offen oder geschlossen und keine Initphase 1132 | if (logging) log("Reaching tilted- in checkWindow"); 1133 | TiltedWindowCount--; //Gekippte Fenster Zähler erniedrigen 1134 | RoomTiltedWindowCount[TempRoomIndex]--; 1135 | if (TiltedWindowCount < 0) TiltedWindowCount = 0; 1136 | if (RoomTiltedWindowCount[TempRoomIndex] < 0) RoomTiltedWindowCount[TempRoomIndex] = 0; 1137 | 1138 | setState(praefix + TempRoom + ".RoomTiltedWindowCount", RoomTiltedWindowCount[TempRoomIndex], true); 1139 | if (logging) log("TiltedWindowCount=" + TiltedWindowCount + " RoomTiltedWindowCount=" + RoomTiltedWindowCount[TempRoomIndex] + " TempRoomIndex=" + TempRoomIndex) 1140 | }; 1141 | 1142 | if (IsInit && RoomTiltedWindowCount[TempRoomIndex] == 0) { 1143 | setState(praefix + TempRoom + ".RoomTiltedWindowCount", RoomTiltedWindowCount[TempRoomIndex], true); 1144 | }; 1145 | 1146 | if (RoomOpenWindowCount[TempRoomIndex] == 0 && RoomOpenDoorCount[TempRoomIndex] == 0) { 1147 | setState(praefix + TempRoom + ".RoomIsOpen", false, true); 1148 | } 1149 | else { 1150 | setState(praefix + TempRoom + ".RoomIsOpen", true, true); 1151 | }; 1152 | } 1153 | /***************Ende Bereich gekippte Fenster Beginn Bereich gekippte Türen*/ 1154 | 1155 | 1156 | if (SensorType[x] == "Door") { 1157 | if (SensorVal[x] == "tilted") { 1158 | if (logging) log("Reaching tilted+ in checkWindow"); 1159 | TiltedDoorCount++; //Gekippte Türen Zähler erhöhen 1160 | RoomTiltedDoorCount[TempRoomIndex]++; 1161 | setState(praefix + TempRoom + ".RoomTiltedDoorCount", RoomTiltedDoorCount[TempRoomIndex], true); 1162 | if (logging) log("TiltedDoorCount=" + TiltedDoorCount + " RoomTiltedDoorCount=" + RoomTiltedDoorCount[TempRoomIndex] + " TempRoomIndex=" + TempRoomIndex) 1163 | } 1164 | else if ((SensorVal[x] != "tilted" && SensorOldVal[x] == "tilted") && IsInit == false) { //Bei Wechsel von gekippt auf offen oder geschlossen und keine Initphase 1165 | if (logging) log("Reaching tilted- in checkDoor"); 1166 | TiltedDoorCount--; //Gekippte Türen Zähler erniedrigen 1167 | RoomTiltedDoorCount[TempRoomIndex]--; 1168 | if (TiltedDoorCount < 0) TiltedDoorCount = 0; 1169 | if (RoomTiltedDoorCount[x] < 0) RoomTiltedDoorCount[x] = 0; 1170 | 1171 | setState(praefix + TempRoom + ".RoomTiltedDoorCount", RoomTiltedDoorCount[TempRoomIndex], true); 1172 | if (logging) log("TiltedDoorCount=" + TiltedDoorCount + " RoomTiltedDoorCount=" + RoomTiltedDoorCount[TempRoomIndex] + " TempRoomIndex=" + TempRoomIndex) 1173 | }; 1174 | 1175 | if (IsInit && RoomTiltedDoorCount[TempRoomIndex] == 0) { 1176 | setState(praefix + TempRoom + ".RoomTiltedDoorCount", RoomTiltedDoorCount[TempRoomIndex], true); 1177 | }; 1178 | 1179 | if (RoomOpenWindowCount[TempRoomIndex] == 0 && RoomOpenDoorCount[TempRoomIndex] == 0) { 1180 | setState(praefix + TempRoom + ".RoomIsOpen", false, true); 1181 | } 1182 | else { 1183 | setState(praefix + TempRoom + ".RoomIsOpen", true, true); 1184 | }; 1185 | } 1186 | /***************Ende Bereich gekippte Türen*/ 1187 | 1188 | 1189 | 1190 | RoomOpenCount[TempRoomIndex] = RoomOpenDoorCount[TempRoomIndex] + RoomOpenWindowCount[TempRoomIndex]; 1191 | setState(praefix + TempRoom + ".RoomOpenCount", RoomOpenCount[TempRoomIndex], true); 1192 | 1193 | if (OpenWindowCount == 0) { //Wenn kein Fenster mehr offen Datenpunkte aktualisieren 1194 | setState(praefix + "WindowsOpen", 0, true); 1195 | setState(praefix + "WindowsTilted", 0, true); 1196 | setState(praefix + "AllWindowsClosed", true, true); 1197 | if (logging) log("Alle Fenster geschlossen."); 1198 | } 1199 | else if (OpenWindowCount != 0) { //ansonsten ebenfalls Datenpunkte (mit anderen Werten) aktualisieren 1200 | setState(praefix + "WindowsOpen", OpenWindowCount, true); 1201 | setState(praefix + "WindowsTilted", TiltedWindowCount, true); 1202 | setState(praefix + "AllWindowsClosed", false, true); 1203 | }; 1204 | 1205 | if (logging) log("Offene Fenster gesamt= " + OpenWindowCount); 1206 | 1207 | if (OpenDoorCount == 0) { //Wenn keine Tür mehr offen Datenpunkte aktualisieren 1208 | setState(praefix + "DoorsOpen", 0, true); 1209 | setState(praefix + "DoorsTilted", 0, true); 1210 | setState(praefix + "AllDoorsClosed", true, true); 1211 | if (logging) log("Alle Türen geschlossen."); 1212 | } 1213 | else { //ansonsten ebenfalls Datenpunkte (mit anderen Werten) aktualisieren 1214 | setState(praefix + "DoorsOpen", OpenDoorCount, true); 1215 | setState(praefix + "DoorsTilted", TiltedDoorCount, true); 1216 | setState(praefix + "AllDoorsClosed", false, true); 1217 | }; 1218 | 1219 | if (logging) log("Offene Türen gesamt= " + OpenDoorCount); 1220 | 1221 | if (IsInit) { // Wenn in Initialisierungsphase (Skriptstart) 1222 | RoomStateTimeStamp[TempRoomIndex] = getState(praefix + RoomList[TempRoomIndex] + ".WindowIsOpen").lc; 1223 | RoomDoorStateTimeStamp[TempRoomIndex] = getState(praefix + RoomList[TempRoomIndex] + ".DoorIsOpen").lc; 1224 | 1225 | } 1226 | else { 1227 | if (SensorType[x] == "Window") VentCheck(TempRoomIndex); 1228 | if (logging) log("RoomStateTimeStamp at checkWindow= " + RoomStateTimeStamp[TempRoomIndex] + " ms =" + formatDate(RoomStateTimeStamp[TempRoomIndex], LogTimeStampFormat)); 1229 | }; 1230 | 1231 | RoomStateTimeCount[TempRoomIndex] = CalcTimeDiff("now", RoomStateTimeStamp[TempRoomIndex]); 1232 | RoomDoorStateTimeCount[TempRoomIndex] = CalcTimeDiff("now", RoomDoorStateTimeStamp[TempRoomIndex]); 1233 | 1234 | } 1235 | 1236 | function CheckForHmShit(val, x) { 1237 | if (logging) log("Reaching CheckForHmShit val=" + val + " typof val=" + typeof (val) + " x=" + x + " Sensor[x]=" + Sensor[x]); 1238 | 1239 | if (Sensor[x].indexOf("hm-rpc.") != -1) { //Prüfen ob Sensor= HM Sensor 1240 | if (getObject(Sensor[x]).common.states) { //Prüfen ob Wertelistentext vorhanden 1241 | if (logging) log(Sensor[x] + " hat Zustandstext " + getObject(Sensor[x]).common.states[val] + ", Wert= " + val + " Wert wird durch Zustandstext ersetzt"); 1242 | return getObject(Sensor[x]).common.states[val]; //Wert durch Zustandstext ersetzen um HM Wertekuddelmuddel bei HM Sensoren zu kompensieren und in Kleinbuchstaben wandeln 1243 | } 1244 | else { 1245 | // if (logging) log(Sensor[x] + "(HM) hat keinen Zustandstext, Wert wird beibehalten") 1246 | return val; 1247 | }; 1248 | } 1249 | else { 1250 | // if (logging) log(Sensor[x] + " ist non HM, Wert wird beibehalten") 1251 | return val; 1252 | }; 1253 | 1254 | } 1255 | 1256 | function SimplyfyWindowStates(val, x) { //Die verschiedenen Gerätestates zu open, close oder tilted vereinfachen 1257 | val = String(val).toLowerCase(); 1258 | val = CheckForHmShit(val, x).toLowerCase(); 1259 | 1260 | if (WindowIsOpenWhen.indexOf(val) != -1) { // Suche in Fensteroffenarray, wenn gefunden, Status auf open setzen 1261 | return "open"; 1262 | } 1263 | else if (WindowIsClosedWhen.indexOf(val) != -1) { // Suche in Fenstergeschlossenarray, wenn gefunden, Status auf closed setzen 1264 | return "closed"; 1265 | } 1266 | else if (WindowIsTiltedWhen.indexOf(val) != -1) { // Suche in Fenstergekipptarray, wenn gefunden, Status auf tilted setzen 1267 | return "tilted"; 1268 | }; 1269 | 1270 | if (val != "open" && val != "closed" && val != "tilted") { // Suche in Fensteroffenarray und Fenstergeschlossenarray, wenn nirgends gefunden, Status auf closed setzen und Logwarnung ausgeben 1271 | log("Unknown Windowstate " + SensorVal[x] + " detected at " + Sensor[x] + ", please check your configuration", "warn"); 1272 | return "unknown"; 1273 | }; 1274 | } 1275 | 1276 | function CreateTimeString(mstime) { 1277 | let TimeString; 1278 | mstime += 1000; //Eine Sekunde erhöhen um 59Min, 59Sek Meldungen zu vermeiden 1279 | let days = Math.floor(mstime / (1000 * 60 * 60 * 24)); 1280 | mstime = mstime % (1000 * 60 * 60 * 24); 1281 | 1282 | let hours = Math.floor(mstime / (1000 * 60 * 60)); 1283 | mstime = mstime % (1000 * 60 * 60); 1284 | 1285 | let mins = Math.floor(mstime / (1000 * 60)); 1286 | mstime = mstime % (1000 * 60); 1287 | 1288 | let seks = Math.floor(mstime / 1000); 1289 | 1290 | if (days > 0) { 1291 | if (days == 1) { //Singular 1292 | TimeString = days + " Tag "; 1293 | } else { //Plural 1294 | TimeString = days + " Tage "; 1295 | }; 1296 | } else { 1297 | TimeString = ""; 1298 | }; 1299 | 1300 | if (hours > 0) { 1301 | if (hours == 1) { //Singular 1302 | TimeString = TimeString + hours + " Std. "; 1303 | } else { //Plural 1304 | TimeString = TimeString + hours + " Std. "; 1305 | }; 1306 | } else { 1307 | TimeString = TimeString + ""; 1308 | }; 1309 | 1310 | if (mins > 0) { 1311 | if (mins == 1) { //Singular 1312 | TimeString = TimeString + mins + " Min. "; 1313 | } else { //Plural 1314 | TimeString = TimeString + mins + " Min. "; 1315 | }; 1316 | } else { 1317 | TimeString = TimeString + ""; 1318 | }; 1319 | /* 1320 | if (seks > 0) { 1321 | if (seks == 1) { //Singular 1322 | TimeString = TimeString + seks + " Sekunde "; 1323 | } else { //Plural 1324 | TimeString = TimeString + seks + " Sekunden "; 1325 | }; 1326 | } else { 1327 | TimeString = TimeString + ""; 1328 | }; 1329 | //if (logging) log(TimeString); 1330 | */ 1331 | if (TimeString == "") TimeString = "gerade eben" 1332 | //if (logging) log("days=" + days + ", hours=" + hours + ", mins=" + mins + ", seks=" + seks + ", Timestring=" + TimeString) 1333 | return TimeString.trim(); 1334 | } 1335 | 1336 | function ClearVentTime(x) { 1337 | if (typeof (VentMsgHandler[x]) == "object") { //Wenn ein Interval oder Timeout gesetzt ist, löschen 1338 | if (logging) log("Clearing Interval for " + x) 1339 | clearInterval(VentMsgHandler[x]); 1340 | clearTimeout(VentMsgHandler[x]); 1341 | }; 1342 | } 1343 | 1344 | function ClearWindowWarnTime(x) { 1345 | if (logging) log("reaching ClearWindowWarnTime - [x] = " + [x]); 1346 | 1347 | if (typeof (OpenWindowMsgHandler[x]) == "object") { //Wenn ein Interval gesetzt ist, löschen 1348 | if (logging) log("Clearing Interval for " + x) 1349 | clearInterval(OpenWindowMsgHandler[x]); // 1350 | RoomWindowMsgCount[x] = 0; //Nachrichtenzähler wieder resetten 1351 | }; 1352 | } 1353 | 1354 | function ClearDoorWarnTime(x) { 1355 | if (logging) log("reaching ClearDoorWarnTime - [x] = " + [x]); 1356 | 1357 | if (typeof (OpenDoorMsgHandler[x]) == "object") { //Wenn ein Interval gesetzt ist, löschen 1358 | if (logging) log("Clearing Door Interval for " + x) 1359 | clearInterval(OpenDoorMsgHandler[x]); // 1360 | RoomDoorMsgCount[x] = 0; //Nachrichtenzähler wieder resetten 1361 | }; 1362 | } 1363 | 1364 | function CreateTrigger() { 1365 | //Trigger für Sensoren erzeugen 1366 | let IgnoreTime; 1367 | for (let x = 0; x < Sensor.length; x++) { //Alle Sensoren durchlaufen 1368 | IgnoreInProcess[x] = true; 1369 | on(Sensor[x], function (dp) { //Trigger in Schleife erstellen 1370 | if (SensorType[x] == "Window") { 1371 | IgnoreTime = WindowIgnoreTime 1372 | } else if (SensorType[x] == "Door") { 1373 | IgnoreTime = DoorIgnoreTime 1374 | }; 1375 | if (logging) log("Trigger= " + x + " Wert= " + dp.state.val + " Alter Wert= " + dp.oldState.val + " dp.channelId=" + dp.channelId + " dp.channelName=" + dp.channelName); 1376 | //if (logging) log("Trigger= " + x + " Wert= " + dp.state.val + " Alter Wert= " + dp.oldState.val); 1377 | if (IgnoreInProcess[x] == true) { //Bei erster Triggerung aktuellen Sensorwert merken und Timeout starten 1378 | // log("Oldstate=" + dp.oldState.val) 1379 | IgnoreValue[x] = SimplyfyWindowStates(dp.oldState.val, x); 1380 | IgnoreInProcess[x] = false; 1381 | if (logging) log("Activating Ignore Timeout for " + x + ", Value to ignore=" + IgnoreValue[x]); 1382 | setTimeout(function () { 1383 | if (logging) log("InTimeout - Trigger= " + x + " Wert= " + dp.state.val + " Alter Wert= " + dp.oldState.val); 1384 | if (SimplyfyWindowStates(getState(Sensor[x]).val, x) != IgnoreValue[x]) { //Nachdem Timeout abgelaufen, vergleichen ob gemerkter Wert mit aktuellem Wert übereinstimmt, wenn nicht, Aktionen starten 1385 | if (logging) log("Ignore Timeout for " + x + " exceeded, Value change happend, starting Functions"); 1386 | SensorVal[x] = SimplyfyWindowStates(getState(Sensor[x]).val, x); // Alles in String und Kleinschreibweise wandeln 1387 | SensorOldVal[x] = IgnoreValue[x]; // Alles in String und Kleinschreibweise wandeln 1388 | CheckWindow(x); 1389 | CreateRoomsWithOpenWindowsList(); 1390 | CreateRoomsWithTiltedWindowsList(); 1391 | CreateRoomsWithOpenDoorsList(); 1392 | CreateRoomsWithTiltedDoorsList(); 1393 | CreateRoomsWithOpeningsList(); 1394 | CreateOverviewTable(); 1395 | } else { 1396 | if (logging) log("Ignore Timeout for " + x + " exceeded, no Value change, nothing to do. Actual Value=" + SimplyfyWindowStates(getState(Sensor[x]).val, x) + " remembered Value=" + IgnoreValue[x]); 1397 | }; 1398 | IgnoreInProcess[x] = true; 1399 | }, IgnoreTime); 1400 | }; 1401 | }); 1402 | }; 1403 | 1404 | //Trigger für Räume erzeugen 1405 | for (let x = 0; x < RoomList.length; x++) { //Alle Räume durchlaufen 1406 | on(praefix + RoomList[x] + ".VentWarnTime", function (dp) { //Trigger für VentwarnTime Einstellfeld in Schleife erstellen 1407 | if (logging) log("Raum= " + RoomList[x] + " VentWarnTime= " + dp.state.val + " Alter Wert= " + dp.oldState.val); 1408 | VentWarnTime[x] = dp.state.val; 1409 | IsInit = true 1410 | ClearVentTime(x); 1411 | VentMsg[x] = ""; 1412 | VentCheck(x); 1413 | IsInit = false 1414 | CreateOverviewTable(); 1415 | }); 1416 | on(praefix + RoomList[x] + ".SendVentMsg", function (dp) { //Trigger für SendMsgDps erzeugen 1417 | SendVentMsg[x] = dp.state.val; 1418 | }); 1419 | on(praefix + RoomList[x] + ".SendWindowOpenCloseMsg", function (dp) { //Trigger 1420 | SendWindowOpenCloseMsg[x] = dp.state.val; 1421 | }); 1422 | on(praefix + RoomList[x] + ".SendDoorOpenCloseMsg", function (dp) { //Trigger 1423 | SendDoorOpenCloseMsg[x] = dp.state.val; 1424 | }); 1425 | on(praefix + RoomList[x] + ".SendWindowWarnMsg", function (dp) { //Trigger 1426 | SendWindowWarnMsg[x] = dp.state.val; 1427 | ClearWindowWarnTime(x); 1428 | }); 1429 | on(praefix + RoomList[x] + ".SendDoorWarnMsg", function (dp) { //Trigger 1430 | SendDoorWarnMsg[x] = dp.state.val; 1431 | ClearWindowWarnTime(x); 1432 | }); 1433 | 1434 | }; 1435 | 1436 | 1437 | on(praefix + "MuteMode", function (dp) { //Trigger für MuteMode erzeugen 1438 | MuteMode = dp.state.val; 1439 | }); 1440 | on(praefix + "SendRoomsWithOpeningsMsg", function (dp) { //Trigger für SendRoomsWithOpeningsMsg erzeugen 1441 | SendRoomsWithOpeningsMsg = dp.state.val; 1442 | }); 1443 | on(praefix + "SendRoomsWithOpeningsMsgRefresh", function (dp) { //Trigger für SendRoomsWithOpeningsMsgRefresh erzeugen 1444 | SendRoomsWithOpeningsMsgRefresh = dp.state.val; 1445 | RoomsWithOpeningsMsgRefresh(dp.state.val); 1446 | }); 1447 | if (PresenceDp != "") { //Trigger fürPresenceDp erzeugen wenn vorhanden 1448 | if (logging) log("PresenceDp available, created Trigger for Presence") 1449 | on(PresenceDp, function (dp) { //Trigger für Presence erzeugen 1450 | Presence = dp.state.val; 1451 | if (logging) log("Presence changed to " + Presence) 1452 | }); 1453 | }; 1454 | 1455 | onStop(function () { //Bei Scriptende alle Timer löschen 1456 | for (let x = 0; x < RoomList.length; x++) { 1457 | ClearVentTime(x); 1458 | ClearWindowWarnTime(x); 1459 | if (typeof RoomsWithOpeningsMsgRefreshTickerObj == "object") clearInterval(RoomsWithOpeningsMsgRefreshTickerObj); 1460 | }; 1461 | }, 100); 1462 | } 1463 | --------------------------------------------------------------------------------