ccremer/fronius-exporter

realtime fronius_site_mppt_voltage & fronius_site_mppt_current_dc with bigger resolution

Opened this issue · 7 comments

As far as I can understand from sources IDC and UDC are accrued from archive data which provide rather low resolution. I have Java code which gets this data from Modbus. It is also accessible directlly from inverter and data resolution is almost the sama as main inverter data (load, grid, pv) but id don't know how to implement this in GO.

I have Fronius Symo 8.2-3-M

My code uses:

		<!-- https://mvnrepository.com/artifact/com.ghgande/j2mod -->
		<dependency>
			<groupId>com.ghgande</groupId>
			<artifactId>j2mod</artifactId>
			<version>2.6.4</version>
		</dependency>

Procedure to acquire data looks as follows:

InetAddress addr = InetAddress.getByName("192.168.1.12"); //Inverter IP 
// Open the connection
con = new TCPMasterConnection(addr);
con.setPort(502);
con.connect();

// inverter
req = new ReadMultipleRegistersRequest(40069, 38);
trans = new ModbusTCPTransaction(con);
req.setUnitID(1);
trans.setRequest(req);
trans.execute();
res = (ReadMultipleRegistersResponse) trans.getResponse();

System.out.println("AC Power value=" + int16(res, 14, 15));
System.out.println("Apparent Power=" + int16(res, 18, 19));
System.out.println("Reactive Power=" + int16(res, 20, 21));
System.out.println("Power Factor=" + int16(res, 22, 23));

// string
req = new ReadMultipleRegistersRequest(40253, 43);
trans = new ModbusTCPTransaction(con);
req.setUnitID(1);
trans.setRequest(req);
trans.execute();
res = (ReadMultipleRegistersResponse) trans.getResponse();

System.out.println("String 1. DC Current=" + uint16(res, 19, 2));
System.out.println("String 1. DC Voltage=" + uint16(res, 20, 3));
System.out.println("String 1. DC Power=" + uint16(res, 21, 4));
System.out.println("String 1. Temperature=" + int16(res, 22, -1));

System.out.println("String 2. DC Current=" + uint16(res, 39, 2));
System.out.println("String 2. DC Voltage=" + uint16(res, 40, 3));
System.out.println("String 2. DC Power=" + uint16(res, 41, 4));
System.out.println("String 2. Temperature=" + int16(res, 42, -1));
// Close the connection
con.close();

And there are two functions thats converts modbus integers to floats:

    public static BigDecimal uint16(ReadMultipleRegistersResponse response, int valueRegisterIdx, int sfRegisterIdx) {
        Register vr = response.getRegister(valueRegisterIdx);
        Register sfr = sfRegisterIdx > -1 ? response.getRegister(sfRegisterIdx) : null;

        BigDecimal v = new BigDecimal(vr.toUnsignedShort()); // unsigned 16-bit value (unsigned short)
        if (sfr != null)
            v = v.movePointRight(sfr.toShort());
        return v;
    }

    public static BigDecimal int16(ReadMultipleRegistersResponse response, int valueRegisterIdx, int sfRegisterIdx) {
        Register vr = response.getRegister(valueRegisterIdx);
        Register sfr = sfRegisterIdx > -1 ? response.getRegister(sfRegisterIdx) : null;

        BigDecimal v = new BigDecimal(vr.toShort()); // unsigned 16-bit value (unsigned short)
        if (sfr != null)
            v = v.movePointRight(sfr.toShort());
        return v;
    }

Mabe somebody will implement this in the exporter to boost current and voltage data resolution.

Hi.
I'm not sure if I understand your question.

Do you need more live data? Or is float64 (double in Java) too small for the values you have? Is this why you're using BigDecimal?

This exporter uses the Symo's JSON API over HTTP to access the values from Symo. Unless you can provide me with a sample JSON request that delivers the values you need, I fear you'll have to continue querying your Symo with your code via Modbus. You could extend your code with the Prometheus Client in Java and then combine the data in Prometheus or Grafana Dashboards.

That is not problem of datatype but count of archive data - time resolution. Voltage and current values changes only by every 1 minute when ie. load value gets new value for every metrics request. Chart in grafana of voltage and current looks like stairs.

obraz

Ah I see.
I see the value of that, but unless I have a JSON sample response, there's nothing I can do.

So, that's the point - add another, parallel Modbus datasource and reads voltage values from Modbus instead of archives. There can be also this as an option defined.
GOlang has a libraries to comunicate with modbus (ie: simonvetter/modbus or goburrow/modbus) so it is possible to do that propably that simple like in my java example.

Hi.
Unfortunately, I'm very reluctant to add Modbus to this project. First, I have zero experience with Modbus. Second, I don't want to spend time implementing something I personally don't have or need. I'm the only maintainer so far. What if people have a problem with Modbus and open issues? I won't be able to help them and fix bugs. Furthermore, I can't even test it since I don't have easy access to a device.

If you can figure out if the same values are accessible over HTTP/JSON, we can discuss it again, but otherwise I won't implement or accept a PR for Modbus...

@gitwasi: Have you tried some generic modbus exporter? E. g. https://github.com/RichiH/modbus_exporter

I'm on the way. I try to figure it how to configure this.