Transformation für String

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

BOP
Beiträge: 197
Registriert: 23. Sep 2018 19:43
Answers: 1

Transformation für String

Beitrag von BOP »

Hallo!
Ich benötige Hilfe bei einer Transformation. Bei RegEx werde ich wohl nie im Leben richtig durchsteigen und JavaScript habe ich bisher noch nicht gelernt. :D

Ich erhalte, von MobileAlert Geräten, folgenden String:

Code: Alles auswählen

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sensor &#220;berblick</title>
    <link href="/Content/css?v=Eslk_2H6Ss2i4k1dsN9Z3XkjPw7JieA8ojfWaoiEJ101" rel="stylesheet" />
    <script src="/bundles/modernizr?v=incVuEFe6J4P07A0AcRsbJic_UE5MwkRMEGcOtk94TE1"></script>
</head>

<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse"
                    data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span
                        class="icon-bar"></span> </button>
                <div class="navbar-brand">MOBILE ALERTS</div>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="/">Home</a></li>
                    <li><a href="/Home/SensorsOverview?phoneid=519032776604">Sensoren</a></li>
                    <li><a href="/Home/Actions?phoneid=519032776604">Aktionslog</a></li>
                    <li><a href="/Home/Imprint?phoneid=519032776604">Impressum</a></li>
                    <li><a href="/Home/Privacy?phoneid=519032776604">Datenschutzerkl&#228;rung</a></li>
                </ul>
            </div>
        </div>
    </div>
    <div class="container body-content">
        <h3>&#220;berblick f&#252;r Phone ID 519032776604</h3>
        <p><a href="/">Zur&#252;ck zu Home</a></p>
        <div class="panel panel-default">
            <div class="panel-body">
                <div class="sensor">
                    <div class="sensor-header">
                        <h3> <a
                                href="/Home/MeasurementDetails?deviceid=0216CBA48229&amp;vendorid=e3cee4fa-a164-463e-92b0-c1c218dae475&amp;appbundle=eu.mobile_alerts.weatherhub">Aussentemperatur
                            </a> 
                        </h3>
                        <div class="sensor-component">
                            <h5>ID</h5>
                            <h4>0216CBA48229</h4>
                        </div>
                    </div>
                    <div class="nofloat"></div>
                    <div class="sensor-component">
                        <h5>Zeitpunkt</h5>
                        <h4>22.09.2021 13:15:35</h4>
                    </div>
                    <div class="sensor-component">
                        <h5>Temperatur</h5>
                        <h4>20,1 C</h4>
                    </div>
                </div>
            </div>
        </div>
        <div class="panel panel-default">
            <div class="panel-body">
                <div class="sensor">
                    <div class="sensor-header">
                        <h3> <a
                                href="/Home/MeasurementDetails?deviceid=026ECD8ABC79&amp;vendorid=e3cee4fa-a164-463e-92b0-c1c218dae475&amp;appbundle=eu.mobile_alerts.weatherhub">Schlafzimmer
                            </a> 
                        </h3>
                        <div class="sensor-component">
                            <h5>ID</h5>
                            <h4>026ECD8ABC79</h4>
                        </div>
                    </div>
                    <div class="nofloat"></div>
                    <div class="sensor-component">
                        <h5>Zeitpunkt</h5>
                        <h4>22.09.2021 13:13:55</h4>
                    </div>
                    <div class="sensor-component">
                        <h5>Temperatur</h5>
                        <h4>18,4 C</h4>
                    </div>
                    <div class="sensor-component">
                        <h5>Luftfeuchte</h5> <!-- Luftfeuchtigkeit -->
                        <h4>60%</h4>
                    </div>
                </div>
            </div>
        </div>
        <div class="panel panel-default">
            <div class="panel-body">
                <div class="sensor">
                    <div class="sensor-header">
                        <h3> <a
                                href="/Home/MeasurementDetails?deviceid=0258290D6C2A&amp;vendorid=e3cee4fa-a164-463e-92b0-c1c218dae475&amp;appbundle=eu.mobile_alerts.weatherhub">Wohnzimmer</a>
                        </h3>
                        <div class="sensor-component">
                            <h5>ID</h5>
                            <h4>0258290D6C2A</h4>
                        </div>
                    </div>
                    <div class="nofloat"></div>
                    <div class="sensor-component">
                        <h5>Zeitpunkt</h5>
                        <h4>22.09.2021 13:12:38</h4>
                    </div>
                    <div class="sensor-component">
                        <h5>Temperatur</h5>
                        <h4>21,1 C</h4>
                    </div>
                </div>
            </div>
        </div>
        <hr />
        <footer>
            <p>&copy; 2021 - DATA INFORMATION SERVICES GmbH</p>
        </footer>
    </div>
    <script src="/bundles/jquery?v=8OoS0awDZyFg-cbyVzvkILERIE1DGSe3sRQdCSYrgEQ1"></script>
    <script src="/bundles/bootstrap?v=nVPYveeA6w58RVBNc8KhWwRKnYjvXImjjVbPBUuBfrI1"></script>
