Creating acload-dbus-Service (including vrm-Instance)

Hello community,

I am currently working on a python script interfacing with the dbus to both get values from it and publish a vrm accesible “acload-instance” to it. I have already set up all paths and can query them using the dbus command-line tool. However I cannot see them besides the path “CustomName” as if “victron” rejects them in some form (deduced by the fact that both vrm and dbus-spy dont show them but “dbus-send” does). I also created the entry /Settings/Devices/SERIAL/ClassAndVrmInstance and queried its value to use for my “DeviceInstance” - Path. I can link to my code or show relevant parts if needed but I figured these symptoms are already enough for an experienced user to detect the issue.


Even though this is how it should look like:

When you create a parameter in your python code, you must explicitly specify that it is writable from the outside world. Eg:

	self.DbusService.add_path ('/Shutdown', 0, writeable = True, onchangecallback = self.\_handlechangedvalue)

Not seeing parameters in dbus-spy suggests your python code is importing a velib_python that is out of date/sync with what the rest of the system is running. This can vary by firmware version so my solution was to copy the one from /opt/victronenergy/dbus-systemcalc-py.

Why not just use the virtual node capabilities in nodered?

Because not everyone wants to bloat its OS with Node-Red…
Everything that Node-Red does can also be done in small tidy and light scripts, without the overhead load that Node-Red introduces…

That’s a matter of opinion. Many do not know this functionality exists and are trying to reinvent the wheel, so it helps to mention it.
It also is a maintained interface that is tested, enhanced and persists updates while not making a completely unsupported system.
So there are benefits.

  1. From what I remember, some experts here are saying that anything Node-Red is also unsupported. If something on large image is not working, first thing is to revert to standard image and try in that environment, isn’t it?
  2. Some wheels sometimes are quite square and then it can’t be a reinventing thing… :grin:

Any modification is technically not supported, there is a difference in that node red and the interfaces victron provide are maintained, enhanced and should always work version to version. If they don’t they are fixed for regressions. The same can’t be said for custom code. Each has a benefit, people need to choose what works for them.
Both ultimately have similar drawbacks, one has less risk for keeping up with a moving code-base.

@nickdb
Maybe we are a little bit off topic here in regard with the original question.
Let’s try to help if we can…

@Fabian
I’ve had the same situation as you are having when I’ve tried to create the paths and services by other means.
Meaning using C or Python, but using the OS dbus functions.
Finally, I’ve used the velib_python (found on “ext” folder) and the functions inside vedbus.py and ve_utils.py scripts.
They are taking care about everything, including the visibility onto the dbus-spy and other victron related environments.
Especially pay attention to the “add_mandatory_paths” function.

Thank you guys for the discussion. I was afraid noone messes around with this stuff here. Mismatching velib versions are quite probable, I may have cloned them from github at some point… Makes me wonder, why the library is not centralized in some way but everyone has its own “truth”. I did look at several of these examples, aswell as the mandatory paths, so I doubt I missed something there. I also call the register()-method. Every path I have is added the same way in a for-loop. I am using VeDbusService, so I am not reinventing the tire rubber aswell.

@nickdb There probably is a solution to my problem purely in NodeRED (which I also use(d)). I am interested in software development and wanted to fiddle around with developing things for the cerbo. I also installed the venus-sdk and crosscompiled for the cerbo. There is a good chance I will rewrite my program in C(++) just to learn something.

I will get back to you if I still cant figure it out. Until then.

(bonus question: There are service-scripts under /opt/victronenergy/service (im not sure if this is the exact path) which is a write-protected directory for good reason. Is there a better intended way to auto-start (python-)applications than to remove write-protection there?)

I put all my services on /opt/victronenergy/service from where are copied at boot to /service and run.

Once you ssh with the root password onto OS, you can write on /opt/victronenergy/service…
Don’t know why in your case is R/O…

If you want to implement all these in C, you need to implement and register helpers to all actions: read, write, display, broadcast, etc.
It’s not worth it… Just use the velib_python. You’ll see that the basics are not changed between versions.

Thanks for the warning. It was just an idea. I assumed that there is an equivalent to the ve-lib in the compiled language world.

I’ll give an update if I managed to add a run script to the service.

Anyway, I managed to make it work, although I am hesitant to describe my “disturbing” fix. I literally changed nothing, expect the /ProductId from a string value to a numeric value. However this alone did not fix it. I tested by gradually increasing the amount of paths I added to the dbus-service. I started with let’s say 5 paths, ran the python script, uncommented 5 more and started it again and so on. That way the visible paths on the dbus kept increasing. After adding all paths required by acload (and optional ones) I saw the controls in the vrm appear (switchable output and energy data). I have no reasonable explanation for this and did not do a deep dive in the ve_lib to understand this behavior.

Both the writable=True (this means that a user-interaction through let’s say vrm can write the value, no?) and the ve-lib version did not have any effect.

Thanks for jogging my brain.

For anyone wondering: this is how I added my paths, as basic as it gets:


for path in self._paths.values():
    item = self._dbusservice.add_path(
        path.path,
        path.initial,
        writeable=path.writeable,
        onchangecallback=self._handlechangedvalue,
    )
    logger.info(f"Item {item} added.")