manio/skymax-demo

Simultaneosly reading and writing data

dilyanpalauzov opened this issue · 4 comments

What happens, if inverter_poller reads data, and at the same time another inverter_poller is started, which sends commands? Does this work?

I call inverter_poller -1 every five seconds. From time to time I want to send a command to the inverter. Will this cause a mess, when both processes access /dev/hidrawX at the same time, do the processes wait for each other, by means of some locks?

Would this avoid any simultaneous read-write problems?

diff --git a/inverter.cpp b/inverter.cpp
index e8063eb..5a95b6b 100644
--- a/inverter.cpp
+++ b/inverter.cpp
@@ -75,6 +75,10 @@ bool cInverter::query(const char *cmd, int replysize) {
         return false;
     }
 
+    struct flock lock;
+    memset (&lock, 0, sizeof(struct flock));
+    lock.l_type = F_WRLCK;
+    fcntl (fd, F_SETLKW, &lock);
 
     // Once connected, set the baud rate and other serial config (Don't rely on this being correct on the system by default...)
     speed_t baud = B2400;
manio commented

I assume you are talking about different processes which are started from the operating system. I think that it will not be a mess because probably when one process is accessing the device then the other one will probably can't open the device (it will be busy). But I am not sure about this - it depends on the file open call, probably a exclusive open can also be used here.

I am not sure if your code would help here - probably not because this lock will only work "inside" this single process, not a multiple called by the OS.
For you to be safe then some global lock on the /dev/hidraw should be used (I mean open it exclusively so no other process can open the device if the other is accessing it, tbh maybe it is working like this currently, isn't it?), or some general operating system-wide lock can be used for this.

But all this is out of scope of this simple demo project.

Personally I moved to rust for accessing the inverter for my purposes (I'm using hard), and rust multi threading is way safer and better.

This project was only as the example how to access the inverter and use it's protocol. Much better approach for your use-case would be running a kind of daemon which opens the inverter and doing all stuff in a loop:

  • accessing the inverter in idle time
  • inject your specific commands when you want to

My experience is, that all processes can open the /dev/hidrawX device. Or rather, the biggest problem ever was that new process invocations received sometimes data from old invocations. I assume this was because there was a timeout in cInverter::query() and the process quit, before consuming its all data. Or because the second thread requested some data, while the first threaq exit(0)ed the process. In anycase it works now for me, when I increase the timeout to 15s and apply #15.

flock () and fcntl (fd, F_SETLKW, &lock); are supposed to lock across processes, but somehow they have not for /dev/hidraw0. Maybe at the time I tried to solve it, it was a combination of different problems which lead me to this conclusion. At the end I use flock() on the configuration file instead of fcntl(F_SETLKW) on the device file and it works.

I do not know Rust. I like inverter_poller and C++, but since I run it on constrained device, I might rewrite it in C, saving 1.5MB from libstdc++.so.6.0.28. For such small executable, C shall be fine.

Do I understand correctly, that you do not have this Inverter model (Axpert, Effekta, No name) anymore, that is why you lost interest on developing inverter_poller further?

Do you know who wrote https://github.com/ned-kelly/docker-voltronic-homeassistant/blob/master/manual/HS_MS_MSX_RS232_Protocol_20140822_after_current_upgrade.pdf , or where is this file from?

manio commented

Thank you for your contributions!

Do I understand correctly, that you do not have this Inverter model (Axpert, Effekta, No name) anymore, that is why you lost interest on developing inverter_poller further?

My project initially was only rather a proof-of-concept / sample / demo how I am making a working communication with the inverter using a C code. I can't stand the official java-based application for this inverter and I also didn't find any open-source C/C++ code for this communication at that time, that is why I created this project on github.
Later it was enhanced by community to be able to use eg in home-assistant. I am of course still maintaining it but I am not using this project daily anymore since I developed hard and I implemented only relevant communication for me (monitoring current parameters and mode and writing statistics to influxdb + sending SMS notifications when there is power outage). So I just switched to rust (which I like very much) for communication with my inverter and integrated my Axpert part in my whole home automation daemon.

Do you know who wrote https://github.com/ned-kelly/docker-voltronic-homeassistant/blob/master/manual/HS_MS_MSX_RS232_Protocol_20140822_after_current_upgrade.pdf , or where is this file from?

When I was starting this project I fetched it from some forums, you can read exactly in my blog:
https://skyboo.net/2017/03/monitoring-voltronic-power-axpert-mex-inverter-under-linux/
The protocol was probably obtained from manufacturer and/or enhanced by someone from the forums. I don't know the future of this document/or the enhancements.
The one thing I don't like about the protocol is a "wild west" - it can differ slightly on the manufacturer and even a firmware versions - and this is harder to maintain in such project.