Deye Sun600G3 microinverter status query via curl

Hi experts,

I recently set up a Deye Sun600G3 solar microinverter and would like to read its data into openHAB.
On the command line it is very easy: (tested with ver 1.53, might be different with earlier/later)

curl -u user:password inverterhostname_ or_ ip/status.html | grep "$dat = "

prints the data that is visible on the status page in the web UI, among which is the current power generated in W, also the daily and permanent totalizer in kWh. Plus some info about serial#, versions, local access point and connected Wifi.

I’m not a programmer and got lost in the documentation on bindings quickly. Maybe someone is interested in making a binding/thing from this, or is there possibly a simple template somewhere to modify?

Thanks,
Georg

The Exec Binding and the HTTP Binding come to mind.

Post the data and we’ll see. :slight_smile:

Thanks for the very quick response. Here is the reply of the inverter to the curl request. Some bits changed for privacy purpose. Comments marked “–”.

% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:–:-- --:–:-- --:–:-- 0var webdata_sn = "2211252261 ";
var webdata_msvn = " ";
var webdata_ssvn = " ";
var webdata_pv_type = “”;
var webdata_rate_p = “”;
var webdata_now_p = “84”; --Current solar power
var webdata_today_e = “4.0”; --Today total - seems to be not working properly, inverter does not reset the totalizer after dark
var webdata_total_e = “4.1”; --Permanent total
var webdata_alarm = “”;
var webdata_utime = “1”;
var cover_mid = “–Serial#OfTheInternalController,InverterSerialIsDifferent”;
var cover_ver = “MW3_16U_5406_1.53”;
var cover_wmode = “APSTA”;
var cover_ap_ssid = “–InternalAccessPointSSID”;
var cover_ap_ip = “10.10.100.254”;
var cover_ap_mac = “–InternalAccessPointMAC”;
var cover_sta_ssid = “–ConnectedNetworkSSID”;
var cover_sta_rssi = “49%”;
var cover_sta_ip = “192.168.178.123”;
var cover_sta_mac = “–InternalWlanClientMAC”;
var status_a = “0”;
var status_b = “0”;
var status_c = “0”;
100 11878 100 11878 0 0 212k 0 --:–:-- --:–:-- --:–:-- 214k

Cheers,
Georg