</body>

</html>
Daraus möchte ich gerne die Werte extrahieren.
Ein Gerät ist eindeutig durch seine Device-ID bestimmt. Also beispielsweise 0216CBA48229. In diesem Beispiel möchte also "20,1" zurück bekommen.

Wenn mir da jemand helfen könnte, wäre ich dankbar!

Gruß

Benutzeravatar
udo1toni
Beiträge: 13942
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Transformation für String

Beitrag von udo1toni »

Problere mal

Code: Alles auswählen

REGEX(.*0216CBA48229</h4>.*Temperatur</h5>.*<h4>(.*)</h4>.*)
Erklärung:
.* bedeutet: eine beliebige Anzahl beliebiger Zeichen
Es sollte also eine beliebige Zeichenkette, gefolgt von der ID, gefolgt von </h4>, gefolgt von einer beliebigen Zeichenkette, gefolgt vom Wort Temperatur und </h5>, gefolgt von einer beliebigen Zeichenkette, gefolgt von <h4>, nun folgt der gesuchte Wert, gefolgt von </h4>, gefolgt von einer beliebigen Zeichenkette.

Der Match ist etwas ungenau, aber vielleicht klappt er dennoch.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

BOP
Beiträge: 197
Registriert: 23. Sep 2018 19:43
Answers: 1

Re: Transformation für String

Beitrag von BOP »

Hallo Udo,
danke, das war direkt ein Volltreffer!

BOP
Beiträge: 197
Registriert: 23. Sep 2018 19:43
Answers: 1

Re: Transformation für String

Beitrag von BOP »

Nachtrag. Zumindest fast.

Code: Alles auswählen

2021-10-04 09:04:29.757 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'MobileAlerts_Grund_Daten_Ruckgabewert' changed from  to 19,6 C
EDIT: Habe den Ausdruck dann mal angepasst:
REGEX(.*0206EBE44217</h4>.*Temperatur</h5>.*<h4>(.*)C</h4>.*)

Jetzt sieht es ganz gut aus.

Benutzeravatar
udo1toni
Beiträge: 13942
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Transformation für String

Beitrag von udo1toni »

Ah. Das ist etwas ungünstig.
Das C bekommst Du noch leicht weg, indem Du es im Term außerhalb der inneren Klammern einträgst. Das größere Problem ist hier aber das Komma, das muss noch in einen Punkt gewandelt werden.

Wir reden von openHAB3? Und wir reden von Channels, nicht von Rules?
Dann kanst Du in einem http Channel auch mehrere Transformations verketten. Sähe so aus:

Code: Alles auswählen

REGEX:.*0216CBA48229</h4>.*Temperatur</h5>.*<h4>(.*) C</h4>.*∩JS:comma2dot.js
∩ ist das Zeichen zum Verketten mehrerer Transformations. Es ist am einfachsten, es aus der UI mittels Copy&Paste zu verwenden.

Nun fehlt noch das JavaScript Script:
$OPENHAB_CONF/transform/comma2dot.js:

Code: Alles auswählen

(function(i) {
    return i.replace(",",".");
})(input)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

BOP
Beiträge: 197
Registriert: 23. Sep 2018 19:43
Answers: 1

Re: Transformation für String

Beitrag von BOP »

Hi, ja, OH 3.

Ich habe aber ein exec-Binding Thing angelegt, welches ein Skript ausführt (die Browserkennung wird benötigt):

