openHAB

Anbindung des Controllers an externe Hausautomationssysteme.
Benutzeravatar
seppy
Beiträge: 226
Registriert: 19. September 2016, 10:11

openHAB

Beitrag von seppy »

Hallo Zusammen,
da ich die letzten Schritte um meinen Poolbau abzuschließen mangels Wärme auf das kommende Jahr verschieben muss, habe ich gestern den Controller provisorisch in Betrieb genommen um die Temperatur im Technikraum erfassen zu können. Da ich für meine Hausautomatisierung auf openHAB setze habe ich gestern die Anbindung des Controllers umgesetzt. Für alle die evtl. ähnliches vorhaben hier meine Umsetzung:

In openHAB habe ich zwei Items erzeugt, die über das HTTP Binding gefüttert werden:

Code: Alles auswählen

/**
 * Temperatur vom PoolController
 * Default Intervall: 60000 Millisekunden
 */
Number PoolControllerTempBecken
	"Temperatur Becken [%.1f °C]"
	<temperature>
	{http="<[http://192.168.XXX.XXX/GetState.csv:60000:JS(poolctrl_temp1.js)]"}	

Number PoolControllerTempTechnik
	"Temperatur Technikraum [%.1f °C]"
	<temperature>
	{http="<[http://192.168.XXX.XXX/GetState.csv:60000:JS(poolctrl_temp2.js)]"}
Für alle nicht openHAB Nutzer, dass Binding bietet in diesem Fall den Transportweg http an. Hier auf die GetState des Controllers im Intervall 60000 Millisekunden. Das Ergebnis wird an die Javascript Transform Datei "poolctrl_tempX.js" gegeben, die jeweils genau den benötigten Wert zurückliefert. In meinem Fall habe ich mich entschieden die Berechnung des Wertes aus Gain, Offset und Value im Javascript zu machen, da ich so in openHAB nicht weiter machen muss.
Die Transform Datei sieht so aus (ich habe die Funktion CSVToArray in die Datei gepackt, damit es nachvollziehbar bleibt. Eigentlich lade ich diese zentral):

Code: Alles auswählen

/**
* Javascript Transformator, aus dem Rückgabe CSV des PoolControllers den passenden Wert extrahiert.
*  Die Spalte col bestimmt den entsprechenden Rückgabewert.
*/
var col = 9;
function CSVToArray( strData, strDelimiter ){
    // Check to see if the delimiter is defined. If not,
    // then default to comma.
    strDelimiter = (strDelimiter || ",");

    // Create a regular expression to parse the CSV values.
    var objPattern = new RegExp(
        (
            // Delimiters.
            "(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +

            // Quoted fields.
            "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +

            // Standard fields.
            "([^\"\\" + strDelimiter + "\\r\\n]*))"
        ),
        "gi"
        );


    // Create an array to hold our data. Give the array
    // a default empty first row.
    var arrData = [[]];

    // Create an array to hold our individual pattern
    // matching groups.
    var arrMatches = null;


    // Keep looping over the regular expression matches
    // until we can no longer find a match.
    while (arrMatches = objPattern.exec( strData )){

        // Get the delimiter that was found.
        var strMatchedDelimiter = arrMatches[ 1 ];

        // Check to see if the given delimiter has a length
        // (is not the start of string) and if it matches
        // field delimiter. If id does not, then we know
        // that this delimiter is a row delimiter.
        if (
            strMatchedDelimiter.length &&
            strMatchedDelimiter !== strDelimiter
            ){

            // Since we have reached a new row of data,
            // add an empty row to our data array.
            arrData.push( [] );

        }

        var strMatchedValue;

        // Now that we have our delimiter out of the way,
        // let's check to see which kind of value we
        // captured (quoted or unquoted).
        if (arrMatches[ 2 ]){

            // We found a quoted value. When we capture
            // this value, unescape any double quotes.
            strMatchedValue = arrMatches[ 2 ].replace(
                new RegExp( "\"\"", "g" ),
                "\""
                );

        } else {

            // We found a non-quoted value.
            strMatchedValue = arrMatches[ 3 ];

        }


        // Now that we have our value string, let's add
        // it to the data array.
        arrData[ arrData.length - 1 ].push( strMatchedValue );
    }

    // Return the parsed data.
    return( arrData );
}