Exec Binding:

  1. Install Exec Binding.
  2. Install RegEx Transformation Service (not sure whether it is a requirement though).
  3. Add new Exec Thing.
  4. Add your command to the Exec Thing:
  5. You MUST whitelist your command, see Exec - Bindings | openHAB.
  6. Use REGEX(.*var webdata_now_p = "(.*)";.*) as value for ‘Transformation’ to extract the current solar power (use https://regex101.com to test your regexes).
  7. Set Interval and Timeout and enable Autorun.
  8. Link an item to the channel output of your Exec Thing (note that the channel type is String).
2 Likes

Hi again,

thanks very much for your help!
I got it working, with your regex slightly modified to get the info as string from the inverter answer and a second regex to transform into a number:

  1. Need a “non-greedy” regex in the Transformation field, otherwise OH (or Java?) gets confused by the double quote within the inverter answer. Difference is the question mark.
    Transformation: REGEX(.*var webdata_now_p = "(.*?)\".*)

  2. Second regex in Channel/Profile setting to convert string to number:
    Profile Configuration: (?<=\()\d(?=\))

Edit:
The string-to-number regex is not required, inverter is sending power as integer only, and when there is an issue or no DC power it does not reply to the curl request.
OpenHAB seems to do the cast/conversion from string to number automatically, trends etc. are working fine.

Cheers,
Georg

1 Like

I also use the Exec Binding but I don’t edit the return value via REGEX in the binding.

I use the following rule and just read the values I am interested in from the string and write them to the corresponding itemes.

configuration: {}
triggers:
  - id: "2"
    configuration:
      itemName: PV_Befehl_Ruckgabewert
    type: core.ItemStateChangeTrigger
  - id: "3"
    configuration:
      time: 23:00
    type: timer.TimeOfDayTrigger
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/javascript;version=ECMAScript-2021
      script: >
        /*
          curl -u admin:openHAB 192.168.53.22/status.html | grep "$dat = "

          var webdata_ssvn = "";
          var webdata_pv_type = "";
          var webdata_rate_p = "";
          var webdata_now_p = "41";
          var webdata_today_e = "0.60";
          var webdata_total_e = "0.7";
          var webdata_alarm = "F13";
          var webdata_utime = "0";
          var cover_mid = "39189";
          var cover_ver = "MW3_16U_5406_1.53";
          var cover_wmode = "APSTA";
          var cover_ap_ssid = "AP_391893";
          var cover_ap_ip = "10.xx.xx.254";
          var cover_ap_mac = "EC:FD:F8:94";
          var cover_sta_ssid = "";
          var cover_sta_rssi = "80%";
          var cover_sta_ip = "192.168.53.22";
          var cover_sta_mac = "E8:FD:F8:94";
          var status_a = "1";
          var status_b = "0";
          var status_c = "0";
        */

        var zonedDateTimeCheck = Java.type('java.time.ZonedDateTime');

        // Set EnergyToday at 23:00 to 0 is triggered via cron job
        zonedDateTimeCheck = zonedDateTimeCheck.now().getHour();
        if (parseInt(zonedDateTimeCheck) > 22) {
          items.getItem('PvNumberEnergyToday').postUpdate('0');
        }

        var returnString  = items.getItem('PV_Befehl_Ruckgabewert').state;
        var sunElPosition = items.getItem('LokaleSonnendaten_Position_Elevation').state; 

        var returnStringSplit = returnString.toString().split("var webdata_now_p = \"");

        if(returnStringSplit[1] === undefined) {
          // If the string is empty and i am after sundown then set PvNumberPower to '0'.
          // console.log("String is empty at " + sunElPosition);
          if (parseFloat(sunElPosition) < 2.0) {
              items.getItem('PvNumberPower').postUpdate('0');
          }
        } else {
          var returnStringSplitSplit = returnStringSplit[1].split("\";");
          if ((returnStringSplitSplit[0] == '') || (returnStringSplitSplit[0] === undefined)) {
            //console.log("is empty(1b)");
          } else {
            var webdata_now_p = returnStringSplitSplit[0];
            //console.log("is empty(1c)" + webdata_now_p);
            items.getItem('PvNumberPower').postUpdate(webdata_now_p);
          }

          //----------
          returnStringSplit = returnString.toString().split("var webdata_today_e = \"");
          returnStringSplitSplit = returnStringSplit[1].split("\";");
          if ((returnStringSplitSplit[0] == '') || (returnStringSplitSplit[0] === undefined)) {
            //console.log("is empty(2b)");
          } else {
            var webdata_today_e = returnStringSplitSplit[0];
            //console.log("is empty(2c)" + webdata_today_e);
            items.getItem('PvNumberEnergyToday').postUpdate(webdata_today_e);
          }

          //----------
          returnStringSplit = returnString.toString().split("var webdata_total_e = \"");
          var returnStringNumberEnergy = returnStringSplit[1].split("\";");
          var webdata_total_e = Number.parseFloat(returnStringNumberEnergy[0]);
          // Total energy must be gerater the 0
          if (webdata_total_e > 0) {
            items.getItem('PvNumberEnergy').postUpdate(webdata_total_e);  
          }
        }
    type: script.ScriptAction

Hi HolBaum5,

I tried your method. But when I use your Rule I get the Error: “Failed: TypeError: items.getItem is not a function.” Can you tell me why?

Thanks in advance
Joko

@Joko did you install the JS binding?
grafik

Did you add the line from the exec binding ‘Befehl’ to the file
‘exec.whitelist’ file.

I have adjusted the script a bit so that I have a new Energy Today value every day.