Cannot publish generator state with MQTT on Venus OS

I built a simple Generator start/stop relay to interface between my Venus OS and Home Assistant on my RV since the single relay provided by Victron will not work for my Onan QG 4000 Generator. When the generator is cold or has not run for a while it could take up to 30 seconds to start.

I’m using a Wemos 32 (overkill but what I had on hand), 2-3.3V relays, and an Optocoupler to read the state of the Onan generator built into the RV. I’ve wired one relay to the Yellow Start circuit and the other to the Brown Stop circuit. The optocoupler ties into the Red run-time display on my control panel to sense if the generator is running. I have a very simple ESPHome yaml file programmed to the Generator Relay and I can control the starting and stopping of the Generator using Home Assistant.

I’m using MQTT and my plan is to get the start/stop/states from the Venus OS. I can publish

  • victron-rv/W/INSTANCE/generator/0/AutoStartEnabled = {“value”:0}
  • victron-rv/W/INSTANCE/generator/0/AutoStartEnabled = {“value”:1}
    from Home Assistant and this is working fine.

I don’t have the two systems tied together yet while testing. When I start the generator with Home Assistant and receive the status that it’s running, I publish the state {“value”:1} to the topic “victron-rv/W/INSTANCE/generator/0/State” but the state does NOT update. When I stop the generator from Home Assistant and receive the status that it’s not running I publish the state {“value”:0} to the topic victron-rv/W/INSTANCE/generator/0/State" In either case, the state on the Venus OS does Not Update.

I’m using MQTT Explorer to watch the messages.

I did remote into the Venus OS console and did a manual start for 1 minute from there just to watch the messages. The generator does not yet start from the Venus OS during this point of the testing process. I’m not yet using the state value from Venus OS to start the generator.

  • victron-rv/W/INSTANCE/generator/0/State = {“value”:1}.
  • The Runtime and ManualStartTimer start the countdown.
  • victron-rv/W/INSTANCE/generator/0/RunningByCondition = {“value”:“manual”}
  • victron-rv/W/INSTANCE/generator/0/RunningByConditionCode = {“value”:1}
  • victron-rv/W/INSTANCE/generator/0/ManualStartManualStart = {“value”:1}
    When the manual start timer times out,
  • victron-rv/W/INSTANCE/generator/0/State = {“value”: 4}
  • victron-rv/W/INSTANCE/generator/0/State = {“value”:0}

I also noticed I am unable to toggle the QuietHours on and off by publishing:

  • victron-rv/W/INSTANCE/generator/0/QuietHours = {“value”:1} or
  • victron-rv/W/INSTANCE/generator/0/QuietHours = {“value”:0}

Is there something preventing me from doing this? If so, I will not be able to finish the integration because I am relying on the state value do tie the two systems together. When I start the generator with Home Assistant, no timers run on the Venus OS. I’m assuming by writing the State {“value” = 1} will tell Venus OS that the generator is running.

The values on mqtt are a representation of the values in DBus.

Everytime a device or the system is changing something on the Bus, it will be reflected in MQTT.

The other way round - writing something to the /W/ Topic - only works for dbus values that are marked writeable. If they are marked readonly, they can’t be changed through mqtt.

Then, control of that value is purely up to the dbus service, owning that variable.

For a typical service you could say:

  • Can the value be changed through the UI, like Autostart / CustomName / other config? Then it’s writeable and can be modified through /W/ on mqtt.
  • Does the value represent a state that is usually provided by the device connected? (State, Voltage, Power) - then it’s typically readonly and managed by the respective service implementation.

Also QuitHoursActive is not a (writeable) Value, representing wether that mode should be active or not. It is a readonly state, indicating if the device is currently within the quiet hours.

Basically everything but AutoStartEnabled and ManualStart is readonly:

Full list:
https://www.victronenergy.com/upload/documents/CCGX-Modbus-TCP-register-list-3.40.xlsx

So, the only way to get (external) control over the generators State-Value would be to provide your own service impelemtation of com.victronenergy.generator (can be done with Python), and have that implementation update values on dbus with values it receives from your Home-Control.

Maybe can be achieved through Modbus-TCP, but have no experience with that.

1 Like

Quiet hours can be enabled/disabled via mqtt using path
**/W/“device_id”/settings/0/Settings/Generator0/QuietHours/Enabled

Other generator settings can be made via the settings path similar to above. The generator path you are using is for the current states. (Read only)

1 Like

OK, First thank you dognose for the register list! That really helps! I’m not fluent in Python and would prefer to keep things as “stock” as possible. I had a little more time today to do some more investigation and thinking.
First, I noticed on the remote console under Generator start/stop settings there is a boolean field called “Link to external running state”. I don’t see a reference to that in the spreadsheet. I’m wondering how this is used. there is nothing in the instructions that describes this either.
Generator Start Settings

I did modify my Home Assistant Automation to Publish
**W/"device_id/generator/0/ManualStart = 1 when I manually start the generator from HA and that does start the timers in Venus which is great! When I turn off the generator I publish **/generator/0/ManualStart = 0 and that turns off the timers. So far, so good…