(function(i) {
    var data = CSVToArray(input,",")
    var offset = data[3][col];
    var gain = data[4][col];
    var value = data[5][col];
    var result = offset + ( gain * value);
    return (Number(result).toFixed(2));
})(input)
Auf die gleiche Weise könnte ich auch andere Werte, bzw. über SetState Operationen ausführen. Wobei ich ein Freund von Spezialisierung bin und alles poolspezifische dem Controller überlasse. Aber Licht bspw. möchte ich auch gerne zentral steuern.

Vielleicht hilft es jemandem.

Viele Grüße,
Seppy

Benutzeravatar
seppy
Beiträge: 226
Registriert: 19. September 2016, 10:11

Re: openHAB

Beitrag von seppy »

Hi,
ich habe heute Abend versucht die Integration in die Hausautomatisierung voran zu bringen. Leider funktioniert nicht mal das Schalten eines Relais per http:

Code: Alles auswählen

http://192.168.5.XXX/SetState.pl?R9=1&RT9=0 
Ich bekomme folgendes zurück, aber geschaltet wird nix:

Code: Alles auswählen

0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
Hat jemand eine Idee wo mein Problem liegt? Ich komme aus dem gleichen Netz.

Grüße,
Seppy

Benutzeravatar
Alex
Administrator
Beiträge: 9988
Registriert: 28. Mai 2014, 23:00

Re: openHAB

Beitrag von Alex »

Wenn das Relais manuell OFF geschaltet ist oder wenn es von einer internen Regeln explizit OFF gesetzt ist, kannst du es so nicht schalten.

Benutzeravatar
seppy
Beiträge: 226
Registriert: 19. September 2016, 10:11

Re: openHAB

Beitrag von seppy »

Heißt das es muss auf AUTO stehen? Ich habe keine Regeln aktiv die auf die Beleuchtungsrelais wirken.

Benutzeravatar
Alex
Administrator
Beiträge: 9988
Registriert: 28. Mai 2014, 23:00

Re: openHAB

Beitrag von Alex »

ja muss auf AUTO stehen

Benutzeravatar
seppy
Beiträge: 226
Registriert: 19. September 2016, 10:11

Re: openHAB

Beitrag von seppy »

Wie immer, wenn man es richtig macht funktioniert es auch! Die Beleuchtung im Pool wird jetzt mit der sonstigen Außenbeleuchtung über openHab geschaltet.
Perfekt!

Robby
Beiträge: 7
Registriert: 30. Dezember 2016, 19:45

Re: openHAB

Beitrag von Robby »

Hallo Seppy
Ich bin noch neu in OpenHab. Kannst du mir vielleicht etwas genauer erklären wie du das gemacht hast?
Muss ich in der /etc/openhab2/services/http.cfg Datei auch noch etwas konfigurieren?
Wo hast du die Datei poolctrl_tempX.js gespeichert? Ins items Verzeichnis?
Vielen Dank und liebe Grüsse
Robby

Benutzeravatar
seppy
Beiträge: 226
Registriert: 19. September 2016, 10:11

Re: openHAB

Beitrag von seppy »

Hi,
wenn Du eine aktuelle Version von openHab nutzt, muss der http Service nicht weiter konfiguriert werden.

Die Javascript Datei ist eine sogenannte transformation. Diese liegen alle im entsprechenden Ordner.

Wenn Du Detailhilfe bei openhab brauchst kannst Du Dich gerne im openhabforum.de anmelden.

Viele Grüße,
Seppy

Hans_Karl
Beiträge: 7
Registriert: 14. November 2022, 17:51

Re: openHAB

Beitrag von Hans_Karl »

Hallo zusammen,

ich probiere seit 14 Tagen die Integration des Pooldigital Controllers in mein Openhab-System.
Allerdings bis jetzt komplett ohne Erfolg.

