you made my day @pirx - thank you very much! It’s working and I added some stuff (and some minor changes, because auf misspellings). Will post the config asap for others.
1 Like
so here my config - kudos to @Pirx
Prerequisits:
- tcp1 binding
- JSONPath Transformation
-REGEX Transformation
Create udp.cfg (only tcp.cfg is automatically generated)
# all parameters can be applied to both the TCP and UDP binding unless
# specified otherwise
# Port to listen for incoming connections
port=7090
# Cron-like string to reconnect remote ends, e.g for unstable connection or remote ends
#reconnectcron=0 0 0 * * ?
# Interval between reconnection attempts when recovering from a communication error,
# in seconds
retryinterval=5
# Queue data whilst recovering from a connection problem (TCP only)
#queue=true
# Maximum buffer size whilst reading incoming data
#buffersize=1024
# Share connections within the Item binding configurations
#itemsharedconnections=true
# Share connections between Item binding configurations
#bindingsharedconnections=true
# Share connections between inbound and outbound connections
#directionssharedconnections=true
# Allow masks in ip:port addressing, e.g. 192.168.0.1:* etc
#addressmask=true
# Pre-amble that will be put in front of data being sent
#preamble=
# Post-amble that will be appended to data being sent
#postamble=\r\n
# Perform all write/read (send/receive) operations in a blocking mode, e.g. the binding
# will wait for a reply from the remote end after data has been sent
#blocking=false
# timeout, in milliseconds, to wait for a reply when initiating a blocking write/read
# operation
#timeout=3000
# Update the status of Items using the response received from the remote end (if the
# remote end sends replies to commands)
#updatewithresponse=true
# Timeout - or 'refresh interval', in milliseconds, of the worker thread
refreshinterval=250
# Timeout, in milliseconds, to wait when "Selecting" IO channels ready for communication
#selecttimeout=1000
# Used character set
charset=ASCII
Rules (not yet finished - but my needs for report 2 and 3 mostly implemented)
rule "Request Keba report"
when
Time cron "*/30 * * * * ?" // check every 5 seconds
then
Keba_send.sendCommand("report 2")
Thread::sleep(10000)
Keba_send.sendCommand("report 3")
end
rule "Receive messages from the KEBA Wallbox"
when
Item Keba_receive changed
then
// Messages, which starts with "TCH" will be skipped
if (Keba_receive.state.toString.substring(0,3) == "TCH" )
return
// requested reports always consists an "ID"
var String jvalue = transform("JSONPATH", "$.ID", Keba_receive.state.toString)
if ( jvalue.substring(0,1) != "{" ) {
Keba_response.postUpdate( jvalue )
if (jvalue == "2") { // Report 2
KebaPlugState.postUpdate( transform("JSONPATH", "$.Plug", Keba_receive.state.toString) )
KebaState.postUpdate( transform("JSONPATH", "$.State", Keba_receive.state.toString) )
KebaSystemCurrent.postUpdate( Float.parseFloat(transform("JSONPATH", "$.['Max curr']", Keba_receive.state.toString)) / 1000 ) //reported in mA, transformed to Ampere
KebaCurrent.postUpdate( Float.parseFloat(transform("JSONPATH", "$.['Curr HW']", Keba_receive.state.toString)) / 1000 ) //reported in mA, transformed to Ampere
KebaUptime.postUpdate( transform("JSONPATH", "$.Sec", Keba_receive.state.toString) )
}
if (jvalue == "3") { // Report 3
KebaI1.postUpdate( Float.parseFloat(transform("JSONPATH", "$.I1", Keba_receive.state.toString) ) / 1000 ) //reported in mA, transformed to Ampere
KebaI2.postUpdate( Float.parseFloat(transform("JSONPATH", "$.I2", Keba_receive.state.toString) ) / 1000 )
KebaI3.postUpdate( Float.parseFloat(transform("JSONPATH", "$.I3", Keba_receive.state.toString) ) / 1000 )
KebaU1.postUpdate( transform("JSONPATH", "$.U1", Keba_receive.state.toString) )
KebaU2.postUpdate( transform("JSONPATH", "$.U2", Keba_receive.state.toString) )
KebaU3.postUpdate( transform("JSONPATH", "$.U3", Keba_receive.state.toString) )
powKebaPower.postUpdate( Float.parseFloat(transform("JSONPATH", "$.P", Keba_receive.state.toString))/1000) //reported in mW, transformed to Watt
eneKebaSessionEnergy.postUpdate( Float.parseFloat(transform("JSONPATH", "$.['E pres']", Keba_receive.state.toString))/10000) //reported in Wh + 1 decimal, transformed to Kilowatthours
eneKebaTotalEnergy.postUpdate( Float.parseFloat(transform("JSONPATH", "$.['E total']", Keba_receive.state.toString))/10000) //reported in Wh +1 decimal, transformed to Kilowatthours
}
}
end
items added (please change to the IP of your wallbox)
//Wallbox
String Keba_receive "fromUDPnode [%s]" {udp="<[192.168.X.XXX:*:'REGEX((.*))']"}
String Keba_send "toUDPnode" {udp=">[192.168.X.XXX:7090:]"}
String Keba_response "Antwort [%s]"
Dimmer KebaCurrentRange "Max. Stromstärke [%.1f %%]" (gWallbox)
Number KebaSystemCurrent "Max. Strom Hardware [%.1f A]" (gWallbox)
String KebaState "Wallbox [MAP(keba_state.map):%s]" <wallbox> (gWallbox)
String KebaPlugState "Stecker: [MAP(keba_plug.map):%s]" (gWallbox)
DateTime KebaUptime "Uptime [%1$tY Y, %1$tm M, %1$td D, %1$tT]" (gWallbox)
Number KebaI1 "Phase 1 [%.1f A]" (gWallbox)
Number KebaI2 "Phase 2 [%.1f A]" (gWallbox)
Number KebaI3 "Phase 3 [%.1f A]" (gWallbox)
Number KebaU1 "Phase 1 [%.1f V]" (gWallbox)
Number KebaU2 "Phase 2 [%.1f V]" (gWallbox)
Number KebaU3 "Phase 3 [%.1f V]" (gWallbox)
Number powKebaPower "Wallbox [%.1f W]" (gWallbox, gPower)
Number eneKebaSessionEnergy "Session [%.1f kWh]" (gWallbox)
Number eneKebaTotalEnergy "Gesamt [%.1f kWh]" (gWallbox, gEnergy)
keba_state.map
0=Hochfahren
1=Nicht bereit
2=bereit
3=Lädt
4=Fehler
5=Auth. Problem
NULL=n.a.
-=n.a.
keba_plug.map
0=nicht angesteckt
1=in der Ladestation
3=verriegelt in Ladestation
5=am Auto angesteckt
7=am Auto verriegelt
NULL=n.a.
-=n.a.
Hope it helps others. As next step I want to add a control (Dimmer item) for the current. As I am metering my total electricity consumption, I want to adapt the Current of the wallbox to not exceed a certain current for the whole house (could also be used for adapting the current to photovoltaics production.
Regards,
HErbert