NEWS

  • Starter

    Liebe Community!

    Kurzfassung
    Hier stelle ich ein Skript für eine Alarmanlage vor. Einfach die Einstellungen im Skript anpassen und über die erzeugten Datenpunkte (default unter javascript.0.Alarmanlage) steuern.

    LG Andreas

    Langfassung

    Aufbau
    Die Alarmanlage besteht aus folgenden Komponenten:

    • Schaltstellen für scharf/unscharf Schaltung
    • Alarmgeber
    • Einbruchsmelder

    Außer den Einbruchsmeldern werden alle Punkte NUR als Datenpunkte angelegt, über die eine weitere Interaktion erfolgen kann. Hierfür bietet ioBroker ja zahlreiche Möglichkeiten wie die Einbindung in eine Visualisierung, die Verwendung in Scripts, Szenen, Blocklys und so weiter.
    Für die Einbruchsmelder werden States aus ioBroker verwendet, die true beim Auslösen sind und false in Ruhe (wenn sie geschlossen sind). Die Namen der Melder sollten sinnvoll vergeben sein, gegebenenfalls daher die name-Attribute der Objekte in ioBroker noch anpassen. Die Melder müssen in Aufzählungen (ENUMs) in ioBroker eingefügt werden. Per default (kann in den Experteneinstellungen im Skript geändert werden) sind das die folgenden Aufzählungen:

    • alarmanlage_aussenhaut
      In dieser Aufzählung befinden sich alle Melder der äußeren Hülle, die überwacht werden soll. Hier gehören Öffnungskontakte, Glasbruchsensoren, Riegelschaltkontakt, etc. hinein.
    • alarmanlage_innenraum
      Hier werden die Melder für die Innenraum-Überwachung zusammengefasst. Das sind im wesentlichen Bewegungsmelder, Näherungssensoren, eventuell auch ganz normale Taster (z.B. für Licht etc.).
    • alarmanlage_verzoegert
      Melder, welche für einen Eingang benötigt werden, der bei Auslösung zu einem verzögerten Alarm führt. Damit kann durch der überwachte Bereich durch die Eingangstür betreten werden und danach (innerhalb der Eingangsverzögerung) unscharf gestellt werden.

    Funktion: scharf/unscharf Schalten
    Grundsätzlich kann die Alarmanlage extern oder intern scharf geschaltet werden. Extern bedeutet, dass sich der Bediener selbst extern aufhält und somit alle verfügbaren Melder verwendet werden.
    Intern bedeutet, dass sich der Bediener intern aufhält und somit nur die Melder zur Überwachung der Außenhaut verwendet werden.
    Die Scharfschaltung für Extern kann auch verzögert erfolgen. Dabei läuft eine Ausgangsverzögerungszeit ab nach dem Schaltbefehl. Nach dem Ende der Verzögerungszeit erfolgt erst die tatsächliche Scharfschaltung.

    Das bedeutet also, dass Melder in Außenhaut oder Innenraum eingeteilt werden. Zusätzlich können Melder aus diesen Gruppen auch als verzögert gelten. Diese drei Gruppen von Meldern müssen in den entsprechenden Aufzählungen enthalten sein.

    ACHTUNG: Scharf (egal, ob extern oder intern) kann nur geschaltet werden, wenn sich alle Melder in Ruhe befinden, also geschlossen sind! Sollte das nicht der Fall sein, so ist die Anlage nicht bereit zur Scharfschaltung. Dies wird in einem eigenen Ready-Datenpunkt angezeigt, sowie im AlarmText.
    Sollte eine Scharfschaltung eingehen, obwohl die Anlage nicht bereit ist, so wird ein Fehler bei der Scharfschaltung durch den Error-Datenpunkt und wieder einem entsprechenden AlarmText angezegt.
    Das kann auch dazu führen, dass bei verzögertem scharf Schalten ein Fehler bei der Scharfschaltung auftritt, den man unter Umständen nicht mehr bemerkt, weil man schon das Haus verlassen hat. Das muss man wissen oder sich einen Hinweis darauf erzeugen, zB durch ein Skript, etwa das Versenden einer Telegram-Meldung im Fehlerfall.

    Funktion: Alarm geben
    Bei scharf gestellter Anlage wird bei Auslösung eines Melders geprüft, welcher Schaltzustand vorherrscht (intern/extern) und welchen Meldergruppen der auslösende Melder zuzuordnen ist. Davon abhängig wird Alarm ausgelöst oder die Eingangsverzögerung gestartet. Nach dieser erfolgt die Alarmierung, sofern nicht zwischenzeitlich unscharf geschaltet wird.

    Bei den Alarmgebern werden drei Datenpunkte angeboten:
    Der AlarmAccoustical ist der akustische Alarm, dieser darf in Ö übrigens 3 Minuten nicht übersteigen. Die Werte bei den Einstellungen werden in Sekunden eingegeben, also maximal 180 Sekunden (keine eingebaute Beschränkung im Skript).
    Der AlarmOptical ist der optische Alarm. Dieser darf so lange dauern, wie gewünscht. Soll er ewig antehen bis zum nächsten unscharf, dann kann die Zahl -1 für die Dauer verwendet werden.
    Der ganz normale Alarm Datenpunkt steht immer auf true, wenn ein Alarm ausgelöst wurde bis zum nächsten unscharf.

    Bedienung oder Verwendung der Input-Datenpunkte
    Über die States im Unterpunkt Input kann die Anlage scharf/unscharf geschaltet werden.
    Mit dem Wert true auf den Datenpunkten erfolgt der Schaltbefehl unmittelbar oder verzögert im Falle von SwitchExternalDelayed.
    Mit dem Wert false wird immer sofort auf unscharf geschaltet.

    Mit unscharf erfolgt auch immer ein Reset der Anlage, d.h. alle Alarme werden beendet und der Status- und Alarmtext entsprechend angepasst.

    Es kann nicht von einem Scharf-Zustand auf einen anderen Scharf-Zustand gewechselt werden, es muss immer dazwischen unscharf geschaltet werden, ansonsten wird ein "Fehler bei der Scharfschaltung" geworfen.

    Verwendung der Output-Datenpunkte
    Über die Output-Datenpunkte können die Alarmgeber angesteuert werden (z.B. über ein zusätliches Script oder Blockly). Es gibt auch eine Menge an weiteren Datenpunkten, die für zusätzliche Funktionen oder Anzeigen in Visualisierungen nützlich sein können. Hier eine Auflistung mit kurzer Erklärung:

    • Active: Schaltzustand der Anlage insgesamt, true=scharf, false=unscharf. [boolean]
    • ActiveInternal: Anlage intern scharf [boolean]
    • ActiveExternal: Anlage extern scharf [boolean]
    • ActiveNumber: gibt Auskunft über den tatsächlichen Zustand mit den Ziffern:
      0 ... unscharf
      1 ... intern scharf
      2 ... extern scharf
      3 ... Eingangsverzögerung aktiv
      4 ... Ausgangsverzögerung aktiv
    • Alarm: true=Alarm ausgelöst, false=kein Alarm [boolean]
    • AlarmAccoustical: Akustischer Alarm aktiv [boolean]
    • AlarmOptical: Optischer Alarm aktiv [boolean]
    • Ready: Anlage bereit zur Scharfschaltung [boolean]
    • EntryDelayActive: Eintrittsverzögerung aktiv [boolean]
    • ExitDelayActive: Ausgangsverzögerung aktiv [boolean]
    • AlarmingDetector: Name des auslösenden Melders [string]
    • AlarmingDetectorJSON: Name und alle weiteren verfügbaren Eigenschaften des auslösenden Melderobjektes und dessen Parent- und ParentsParent-Objekt im JSON-Format. [string]
    • OpenDetectors: Namen aller offenen Melder [string]
    • OpenDetectorsJSON: JSON-String wie beim AlarmingDetector mit Liste aller offenen Melder [string]
    • OpenDetectorsOuterSkingJSON: JSON-String wie beim AlarmingDetector mit Liste aller offenen Melder der Außenhaut [string]
    • OpenDetectorsIndoorJSON: JSON-String wie beim AlarmingDetector mit Liste aller offenen Melder des Innenraums [string]
    • StatusText: Gibt Auskunft über Schaltzustand und aktive Verzögerungen [string]
    • AlarmText: Gibt Auskunft über Alarmzustand und Bereitschaft oder Fehler bei der Scharfschaltung [string]

    Die Texte, die in den Text-Datenpunkten verwendet werden, können in den Einstellungen im Skript angepasst werden.

    Das Skript

    /*
    ########################################################################################################################
    # ALARMSYSTEM
    #
    # Das Skript bildet eine einfache Alarmanlage nach mit der Schaltmöglichkeit
    # für intern und extern.
    # Datenpunkte für Inputs und Outputs werden angelegt.
    # Nähere Beschreibung siehe im ioBroker-Forum unter
    # https://forum.iobroker.net/topic/32885/umfassendes-alarmanlagen-skript
    # Änderungshistorie:
    # 2020-05-01    Andreas Kos     Erstellt
    # 2020-05-02    Andreas Kos     Schaltwunsch mit Number-Datenpunkt Input.SwitchNumber (Idee von @Homer.J.)
    #                               Schaltstatus mit Number-Datenpunkt Output.ActiveNumber (Idee von @Homer.J.)
    # 2020-05-03    Andreas Kos     Korrekturen, u.a. für Melderauswertung (chage: "ne") & AlarmText
    # 2020-05-04    Andreas Kos     - Melder werden aus den Functions (Aufzählungen, enums) dafür geholt. Auch beim Unscharf-
    #                                 schalten, dadurch ist kein Neustarten des Skripts notwendig bei
    #                                 Änderungen an diesen Aufzählungen.
    #                               - Eine Schaltung von einem scharf-Zustand auf einen anderen
    #                                 wird verhindert. ZB von scharf intern auf scharf extern.
    #                                 Es muss immer unscharf dazwischen geschaltet werden.
    # 2020-05-09    Andreas Kos     Zusätzliche Objekte mit JSON-Strings für:
    #                               - den auslösenden Melder
    #                               - alle offenen Melder
    #                               - alle offenen Melder der Außenhaut
    #                               - alle offenen Melder des Innenraums
    #                               Die JSON-String beinhalten das auslösende Objekt, sowie (falls vorhanden)
    #                               das Parent und das ParentsParent-Objekt mit allen in ioBroker verfügbaren Eigenschaften.
    #                               Kleinere Verbesserungen, z.B. bezüglich setzen der AlarmTexte.
    # 2020-05-12    Andreas Kos     Setzen des Datenpunkts idReady zur Bereitschaftsanzeige neu gemacht.
    ########################################################################################################################
    */
    
    // EINBRUCHSMELDER
    // Jeder Melder muss ein State sein, der bei Auslösung true liefert und in Ruhe (geschlossen) false.
    // Die Melder sind in Arrays zusammengefasst, d.h. sie müssen jeweils mit Beistrich voneinander getrennt werden.
    // Die Namen der Melder sollten gut gepflegt sein für eine sinnvolle Verwendung (Attribut name bei den Objekten)
    
    // Melder der Außenhaut
    // Dies können Öffnungskontakte sein von Fenster und Türen in den Außenmauern des Objekts.
    // EINGABE: In der Aufzählung "alarmanlage_aussenhaut" die States einfügen.
    
    // Melder des Innenraums
    // Dies können Bewegungsmelder sein aus dem Inneren.
    // EINGABE: In der Aufzählung "alarmanlage_innenraum" die States einfügen.
    
    // Verzögerte Melder
    // Diese kommen in den Gruppen oben auch vor. Sie bewirken eine Aktivierung der Eingangsverzögerung
    // bei scharf geschalteter Anlage und erlauben während der Ausgangsverzögerung nach dem
    // Scharfschalten das Haus zu verlassen.
    // EINGABE: In der Aufzählung "alarmanlage_verzoegert" die States einfügen.
    
    
    // EINSTELLUNGEN
    const entryDelay =                30;         // Eingangsverzögerung in Sekunden (sollte maximal 60s sein)
    const exitDelay =                 30;         // Ausgangsverzögerung in Sekunden (sollte maximal 60s sein)
    const alarmDurationAccoustical =  180;         // Dauer des akkustischen Alarms in Sekunden (ACHTUNG: in Ö sind maximal 180s erlaubt!)
    const alarmDurationOptical =      -1;         // Dauer des optischen Alarm in Sekunden, -1 für unendlich
    
    // TEXTE FÜR SCHALTZUSTAND
    // Diese Text geben Auskunft über den Zustand der Anlage.
    // Sie werden in den Datenpunkt "javascript.X.Output.StatusText" geschrieben.
    const textStatusInactive =        "unscharf";
    const textStatusActiveInternal =  "scharf intern";
    const textStatusActiveExternal =  "scharf extern";
    const textActiveExternalDelayed = "scharf extern verzögert";
    const textEntryDelayActive =      "Eingangsverzögerung aktiv";
    const textExitDelayActive =       "Ausgangsverzögerung aktiv";
    
    // TEXTE FÜR ALARMIERUNG UND FEHLER
    // Diese Text geben im unscharfen Zustand der Anlage Auskunft über die Bereitschaft
    // zum Scharfschalten (nur möglich, wenn alle Melder geschlossen - in Ruhe - sind) und
    // Fehler bei der Scharfschaltung bzw. bei scharfer Anlage über den Zustand Frieden oder Alarm.
    // Sie werden in den Datenpunkt "javascript.X.Output.AlarmText" geschrieben.
    const textAlarmInactive =         "Alles OK";
    const textAlarmActive =           "Alarm!!";
    const textReady =                 "Bereit";
    const textNotReady =              "Nicht bereit";
    const textError =                 "Fehler bei der Scharfschaltung";
    
    // EXPERTEN-EINSTELLUNGEN
    const pathToCreatedStates = "Alarmanlage";    // Beispiel: States werden erzeugt unter javascript.X.Alarmanlage
    const seperator = ", ";                       // Trenn-String, der zwischen den Meldernamen verwendet wird, im Datenpunkt "OpenDetectors"
    const loglevel = 2;                           // 0 bis 3. 0 ist AUS, 3 ist maximales Logging
                                                // Empfehlung für Nachvollziehbarkeit aller Handlungen ist 2 (Ereignisliste)
    const functionOuterSkin = "alarmanlage_aussenhaut";
    const functionIndoor = "alarmanlage_innenraum";
    const functionDelayedDetectors = "alarmanlage_verzoegert";
    
    /*
       ###############################################################################
                        DO NOT CHANGE ANYTHING BELOW THIS LINE
                             AB HIER NICHTS MEHR ÄNDERN
       ###############################################################################
    */
    
    // ===============================================================================
    // Variablen
    // ===============================================================================
    
    // Arrays für die Melder
    var detectorsOuterSkin = [];
    var detectorsIndoor = [];
    var detectorsDelayed = [];
    
    // Javascript-Instanz mit der das Alarmanlagen-Skript ausgeführt wird
    var javascriptInstance = instance;
    
    // States, die erzeugt werden für Status-Ausgaben
    var idActive = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.Active";
    var idActiveExternal = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.ActiveExternal";
    var idActiveInternal = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.ActiveInternal";
    var idActiveNumber = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.ActiveNumber";
    var idAlarm = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.Alarm";
    var idAlarmAccoustical = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.AlarmAccoustical";
    var idAlarmOptical = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.AlarmOptical";
    var idReady = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.Ready";
    var idEntryDelayActive = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.EntryDelayActive";
    var idExitDelayActive = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.ExitDelayActive";
    var idAlarmingDetector = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.AlarmingDetector";
    var idAlarmingDetectorJSON = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.AlarmingDetectorJSON";
    var idOpenDetectors = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.OpenDetectors";
    var idOpenDetectorsJSON = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.OpenDetectorsJSON";
    var idOpenDetectorsOuterSkinJSON = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.OpenDetectorsOuterSkinJSON";
    var idOpenDetectorsIndoorJSON = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.OpenDetectorsIndoorJSON";
    var idStatusText = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.StatusText";
    var idAlarmText = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.AlarmText";
    var idError = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Output.Error";
    
    // States, die erzeugt werden für Eingaben
    var idSwitchExternal = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Input.SwitchExternal";
    var idSwitchInternal = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Input.SwitchInternal";
    var idSwitchExternalDelayed = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Input.SwitchExternalDelayed";
    var idSwitchNumber = "javascript." + javascriptInstance + "." + pathToCreatedStates + ".Input.SwitchNumber";
    
    // Sonstige globale Variablen, die gebraucht werden
    var timerExitDelay = null;
    var timerTexts = null;
    
    // ===============================================================================
    // Precode
    // ===============================================================================
    
    // Logging
    if (loglevel >= 1) log ("Alarmsystem started.");
    
    getAllDetectors();
    
    // States erzeugen
    myCreateState(idActive, "boolean", false, "Switch Status Total", false, "info.status");
    myCreateState(idActiveExternal, "boolean", false, "Switch Status External", false, "info.status");
    myCreateState(idActiveInternal, "boolean", false, "Switch Status Internal", false, "info.status");
    myCreateState(idAlarm, "boolean", false, "Alarm Status", false, "sensor.alarm");
    myCreateState(idAlarmAccoustical, "boolean", false, "Accoustical Alarm Status", false, "sensor.alarm");
    myCreateState(idAlarmOptical, "boolean", false, "Optical Alarm Status", false, "sensor.alarm");
    myCreateState(idReady, "boolean", false, "Alarmsystem Ready", false, "info.status");
    myCreateState(idError, "boolean", false, "Error Switching Active", false, "info.status");
    myCreateState(idEntryDelayActive, "boolean", false, "Entry Delay Active Status", false, "info.status");
    myCreateState(idExitDelayActive, "boolean", false, "Exit Delay Active Status", false, "info.status");
    myCreateState(idAlarmingDetector, "string", "", "Alarming Detector", false, "text");
    myCreateState(idAlarmingDetectorJSON, "string", "", "Alarming Detector JSON", false, "json");
    myCreateState(idOpenDetectors, "string", "", "Open Detectors", false, "info.name");
    myCreateState(idOpenDetectorsJSON, "string", "", "Open Detectors JSON", false, "json");
    myCreateState(idOpenDetectorsOuterSkinJSON, "string", "", "Open Detectors Outer Skin JSON", false, "json");
    myCreateState(idOpenDetectorsIndoorJSON, "string", "", "Open Detectors Indoor JSON", false, "json");
    myCreateState(idStatusText, "string", "", "Status Text", false, "text");
    myCreateState(idAlarmText, "string", "", "Alarm Text", false, "text");
    myCreateState(idSwitchExternal, "boolean", false, "Enable Surveillance External", true, "switch");
    myCreateState(idSwitchInternal, "boolean", false, "Enable Surveillance Internal", true, "switch");
    myCreateState(idSwitchExternalDelayed, "boolean", false, "Enable Surveillance External Delayed", true, "switch");
    
    myCreateMultiState (idActiveNumber, "number", 0, "Switch Status Number", false, 0, 4,"0:"+textStatusInactive+"; 1:"+textStatusActiveInternal+"; 2:"+textStatusActiveExternal+"; 3:"+textExitDelayActive+"; 4:"+textEntryDelayActive);
    myCreateMultiState (idSwitchNumber, "number", 0, "Switch by Number", true, 0, 3, "0:"+textStatusInactive+"; 1:"+textStatusActiveInternal+" ; 2:"+textStatusActiveExternal+" ; 3:"+textActiveExternalDelayed);
    
    // Melder nach dem Starten checken
    checkDetectors(detectorsOuterSkin.concat(detectorsIndoor));
    
    // ===============================================================================
    // ON-Subscribtions
    // ===============================================================================
    
    // Auf Schaltstellen EXTERN verzögert reagieren (schalten EIN/AUS)
    on ({id: idSwitchExternalDelayed, change: "any"}, function(obj){
        if (loglevel >= 3) log ("Switching External Delayed, Value: " + getState(obj.id).val);
        if (getState(obj.id).val) { // Einschalten, scharf extern VERZÖGERT
            if (loglevel >= 2) log ("Switching required: Delayed External Active");
                if (getState(idActive).val) {
                    if (loglevel >= 3) log ("Alarmsystem already active, switch to inactive first!");
                    setState(idError, true);
                } else {
                    setState(idExitDelayActive, true);
                    if (timerExitDelay) clearTimeout(timerExitDelay);
                    timerExitDelay = setTimeout(switchActiveExternal, exitDelay * 1000);
                }
        }
        else { // Ausschalten, unscharf SOFORT
            if (loglevel >= 2) log ("Switching required: Inactive");
            switchInactive();
        }
    });
    
    // Auf Schaltstellen EXTERN sofort reagieren (schalten EIN/AUS)
    on ({id: idSwitchExternal, change: "any"}, function(obj){
        if (loglevel >= 3) log ("Switching External Immediately, Value: " + getState(obj.id).val);
        if (getState(obj.id).val) { // Einschalten, scharf extern
            if (loglevel >= 2) log ("Switching required: External Active");
            if (getState(idActive).val) {
                if (loglevel >= 3) log ("Alarmsystem already active, switch to inactive first!");
                setState(idError, true);
            } else {
                switchActiveExternal();
            }
        }
        else { // Ausschalten, unscharf
            if (loglevel >= 2) log ("Switching required: Inactive");
            switchInactive();
        }
    });
    
    // Auf Schaltstellen INTERN sofort reagieren (schalten EIN/AUS)
    on ({id: idSwitchInternal, change: "any"}, function(obj){
        if (loglevel >= 3) log ("Switching Internal, Value: " + getState(obj.id).val);
        if (getState(obj.id).val) { // Einschalten, scharf intern
            if (loglevel >= 2) log ("Switching required: Internal Active");
            if (getState(idActive).val) {
                if (loglevel >= 3) log ("Alarmsystem already active, switch to inactive first!");
                setState(idError, true);
            } else {
                switchActiveInternal();
            }
        }
        else { // Ausschalten, unscharf
            switchInactive();
            if (loglevel >= 2) log ("Switching required: Inactive");
        }
    });
    
    // Auf Schaltstelle mit Datenpunkt SwitchNumber reagieren
    // Folgende Reaktionen:
    //      0 ... unscharf schalten
    //      1 ... scharf intern schalten
    //      2 ... scharf extern schalten
    //      3 ... verzögert scharf extern schalten
    on ({id: idSwitchNumber, change: "any"}, function(obj){
        if (loglevel >= 3) log ("Switching Number, Value: " + obj.state.val);
        switch (obj.state.val) {
            case 0:
                if (loglevel >= 2) log ("Switching required: Inactive");
                switchInactive();
                break;
            case 1:
                if (loglevel >= 2) log ("Switching required: Internal Active");
                if (getState(idActive).val) {
                    if (loglevel >= 3) log ("Alarmsystem already active, switch to inactive first!");
                    setState(idError, true);
                } else {
                    switchActiveInternal();
                }
                break;
            case 2:
                if (loglevel >= 2) log ("Switching required: External Active");
                if (getState(idActive).val) {
                    if (loglevel >= 3) log ("Alarmsystem already active, switch to inactive first!");
                    setState(idError, true);
                } else {
                    switchActiveExternal();
                }
                break;
            case 3:
                if (loglevel >= 2) log ("Switching required: Delayed External Active");
                if (getState(idActive).val) {
                    if (loglevel >= 3) log ("Alarmsystem already active, switch to inactive first!");
                    setState(idError, true);
                } else {
                    setState(idExitDelayActive, true);
                    if (timerExitDelay) clearTimeout(timerExitDelay);
                    timerExitDelay = setTimeout(switchActiveExternal, exitDelay * 1000);
                }
                break;
            default:
                if (loglevel >= 3) log ("idSwitchNumber has unknown number!");
        }
    });
    
    // Auf Fehler bei der Scharfschaltung reagieren
    on ({id: idError, val: true, change: "any"}, function(obj){
        if (loglevel >= 1) log ("Error when switching to active.");
        setState(idAlarmText, textError);
    });
    
    // Auf Eingangsverzögerung reagieren
    on({id: idEntryDelayActive, val: true, change: "ne"}, function (obj) {
        if (loglevel >= 2) log ("Entry Delay is active (" + entryDelay + " seconds)");
        setState(idStatusText, textEntryDelayActive);
        setStateDelayed(idAlarmAccoustical, true, entryDelay * 1000);
        setStateDelayed(idAlarmOptical, true, entryDelay * 1000);
    });
    
    // Auf Ausgangsverzögerung reagieren
    on({id: idExitDelayActive, val: true, change: "ne"}, function (obj) {
        if (loglevel >= 2) log ("Exit Delay is active (" + exitDelay + " seconds)");
        setState(idStatusText, textExitDelayActive);
    });
    
    // Auf Akustischen Alarm reagieren
    on ({id: idAlarmAccoustical, val: true, change: "ne"}, function(obj){
        if (loglevel >= 1) log ("ALARM is active!");
        setState(idEntryDelayActive, false);
        setState(idAlarmText, textAlarmActive);
        setState(idAlarm, true);
        setStateDelayed(idAlarmAccoustical, false, alarmDurationAccoustical * 1000);
        if (getState(idActiveExternal).val) setState(idStatusText, textStatusActiveExternal);
        if (getState(idActiveInternal).val) setState(idStatusText, textStatusActiveInternal);
    });
    
    // Auf Optischen Alarm reagieren
    on ({id: idAlarmOptical, val: true, change: "ne"}, function(obj){
        if (alarmDurationOptical >= 0)
            setStateDelayed(idAlarmOptical, false, alarmDurationOptical * 1000);
    });
    
    // Melderauswertung
    on( {id: detectorsOuterSkin.concat(detectorsIndoor), change: "ne"}, function(obj){
        detectorSurveillance(obj);
    });
    
    // Status in Active.Number schreiben
    on ({id: [idActiveInternal, idActiveExternal, idEntryDelayActive, idExitDelayActive], change: "ne"}, function(obj){
        if (loglevel >= 3) log ("on for writing ActiveNumber, Trigger: " + obj.id);
        setActiveNumber();
    });
    
    // Texte korrekt setzen
    on ({id: [idAlarm, idActive, idOpenDetectors], change: "any"}, function (obj) {
        // Das Timeout ggf. abbrechen
        if (timerTexts) clearTimeout(timerTexts);  
        // Nach einem Timeout den Check anfangen
        timerTexts = setTimeout(setTexts, 200);
    });
    
    
    
    // ===============================================================================
    // Funktionen
    // ===============================================================================
    
    // Function setTexts
    // =================
    // Parameter:       keiner
    // Funktion:        Abhängig von den Zuständen scharf/unscharf und
    //                  Alarm / Kein Alarm werden Texte für
    //                  den AlarmText richtig gesetzt. Auch der Datenpunkt idReady wird hier gesetzt.
    // Rückgabewert:    keiner
    function setTexts(){    
        var textListOfDetectors = getState(idOpenDetectors).val;
        if (textListOfDetectors.length > 0) {
            if (!getState(idActive).val)
                // Offene Melder gefunden und unscharf
                setState(idAlarmText, textNotReady);
                setState(idReady, false);
            return false;
        } else {
            if (getState(idActive).val && !getState(idAlarm).val)
                // kein offener Melder gefunden und scharf und kein Alarm
                setState(idAlarmText, textAlarmInactive);
            else if (!getState(idActive).val)
                // kein offener Melder gefunden und unscharf
                setState(idAlarmText, textReady);
                setState(idReady, true);
            return true;
        }
    }
    
    // Function getAllDetectors
    // ========================
    // Parameter:       keiner
    // Funktion:        Über die Funktion getDetectorsFromFunction werden
    //                  alle Melder von den Functions geholt und in die
    //                  globalen Variablen dafür geschrieben.
    // Rückgabewert:    keiner
    function getAllDetectors(){
        detectorsOuterSkin = getDetectorsFromFunction(functionOuterSkin);
        detectorsIndoor = getDetectorsFromFunction(functionIndoor);
        detectorsDelayed = getDetectorsFromFunction(functionDelayedDetectors);
    }
    
    // Function getDetectorsFromFunction
    // =================================
    // Parameter:       functionString
    //                  Name der Function, in der die Melder enthalen sind.
    // Funktion:        Alle Teilnehmer der übergebenen Function werden
    //                  in ein Array geschrieben.
    // Rückgabewert:    Array der Melder
    function getDetectorsFromFunction( functionString ) {
        if (loglevel >= 3) log ("Function getDetectorsFromFunction");
        var detectors = [];
        $('state(functions='+functionString+')').each(function(id, i) {
            detectors.push(id);
            if (loglevel >= 3) log ("This detector was added to surveillance from function "+functionString+": " + id);
        });
        return detectors;
    }
    
    // Function detectorSurveillance
    // =============================
    // Parameter:       obj
    //                  Objekt des auslösenden Melders
    // Funktion:        Abhängig vom Schaltzustand werden die Melder überprüft.
    //                  Bei unscharf wird nur die Liste der offenen Melder und die
    //                  Bereitschaft der Anlage zum Scharfschalten gepfelgt.
    //                  Bei scharf geschalteter Anlage ist es anders:
    //                  Es wird geprüft, ob der auslösende Melder in den Außenhaut- oder
    //                  Innenraum-Meldern enthalten ist und ob dieser ein verzögerter Melder ist.
    //                  Abhängig davon wird entweder sofort oder verzögert Alarm ausgelöst.
    // Rückgabewert:    keiner
    function detectorSurveillance (obj) {
        var active = getState(idActive).val;
        var activeExternal = getState(idActiveExternal).val;
        var activeInternal = getState(idActiveInternal).val;
        var ready;
        
        if (loglevel >= 2) log ("Surveillance of detectors started, triggering detector: " + obj.common.name);
    
        // Alle offenen Melder feststellen
        ready = checkDetectors(detectorsOuterSkin.concat(detectorsIndoor));
    
        // Auslösenden Melder schreiben
        setState(idAlarmingDetector, obj.common.name);
        setState(idAlarmingDetectorJSON, JSON.stringify(  getDetectorObject(obj.id)  ));
    
        // Prüfen, wie der der Schaltzustand ist
        // bei unscharf
        if (!active) {
            if (loglevel >= 2) log ("Alarmsystem is Inactive");
        }
        // bei scharf intern
        if (activeInternal) {
            if (loglevel >= 2) log ("Alarmsystem is Internal Active");
            if (detectorsOuterSkin.indexOf(obj.id) != -1) {
                if (loglevel >= 3) log ("Detector is part of Outer Skin");
                if (detectorsDelayed.indexOf(obj.id) != -1) {
                    if (loglevel >= 3) log ("Detector is part of Delayed Detectors");
                    if(!getState(idAlarm).val) setState(idEntryDelayActive, true);
                    else {
                        if (loglevel >= 3) log ("EntryDelay was already active, alarming now");
                        setState(idAlarmAccoustical, true);
                        setState(idAlarmOptical, true);
                    }
                } else {
                    if (loglevel >= 3) log ("Detector is not delayed");
                    setState(idAlarmAccoustical, true);
                    setState(idAlarmOptical, true);
                }
            }
        }
        // bei scharf extern
        if (activeExternal) {
            if (loglevel >= 2) log ("Alarmsystem is External Active");
            if (detectorsOuterSkin.concat(detectorsIndoor).indexOf(obj.id) != -1) {
                if (loglevel >= 3) log ("Detector is part of Outer Skin or Indoor");
                if (detectorsDelayed.indexOf(obj.id) != -1) {
                    if (loglevel >= 3) log ("Detector is part of Delayed Detectors");
                    if(!getState(idAlarm).val) setState(idEntryDelayActive, true);
                    else {
                        if (loglevel >= 3) log ("EntryDelay was already active, alarming now");
                        setState(idAlarmAccoustical, true);
                        setState(idAlarmOptical, true);
                    }
                } else {
                    if (loglevel >= 3) log ("Detector is not delayed");
                    if (loglevel >= 2) log ("System is ALARMING now!");
                    setState(idAlarmAccoustical, true);
                    setState(idAlarmOptical, true);
                }
            }
        }
    }
    
    // Function myCreateState
    // =======================
    // Parameter:       id      ... id des neu anzulegenden Datenpunkts
    //                  typ     ... typ des anzulegenden Datenpunkts ("boolean", "string", "number", etc.)
    //                  val     ... Wert, den der Datenpunkt nach dem Anlegen haben soll
    //                  descr   ... Name als String
    //                  writeaccess Schreibrechte true oder false
    // Funktion:        Mit der Funktion createState wird der neue Datenpunkt mit den übergebenen
    //                  Parametern angelegt.
    // Rückgabewert:    keiner
    function myCreateState(id, typ, val, descr, writeaccess, role) {
        if (loglevel >= 3) log ("Function myCreateState for " + id);
        createState(id, val,    {read: !writeaccess, 
                                write: writeaccess, 
                                name: descr,
                                type: typ,
                                def: val,
                                role: role ? role : "state"
        });
    }
    
    // Function myCreateMultiState
    // ===========================
    // Parameter:       id      ... id des neu anzulegenden Datenpunkts
    //                  typ     ... typ des anzulegenden Datenpunkts ("boolean", "string", "number", etc.)
    //                  val     ... Wert, den der Datenpunkt nach dem Anlegen haben soll
    //                  descr   ... Name als String
    //                  min     ... Minimalwert
    //                  max     ... Maximalwert
    //                  list    ... Liste mit Werten und Bezeichnern im Format "0:Text0; 1:Text1; 2:Text2"
    //                  writeaccess Schreibrechte true oder false
    // Funktion:        Mit der Funktion createState wird der neue Datenpunkt mit den übergebenen
    //                  Parametern angelegt.
    // Rückgabewert:    keiner
    function myCreateMultiState(id, typ, val, descr, writeaccess, minimum, maximum, list, role) {
        if (loglevel >= 3) log ("Function myCreateMultiState for " + id);
        createState(id, val, {  read: true, 
                                write: writeaccess, 
                                name: descr,
                                type: typ,
                                def: val,
                                min: minimum, 
                                max: maximum, 
                                states: list,
                                role: role ? role : "state"
        });
    }
    
    
    // Function switchActiveExternal
    // =============================
    // Parameter:       keiner
    // Funktion:        Nach Prüfung auf Bereitschaft zum externen Scharfschalten, wird 
    //                  scharf geschaltet oder ein Fehler angezeigt.
    // Rückgabewert:    keiner
    function switchActiveExternal () {
        if (loglevel >= 3) log ("Function switchActiveExternal");
        setState(idExitDelayActive, false);
        var ok = checkDetectors(detectorsOuterSkin.concat(detectorsIndoor));
        if (ok) {
            setState(idActiveExternal, true);
            setState(idActive, true);
            setState(idStatusText, textStatusActiveExternal);
            setState(idAlarmText, textAlarmInactive);
            setState(idAlarmingDetector,"");
            setState(idError, false);
            if (loglevel >= 2) log ("Switched to External Active");
        } else {
            if (loglevel >= 2) log ("NOT ready to switch to External Active!");
            setState(idError, true);
        }
    }
    
    // Function switchActiveInternal
    // =============================
    // Parameter:       keiner
    // Funktion:        Nach Prüfung auf Bereitschaft zum internen Scharfschalten, wird 
    //                  scharf geschaltet oder ein Fehler angezeigt.
    // Rückgabewert:    keiner
    function switchActiveInternal () {
        if (loglevel >= 3) log ("Function switchActiveInternal");
        var ok = checkDetectors(detectorsOuterSkin);
        if (ok) {
            setState(idActiveInternal, true);
            setState(idActive, true);
            setState(idStatusText, textStatusActiveInternal);
            setState(idAlarmText, textAlarmInactive);
            setState(idAlarmingDetector,"");
            setState(idError, false);
            if (loglevel >= 2) log ("Switched to Internal Active");
        } else {
            if (loglevel >= 2) log ("NOT ready to switch to Internal Active!");
            setState(idError, true);
        }
    ;}
    
    // Function switchInactive
    // =============================
    // Parameter:       keiner
    // Funktion:        Es wird unscharf geschaltet und die ganze Anlage resetiert.
    // Rückgabewert:    keiner
    function switchInactive () {
        if (loglevel >= 3) log ("Function switchInactive");
        if (timerExitDelay) clearTimeout(timerExitDelay);
        setState(idEntryDelayActive, false);
        setState(idExitDelayActive, false);
        setState(idActiveExternal, false);
        setState(idActiveInternal, false);
        setState(idActive, false);
        setState(idError, false);
        clearStateDelayed(idAlarmAccoustical);
        clearStateDelayed(idAlarmOptical);
        setState(idAlarmAccoustical, false);
        setState(idAlarmOptical, false);
        setState(idAlarm, false);
        setState(idAlarmText, textAlarmInactive);
        setState(idStatusText, textStatusInactive);
        checkDetectors(detectorsOuterSkin.concat(detectorsIndoor));
        if (loglevel >= 2) log ("Switched to Inactive");
        getAllDetectors();
    }
    
    // Function setActiveNumber
    // =======================
    // Parameter:       keine
    // Funktion:        Prüft ob intern scharf, extern scharf oder unscharf ist und
    //                  ob jeweils Eingangs- oder Ausgangsverzögerung aktiv ist.
    //                  Abhängig davon wird der Datenpunt "Output.ActiveNumber"
    //                  wie folgt gesetzt:
    //                    0 ... unscharf
    //                    1 ... intern scharf
    //                    2 ... extern scharf
    //                    3 ... Eingangsverzögerung aktiv
    //                    4 ... Ausgangsverzögerung aktiv
    // Rückgabewert:    keiner
    function setActiveNumber () {
        if (loglevel >= 3) log ("Function setActiveNumber");
        var internal = getState(idActiveInternal).val;
        var external = getState(idActiveExternal).val;
        var entry = getState(idEntryDelayActive).val;
        var exit = getState(idExitDelayActive).val;
        if (!external && !internal) {
            if (exit)
                setState(idActiveNumber, 4);
            else
                setState(idActiveNumber, 0);
        }
        if (internal) setState(idActiveNumber, 1);
        if (external){
            if (entry)
                setState(idActiveNumber, 3);
            else
                setState(idActiveNumber, 2);
        }
    }
    
    // Function checkDetectors
    // =======================
    // Parameter:       detectors
    //                  Array mit Melder-IDs
    // Funktion:        Alle Melder aus dem Array werden geprüft und alle offenen
    //                  Melder werden in einen Datenpunkt geschrieben als String.
    //                  Das Trennzeichen zwischen den Meldernamen ist die globale
    //                  Variable "seperator".
    // Rückgabewert:    true, wenn alle Melder in Ruhe sind
    //                  false, wenn ein oder mehr Melder ausgelöst sind
    function checkDetectors ( detectors ) {
        if (loglevel >= 3) log ("Function checkDetectors");
        var i=0;
        var textListOfDetectors="";
        var objOpenDetectors = {
            title: "All open detectors",
            zone: null,
            listOfDetectors:    []
        };
        var objOpenDetectorsOuterSkin = {
            title: "Open detectors outer skin",
            zone: functionOuterSkin,
            listOfDetectors:    []
        };
        var objOpenDetectorsIndoor = {
            title: "Open detectors indoor",
            zone: functionIndoor,
            listOfDetectors:    []
        };
        while(i < detectors.length) {
            if (getState(detectors[i]).val) {
                if (textListOfDetectors.length > 0) textListOfDetectors += seperator;
                textListOfDetectors += getObject(detectors[i]).common.name;
                var detObj = getDetectorObject(detectors[i]);
                objOpenDetectors.listOfDetectors.push(detObj);
                if (detectorsOuterSkin.indexOf(detectors[i]) != -1) objOpenDetectorsOuterSkin.listOfDetectors.push(detObj);
                if (detectorsIndoor.indexOf(detectors[i]) != -1) objOpenDetectorsIndoor.listOfDetectors.push(detObj);
            }
            i++;
        }
        if (loglevel >= 3) log ("Open Detectors found: " + (textListOfDetectors.length ? textListOfDetectors : "none"));
        
        // Datenpunkte schreiben
        setState(idOpenDetectors, textListOfDetectors);
        setState(idOpenDetectorsJSON, JSON.stringify(objOpenDetectors));
        setState(idOpenDetectorsOuterSkinJSON, JSON.stringify(objOpenDetectorsOuterSkin));
        setState(idOpenDetectorsIndoorJSON, JSON.stringify(objOpenDetectorsIndoor));
    
        if (textListOfDetectors.length > 0) {
            return false;
        } else {
            return true;
        }
    }
    
    // Function getDetectorObject
    // ==========================
    // Parameter:       id
    //                  id eines Melder-States
    // Funktion:        Vom Melder mit der id wird das Objekt über getObjekt(id) geholt,
    //                  sowie von seinem Parent und ParentsParent.
    //                  Alle Objekte kommen in ein großes Objekt und werden zurück gegeben.
    // Rückgabewert:    Das Objekt des Melders samt Parent und ParentsParent (sofern es welche gibt)
    function getDetectorObject (id) {
        if (loglevel >= 3) log ("Function getDetectorObject for id: " + id);
        // ioBroker Parent-Datenpunkt (z.B. Kanal), kann auch null sein (zB bei KNX)
        var idParent = id.substr(0, id.lastIndexOf("."));
        // ioBroker ParentsParent-Datenpunkt (z.B. Gerät), kann auch null sein (zB bei KNX)
        var idParentsParent = idParent.substr(0, idParent.lastIndexOf("."));
    
        // Objekte dazu holen
        var obj    = getObject(id);
        var objParent = getObject(idParent);
        var objParentsParent = getObject(idParentsParent);
    
        // Alle Objekte in ein großes Objekt sammeln
        var detectorsObj = {
            id:             id,
            self:           obj,
            parent:         objParent,
            parentsparent:  objParentsParent
        };
    
        // Rückgeben
        return detectorsObj;
    }
    

    Änderungshistorie

    • 2020-05-01, Erstellung
    • 2020-05-02, Number-Datenpunkte für Ein- und Ausgabe des Schaltzustands (Idee von Homer.J..)
    • 2020-05-03, Korrekturen, u.a. für Melderauswertung (chage: "ne") & Status-Text
    • 2020-05-04, Melder werden aus den Functions (Aufzählungen, enums) dafür geholt. Auch beim Unscharf-schalten, dadurch ist kein Neustarten des Skripts notwendig bei Änderungen an diesen Aufzählungen.
      Eine Schaltung von einem scharf-Zustand auf einen anderen wird verhindert. ZB von scharf intern auf scharf extern. Es muss immer unscharf dazwischen geschaltet werden.
    • 2020-05-09, Zusätzliche Objekte mit JSON-Strings für:
      _ den auslösenden Melder
      _ alle offenen Melder
      _ alle offenen Melder der Außenhaut
      _ alle offenen Melder des Innenraums
      Die JSON-String beinhalten das auslösende Objekt, sowie (falls vorhanden) das Parent und das ParentsParent-Objekt mit allen in ioBroker verfügbaren Eigenschaften.
      Außerdem kleinere Verbesserungen, z.B. bezüglich setzen der AlarmTexte.
    • 2020-05-12 Andreas Kos Setzen des Datenpunkts idReady zur Bereitschaftsanzeige neu gemacht.

  • andreaskos
    erst einmal, ein Dank an dich, dass Du dein Fachwissen mit uns teilst, alleine durch das Lesen deiner Script-Vorstellung habe ich schon einiges dazugelernt 👍

  • Forum Testing Most Active

    andreaskos

    javascript.1	2020-05-02 07:50:42.371	error	(17536) at process._tickCallback (internal/process/next_tick.js:68:7)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at promise.then (C:\Program Files\iobroker\Test\node_modules\standard-as-callback\built\index.js:19:49)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at tryCatcher (C:\Program Files\iobroker\Test\node_modules\standard-as-callback\built\utils.js:11:23)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at client.get (C:\Program Files\iobroker\Test\node_modules\iobroker.js-controller\lib\states\statesInRedis.js:616:17)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at adapter.getForeignState (C:\Program Files\iobroker\Test\node_modules\iobroker.javascript\main.js:1055:17)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at createProblemObject (C:\Program Files\iobroker\Test\node_modules\iobroker.javascript\main.js:1464:17)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at prepareScript (C:\Program Files\iobroker\Test\node_modules\iobroker.javascript\main.js:1411:37)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at compile (C:\Program Files\iobroker\Test\node_modules\iobroker.javascript\main.js:1188:28)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at Object.createScript (vm.js:277:10)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) at new Script (vm.js:83:7)
    javascript.1	2020-05-02 07:50:42.371	error	(17536) SyntaxError: Unexpected token var
    javascript.1	2020-05-02 07:50:42.371	error	(17536) ^^^
    javascript.1	2020-05-02 07:50:42.371	error	(17536) var detectorsDelayed = [
    javascript.1	2020-05-02 07:50:42.370	error	at script.js.Alarm.Alarm1:36
    javascript.1	2020-05-02 07:50:42.370	error	(17536) script.js.Alarm.Alarm1 compile failed:
    

    Screenshot (2390)_LI.jpg

  • Starter

    Ah Danke, das war der Beistrich bei den beispielhaft eingegebenen Daten.
    Der Benutzer selbst trägt die Melder in die Arrays ein.

  • Forum Testing

    Hi andreaskos cooles Script funktioniert sehr gut eine Frage kannst du Vielleicht einen Datenpunkt einarbeiten über den man unscharf intern scharf und extern scharf über eine Zahl schalten kann soll heißen bei Status 0 unscharf bei Status 1 extern scharf und bei Status 2 intern und vielleicht bei 3 Blocked.
    Grund ich schalte meine Anlage über meine Apple Homeapp und diese wird über Zahlen getriggert.
    Wäre echt cool wenn du das einarbeiten könntest.

    Screenshot_2020-05-02 objects - ioBroker.png

    Grüße

  • Starter

    Hi Homer.J.!
    Ja, gute Idee! Das nehm ich gern auf. Ich würde es aber so machen:
    0 ... unscharf
    1 ... scharf intern
    2 ... scharf extern
    3 ... scharf extern verzögert
    OK? Was meinst du mit Blocked?

  • Forum Testing

    andreaskos wenn man die Anlage auf Grund eines offenen Fensters z.B. nicht scharf schalten kann.
    Ist nur so eine Idee.
    Was auch schön wäre für die gleichen punkte dann ein Output.
    Kann man vielleicht auch die akustische Ausgabe trennen soll heißen bei Alarm extern Sirene außen und bei intern innen.

  • Forum Testing Most Active

    andreaskos

    Cool, teste gerade.
    Interessant wäre noch:

    Scharf/unscharf stellen mit Code (Pin)
    Ausgabe der Sensoren als Json/Html
    Unterteilung Außenhaut/Innenraum
    Log Ausgabe der Ereignisse in einen DP
    Alarmanlage aktiv via Date/Time ( zb. Alarm nur in der Zeit von 22:00 - 05:00 Uhr ?

    Vergabe eine Alias Name?Derzeit ist die Ausgabe :

    Bewegungsmelder Vorraum2.MOTION
    Alias: Bewegungsmelder Vorraum

  • Starter

    Danke für dein Feedback sigi234

    Das Skript soll ja nur die Alarmanlage abbilden. Auf welche Art die Scharf- oder Unscharf-Schaltung erfolgt, obliegt dann dem User. Das heißt, wie die Datenpunkte angesprochen werden, ob über eine Code-Eingabe, eine Zeitschaltuhr oder andere kreative Ideen (zB in Abhängigkeit der Anwesenheit) ist nicht Teil davon.

    Betreffend der Namen müssen diese eben in ioBroker gepflegt werden. Ich wollte so wenig Eingaben wie möglich haben, deshalb dieser Weg. Ein Alias-Name wäre dann eine zusätzliche Eingabe. Natürlich möglich, aber ioBroker bietet diese Möglichkeit ja schon von sich aus.

    Die ausgelösten Sensoren als JSON-String zur Verfügung zu stellen find ich super! Ich nehme es mal in meine ToDo-Liste auf. Ebenso, dass zusätzlich je eine getrennte Liste für Außenhaut und Innenraum-Melder geführt wird.

  • Starter

    Ich habe einmal die Idee von Homer.J. eingearbeitet. Es gibt jetzt je zwei Number-Datenpunkte:

    Input.SwitchNumber gibt die Schaltzustände ein wie folgt:
    0 ... unscharf schalten
    1 ... scharf intern schalten
    2 ... scharf extern schalten
    3 ... verzögert scharf extern schalten

    Output.ActiveNumber gibt Auskunft über den tatsächlichen Zustand mit den Ziffern:
    0 ... unscharf
    1 ... intern scharf
    2 ... extern scharf
    3 ... Eingangsverzögerung aktiv
    4 ... Ausgangsverzögerung aktiv

    Es werden dafür die eingebenen Texte unter Einstellungen am Anfang des Skripts benutzt.
    ksnapshot02.jpg

  • Forum Testing

    andreaskos funktioniert mit der Homeapp 👍 leider sind aber die Nummer vertauscht deswegen hatte ich 1 als extern scharf und 2 als intern scharf kann ich das für mich selber anpassen. ?
    Hab es für mich angepasst und funktioniert Klasse.
    Danke für das schnelle umsetzen.

  • Starter

    Sehr schönes Skript. Ich finde es auch gut, wenn nicht alle Funktionen hier integriert sind, sondern wirklich nur die Kernfunktionen einer Alarmlösung.

    Für die Benachrichtigung bei Alarm oder fehlerhaften Scharfschalten etc. Zum Beispiel in der VIS Oberfläche, per Licht, telegram oder Email verweise ich Mal auf den MessageHandler:

    https://forum.iobroker.net/topic/32207/script-messagehandler-nachrichten-protokollieren-vis

    Eine Integration sollte durch die Datenpunkte dieses Skripts prima durchführbar sein.

  • Starter

    Ich habe das Skript nun installiert und teste gerade etwas herum:

    Folgendes ist mir noch unklar (siehe Bild dazu unten):

    • Output State "alarm" steht auf true, obwohl State AlarmText = "Alles OK" (Meine Vermutung ist, dass die Zustände nicht zurückgesetzt werden, wenn ein vorheriger Alarm eingetreten ist)
    • Datenpunkt Input "SwitchNumber" ist 1, Output der "ActiveNumber" ist aber 2

    2020-05-03 09_42_41-objects - ioBroker.png

    Ich habe übrigens im Nachrichtenskript angefangen Nachrichten für dieses Alarmanlagenskript zu ergänzen:

    2020-05-03 09_48_05-vis.png

  • Forum Testing

    andreaskos kannst du vielleicht noch Fenstergriffe mit einarbeiten wo der Status mit Zahlen ist,
    0 geschlossen, 1 gekippt, 2 geöffnet.
    Funktioniert auch so hat sich also erledigt.
    Grüße

  • Starter

    Homer.J. hast du dein MDCSS Alarmanlagenview auf dieses Skript bereits angepasst?

    Ich meine dieses hier:

    https://forum.iobroker.net/topic/19970/suche-alarmanlagen-views/43

    Kannst du vielleicht die neueste Version bereitstellen?

  • Forum Testing

    Tirador bin gerade beim anpassen, wenn es fertig ist kein Problem.

  • Starter

    Homer.J. das wäre prima.


  • Hallo,

    tolle Arbeit, super Skript. Werde wohl demnächst mal mein altes Skript von 2016 ersetzen.

    Ich habe einige Vorschläge zum Skript:

    • die Javascript Instanz lässt sich durch instance abfragen. createState() darf eh nur in der Instanz, in der das Skript läuft States anlegen (und im neuen 0_userdata-Pfad)
    • Bitte beim Anlegen von Datenpunkten auch Rollen vergeben (Liste möglicher Werte).
    • die Ausgabe des Sensor Namens hast du über common.name schon realisiert ("Die Namen der Melder sollten gut gepflegt sein"). Es gibt aber sehr viel mehr Infos im Objekt, die man ausgeben könnte
    on({
        id: idTrigger,
        change: "ne"
    }, function(obj) {
            log("obj.id " + obj.id);
            log("obj.name " + obj.name);
            log("obj.deviceName " + obj.deviceName);
            log("obj.deviceId " + obj.deviceId);
            log("obj.channelId " + obj.channelId);
            log("obj.channelName " + obj.channelName);
            log("obj.common.name " + obj.common.name);
            log("obj.common.desc " + obj.common.desc);
            log("obj.state.ts (formatiert) " + formatDate(obj.state.ts, "TT.MM.JJJJ SS:mm:ss"));
    });
    

    Ist die Subscription von Rollen nicht geplant? So kann man leicht zB alle Bewegungsmelder eines Raumes oder die Tür-Fenster-Kontakte auf einmal überwachen, die z.B. einer Rolle "Alarmsensoren_Aussenhaut" zugeordnet sind. Das reduziert die Wartungsarbeit beim Wechsel von Sensor-Hardware.

    const motion_kizi = $("channel[state.id=*.MOTION](rooms=Kinderzimmer)");
    motion_kizi.on(function(obj){
        if (obj.state.val && (getState(idAlarmanlage).val === 1 || getState(idAlarmanlage).val) ) { // wenn Alarmanlage ein
           setState("scene.0.licht_kinderzimmer_alles_ein", true);  // alle Lichter an
           // weitere Aktionen
       }
    });
    

    Top Arbeit 👍
    Pix

  • Forum Testing

    Hi andreaskos hab jetzt mal meine komplette Anlage umgestellt irgendetwas passt da noch nicht, wenn ich jetzt meine Alarmanlage aktiviere dauert es nicht lang das irgendein Kontakt auslöst obwohl sich kein Status verändert hat soll heißen es wurde weder ein Fenster geöffnet noch ging ein Bewegungsmelder.
    Es wir aber komischerweise in dem Datenpunkt Alarming Detector genau der auslösende Kontakt angezeigt obwohl sich nichts ändert.

  • Starter

    Cool, vielen Dank für euer Feedback!

    Ich möchte kurz Feedback geben zu den Punkten:
    Tirador
    Solche Dinge passieren, wenn von einem scharf-Zustand auf einen anderen scharf-Zustand geschaltet wird, in deinem Fall direkt von scharf extern auf scharf intern. Ein Rückesetzen wird immer nur beim Schalten auf unscharf durchgeführt (auch die Texte stimmen nur so). Ich wollte das vorerst nicht per Programmierung sperren. Jetzt mit der Möglichkeit über den Number-Datenpunkt zu schalten passiert das natürlich noch leichter. Sollte ich das Abfangen im Code? Was soll dann aber passieren?

    pix

    • Ah, super - ich hab mich gefragt, ob etwas gibt, die Intanz abzufragen, aber dann nicht mehr nachgesehen - Danke!!
    • OK, ich werd Rollen mitvergeben.
    • Subscription auf Rollen ist auch cool. Ich muss zugeben, dass ich mich mit Rollen bisher kaum auseinander gesetzt habe. Das würde die Pflege deutlich vereinfachen. Kann ein Melder auch mehrere Rollen haben? Oder wie kann ich sonst damit umgehen, dass ein Melder gleichzeitig zB die Außenhaut-Rolle haben kann UND auch ein verzögerter Melder sein kann?

    LG Andreas

Suggested Topics

1.5k
Online

34.6k
Users

40.7k
Topics

557.5k
Posts