Next
Now I’m looking at */N/“device_id”/generator/0/State. It publishes the following: 0=Stopped;1=Running;2=Warmup;3=Cooldown;4=Stopping;10=Error. I need to do some more research with these state values. Thanks to Derrick’s post I see a way to configure “Warmup” or “Cooldown” time. I did play with changing the quiet hours Enabled by writing the {“value”: 0 } or {“value”:1} but there also is a max and min value . I tried changing the max, min values but they did not change. The enabled value does. Works Great! I can’t seem to find these registers on the spreadsheet.

I did see state 4 “Stopping” in the MQTT History. It looks like there is no verification that the generator actually starts in Venus OS. I’m on v3.41.

It just sets the state = 1 Running when it’s supposed to be running. Is this the correct assumption? It would be way more helpful to report back to Venus the generator is actually started and/or running not just when it should be.

Lastly, does anyone know if there any way to use substitutions or !secrets to hide the device_id? It sure would make collaboration much more secure.

Thank you for your time!

The max and min values are informative only, they show you what values can be accepted by the register, they cannot be changed. If you attempt to publish a value outside of the min/max value it will simply be ignored.

Link to external running state has to do with a digital input. If you use a generator running signal to activate the digital input, selecting this option will ‘link’ the external run signal to the cerbo status.

Which would be, what he is attempting to do?

If i got it right, he has his own generator controller and wants to display the state in vrm / cerbo.

So, he could use an IO of his arduino, connect that with a digital in of the cerbo, and link the generator state with that digital input?

That way he could set the State Indicator variable by toggling the IO on his controller?

Or is the link the “other way round” to pull a digital out pin high, when the internal dbus value becomes true?

You have that correct, in that the triggering of the cerbo digital input will change the status of the cerbo (thereby changing the dbus status) from ‘stopped’ to ‘running’ and vice versa. In order for this to work properly, relay one has to be enabled for generator start/stop and digital input one selected as ‘generator’. You might also check out guimods, Kevin has made some rather nice enhancements to the generator python script.

That is correct in both respects. My controller resides in the wall behind the RF control panel and taps into the generator start/stop switch wiring along with the runtime clock. Super simple 3 short wires plus power to the ESP32.

I have Relay 1 setup as Generator Start/Stop. Turning on LinkToExternalStatus changes the value in */N/Device_id/settings/0/Settings/Generator0/LinkToExternalStatus = {“value”:1} I turned on DigitalInput1 and assigned it Generator.