Code: Alles auswählen

#!/bin/bash
curl https://measurements.mobile-alerts.eu/Home/SensorsOverview?phoneid=519032776604 -A Mozilla
Dem Channel "Rückgabewert" habe ich dann ein neues Item zugewiesen und unter Profile dann die REGEX Anweisung eingetragen.

ABER: Ich muss gerade leider feststellen, dass der Ausdruck doch nicht richtig funktioniert. Er rutscht bei den Temperaturen im String bis zum letzten Wert durch.
Ich erhalte also immer den Wert der DeviceID=0258290D6C2A.

Anmerkung: Nicht wundern, dass der Link oben nicht funktioniert, ich habe die IDs geändert, da ich sie hier nicht öffentlich posten wollte.

Benutzeravatar
udo1toni
Beiträge: 13942
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Transformation für String

Beitrag von udo1toni »

Ah. Das ist natürlich ärgerlich... eigentlich sollte er so kurz wie möglich matchen...

Macht aber nix, wir können den Match ja noch weiter spezifizieren:

Code: Alles auswählen

REGEX:.*0216CBA48229</h4>.*Temperatur</h5>.*<h4>(.*) C</h4>.*deviceid=026ECD8ABC79.*
Die zweite ID ist die nachfolgende, so dass nun nur noch einmal Temperatur als Schlüsselwort vor dem eigentlichen Wert vorkommt.

Über die Profile kannst Du Transformations nicht verknüpfen.

Da Du exec verwendest, kannst Du meines Wissens die beiden Transformations auch im Channel nicht verknüpfen (Probieren könntest Du es natürlich...)
Aber auch das exec Binding bietet im Channel selbst eine incomming transformation. Du kannst also den Wert an dieser Stelle separieren und im Profile das JavaScript verwenden, um aus dem Komma einen Punkt zu machen.

Allerdings...

Wie sieht es denn aus? Du willst vermutlich nicht nur die eine Temperatur auswerten, oder? Dann wäre es ja sinnvoller, das Separieren der Werte von einer Rule ausführen zu lassen, einfach, weil Du dort alle Freiheiten hast.

Und noch eine andere Frage: Ist das die einzige Möglichkeit, die Werte abzufragen? Um was für ein Device handelt es sich denn? Unter https://mobile-alerts.eu/info/public_se ... tation.pdf gibt es nämlich eine Dokumentation einer Api, die direkt JSON zurückliefern würde. Das wäre extrem viel einfacher zu handhaben.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

BOP
Beiträge: 197
Registriert: 23. Sep 2018 19:43
Answers: 1

Re: Transformation für String

Beitrag von BOP »

udo1toni hat geschrieben: 4. Okt 2021 10:56 Macht aber nix, wir können den Match ja noch weiter spezifizieren:

Code: Alles auswählen

REGEX:.*0216CBA48229</h4>.*Temperatur</h5>.*<h4>(.*) C</h4>.*deviceid=026ECD8ABC79.*
Die zweite ID ist die nachfolgende, so dass nun nur noch einmal Temperatur als Schlüsselwort vor dem eigentlichen Wert vorkommt.
So funktioniert es!
ma1.jpg
Da Du exec verwendest, kannst Du meines Wissens die beiden Transformations auch im Channel nicht verknüpfen (Probieren könntest Du es natürlich...)
Hatte ich schon probiert. Geht leider nicht. Oder ich habe die passende Syntax nicht gefunden.
Aber auch das exec Binding bietet im Channel selbst eine incomming transformation. Du kannst also den Wert an dieser Stelle separieren und im Profile das JavaScript verwenden, um aus dem Komma einen Punkt zu machen.
100%ig habe ich dich nicht verstanden. Habe es mit der Transformation im Binding probiert. Das hat aber anscheinend keine Auswirkungen!?
Fehler erhalte ich keine. Aber Kommas sind auch noch im String.
ma2.jpg
Wie sieht es denn aus? Du willst vermutlich nicht nur die eine Temperatur auswerten, oder? Dann wäre es ja sinnvoller, das Separieren der Werte von einer Rule ausführen zu lassen, einfach, weil Du dort alle Freiheiten hast.
Da dachte ich auch schon dran. Aber direkt den richtigen Wert zu holen finde ich auch nicht unelegant.
Und noch eine andere Frage: Ist das die einzige Möglichkeit, die Werte abzufragen? Um was für ein Device handelt es sich denn? Unter https://mobile-alerts.eu/info/public_se ... tation.pdf gibt es nämlich eine Dokumentation einer Api, die direkt JSON zurückliefern würde. Das wäre extrem viel einfacher zu handhaben.
Die genauen Device-Kennzeichnungen kenne ich leider nicht. Die stehen bei meinen Eltern rum. Was ich bisher so lesen konnte, funktioniert die API nur mit neueren Geräten.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Benutzeravatar
udo1toni
Beiträge: 13942
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Transformation für String

