API integration for Solplanet inverter (AISWEI)

I played around with the old Aiswei app android AISWEI app and captured additional endpoints that are in plain http and without credentials. all accessible via http://>you_invert_ip>:8484/…

  • getdev.cgi?device=3
    Exposes settings related to export power and power factor limits in JSON format. e.g.
"{
  ""mod"": 0,
  ""enb"": 0,
  ""exp_m"": 0,
  ""regulate"": 5,
  ""enb_PF"": 5,
  ""target_PF"": 0,
  ""abs"": 0,
  ""abs_offset"": 0,
  ""total_pac"": 203,
  ""total_fac"": 8000,
  ""meter_pac"": 0
}"
  • setting.cgi
    POST JSON to adjust PF and Export power limits e.g.:
{"device":3,"action":"setmeter","value":{"target":1000,"regulate":10,"enb_PF":5,"target_PF":0,"abs":0,"offset":2}}
  • fdbg.cgi
    Exposes lots of settings in MODBUS formatted coding. See modbus manual further up to get and idea.
    POST requests. e.g. to query the Active Power settings:
{"data":"030300c800010416"}

response

{"dat":"ok","data":"03030200010044"}

which basically means Active Power = on.

Don’t mess around blindly with the fdbg.cgi as you can hurt your installation and potentially fry your inverter.

Lot of stuff to investigate here!

1 Like

I managed to get a modbus connection running via the wi-fi dongle now.
Here’s how to reproduce it:

Add modbus connection in configuration.yaml:

modbus: !include modbus.yaml

Create modbus.yaml in the config dir and enter this (just one POC command for now to retrieve active power)

- name: modbus_solplanet
  type: rtuovertcp
  host: 127.0.0.1
  port: 502
  sensors:
    - name: Active Power
      unit_of_measurement: W
      slave: 3
      address: 1370
      input_type: input
      data_type: int32
      min_value: 0

