question

madsci1016 avatar image
madsci1016 asked

Help creating custom Venus driver for SMA SunnyIsland

So I'm working on writing a driver so we can monitor and maybe control SMA SunnyIsland with a Venus device.

Some progress:

https://www.youtube.com/watch?v=-OixqIdJ8g0

https://www.youtube.com/watch?v=9xg28qlUrCc


Beside being "just ok" at python and running into some issues cleaning up my code, I've noticed I can't get consumption to plot on VRM. It will report the correct consumption under system status, but nothing on the actual graph.

I believe I've spoofed a new enough Multi device with the below properties:

/DeviceInstance 261

/ProductId 2754

/FirmwareVersion 476

/HardwareVersion 476


Does anyone know the rules for what VRM will consider valid enough to plot?

Also anyone really good at python willing to help me clean up the code to make work 'the right way'?


Thanks.


Venus OSdriver
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

5 Answers
laurenceh avatar image
laurenceh answered ·

When it come to Python, I generally consider that if you understand what you have written then it is working the “right way”. It’s more important that you can fix it or make changes than take on a load of obscure Cleverly written code that you don’t fully understand.

Having said that, here is a link to the python new service code I wrote for my own sensors. I hope it is clear enough for people to make the their own services.

https://community.victronenergy.com/questions/56566/multiple-dbus-service-instances-in-a-single-driver.html


What is probably more important is building the service directory and scripts so that the service starts and stops properly and creates it’s own logging information under /var/log So that when things go wrong you can work out why. I found that major updates to Victron code (such as from 2.5 to 2.6 ) will introduce things that break previous codes and logging is useful to track down why.

Since writing that code I have also learnt how to handle the creation, saving and loading of local settings by including calls to the localsettings service (if you need to do that at all).

I can’t say exactly what is needed for the VRM to be happy, but making sure you re-create everything On the dbus you can see for the “official device” Usind dbus -yams the dbus spy is a good start. I’m happy to look at your code if you want to post it or say where it can be found.

1 comment
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

madsci1016 avatar image madsci1016 commented ·

Oops, replied above.

0 Likes 0 ·
madsci1016 avatar image
madsci1016 answered ·

I've posted the code on the venus-os developers group. Thanks for any help you can give.

https://groups.google.com/g/victron-dev-venus/c/wpbV8K08DWk

I don't have a working Multi to mimic. Do you mind posting screenshots the vebus dbus values for yours so I can mimic it?

I agree the next challenge is proper "installation" of the driver with startup and logging. Right now I just use the script to kill my tty device with serial-starter and then manually run my script.

Right now I believe the priority is to handle CANbus receives better (with a callback) and then figure out how to make the same script both register a vebus service AND read from the system dbus service at the same time (so I can grab SoC and send it to the SunnyIslands). Right now I'm stuck on that.

2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

madsci1016 avatar image
madsci1016 answered ·

Ok well I found kwhdeltas.py that vrmlogger.py calls to generate energy reports, and it seems kwhdeltas.py is looking for /Energy/* values in the vebus service.


Perhaps I need that.....

1 comment
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

madsci1016 avatar image madsci1016 commented ·

Yep that was it. Now it's plotting!

0 Likes 0 ·
madsci1016 avatar image
madsci1016 answered ·

Rewrote it this weekend and got it to both TX the SoC and receive and post all the telemetry. Still lots of work to clean up.

Code: https://github.com/madsci1016/SMAVenusDriver @LaurenceH

2 comments
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

laurenceh avatar image laurenceh commented ·

@madsci1016

Hey if it works use it. There are only a few things I would tidy up, mainly because I am used to writing for real time programming and try not to cause too much code to be required, loaded or executed if it can be helped. But all of these are stylistic, I would say you have the hang of python and go with what you know. Also you have taught me a thing or two about defining and re-using classes properly.

Having said that

The loading of all of dbusmonitor seems a bit heavyweight unless you are going to use more of it's facilities later, i'm not sure what it is doing for you.

You could use something like:

service = 'com.victronenergy.system'
path = '/'
systemObject = VeDbusItemImport(dbusConn, service, path)
Then when you need it :
values = systemObject._refreshcachedvalue()
values = systemObject.get_value()
soc = values['/Dc/Battery/Soc']

NB if you are only going to use parts of the data from the system service you can set the path to only load part of the data. So.....

path = '/Dc/Battery'
systemObject = VeDbusItemImport(dbusConn, service, path)

Then when you need it
values = systemObject._refreshcachedvalue()
values = systemObject.get_value
soc = values['/Soc']

If you are going to have objects open on multiple services stick them in a data structure.

Then I would look at ways of only updating the bits that have changed in _updatedbus and flattening the if, elif structure of _parse_can_data

So as functions are objects and can be stored in data structures _parse_can_data could rely on a data structure of a dictionary of the can arbitration ids with lambda functions to call for each one.

So if 'canFunctions' is the data structure of ids and functions

then _parse_can_data becomes something like

if msg is not None:
     dummy = canFunctions['msg.arbitration_id'](msg.data)

Each function is customised to do the necessary data transform and write to the dbus so the first one might look like.

lamda(data):
    self._dbusservice["/Ac/ActiveIn/L1/P"] = (getSignedNumber(data[0] + data[1]*256, 16)*100)
    self._dbusservice["/Ac/ActiveIn/L2/P"] = (getSignedNumber(data[2] + data[3]*256, 16)*100)

I have not tested that code but it give an idea of how much the code could be shortened (both in number of lines and how much gets executed each time.)

ditto _handlecantx

You have 6 separate message which are re-defined (mostly unchanged) every 2 seconds.

Then execute the same code repeated inline 6 times.

So you could put the messages into a data structure (defined only once at start up). Update the SOC value in the data structure when it changes, and then loop through the structure sending each message in turn with the same three lines of code, which are not duplicated inline in your programme. In fact is it necessary to send all 6 or could you just send the changed SOC ?

0 Likes 0 ·
madsci1016 avatar image madsci1016 laurenceh commented ·

Not me, this was actually a re-write using Victron's systemcalc.py as a framework. Hence the heavyweight monitor. Future plans do include having some user settings changeable from the Venus interface trickle down into the CAN messages sent to the SMA. (Like requested charge current, voltage target, etc). So might justify using monitor as more things start getting read.

I also stated with ImportItem and had lots of trouble, though likely from my misunderstanding of classes and the gobject mainloop stuff.


Thanks for tips on data structure, once I get this stood up as a self starting driver (next task) that will be good places to start for cleanup. Can you tell I come from the C world? Lol.

0 Likes 0 ·
shingsam avatar image
shingsam answered ·

Hi @madsci1016 i try your code but im not lucky :( this code not work with v3.00

Can you update your code.

Thanks,

2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

Related Resources

Victron Venus OS Open Source intro page

Venus OS GitHub (please do not post to this)

Additional resources still need to be added for this topic