String-Funktionen

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

violine21
Beiträge: 600
Registriert: 20. Sep 2019 05:49
Answers: 7

String-Funktionen

Beitrag von violine21 »

Hallo,
habe folgendes Problem:
Ich bekomme von meiner Solarthermieanlage die erzeugte Gesamtleistung per http, gesplittet in die Werte
MWh und kWh. Sämtliche Werte sind Strings. Diese muss ich noch zusammenfügen.
Beispiel:
MWh = 38
kWh = 102,6
Gesamt = 38102,6 kWh
Liefert die Anlage aber einen kWh-Wert mit 2 Stellen vor dem Komma, passt das nicht mehr, es fehlt die führende Null.

Ich habe mir überlegt, in einer Rule die Anzahl der Zeichen des kWh-Strings zu zählen und dann entsprechend den String zu manipulieren.
z.B.

Code: Alles auswählen

if(kWh.state.length = 4)
"0" + kWh.state)
if(kWh.state.length = 3)
"00" + kWh.state)
Leider funktioniert die String-Längenermittlung mit .lenght nicht. VSC gibt einen Fehler aus:
The method length(int) is undefined for the type State
Habe schon mehrere Varianten probiert, leider ohne Erfolg. Wo liegt mein Fehler?

bastler
Beiträge: 121
Registriert: 7. Jan 2020 19:36
Answers: 2

Re: String-Funktionen

Beitrag von bastler »

wie wäre es die werte nach int oder long zu wandeln, dann kannst du die mwh * 1000 nehmen und dann die kwh einfach dazu addieren? somit wäre egal wie viele stellen dort vorhanden sind. habs nicht probiert aber so die richtung:

Code: Alles auswählen

    mwh_int = (MWh as DecimalType).intValue
    kwh_int = (KWh as DecimalType).intValue
    result = (mwh_int * 1000) + kwh_int

Benutzeravatar
peter-pan
Beiträge: 2758
Registriert: 28. Nov 2018 12:03
Answers: 30
Wohnort: Schwäbisch Gmünd

Re: String-Funktionen

Beitrag von peter-pan »

...eine Alternative:

Code: Alles auswählen

rule "test Regel"

  when
    Item Dummy6 changed to ON
  then
   val a = "38"                           // String 1
   val b = "102.6"                        // String 2
   var c = Float.parseFloat(a + b) // Ergebnis als Float-Value
    logInfo("test Regel", " Der Gesamtwert ist" + c)
end
Zur Erläuterung: Strings werden bei einer Addition aneinander gefügt (konkateniert/Mengenlehre = ab + cd = abcd :lol: ) und dann das Ergebnis einfach in einen Float-Wert umgewandelt.

Edit:

Sorry, das mit der fehlenden Null bei zweistellig hab ich überlesen......Muss noch mal nachdenken :idea:
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.3.5 openhabian

violine21
Beiträge: 600
Registriert: 20. Sep 2019 05:49
Answers: 7

Re: String-Funktionen

Beitrag von violine21 »

peter-pan hat geschrieben: 22. Mai 2020 11:17 Sorry, das mit der fehlenden Null bei zweistellig hab ich überlesen......Muss noch mal nachdenken :idea:
;) ;) ;) Tja, wenn's doch so einfach wäre ;) ;) ;)

Ich habe durch einen ganz blöden Zufall eine Lösung gefunden.
Ich hatte das

Code: Alles auswählen

.toString
noch in der Zwischenablage.
Habe dann zufällig bei einem meiner Versuche hinter dem

Code: Alles auswählen

kWh.state.toString.length
auf Einfügen gedrückt. Ergebnis:

Code: Alles auswählen

logInfo("UVR-Test", kWh.state.toString.length.toString)
Der Fehler ist weg und ich bekomme ein Ergebnis:

Code: Alles auswählen

2020-05-22 11:20:00.027 [INFO ] [ipse.smarthome.model.script.UVR-Test] - 4
Ich versteh den Grund zwar nicht aber so scheint es zu funktionieren. :? :? :?