Ich nutze Openhab seit der 1.X Version und habe aktuell 3.4.4. installiert.
Für die Kommunikation zum Controller habe ich jetzt das http-Binding und Javascript-Transformation installiert.
Den von Seppy aufgeführten Code habe ich in poolctrl_temp1.js im „transformation“-Ordner und in eine Pool.items Datei (im Items-Ordner) kopiert.

Allerdings bekomme ich keine Werte angezeigt und in der LOG-Datei tut sich gar nichts.

Hat jemand einen Tipp, an was das liegen könnte?
Ich glaube, der von Seppy aufgeführte Code ist noch von Openhab 2.X.
Könnte es deshalb etwas mit der Java-Version zu tun haben?
Mit Java habe ich leider gar nichts am Hut. Muss ich etwas in der *.js Datei anpassen?

Falls jemand den Controller in Openhab 3.x eingebunden hat und mir vielleicht die notwendigen Dateien als Muster senden könnte, würde ich mich sehr freuen.

Gruß Hans_Karl

signsy
Beiträge: 7
Registriert: 19. Juni 2021, 06:48

Re: openHAB

Beitrag von signsy »

Hallo @Hans_Karl,

bei mir hat das ursprüngliche Script auch nicht Funktioniert. Daher habe ich ein eigenes Gebastelt:

Code: Alles auswählen

var col = 3;
(function(i) {
    var Rows = input.toString().split('\n');
    var offsetArr = Rows[3].split(',');
    var offset = offsetArr[col].replace('\r', '');
    var gainArr = Rows[4].split(',');
    var gain = gainArr[col].replace('\r','');
    var valueArr = Rows[5].split(',');
    var value = valueArr[col].replace('\r','');
    var result = +offset + ( +gain * +value);
    return (Number(result).toFixed(2));
})(input)
mit "col" wählst du die Spalte aus.
In Openhab3 schaut das dann über die MAIN-UI bei mir so aus:
OH3_HttpThing.png
Ich habe mir nur einen String Channel angelegt der mit mehreren Items verknüpft ist. Die Items wiederum haben dann die unterschliedlichen JS Transformationen:
OH3_HttpThing_RawString.png
Item:
OH3_HttpThing_FilterDruckLink.png
Das ganze gestern Abend selber erst so zusammen gebastelt.

Gruß

Hans_Karl
Beiträge: 7
Registriert: 14. November 2022, 17:51

Re: openHAB

Beitrag von Hans_Karl »

Hallo signsy,

erstmal vielen Dank für die Screenshots und die Hilfe.

Mit den Screenshots hat das Anlegen des http-Things und des Channels funktioniert.
Wenn ich ein String Item erstelle, sehe ich auch die komplette Antwort vom Poolcontroller,
allerdings geben die als Number angelegten Items immer nur „Null“ aus.

Ich habe ein neues Item angelegt und deinen Code in eine „poolctrl_Temp1.js“ kopiert und im "transform"-Ordner abgelegt.
Die Profil-Auswahl beim Item steht auf JS und darunter habe ich die Datei „poolctrl_Temp1.js“ ausgewählt.
Sobald ich dem Item unter „Show advanced“ eine Einheit gebe, z.B. (%.1f °C), dann kommt im LOG eine Fehlermeldung,
dass das Ergebnis nicht auf diese Art transformiert werden kann.
Ohne Einheit kommen keine Fehlermeldungen im LOG, aber auch keine Werte bei den Number-Items.

Hast du noch einen Tipp?

Noch eine Frage zum „col“ und dem JavaScript.
Col steht für die jeweilige Spalte für den Wert der aus den Reihen Offset, Gain und Rohwert ausgelesen und verarbeitet wird?
Das heißt in deinem Beispiel mit Col = 3 wird der 3te Analogkanal berechnet?
Kann es sein das die Zeilen jeweils um eine Nummer erhöht werden müssen?
In der Bedienungsanleitung steht der Offset in Zeile 4, Gain in 5 und Rohwert in Zeile 6, in deinem Script aber die 3,4,5 Zeilen.
Habe es im Script umgestellt, aber auch ohne Erfolg.

Gruß