Beitrag von udo1toni »

Nein, Du kannst die Reihenfolge der Transformation ja nicht beliebig wählen. Im Exec Binding muss zwingend zuerst das REGEX kommen. Falls möglich, könntest Du anschließend mit dem ∩ verknüpfen und die JS-Transformation einbauen.
Falls das Verknüpfen dort nicht funktioniert (wovon ich leider ausgehen muss), fügst Du die JS-Transformation im Profile ein. Die REGEX-Transformation muss aber auf jeden Fall im Channel stehen, sonst kommt ja die ganze Website im Item an.

Die Syntax in der Transformation des Channels ist REGEX:<Regex-Ausdruck> ∩ JS:<dateiname>
wobei die spitzen Klammern nicht hingeschrieben werden, die dienen nur der Kennzeichnung, dass hier nur Platzhalter für den eigentlichen Text angegeben sind.

Wie fragst Du denn konkret die Geräte ab, sprich, was steht in holeMobileAlertsHTML.sh konkret drin (gerne ohne konkrete IDs, IP-Adressen usw.)?
Letztlich musst Du ja dieselbe Seite mehrfach abrufen, um mehrere Werte zu extrahieren, ich finde das äußerst unelegant. Der Bessere Weg (wenn Du die Werte alle haben willst): Du lädst den Inhalt vom Channel Output in ein String Item. Du schreibst eine Rule, die bei einem Update des Items triggert. Die Rule extrahiert mittels REGEX und JS die Zahlenwerte und schreibt sie per postUpdate in die verschiedenen Items.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

BOP
Beiträge: 197
Registriert: 23. Sep 2018 19:43
Answers: 1

Re: Transformation für String

Beitrag von BOP »

Hi,
ich befürchte, wir schreiben etwas aneinander vorbei.
Als Erstes: Meine Things und Items sind alle über die GUI angelegt. Nicht über Dateien. Deswegen ist die Konfiguration an der einen oder andere Stelle etwas abweichend. Und, wie ich fürchte, nicht alles Möglich.

Das Skript beinhaltet (inzwischen) nur noch den curl Befehl. Siehe oben. Und da mir jetzt auffällt, dass das Skript eigentlich unnötig ist, da ich den einen Befehl auch direkt ausführen kann, wird der Befehl jetzt direkt vom Exec-Thing ausgeführt. Ohne Umweg über das Skript.

Code: Alles auswählen

curl https://measurements.mobile-alerts.eu/Home/SensorsOverview?phoneid=519032776604 -A Mozilla
Das wird alle 10 Minuten ausgeführt. Das Ergebnis (Rückgabe-Channel) wird dann an die vier daran verlinkten Items übergeben. Im Profil des jeweiligen Items wird dabei auf den String der jeweilige REGEX Ausdruck ausgeführt.
Der String wird aber nur einmal abgerufen! Jedes Item besitzt aber seinen eigenen REGEX-Ausdruck.

Mein Gedanke, das JavaScript direkt auf dem Thing auszuführen, war eigentlich, dass die Reihenfolge keine Rolle spielen sollte. Ob ich im gesamten String erst alle Komma durch Punkte ersetze und dann das REGEX darauf loslasse oder umgekehrt, sollte doch eigentlich in diesem Fall keinen relevanten Unterschied machen!?

Im Prinzip ist jetzt ja soweit auch alles richtig. Solange ich die Werte nicht als Zahl (für Vergleiche oder ähnliches) benötige, sondern nur als Anzeige in der Sitemap, stört es ja nicht, dass er als String mit Komma vorliegt.

Antworten