violine21
Beiträge: 600
Registriert: 20. Sep 2019 05:49
Answers: 7

Re: String-Funktionen

Beitrag von violine21 »

So, noch etwas "hübsch" gemacht und mit den korrekten Items versorgt:

Code: Alles auswählen

    if(virtual_UVR_kWh.state.toString.length.toString == "3")
        virtual_UVR_Gesamtleistung.postUpdate(virtual_UVR_MWh.state + ".00" + virtual_UVR_kWh.state + " kWh")
    if(virtual_UVR_kWh.state.toString.length.toString == "4")
        virtual_UVR_Gesamtleistung.postUpdate(virtual_UVR_MWh.state + ".0" + virtual_UVR_kWh.state + " kWh")  
    if(virtual_UVR_kWh.state.toString.length.toString == "5")
        virtual_UVR_Gesamtleistung.postUpdate(virtual_UVR_MWh.state + "." + virtual_UVR_kWh.state + " kWh")

    logInfo("UVR", virtual_UVR_Gesamtleistung.state.toString)

Code: Alles auswählen

2020-05-22 11:38:00.044 [INFO ] [g.eclipse.smarthome.model.script.UVR] - 26.027,0 kWh
Vielleicht kennt jemand noch eine andere Möglichkeit zur String-Manipulation.

VG
André

bastler
Beiträge: 121
Registriert: 7. Jan 2020 19:36
Answers: 2

Re: String-Funktionen

Beitrag von bastler »

uuuui :)

Code: Alles auswählen

if(virtual_UVR_kWh.state.toString.length.toString == "3")
... aber wenn ich das so anschaue, du hattest in deinem ersten post:

Code: Alles auswählen

if(kWh.state.length = 4)
vielleicht hat das nur nicht funktioniert weil du nur einmal "=" hattest, probiers doch mal so:

Code: Alles auswählen

if(kWh.state.length == 4)

bastler
Beiträge: 121
Registriert: 7. Jan 2020 19:36
Answers: 2

Re: String-Funktionen

Beitrag von bastler »

... bzw wenn dein kWh ja ein string ist muss es eventuell auch so heißen:

Code: Alles auswählen

if(kWh.state.length.intValue == 4)

violine21
Beiträge: 600
Registriert: 20. Sep 2019 05:49
Answers: 7

Re: String-Funktionen

Beitrag von violine21 »

bastler hat geschrieben: 22. Mai 2020 12:01 ... bzw wenn dein kWh ja ein string ist muss es eventuell auch so heißen:

Code: Alles auswählen

if(kWh.state.length.intValue == 4)
Hab's mal probiert, VSC meckert gleich.
Damit funktionierts:

Code: Alles auswählen

if(kWh.state.toString.length.intValue == 4)
Mit meinem bescheidenen Halbwissen denke ich, das der Item-State, trotz das das Item bereits ein String ist,
zwingend als String interpretiert werden muss. :? :? :?
Die letzte Zuweisung (scheinbar zwingend notwendig)

Code: Alles auswählen

.intValue
bzw.

Code: Alles auswählen

.toString
legt dann fest, als was das Ergebnis interpretiert wird. Als Zahl (4) oder als String ("4").

Vielen Dank fürs Mitüberlegen. Hat etwas Licht ins Dunkel gebracht.

VG André

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

Re: String-Funktionen

Beitrag von udo1toni »

Also grundsätzlich ist ein state ein state und kein String. Entsprechend gibt es auch kein Objekt .length. Man kann aber aus jedem state einen String machen (mit .toString) und dann gibt es auch das Objekt .length. Die saubere Variante ist aber, die Werte in Zahlen zu wandeln.

Code: Alles auswählen

rule "kWh und MWh nach MWh"
when
    Item kWh changed or   // Number Item Eingang
    Item MWh changed      // Number Item Eingang
then
    val Number nKwh = Float::parseFloat(kWh.state.toString.replace(",","."))
    val Number nMwh = Integer::parseInt(MWh.state.toString)
    val Number nErg = nMWh*1000 + nKWh
    Anzeige.postUpdate(nErg) // Number Item Ausgang