signsy
Beiträge: 7
Registriert: 19. Juni 2021, 06:48

Re: openHAB

Beitrag von signsy »

Hallo Hans_Karl,

wenn du den String im "String-Item" siehst ist das schon mal gut.

Wieso da immer ein NULL raus kommt kann ich dir so jetzt auch nicht beantworten. Leg mal ein String Item an und nutze die entsprechende .js transform. Siehst du dann einen Wert?

Das State-Format unter "show advanced" musst du leer lassen oder auf %s setzen. Das ist nur interessant für die Weiterleitung an die Transformationsfunktion. Dass hier ein Fehler raus kommt wenn du etwas ein gibst ist klar:
HTTPThing->String-Channelabfrage->Itemmapping mit State-Format "%s" (String)->Transofrmationsfunktion->Item
Wenn du dort etwas eingibst versuchst du noch vor der Transformation den gesamten String in eine Zahlenkombination mit 1ner Nachkommstalle und °C dahinter zu ändern. Das kann nicht klappen.

Zum Thema col:
In der Programmierwelt fängt immer alles mit 0 an. Also Col=0 ist die 1. Spalte, Col=1 ist die 2. Spalte usw.
Das gleiche gilt für die Reihen:
0=Reihe 1 usw. Daher müsste das von mir schon passen ;)

Hans_Karl
Beiträge: 7
Registriert: 14. November 2022, 17:51

Re: openHAB

Beitrag von Hans_Karl »

Hallo signsy,

wie fast immer sitzt der Fehler zwischen Rückenlehne und Bildschirm.

Knackpunkt war die Java-Version. Hatte das Script in einer Testumgebung von Openhab 3.4. auf meinem Windows-PC getestet.
Da ich zwischenzeitlich schon mal mit Openhab 4 gespielt hatte, hatte ich Java 17 installiert und nicht mehr Java 11.
In Java 17 scheint die Unterstützung für das bisherige Java-Script entfallen zu sein.
Habe es dann heute einfach mal auf dem RasPI probiert und siehe da, es läuft ohne Probleme.

Noch mal vielen Dank.

P.S. Und das Script habe ich auch verstanden.

Gruß Hans_Karl

signsy
Beiträge: 7
Registriert: 19. Juni 2021, 06:48

Re: openHAB

Beitrag von signsy »

Hallo Hans_Karl,

das es mit der Java Version von OH4 zutun hat kann ich mir fast nicht vorstellen. Die JavaScript-Funktionen die ich nutze sind "Standard"-Funktionen die eigentlich in allen JAVA Versionen vorhanden sein müssten.
Ich denke eher das hat damit zu tun wie OH4 Item updatest bzw. Wertumrechnungen (Text->Number) umsetzt.

Ich hab schon länger geplant auf OH4 umzusteigen. Nur fehlt mir aktuell die Zeit dafür. Sobald ich das geupdatet hab schaue ich mir den Code noch einmal an und aktualisiere hier das Skript.

Gruß

Hans_Karl
Beiträge: 7
Registriert: 14. November 2022, 17:51

Re: openHAB

Beitrag von Hans_Karl »

Hallo signsy,

bin mir natürlich nicht 100% sicher, aber schau dir mal den zweiten Punkt von den Bemerkungen zum Milestone-Start an:
https://community.openhab.org/t/openhab ... lds/145132

Falls jemand Interesse an der textbasierten Variante hat, dann einfach melden.

Gruß Hans_Karl

signsy
Beiträge: 7
Registriert: 19. Juni 2021, 06:48

Re: openHAB

Beitrag von signsy »

Hallo @Hans_Karl,

natürlich das letzte mal das Antworten vergessen. Trotzdem wegen der Vollständigkeit hier noch meine Anpassungen an OH4.
An der Grundkonfiguration des "Things" ändert sich nichts. Da bleibt alles wie in meinem Post vom 19. Juni 2023.
Statt der JS-Transformation nutze ich jetzt das ECMAScript 11 (wie es in OH4 jetzt quasi Standard ist).
OH4 Thing config.png
Die poolctr_SolarTemp.js transformation schaut dann wie folgt aus:

Code: Alles auswählen

/**
* Javascript Transformator, aus dem Rückgabe CSV des PoolControllers den passenden Wert extrahiert.
*  Die Spalte col bestimmt den entsprechenden Rückgabewert.
*/
var col = 10;
(function(i) {
    var Rows = input.toString().split('\n');
    var offsetArr = Rows[3].split(',');
    var offset = offsetArr[col].replace('\r', '');
    var gainArr = Rows[4].split(',');
    var gain = gainArr[col].replace('\r','');
    var valueArr = Rows[5].split(',');
    var value = valueArr[col].replace('\r','');
    var result = +offset + ( +gain * +value);
    return (Number(result).toFixed(2));
})(input)
Wobei "col" den jeweiligen Wert beschreibt.

Gruß

signsy
Beiträge: 7
Registriert: 19. Juni 2021, 06:48

Re: openHAB

Beitrag von signsy »

Hallo zusammen,
hier jetzt nochmal eine Aktualisierung die das ganze etwas vereinfacht und auch die Steuerung zulässt:
Das Thing ist als HTTP Binding angelegt:
httpThing.png
...IP natürlich entsprechend anpassen.

Dann habe ich jetzt einen Channel für die Pumpe als Switch Type mit einem Switch verbunden:
Das Profil bleibt bei "Standard".
pump.png
Interessant wird es bei dem Channel. Hier habe ich die Transormations angepasst:
channel.png
Wichtig hierbei ist jetzt die Status-Transformation, Status-URL Erweiterung und die Command-URL-Erweiterung.
Status URL ist nach wie vor die "GetState.csv".
Die Command ändert sich jetzt und spricht absofort via "/SetState.pl" das Relais direkt an. Hier muss das entsprechende Relais ausgewählt werden. In meinem Fall ist R1 die Pumpe.
Es kann auch ein abschaltwert zur URL (siehe Forumssuche zu /SetState.pl) hinzugefügt werden. z.B. /SetState.pl?R1=%2$s?RT=3000. '%2$s' wird durch den State des Switch Items ersetzt. RT=3000 bedeutet eine Rücksetzzeit von 3000ms.

Es gibt nur noch eine StatusTransformation JS-Datei, welche jetzt via Parameter angesteuert wird. Angelegt via UI (Transformations->JS)
transformation1.png
transformation1.png (22.55 KiB) 20 mal betrachtet
transformation2.png
Hier der Code zum kopieren:

Code: Alles auswählen

(function(data, column, type="value") {

    var col = +column;
    var Rows = data.toString().split('\n');
    var offsetArr = Rows[3].split(',');
    var offset = offsetArr[col].replace('\r', '');
    var gainArr = Rows[4].split(',');
    var gain = gainArr[col].replace('\r','');
    var valueArr = Rows[5].split(',');
    var value = valueArr[col].replace('\r','');
    var result = +offset + ( +gain * +value);
    switch(type)
      {
        case "relais":
            return Number(result)&1;
          break;
        default:
          return (Number(result).toFixed(2));
          break;
      }
})(input,column,type)
Und hier noch die Erklärung zur Status-Transformation:
JS:config:js:poolctrl_csvToState?column=16&type=relais
-->Ruft die JS Transformation "config:js:poolctr_csvToState" auf. Dabei wird die zu verwendende Spalte in der CSV Datei via "column=xx" und der typ als "relais" übergeben.
Diese sind im Script als "column" und "type" dann verwendbar.
Falls der Typ "relais" ist schaue ich mir nur das letzte Bit des Werts an. Dieser kann zwischen 0 und 3 sein wobei:
0=Automatik/Aus
1=Automatik/Ein
2=Manuell/Aus
3=Manuell/Ein
ist.
Das Umschalten via Openhab geht dann nur solange die ProCon im Automatik Modus ist. Ansonsten wird der schalter beim nächsten Lese-Zyklus einfach wieder auf den Manuell vorgegebenen wert zurückgesetzt.

P.S. Das ganze ist mit OH 4.3.5 gemacht.