Hello,

This tutorial will show you how to display your solar power information from a Victron Energy Colour Control GX via the MQTT 3 binding on your openHAB 3 interface.

This tutorial assumes you already have ethernet or wifi connected and working on your CCGX, and a MQTT bridge and thing setup on your openHAB 3 setup.

Find the IP/host CCGX device. (I also add this IP to my /etc/hosts file to make life easier on the command line)

  • Install mosquitto clients for testing/debugging on your development machine (ie. on Debian);
sudo apt-get install mosquitto-clients

This gives us two clients. mosquitto_pub can be used to publish messages to a broker and mosquitto_sub can be used to subscribe to a topic to receive messages.

  • Find your CCGX VRM Portal ID in Settings->Services->VRM online portal or issue
mosquitto_sub -h ccgx -t "#"

Replace ccgx with your IP or add it to your system’s hosts file. The response will be a 12 character hex value and look something like

{"value": "a0f6fd5aa8c8"}

a0f6fd5aa8c8 is your portal ID, please substitute this ID in all further examples

  • Since the MQTT scripts on the CCGX go to sleep after 60 seconds let’s add a rule to let the CCGX know someone is listening and therefore keep sending information.
triggers:
  - id: "1"
    configuration:
      cronExpression: 0/30 * * * * ? *
    type: timer.GenericCronTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: |
        val actions = getActions("mqtt", "mqtt:broker:ccgx")
        actions.publishMQTT("R/a0f6fd5aa8c8/system/0/Serial", "")
        logInfo("Solar", "CCGX MQTT Keep Alive Timer fired!!")
    type: script.ScriptAction

Now with the CCGX constantly sending out messages we can play around with what we want to read.

On the command line issue

mosquitto_sub -h ccgx -t "N/#" -v

to watch all the messages being sent from the CCGX. There is a lot! It will show the topic and the value. Assign the topics to individual channels through the GUI or code.

UID: mqtt:topic:ccgx:ccgx
label: CCGX
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:ccgx
location: Shed
channels:
  - id: pv_battery_soc
    channelTypeUID: mqtt:dimmer
    label: Battery SoC
    description: ""
    configuration:
      stateTopic: N/a0f6fd5aa8c8/system/0/Dc/Battery/Soc
      transformationPattern: JSONPATH:$.value
  - id: pv_battery_voltage
    channelTypeUID: mqtt:number
    label: Battery Voltage
    description: null
    configuration:
      formatBeforePublish: "%.4f"
      stateTopic: N/a0f6fd5aa8c8/system/0/Dc/Battery/Voltage
      transformationPattern: JSONPATH:$.value
  - id: pv_power_pv
    channelTypeUID: mqtt:number
    label: Solar Power
    description: null
    configuration:
      stateTopic: N/a0f6fd5aa8c8/system/0/Dc/Pv/Power
      transformationPattern: JSONPATH:$.value
  - id: pv_power_consumption
    channelTypeUID: mqtt:number
    label: Consumption
    description: null
    configuration:
      stateTopic: N/a0f6fd5aa8c8/system/0/Ac/Consumption/L1/Power
      transformationPattern: JSONPATH:$.value

Add new equipment to your semantic model. Add ā€˜points from thing’ to your equipment and choose your mqtt thing with all the channels added. They can now be viewed on the MainUI.

Enjoy!

3 Likes

Thanks @Zooka great work, I had some trouble getting my CCGX back online after switching to OH3. When I implement your ā€œkeep awakeā€ rule in OH3 it does work, but it gives me the following error in the log - any ideas as to the cause? I have the correct ID.