end
Nun liegt die Anzahl der kWh als Zahl in einem Item vor.

Das replace wird gebraucht, falls der Zahlenwert tatsächlich ein Komma als Dezimaltrenner enthält.
Ich habe die Rule nicht getestet :) aber so sollte es gehen.

Für meine PV-Anlage zimmere ich die verschiedenen Werte als String zusammen (Momantan / Tag / Jahr /Total) wobei ich die Einheiten automatisch anpasse. Die rule hatte ich schon vor UoM im Einsatz, es könnte sein, dass man da jetzt bequemere Wege nutzen kann:

Code: Alles auswählen

rule "PV-Anlage Update"
 when 
    Item PV_Current received update
 then
    var String strCurr  = "Err; "
    var String strDay   = "Err; "
    var String strYear  = "Err; "
    var String strTotal = "Err; "
    logDebug("PV-update", "Start der Rule")
    if (PV_Current.state instanceof Number) {
        if (PV_Current.state > 1000) 
            strCurr = String::format("%.2f kW; ", (PV_Current.state as Number) / 1000)
        else 
            strCurr = PV_Current.state.format("%d W; ")
    }
    logDebug("PV-update", "strCurr = {}",strCurr)
    if (PV_DaySum.state instanceof Number) {
        if (PV_DaySum.state > 1000)
            strDay = String::format("%.2f kWh/d; ", (PV_DaySum.state as Number) / 1000)
        else
            strDay = PV_DaySum.state.format("%d Wh/d; ")
    }
    logDebug("PV-update", "strDay = {}",strDay)
    if (PV_YearSum.state instanceof Number) {
        if (PV_YearSum.state > 1000000)
            strYear = String::format("%.2f MWh/y; ", (PV_YearSum.state as Number) / 1000000)
        else if (PV_YearSum.state > 1000)
            strYear = String::format("%.2f kWh/y; ", (PV_YearSum.state as Number) / 1000)
        else
            strYear = PV_YearSum.state.format("%d Wh/y; ")
    }
    logDebug("PV-update", "strYear = {}",strYear)
    if (PV_Total.state instanceof Number) {
        if (PV_Total.state > 1000000)
            strTotal = String::format("%.2f MWh/t", (PV_Total.state as Number) / 1000000)
        else if (PV_Total.state > 1000)
            strTotal = String::format("%.2f kWh/t", (PV_Total.state as Number) / 1000)
        else
            strTotal = PV_Total.state.format("%d Wh/t")
    }
    logDebug("PV-update", "strTotal = {}",strTotal)
    MyPV.postUpdate(strCurr + strDay + strYear + strTotal)
end
Ich war zu faul, mit die Funktion als Lambda anzulegen. Die ersten beiden Werte können maximal im kWh-Bereich liegen, entsprechend lohnt es sich dort nicht, die Umrechnung für MWh vorzusehen. Die Itemnamen sollten sprechend sein :) und in der Sitemap sieht das Ganze dann so aus:
pv3.png
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
peter-pan
Beiträge: 2758
Registriert: 28. Nov 2018 12:03
Answers: 30
Wohnort: Schwäbisch Gmünd

Re: String-Funktionen

Beitrag von peter-pan »

... hat mir keine Ruhe gelassen ;) .
noch 'ne Alternative:

Code: Alles auswählen

rule "test1 Regel"

  when
    Item Dummy6 changed to ON
  then
    val a = "38"         // Json-String 1
    val b = "92.6"       // Json-String 2
    var d = 0.0
      if (Float.parseFloat(b) < 100) {
        d = Float.parseFloat(a + "0" + b)
      }
      else {
        d = Float.parseFloat(a + b)
      }
    logInfo("test Regel", " Der Gesamtwert ist: " + d)
end
Mit der Regel kannst du wieder direkt spielen. Ersetze Variable "b" einfach mit einem Wert >= 100.
Sollte gehen :)
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.3.5 openhabian

Antworten