Built a Node Red flow like below. It opens a tcp port 502 on the HA system and convert to and from hex string and JSON, basically behaving like a proxy translater service (just replace with your inverter IP in the http request:

[
    {
        "id": "094fa30b52f0902e",
        "type": "tab",
        "label": "Solplanet modbus via FDBG.CGI",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "8e966d69e2e7fffa",
        "type": "http request",
        "z": "094fa30b52f0902e",
        "name": "",
        "method": "POST",
        "ret": "obj",
        "paytoqs": "query",
        "url": "http://192.168.1.127:8484/fdbg.cgi",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [
            {
                "keyType": "Content-Type",
                "keyValue": "",
                "valueType": "application/json",
                "valueValue": ""
            }
        ],
        "x": 170,
        "y": 240,
        "wires": [
            [
                "fba4c181689f43f5"
            ]
        ],
        "info": "Call FDBG.CGI"
    },
    {
        "id": "f7175970bcfa5bc0",
        "type": "tcp in",
        "z": "094fa30b52f0902e",
        "name": "",
        "server": "server",
        "host": "",
        "port": "502",
        "datamode": "stream",
        "datatype": "buffer",
        "newline": "",
        "topic": "",
        "trim": false,
        "base64": false,
        "tls": "",
        "x": 130,
        "y": 100,
        "wires": [
            [
                "3af19067e5e83ce9",
                "fcb1504cb7d64448"
            ]
        ]
    },
    {
        "id": "082c048a0f2b256f",
        "type": "tcp out",
        "z": "094fa30b52f0902e",
        "name": "",
        "host": "",
        "port": "",
        "beserver": "reply",
        "base64": false,
        "end": false,
        "tls": "",
        "x": 150,
        "y": 360,
        "wires": []
    },
    {
        "id": "3af19067e5e83ce9",
        "type": "debug",
        "z": "094fa30b52f0902e",
        "name": "modbus input",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "true",
        "targetType": "full",
        "statusVal": "payload",
        "statusType": "auto",
        "x": 340,
        "y": 100,
        "wires": []
    },
    {
        "id": "fcb1504cb7d64448",
        "type": "function",
        "z": "094fa30b52f0902e",
        "name": "form JSON",
        "func": "var Hexstring = msg.payload.toString('hex');\nmsg.payload = {\n            \"data\": Hexstring\n}\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 150,
        "y": 180,
        "wires": [
            [
                "8e966d69e2e7fffa"
            ]
        ]
    },
    {
        "id": "fba4c181689f43f5",
        "type": "function",
        "z": "094fa30b52f0902e",
        "name": "form buffer",
        "func": "var Response = msg.payload;\nmsg.payload = Buffer.from(msg.payload.data, \"hex\");\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 170,
        "y": 300,
        "wires": [
            [
                "a6a8edf93eff2972",
                "082c048a0f2b256f"
            ]
        ]
    },
    {
        "id": "a6a8edf93eff2972",
        "type": "debug",
        "z": "094fa30b52f0902e",
        "name": "Inverter response",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 370,
        "y": 300,
        "wires": []
    }
]

If all goes well, you now have an active power sensor.
From here it’s just a matter of adding more functions to the modbus.yaml file.
All the functions in the document shared by derkorte can be implemented wihtout any additional hardware.

1 Like

Hi Johan , I have a Solplanet ASW 6000 H - S2 hybrid and I´m trying to read/write the inverter over the API to configure the inverter (export 0 when price -) and read information like export energy the electrical network , house energy consumption, etc…

My inverter has 4 ports, but the COM port RS485 in my inverter is used for comunicate with the meter (master/inverter — slave/meterSDM230) . I need to connect to inverter(slave) with a master (to ask it with API). ¿Have yout advance about it?

I´m using the information from the last post from keld1 user to read/write the API:

Thank you very much about your work. I think that I have the value of export/import to/from grid.

// 20240802091729
// http://192.168.1.21:8484/**getdev.cgi?device=3**

{
  "mod": 2,
  "enb": 1,
  "exp_m": 0,
  "regulate": 5,
  "enb_PF": 5,
  "target_PF": 0,
  "total_pac": 1393,
  "total_fac": 6000,
  "meter_pac": 333, //**here is the VALUE**
  "sn": "EASTRONB3240XXXXXXXX",
  "manufactory": "EASTRON",
  "type": "1",
  "name": "SDM230",
  "model": 2,
  "abs": 0,
  "offset": 2
} 

It give me this value about the EASTRON SDM230 meter.
“+ VALUE” is energy kWh import from grid.
“- VALUE” is energy kWh export to the grid.

Do you know where (address) to extract this informaticon with a sensor modbus.yaml and Node Red? This is my next challenge :wink:

Working!

1 Like

Hi! I just got a solplanet t3 hybrid inverter. I used codes what are provided here, thanks for that. Problem is that I had Nordpool sensors already defined in configurration.yaml, so I have tried several ways to use multiple sensor so I stored solar.yaml and norpool.yaml in own sensors directory and importted them by:
(configuration.yaml)
sensor: !include_dir_merge_named sensors/
template: !include_dir_merge_named template/
in sensors directory I have :
Nordpool.yaml >>

platform: nordpool     # Country/region to get the energy prices for. 
region: "FI"

# Override HA local currency used to fetch the prices from the API.
currency: "EUR"

# Add Value Added Taxes (VAT)?
VAT: True

# Energy price rounding precision.
precision: 3

# Percentage of average price to set the low price attribute
# low_price = hour_price < average * low_price_cutoff
low_price_cutoff: 0.95

# Display price in cents in stead of (for example) Euros.
price_in_cents: true

# Price displayed for MWh, kWh or Wh
price_type: kWh

# Template to specify additional cost to be added to the tariff.
# The template price is in EUR, DKK, NOK or SEK (not in cents).
# For example: "{{ current_price * 0.19 + 0.023 | float}}" 
additional_costs: "{{0.0|float}}"

and

solar.yaml

  • platform: rest
    resource: http://myip:8484/getdevdata.cgi?device=2&sn=dongleserial
    scan_interval: “00:00:10”
    name: solplanet
    value_template: “OK”
    json_attributes:
    • flg # ???
    • tim # date/time
    • tmp # inverter temperature / 10
    • fac # frequency / 100
    • pac # actual power watt
    • sac # apparent power
    • qac # reactive power
    • eto # total produced / 10
    • etd # total producted daily / 10
    • hto # running time
    • pf # ???
    • wan # ???
    • err # ???
    • vac # voltage / 10
    • iac # current / 10
    • vpv # string voltage
    • ipv # string current
    • str
      dongle returns:
      {
      “flg”: 1,
      “tim”: “20240821092224”,
      “tmp”: 380,
      “fac”: 5002,
      “pac”: 3316,
      “sac”: 3316,
      “qac”: 1,
      “eto”: 425,
      “etd”: 47,
      “hto”: 36,
      “pf”: 100,
      “err”: 0,
      “vac”: [2349, 2326, 2356],
      “iac”: [48, 49, 49],
      “vpv”: [4898, 0, 3000],
      “ipv”: [686, 0, 64],
      “str”: ,
      “stu”: 1,
      “pac1”: 1126,
      “qac1”: 0,
      “pac2”: 1124,
      “qac2”: 0,
      “pac3”: 1139,
      “qac3”: 0
      }

template.yaml >>

sensor:

  • name: “solplanet_current_production”
    unique_id: solplanet_current_production
    state: “{{ state_attr(‘solplanet’, ‘pac’) | float }}”
    unit_of_measurement: “W”
    device_class: energy
    state_class: measurement
  • name: “solplanet_daily_production”
    unique_id: solplanet_daily_production
    state: “{{ state_attr(‘solplanet’, ‘etd’) | float / 10 }}”
    unit_of_measurement: “kWh”
    device_class: energy
    state_class: total_increasing
  • name: “solplanet_total_production”
    unique_id: solplanet_total_production
    state: “{{ state_attr(‘solplanet’, ‘eto’) | float / 10 }}”
    unit_of_measurement: “kWh”
    device_class: energy
    state_class: total_increasing
  • name: “solplanet_temperature”
    unique_id: solplanet_temperature
    state: “{{ state_attr(‘solplanet’, ‘tmp’) | float / 10 }}”
    unit_of_measurement: “°C”
    device_class: temperature
    state_class: measurement

no errors and restart ok and Norpool works fine, but solplanet sensors are still not available.

any ideas?

Hi, I found a solution for this by testing hard. Thanks for the examples…

Are you getting json with data when you put this into your browser?
http://192.168.1.15:8484/getdevdata.cgi?device=2&sn=SP00066032310236

If you do, try using this format:

rest:
  - authentication: basic
    resource: http://192.168.1.15:8484/getdevdata.cgi?device=2&sn=SP00066032310236
    scan_interval: "00:00:10"
    timeout: 20 # sec
    sensor:
      - name: solplanet
        value_template: "OK"
        json_attributes:
          - "flg"
          - "tim"
          - "tmp"
          - "fac"
          - "pac"
          - "sac"
          - "qac"
          - "eto"
          - "etd"
          - "hto"
          - "pf"
          - "wan"
          - "err"
          - "vac"
          - "iac"
          - "vpv"
          - "ipv"
          - "str"

for sensors:

template:
  - sensor:
      - name: "Solplanet Current Production"
        unique_id: solplanet_current_production
        state: "{{ state_attr('sensor.solplanet', 'pac') }}"
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
      [- etc...]

Keep in mind, that your main sensor’s entity_id is sensor.solplanet

As for attribute flg, the values are as follows:

Device State:
0 = Wait
1 = Normal
2 = Fault
4 = Checking

Hi, two weeks ago I started working at integration for solplanet inverters. You can check it here: GitHub - zbigniewmotyka/home-assistant-solplanet: An Home Assistant integration for Solplanet inverters

To add new device you only need to provide inverter ip address.

Right now it provides monitoring of energy production and I’m working on battery monitoring.

4 Likes

This is nice!

I’ve found out that the device actually provides new values every 10 seconds. Do you think you can drop the refresh timer?

I’m using those near-realtime values to calculate my current electricity usage, combined with energy injection/extraction readings from the power grid.

Sure, I will make this time configurable via UI, so everyone will be able to adjust it to own needs.

I’ve made changes in integration which allows to specify interval for reading data from inverter. By default its 60s. If you want to change this value for already added device you have to remove it and add it again.

Awesome @zmszaman !!

Would it be also possible to not just read some of the data, but also set some specific data?
I would like to manually set the SOC min and max level manually with such a plugin. Would that be possible?

Thanks

@Chavell3 Yes, it is possible. Few minutes ago I’ve released v0.4.0-beta1 version which contains select field to choose battery work mode.
It is also possible to prepare configuration fields for min and max level, as this data is sent to inverter when battery work mode is changed.

awesome. That sounds really great! I’ll check that out