digitalinput
  1
    Mgmt
      ProcessVersion = {"value":"0.23"}
      Connection = {"value":"/dev/gpio/digital_input_1"}
      ProcessName = {"value":"/opt/victronenergy/dbus- 
  digitalinputs/dbus_digitalinputs.py"}
  State = {"value":11}
  InputState = {"value":1}
  Type = {"value":9}
  Alarm = {"value":0}
  ProductName = {"value":"Generator"}
  Connected = {"value":1}
  ProductId = {"value":41318}
  CustomName = {"value":""}
  DeviceInstance = {"value":1}
  Count = {"value":0}

I have a pi in the “basement” next to my MPPT 100/30 solar charge controller & Smart Battery shunts all wired to the VE bus going to the pi.

Eventually I will purchase a MultiPlus inverter but not in the budget at the moment. I do have A/C monitoring in HA but these values are unfortunately not natively writeable to the D-Bus.

My Home Assistant (HA) server is located in an overhead bin above the driver’s seat attached to a router running Zero-tier with a cellular hotspot for continuous connectivity to the RV with a phone/laptop/etc.

Communication across the system is done with MQTT and ESPhome to a single interface on HA. This eliminates running physical control wires which is impractical and in some cases extremely difficult.

When we travel, we overnight “boondock” at harvest host sites. Some allow generators, other do not and some restrict the times. So I want to be able to control all of these functions from a single HA dashboard. We’ve had some issues running low on battery power and I’d rather not be woken up at 3 am with a low battery alarm to manually start the generator for heat when generator use is OK.

There is no provision in Venus to validate if the generator is running and it could take up to 3-30 second “start” cycles to actually fire up the generator. I can perform those start cycles and validate the generator starts/stops in HA. The DigitalInput/1/State = {“value”:11} with doing nothing? According to the spreadsheet, com.victronenergy.digitalinput
State is NOT writeable.

The reporting functions in Venus are great as long as the states get set correctly. That’s why I was hoping to set the state after the generator starts/stops. Since that is not possible I’m re-thinking the control logic. The Manual Start works great from the HA side to the D-Bus side reported in my last post. My goal is to try to use the AutoStart state from the D-Bus side to start/stop the generator on the HA side. The timers will be off a few seconds by no big deal.

Wordy, sorry, but I hope this clarifies what I’m trying to accomplish.

Yes, it is not writeable (externally) because it represents the state of the wire that is physically connected to the respective digital input pin.

So, in this case, you would need to run 1 Wire from your ESP or PI to that digital in, pull it up, when the generator is running - and the generator in cerbo will change it’s state to true.

Something like:

  • HA decides to start generator
  • HA sends instructions to your controller
  • Controller does it’s work
  • Controller detects (or assumes) Generator is now running
  • Controller pulls the wire connected to the cerbo High
  • Cerbo notes digital in is high
  • Cerbo sets State = true for the generator service

Actually I think what I would do is putting a optocoupler in front of an eventual generator LED, that indicates the running state and wire that up with the cerbo. (If the generator has no dedicated IO port for this)

Hence you’ll get a REAL state input, not a state input based on the (invalidated?) “Yeah, I said start”.

Just make sure to check the documentation about the voltage limits for the digital input pins. MicroControllers can easily be fried by applying a too high voltage to their inputs.

I have an optocoupler (indicated by the arrow) tied to the generator start/stop controller so I know when the generator is running or not running. It uses the hour meter circuit powered when the generator is running.

Flow 1 is the MANUAL generator start logic regardless when where the start input comes from.

In manual mode everything works great by monitoring the state of the optocoupler. Using MQTT, I publish to the Topic: victron-rv/W/device_id/generator/0/ManualStart {“value”:1} . The Cerbo knows the generator has manually started and run timers work as expected. State Topic: victron-rv/N/device_id/generator/0/State = 1

Flow 2 is the MANUAL generator STOP logic. This is also working as expected. I publish to the Topic: victron-rv/W/device_id/generator/0/ManualStart {“value”:0} and the timers in the Cerbo stop and when Cerbo is updated with ManualStart = 0 and state topic: state_topic: victron-rv/N/device_id/generator/0/State = 0

I can’t physically get a control wire from the ESP to the Pi because there is a large grey water tank in the way. That is the reason for using MQTT messages. The system works great in manual mode.
The issue I’m having is when I try utilizing the AutoStart features of the Cerbo.

I am using GUI Mods and there is a switch to Link to external running state. But reading Kevin’s program I can’t find that register to let the Cerbo that the generator is running.

Flow 3 Shows the flow when AutoStart is enabled. The intent is use RunningByCondition to start the generator. I can evaluate that topic to start the generator but I can’t find where to digitalwrite to let the Cerbo know the generator is actually running to update the victron-rv/N/device_id/generator/0/State value. This register is not writable using the /W/ topic.

So I ran 8 tests today using the TestRun condition to watch what happens using MQTT Explorer. I’m pretty sure the problem stems from not knowing what the topic is of the external generating state. I’m assuming if I can digitally write to this location, I would be able to get everything working properly. Not to be accused of not doing my homework, I’ve included my test results below.

Test1
Conditions:

  • Link to external running state: disabled
  • Test Run: Enabled 300 sec (5 mins)
  • Running by condition: TestRun
  • ManualStart: 0
  • State: 1
Results: At prescribed time the test run starts, Cerbo timers start. When the Runtime reaches 300 sec, state changed to 4 (stopping) then 0 (stopped)

Test2
Conditions:

  • Link to external running state: disabled
  • Test Run: Enabled 300 sec (5 mins)
  • Running by condition: TestRun
  • ManualStart: 0
  • State: 1

Results: At prescribed time the test run starts, Cerbo timers start. Cerbo thinks generator is running but its not.

Test3

Test3
During the test run, the generator was started Enabled (MQTT Publish victron-rv/W/device_id/generator/0/ManualStart {“value”:1})
Conditions:

  • Link to external running state: disabled
  • Test Run: Enabled 300 sec (5 min)
  • Running by condition: TestRun
  • ManualStart: 1
  • State: 1

Results: The running by condition remains TestRun. Runtime continues to increase

Test4

Test4
The test run stopped at prescribed run time 300 sec.
Conditions:

  • Link to external running state: disabled
  • Test Run: Enabled 300 Sec (5 min)
  • Running by condition: Manual
  • ManualStart: 1
  • State: 1

Results: Since manual start was enabled, the Running by condition changed from TestRun to Manual when Runtime > 300 and the generator did not stop. Cerbo run timers continued to run.

Test5
Conditions:

  • Link to external running state: enabled
  • Running by condition: Manual
  • ManualStart: 1
  • State: 1

Results: Cerbo timers did not start

Test6
Continuing from TestRun5,
Conditions:

  • Link to external running state: enabled
  • Running by condition: TestRun
  • ManualStart: 1
  • State: 1
  • Results: Cerbo timers still not running. Running by condition changed to TestRun, but the cerbo timers did not start. Must be something to do with enabling the link to external running state.

    Test7
    Conditions:

    • Link to external running state: enabled
    • Running by condition: TestRun
    • ManualStart: 0
    • State: 1

    Results: Manual Start Disabled and timers did not change

    Test8
    Conditions:

    • Link to external running state: disabled
    • Running by condition: TestRun
    • ManualStart: 0
    • State: 1

    Results: Timers started as expected

    The last flow is to stop the generator when the RunningByCondition has been satisfied.