Herzlich willkommen im openHAB Forum!
Ich fürchte, das wird so eher gar nicht funktionieren (allerdings habe ich keine Erfahrung mit dem Binding, ich kann mich da auch gut irren).
Mein Vorschlag: Betrachte den Channel als reinen Sende- und Empfangskanal.
Lege für jeden Switch und jeden Wert ein passendes Item an, welches aber
nicht mit dem Channel verlinkt wird.
Stattdessen schreibst Du zwei Rules, die eine für die Senderichtung, die andere für die Empfangsrichtung. Innerhalb der beiden Rules errechnest Du dann aus dem gelieferten String die Zustände der Items und setzt diese per postUpdate bzw. Du nutzt die Itemzustände, um den passenden Befehlsstring zusammenzusetzen.
onValue und offValue wären für den switch Channel hier übrigens 1 bzw. 0. Aber es gibt im Thing keine Möglichkeit, den Sendestring korrekt zusammenzusetzen, wohl aber innerhalb einer Rule.
Items:
Code: Alles auswählen
String OneWireSend // wird nur zum Senden verwendet
String OneWireReceive // wird nur zum Empfang verwendet
DateTime OW_EventTime "Letzter Empfang um"
Number OWD1_Value "Messwert D 1"
Number OWD2_Value "Messwert D 2"
Number OWD3_1_Value "Messwert D 3.1"
Number OWD3_3_Value "Messwert D 3.3"
Group gOwd
Switch gOwd_3_4_1 "1-Wire 3-4 Ch. 1" (gOwd)
Switch gOwd_3_4_2 "1-Wire 3-4 Ch. 2" (gOwd)
Switch gOwd_3_4_3 "1-Wire 3-4 Ch. 3" (gOwd)
Switch gOwd_3_4_4 "1-Wire 3-4 Ch. 4" (gOwd)
Switch gOwd_3_4_5 "1-Wire 3-4 Ch. 5" (gOwd)
Switch gOwd_3_4_6 "1-Wire 3-4 Ch. 6" (gOwd)
Switch gOwd_3_4_7 "1-Wire 3-4 Ch. 7" (gOwd)
Switch gOwd_3_4_8 "1-Wire 3-4 Ch. 8" (gOwd)
Rule:
Code: Alles auswählen
rule "1-Wire Senderichtung"
when
Member of gOwd received command // eines der Switch Items wurde betätigt
then
val strChan = triggeringItem.name.split("_").get(3) // der Teilstring nach dem dritten Unterstrich
val strOnOff = if(receivedCommand == ON) "1" else "0"
val myCommand = "set,owd,out,3," + strChan + "," + strOnOff
OneWireSend.sendCommand(myCommand)
end
Es gibt ja noch OWD3_2, falls Du dieses mittels
set,owd,out,1,n schalten kannst, könnte man die entsprechenden Switch Items einfach der Gruppe hinzufügen und die Rule um die Abfrage der vorletzten Stelle erweitern. Der String myCommand muss dann halt noch eine weitere Variable enthalten, deren Wert Du vorher aus dem Itemnamen errechnen musst.
Die Empfangsseite ist leider etwas komplexer, aber auch zu bewältigen. Meine Herangehensweise ist hier, das Ganze mit einer Schleife zu realisieren, statt REGEX zu verwenden.
Das Ganze fängt harmlos an und steigert sich zu einem furiosen Finale
Code: Alles auswählen
rule "1-Wire Empfangsrichtung"
when
OneWireReceive received update
then
val lMessage = newState.split("\n") // newState -> aktueller Status des triggernden Items
lMessage.forEach[entry|
val strName = entry.split("\\|").get(0) // Teilstring links vom |
val strVal = entry.split("\\|").get(1) // Teilstring rechts vom |
switch(strName) {
case "1_EVT" : OW_EventTime.postUpdate(strVal)
case "1_OWD1" : OWD1_Value.postUpdate(Integer::parseInt(strVal).doubleValue/100)
case "1_OWD2" : OWD2_Value.postUpdate(Integer::parseInt(strVal).doubleValue/100)
case "1_OWD3_1" : OWD3_1_Value.postUpdate(Integer::parseInt(strVal).doubleValue/100)
case "1_OWD3_3" : OWD3_3_Value.postUpdate(Integer::parseInt(strVal).doubleValue/100)
case "1_OWD3_2" : {
val java.math.BigInteger biVal = java.math.BigInteger.valueOf(Integer::parseInt(strVal,2))
gOwd.members.filter[i|i.name.split("_").get(1) == "2"].sortBy[name].forEach[i,count|
i.postUpdate(if(biVal.testBit(count)) ON else OFF)
]
}
case "1_OWD3_4" : {
val java.math.BigInteger biVal = java.math.BigInteger.valueOf(Integer::parseInt(strVal,2))
gOwd.members.filter[i|i.name.split("_").get(1) == "4"].sortBy[name].forEach[i,count|
i.postUpdate(if(biVal.testBit(count)) ON else OFF)
]
}
}
]
end
Zunächst wird der empfangene String an den Zeilenumbrüchen gesplittet. lMessage ist anschließend eine Liste aller Zeilen.
Anschließend wird für jeden Eintrag in der Liste der gleiche Code abgearbeitet.
Die Zeile wird an der Pipe gesplittet, links steht der Name, der landet in strName, rechts der Wert, der in strVal gespeichert wird.
Nun wird abhängig von strName unterschiedlicher Code ausgeführt. Da es etliche unterschiedliche Namen gibt, bietet sich hier switch() an.
Falls strName die Werte 1_EVT, 1_OWD1, 1_OWD2, 1_OWD3_1 oder 1_OWD3_3 enthält, wird der String in strVal als Integer eingelesen und anschließend als Float mit doppelter Genauigkeit durch 100 geteilt. Danach wird das Ergebnis im jeweiligen Item gespeichert.
Enthält strName stattdessen 1_OWD3_2 oder 1_OWD3_4, wird es zugegebenermaßen übel...
Im ersten Schritt wird strVal als Binärwert in BigInteger gewandelt. Leider sieht das sehr kompliziert aus, das liegt allerdings nur daran, dass java.math.BigInteger gewöhnlich nicht zur Verfügung steht, es muss also importiert werden.
Warum BigInteger hier der "richtige" Datentyp ist? Weil nur BigInteger eine Methode
.testBit() hat, und die macht uns gleich das Leben so viel leichter...
Nun wird die Gruppe der Switch Items gefiltert (die haben wir ja schon, also können wir sie auch ruhig intensiv nutzen...), und zwar auf die Items, welche in dem ausgewerteten Byte dargestellt werden.
Die entstehende Liste der Items wird nun durchlaufen und für jedes Item wird das korrespondierende Bit ausgewertet.
Ist das Bit gesetzt (true), so wird als Wert ON für den Switch gesetzt, ansonsten OFF.
Weil dieser Code schon ziemlich... äh... ist, habe ich das Ganze in openHAB5.1.0 getestet (allerdings nur gegen den String, der im Ausgangspost steht... ich habe kein Device, welches mit TCP/UDP angesteuert werden müsste...) Der Code sollte mit jeder openHAB Version funktionieren - bis hinunter zu openHAB1.0 (mit ein paar kleineren Anpassungen...).
Wichtig ist natürlich noch, dass die Namen der Items passend gewählt werden, nur so kann man die Gruppe effizient durchlaufen. Die Itemnamen müssen dabei nicht exakt so aussehen wie im Beispiel, wichtig ist nur, dass die Unterscheidungsmerkmale, nach denen gefiltert oder gesucht wird immer an identischer Stelle zu finden sind, so dass man die Werte berechnen und auswerten kann.
openHAB5.0.1 stable in einem Debian-Container (trixie, OpenJDK 21 headless runtime) (Proxmox 9.0.6, LXC)