[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '85056be4f0' failed: null

Thanks!

Was having issues too, try this one mate.

actions.get("mqtt", "mqtt:broker:1e24481776").publishMQTT("R/a0f6fd5aa8b8/system/0/Serial", "");

1 Like

@Zooka I owe you an apology, your initial rule actually works - I was pointing the getActions to the incorrect MQTT broker, your rule is working well now that the rule points to the correct broker. Rookie mistake…

2021-02-14 11:28:30.238 [INFO ] [org.openhab.core.model.script.Solar ] - CCGX MQTT Keep Alive Timer fired!!

Keep up that great work!

All good.

I figured out how to identify the charging state easier using Profiles. So no more having to use rules, etc… much cleaner.

MQTT topic
N/a0f6fd5aa8b8/solarcharger/258/State {"value": 3}

Add another channel to your Victron broker, add the item to model and apply a profile to it using MAP transformation.

$ cat /etc/openhab/transform/VictronChargerState.map

0=Off
2=Fault
3=Bulk
4=Absorption
5=Float
6=Storage
7=Equalize (manual)
11=Power supply mode
246=Repeated absorption
247=Auto equalize/Recondition
248=BatterySafe

Or you may prefer the overall system state.

N/a0f6fd5aa8b8/system/0/SystemState/State {"value": 9}

$ cat /etc/openhab/transform/VictronSystemState.map

0=Off
1=Low power
2=VE.Bus Fault condition
3=Bulk charging
4=Absorption charging
5=Float charging
6=Storage mode
7=Equalisation charging
8=Passthru
9=Inverting
10=Assisting
256=Discharging
257=Sustain

More.

Enjoy!

2 Likes

Hi @Zooka

thanks for your work! Was just migrated from a working OH2.5 system where everything was fine. However, on OH3 I’m struggling to get values other than ā€œ0ā€ on the PV_Power channel (all other channels are working fine). I do see the PV_Power values in the console with ā€œmosquitto_sub -h ccgx -t ā€œ#ā€ā€ (during the day). Has anyone else seen this problem? Could it be that openhab looses connection after the PV_Power channel disappears during the night?

Thanks!

Update: one workarround is to restart the mqtt-broker. After that (if there is a value published on the the PV_Power channel) I get the actual values. However, after the next night (when PV_Power goes to sleep again) I only get the value ā€œ0ā€ the next day even I do see other values in the mosquitto console…

Any hints on that problem?

Hello,
I also managed to display the data from the victron inverter in openhab but I receive this error now:

java.lang.IllegalArgumentException: json string can not be null or empty
        at com.jayway.jsonpath.internal.Utils.notEmpty(Utils.java:383)
        at com.jayway.jsonpath.internal.ParseContextImpl.parse(ParseContextImpl.java:36)
        at com.jayway.jsonpath.JsonPath.read(JsonPath.java:498)
        at org.openhab.transform.jsonpath.internal.JSonPathTransformationService.transform(JSonPathTransformationService.java:63)

I think we need an openhab rule that ignores all empty or null messages.
Does anyone help us?
Thank you

Hi,
Thanks for the examples, I have been able to set a keep alive rule and can view the ccgx messages via MQTT.fx so I know that works. However I cannot seem to get the values into OH3. I have tried so many different combinations but I never see any values. Any ideas or example setups that I can use please?

Things-Datei

Bridge mqtt:broker:venus [ host="192.168.xxx.xxx",port="1883", secure=false ]
Thing mqtt:topic:mything "mything" (mqtt:broker:venus) {
  Channels:
    Type number : V_AC_V_L1 "Victron Verbrauch L1" [ stateTopic="N/0035ff9a24d7/system/0/Ac/Consumption/L1/Power", transformationPattern="JSONPATH:$.value"]
    Type number : V_AC_V_L2 "Victron Verbrauch L2" [ stateTopic="N/0035ff9a24d7/system/0/Ac/Consumption/L2/Power", transformationPattern="JSONPATH:$.value"]
    Type number : V_AC_V_L3 "Victron Verbrauch L3" [ stateTopic="N/0035ff9a24d7/system/0/Ac/Consumption/L3/Power", transformationPattern="JSONPATH:$.value"]
    Type number : V_AC_G_L1 "Victron Netz L1"      [ stateTopic="N/0035ff9a24d7/system/0/Ac/Grid/L1/Power", transformationPattern="JSONPATH:$.value"]
    Type number : V_AC_G_L2 "Victron Netz L2"      [ stateTopic="N/0035ff9a24d7/system/0/Ac/Grid/L2/Power", transformationPattern="JSONPATH:$.value"]
    Type number : V_AC_G_L3 "Victron Netz L3"      [ stateTopic="N/0035ff9a24d7/system/0/Ac/Grid/L3/Power", transformationPattern="JSONPATH:$.value"]

    Type number : V_DC_Power "Victron DC Power"    [ stateTopic="N/0035ff9a24d7/battery/512/Dc/0/Power", transformationPattern="JSONPATH:$.value"]
    Type number : V_DC_Volt "Victron DC Volt"      [ stateTopic="N/0035ff9a24d7/battery/512/Dc/0/Voltage", transformationPattern="JSONPATH:$.value"]
    
    Type number : V_Batt_Soc "Victron Batt Soc"    [ stateTopic="N/0035ff9a24d7/system/0/Dc/Battery/Soc", transformationPattern="JSONPATH:$.value"]
    Type number : V_Batt_Temp "Victron Batt Temp"  [ stateTopic="N/0035ff9a24d7/system/0/Dc/Battery/Temperature", transformationPattern="JSONPATH:$.value"]
    Type number : V_Batt_Stat "Victron Batt State" [ stateTopic="N/0035ff9a24d7/system/0/Dc/Battery/State", transformationPattern="JSONPATH:$.value"]
    Type number : V_Batt_Stat1 "Victron Batt Status1"  [ stateTopic="N/0035ff9a24d7/system/0/Batteries", transformationPattern="JSONPATH:$.value[0].state"]
    
    Type number : V_Sys_Stat "Victron Sys Status"  [ stateTopic="N/0035ff9a24d7/system/0/SystemState/State", transformationPattern="JSONPATH:$.value"]
}

Items-Datei

Group Victron         "Victron"                          <energy>      (Garage)  ["Inverter"]
 Number V_AC_V_L1      "Victron Verbrauch L1 [%.1f W]"                 (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_AC_V_L1" }
 Number V_AC_V_L2      "Victron Verbrauch L2 [%.1f W]"                 (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_AC_V_L2" }
 Number V_AC_V_L3      "Victron Verbrauch L3 [%.1f W]"                 (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_AC_V_L3" }
 Number V_AC_G_L1      "Victron Netz L1 [%.1f W]"                      (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_AC_G_L1" }
 Number V_AC_G_L2      "Victron Netz L2 [%.1f W]"                      (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_AC_G_L2" }
 Number V_AC_G_L3      "Victron Netz L3 [%.1f W]"                      (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_AC_G_L3" }

 Number V_DC_Power     "Victron Battery Power [%.1f W]"                (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_DC_Power" }
 Number V_DC_Volt      "Victron Battery Volt [%.1f V]"                 (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_DC_Volt" }

 Number V_Batt_Soc     "Victron Battery Soc [%.1f %%]"  <battery>      (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_Batt_Soc" }
 Number V_Batt_Temp    "Victron Battery Temp [%.1f °C]" <temperatur>   (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_Batt_Temp" }
 Number V_Batt_Stat    "Victron Battery Status [MAP(VictronBatteryState.map):%s]" <text> (Victron) ["Energy"]   { channel="mqtt:topic:mything:V_Batt_Stat" }
 Number V_Batt_Stat1   "Victron Status [MAP(VictronSystemState.map):%s]" (Victron) ["Energy"] { channel="mqtt:topic:mything:V_Batt_Stat1" }

 Number V_Sys_Stat     "Victron Status [MAP(VictronSystemState.map):%s]" (Victron) ["Energy"] { channel="mqtt:topic:mything:V_Sys_Stat" }

Rule for Keep-Alive

val actions = getActions("mqtt", "mqtt:broker:venus")
actions.publishMQTT("R/xxxxxxxxxx/system/0/Serial", "")
logInfo("Solar", "CCGX MQTT Keep Alive Timer fired!!")

2 Likes