Programmatically read data from your Solar Inverter (Voltronic, Axpert, Mppsolar PIP, Voltacon, Effekta etc) and interface with Home Assistant via MQTT - Works with RS232 & USB!

I use a simple python script that polls the inverter, extract data and send them to an mqtt broker.

See my repo: https://github.com/andrea1388/solarinverter2mqtt.git

Hello. I have a solar inverter of the brand Effekta ax-p1. It has a usb 2.0 type b communication port: here is a picture:

How do I integrate it into esphome (and Home assitant) and what do I need for it. Thanks for every reply. (inverter works with WachPower app.)

For those who need it Inverter- Mecer Axpert 5.6K MKS IV 5600VA / 5600W 48V Pure Sine Wave MPPT Inverter charger:
via USB
Qpiri=103
Qpiws=40
qmod =5
qpigs=110

Got this up and running after 3 weeks of tinkering and playing around with it. Installing docker was the most annoying thing. HA amazing and must say working well. Just a few things if anyone can help. Looked through the thread and not sure where to go from here. My battery re discharge voltage is fooked. See below: If anyone can give some guidance on where to begin debugging this it would be great.

Does anyone have Welion hybrid inverter Eco series (4200w & 6200w)? I just got one and would like to get it into HA.
Welion hybrid inverter

It appears also to be the same as Anern hybrid inverter Evo series (4200w & 6200w). If you have integrated this also kindly post your config.

Both inverters have RJ45 rs232 and I am hoping a USB to RJ45 console cable will work. If you have a better way kindly let me know also.
image

Hi, I’m setting up this docker images for me. And I can get data from inverter and push it to mqtt by executing docker exec -it voltronic-mqtt bash -c '/opt/inverter-mqtt/mqtt-push.sh'

But I can’t make it to work automatically every 30 sec according to update interval. What I can be doing wrong?
Both docker images are running


Thanks

Back after a few years as I’ve changed environments and just wanted to share what I had to do to get this working again.

Moved off Rpi4 onto a more powerful x86 ProxMox environment and also moved away from USB>RS233 adaptor to straight Micro USB as my MPP7248 supports that.

Now on Debian 12 VM, latest docker/portainer but had to change inverter.conf to;

device=/dev/hidraw0

qpiri=104
qpiws=40
qmod=5
qpigs=110

For other people having issues, run the poller in debug mode with docker exec -it voltronic-mqtt bash -c '/opt/inverter-cli/bin/inverter_poller -d -1 and watch what the output is, if you’re getting reply too short or incorrect stop/start bits then keep reducing the buffer size of the query and run it again, you do not have to restart the container, the buffer changes are instant.

My original config for qpiri, for example, was 108 bytes, and I kept being told reply too short until I worked back by 1 - on USB it’s only 98. This is the same inverter so just test yours. If you are getting zero bytes the port is in use elsewhere or not communicating at all.

If you are using USB>RS232 then I would suggest using screen or minicom to open the port specirfically at 2400 or 9600 baud and sending a QPIGS and seeing if there’s any response. On my old Debian 11 box, the port speed/options were being reset and I had to run a script at boot time to set them each time.

That said, it’s much faster on USB, though stability remains to be seen, only been up a day. I didn’t realise the BMS USB port on the inverter control module could be used this way, I thought it was just for receiving data from a BMS (I use Bluetooth straight into HassOS for the BMS). I also need to test today if I can still push commands (I often change the max AC charging input for example).

The point of all this was;

  • Get the voltronic container/portainer away from HA so HA is fully supported, full HassOS deployment, and will update more easily.
  • Hopefully improve stability of HA as I’ve had issues with that on the Rpi4, HA drops, then Debian would refuse SSH until it was rebooted.
  • Allow me to run some other cool VMs (pi hole, plex etc).

Useful commands;

To confirm your USB/RS232 adaptor has been seen by the host.
dmesg | grep ttyUSB

To poll in debug mode.
docker exec -it voltronic-mqtt bash -c ‘/opt/inverter-cli/bin/inverter_poller -d -1’

To check USB/RS232 port settings
stty < /dev/ttyUSB0

To change port speed of USB/RS232
stty -F /dev/ttyUSB0 9600

To watch the port output, set the port speed, and attempt to send commands
screen /dev/ttyUSB -b 9600

To see what else might be using your USB/RS232 port so you can kill those processes
lsof /dev/ttyUSB0

Hope this helps someone.

​​

​​

Further to the above, I no longer appear to be able to send commands to the inverters, I have some buttons setup that publish to the parent topic that used to work fine so I know the commands are good it’s clearly an MQTT issue, but I’m unsure how to troubleshoot it, assistant appreciated.

Have just got an eco worthy 800w hybrid inverter 800W 12V Solar Panel Inverter All in One Hybrid with 50A PWM Controller Off-Grid | eBay which I believe is a clone of these. Have connected the included rj54- serial cable to one of these StarTech.com 17in (43cm) 1-Port USB to RS232 DB9 Serial Adapter Cable, USB to Serial Adapter Cable - M/M : Amazon.co.uk: Computers & Accessories have created the docker container and have the data being published into my emqx mqtt broker. However this data appears empty I have tried running sudo docker exec -it voltronic-mqtt bash -c ‘/opt/inverter-cli/bin/inverter_poller -d -1’ but it is coming back as QMOD/QPIGS/QPIRI/QPIWS reply too short (0 bytes) have tried stty -F /dev/ttyUSB0 9600 & 2400 raw with no change any further advise?
Many Thanks

So after playing now have this, now I feel that means im getting closer but no idea really :rofl: any ideas? Have connected it to a device running watchpower and am able to get live data so know inverter and cable are working
qpiri=97
qpiws=20
qmod=4
qpigs=110

marc@debian-server:~/docker/inverter$ sudo docker exec -it voltronic-mqtt bash -c ‘/opt/inverter-cli/bin/inverter_poller -d -1’
Sat Sep 28 21:02:14 2024 INVERTER: Debug set
Sat Sep 28 21:02:14 2024 INVERTER: Current CRC: 49 C1
Sat Sep 28 21:02:15 2024 INVERTER: QMOD reply size (4 bytes)
configuration options for the actual inverter polling process…es. Buffer: (B��I�

The device to read from…

Use: /dev/ttyS0 if you have a serial device,

/dev/ttyUSB0 if a USB<>Serial,

/dev/hidraw0 if you’re connecting via the USB port on the inverter.

device=/dev/ttyUSB0

How many times per hour is the program going to run…

This is used to calculate the PV & Load Watt Hours between runs…

If unsure, leave as default - it will run every minute…

(120 = every 30 seconds)…

run_interval=120

This allows you to modify the amperage in case the inverter is giving an incorrect

reading compared to measurement tools. Normally this will remain ‘1’

amperage_factor=1.0

This allows you to modify the wattage in case the inverter is giving an incorrect

reading compared to measurement tools. Normally this will remain ‘1’

watt_factor=1.01

The following settings allow you to modify runtime buffers.

N.B. These values may not be applicable to all inverter types, as such you will

need

Sat Sep 28 21:02:15 2024 INVERTER: Current CRC: B7 A9
Sat Sep 28 21:02:16 2024 INVERTER: QPIGS reply size (110 bytes)
Sat Sep 28 21:02:16 2024 INVERTER: QPIGS: 110 bytes read: (001.0 00.0 229.0 50.0 0156 0070 015 417 13.06 000 100 0558 0000 000.0 00.00 00009 10010000 10 08 00000 000
Sat Sep 28 21:02:16 2024 INVERTER: QPIGS query finished
Sat Sep 28 21:02:16 2024 INVERTER: Current CRC: F8 54
Sat Sep 28 21:02:19 2024 INVERTER: QPIRI read timeout
Sat Sep 28 21:02:19 2024 INVERTER: QPIRI reply too short (7 bytes)
Sat Sep 28 21:02:19 2024 INVERTER: Current CRC: B4 DA
Sat Sep 28 21:02:19 2024 INVERTER: QPIWS reply size (22 bytes)
Sat Sep 28 21:02:19 2024 INVERTER: QPIWS: incorrect start/stop bytes. Buffer: (. 04.4.3 0080012. 150 0156 0070 015 417 13.06 000 100 0558 0000 000.0 00.00 00009 10010000 10 08 00000 000
Sat Sep 28 21:02:24 2024 INVERTER: Current CRC: 49 C1
Sat Sep 28 21:02:25 2024 INVERTER: QMOD reply size (4 bytes)
.3 0080012. 150 0156 0070 015 417 13.06 000 100 0558 0000 000.0 00.00 00009 10010000 10 08 00000 000
Sat Sep 28 21:02:25 2024 INVERTER: Current CRC: F8 54
Sat Sep 28 21:02:26 2024 INVERTER: QPIRI reply size (97 bytes)
Sat Sep 28 21:02:26 2024 INVERTER: QPIRI: 97 bytes read: (230.0 04.3 230.0 50.0 04.3 1000 0800 12.0 11.5 10.5 14.5 13.5 2 20 50 0 0 0 - 01 1 0 13.5 0 0
Sat Sep 28 21:02:26 2024 INVERTER: QPIRI query finished
Sat Sep 28 21:02:26 2024 INVERTER: Current CRC: B4 DA
Sat Sep 28 21:02:28 2024 INVERTER: QPIWS reply size (22 bytes)
Sat Sep 28 21:02:28 2024 INVERTER: QPIWS: incorrect start/stop bytes. Buffer: (000000000000000000000 04.3 1000 0800 12.0 11.5 10.5 14.5 13.5 2 20 50 0 0 0 - 01 1 0 13.5 0 0
Sat Sep 28 21:02:33 2024 INVERTER: Current CRC: 49 C1
Sat Sep 28 21:02:34 2024 INVERTER: QMOD reply size (4 bytes)
000000000000000 04.3 1000 0800 12.0 11.5 10.5 14.5 13.5 2 20 50 0 0 0 - 01 1 0 13.5 0 0
Sat Sep 28 21:02:34 2024 INVERTER: Current CRC: B4 DA
Sat Sep 28 21:02:35 2024 INVERTER: QPIWS reply size (22 bytes)
Sat Sep 28 21:02:35 2024 INVERTER: QPIWS: incorrect start/stop bytes. Buffer: (000000000000000000000 04.3 1000 0800 12.0 11.5 10.5 14.5 13.5 2 20 50 0 0 0 - 01 1 0 13.5 0 0
Sat Sep 28 21:02:40 2024 INVERTER: Current CRC: 49 C1
Sat Sep 28 21:02:41 2024 INVERTER: QMOD reply size (4 bytes)
000000000000000 04.3 1000 0800 12.0 11.5 10.5 14.5 13.5 2 20 50 0 0 0 - 01 1 0 13.5 0 0
Sat Sep 28 21:02:41 2024 INVERTER: Current CRC: B4 DA
Sat Sep 28 21:02:42 2024 INVERTER: QPIWS reply size (22 bytes)
Sat Sep 28 21:02:42 2024 INVERTER: QPIWS: incorrect start/stop bytes. Buffer: (000000000000000000000 04.3 1000 0800 12.0 11.5 10.5 14.5 13.5 2 20 50 0 0 0 - 01 1 0 13.5 0 0
Sat Sep 28 21:02:47 2024 INVERTER: Current CRC: 49 C1
Sat Sep 28 21:02:49 2024 INVERTER: QMOD reply size (4 bytes)
000000000000000 04.3 1000 0800 12.0 11.5 10.5 14.5 13.5 2 20 50 0 0 0 - 01 1 0 13.5 0 0
Sat Sep 28 21:02:49 2024 INVERTER: Current CRC: B4 DA
Sat Sep 28 21:02:50 2024 INVERTER: QPIWS reply size (22 bytes)
Sat Sep 28 21:02:50 2024 INVERTER: QPIWS: incorrect start/stop bytes. Buffer: (000000000000000000000 04.3 1000 0800 12.0 11.5 10.5 14.5 13.5 2 20 50 0 0 0 - 01 1 0 13.5 0 0

So have data going into my MQTT broker, wont auto populate in home assistant. For anyone who need them,
qpiri=97
qpiws=40
qmod=5
qpigs=110

Now question one sensor that seems to be missing is grid power. Have booted up a copy of solarassistant to try and my inverter does provide this information just not showing in mqtt. Any way to edit this to gain that information?

Also feel there is an issue with mqtt device tag, rather than my device showing as one, then each entity under it, each one shows as a separate device as you can see from my mqtt explore

Thank you so much! now finally work perfectly!!!

1 Like

Hello! I have similar inverter model and wanna read raw data from it. Could you describe your setup and how you configured it? Can simple laptop with ubuntu read the data directly from inverter? I’m newbee so sorry for my dumb questions.

Hi,

I just plugged an USB cable into the inverter and my RaspberryPi running debian.
Ubuntu is a debian derivate and this python code should run on your laptop too.

import time

import hidapi as hid


def communicate_with_hid_device(vendor_id, product_id, command_str):
    try:
        device = hid.Device(vendor_id=vendor_id, product_id=product_id)
        print("Device opened.")
        device.nonblocking = True

        command_bytes = command_str.encode('ascii')
        device.write(command_bytes)
        print(f"command sent: {command_bytes}")

        time.sleep(1)
        response = device.read(64)
        if response:
            print(f"Response: {bytes(response).decode(errors='ignore')}")
        else:
            print("Got no response")

        device.close()

    except Exception as e:
        print(f"Fehler bei der HID-Kommunikation: {e}")

if __name__ == "__main__":
    vendor_id = 0x0665  # Cypress Semiconductor
    product_id = 0x5161  # USB to Serial
    command = "QPIGS\r"  # Beispielbefehl als String

    communicate_with_hid_device(vendor_id, product_id, command)

This is just a test script.

Hope it will help.

Ciao
bama

1 Like

Hi,
I’m using an Voltronic (EASUN branded) since 12 months. And it is the second USB serial device that is been killed by it … Suddenly, I don’t receive any data on the voltronic-mqtt container, and when I plug the USB serial device into my computer, it isn’t detected anymore …

Has anyone experencied such a problem?

Dear Joubert,
I connected an ESP8266 connected to the serial (RS232 cable) of an EASUN 8kW Hybrid Inverter and I read correctly the inverter status parameters.

To setup pipsolar current_max_ac_charging_current I adapted your suggested approach and code (see my code).

Now it happens that only in some cases of selected helper values ​​the current_max_ac_charging_current
is recorded in the inverter, in other cases a very different value is transmitted and since it does not belong to the set of allowed values, it is not recorded. Here is the list:

Helper: 2, 10, 20, 30, 40,50, 60, 70,80, 90,100,110,120 Amps
Registration: 153,218,139,188,185,56,103,152,12,131,100,110,120 Amps

Note that only in the cases of setup higher than 100: 100A, 110A, 120A the values ​​are registered in the inverter.

Can You help me ?

Here is the Logs of unsuccessful & successful registration:

[14:00:00][D][main:238]: STARTING VARIABLE ACCurrent
[14:00:00][D][pipsolar.output:015]: Will write: MUCHGC020 out of value 20.000000 / 20
[14:00:00][D][pipsolar:860]: got command: MUCHGC020
[14:00:00][D][pipsolar:851]: Command queued successfully: MUCHGC020 with length 9 at position 0
[14:00:00][D][main:063]: VARIABLE ACCurrent ENDS
[14:00:00][D][uart_debug:158]: >>> “MUCHGC020\xF3\xF1\r”
[14:00:00][D][pipsolar:811]: Sending command from queue: MUCHGC020 with length 9
[14:00:00][W][component:237]: Component esphome.coroutine took a long time for an operation (66 ms).
[14:00:00][W][component:238]: Components should block for at most 30 ms.
[14:00:00][D][uart_debug:158]: <<< “(NAKss\r”
[14:00:00][D][pipsolar:043]: response length for command OK
[14:00:00][D][pipsolar:776]: checking crc on incoming message
[14:00:00][D][pipsolar:779]: CRC OK
[14:00:00][D][pipsolar:049]: command not successful

[14:25:47][D][main:238]: STARTING VARIABLE ACCurrent
[14:25:47][D][pipsolar.output:015]: Will write: MUCHGC0100 out of value 100.000000 / 100
[14:25:47][D][pipsolar:860]: got command: MUCHGC0100
[14:25:47][D][pipsolar:851]: Command queued successfully: MUCHGC0100 with length 10 at position 1
[14:25:47][D][main:063]: VARIABLE ACCurrent ENDS
[14:25:47][D][uart_debug:158]: >>> “MUCHGC0100A\r”
[14:25:47][D][pipsolar:811]: Sending command from queue: MUCHGC0100 with length 10
[14:25:47][W][component:237]: Component esphome.coroutine took a long time for an operation (70 ms).
[14:25:47][W][component:238]: Components should block for at most 30 ms.
[14:25:47][D][uart_debug:158]: <<< “(ACK9 \r”
[14:25:47][D][pipsolar:043]: response length for command OK
[14:25:47][D][pipsolar:776]: checking crc on incoming message
[14:25:47][D][pipsolar:779]: CRC OK
[14:25:47][D][pipsolar:047]: command successful

[14:25:56][D][main:238]: STARTING VARIABLE ACCurrent
[14:25:56][D][pipsolar.output:015]: Will write: MUCHGC010 out of value 10.000000 / 10
[14:25:56][D][pipsolar:860]: got command: MUCHGC010
[14:25:56][D][pipsolar:851]: Command queued successfully: MUCHGC010 with length 9 at position 2
[14:25:56][D][main:063]: VARIABLE ACCurrent ENDS
[14:25:56][D][pipsolar:776]: checking crc on incoming message
[14:25:56][D][pipsolar:779]: CRC OK
[14:25:56][D][pipsolar:483]: Decode QFLAG
[14:25:56][D][uart_debug:158]: >>> “MUCHGC010\xA6\xA2\r”
[14:25:56][D][pipsolar:811]: Sending command from queue: MUCHGC010 with length 9
[14:25:56][W][component:237]: Component esphome.coroutine took a long time for an operation (64 ms).
[14:25:56][W][component:238]: Components should block for at most 30 ms.
[14:25:57][D][uart_debug:158]: <<< “(NAKss\r”
[14:25:57][D][pipsolar:043]: response length for command OK
[14:25:57][D][pipsolar:776]: checking crc on incoming message
[14:25:57][D][pipsolar:779]: CRC OK
[14:25:57][D][pipsolar:049]: command not successful

================================

Here is a fragment of ESPHOME code:
</>
api:
services:
- service: ac_grid_current
variables:
ACCurent: float
then:
- logger.log: “STARTING VARIABLE ACCurrent”
- output.pipsolar.set_level:
id: pipsolar_current_max_ac_charging_current
value: !lambda ‘return ACCurent;’
- logger.log: “VARIABLE ACCurrent ENDS”
output:

  • platform: pipsolar
    pipsolar_id: inverter0
    current_max_ac_charging_current:
    possible_values:
    • 2
    • 10
    • 20
    • 30
    • 40
    • 50
    • 60
    • 70
    • 80
    • 90
    • 100
    • 110
    • 120
      id: pipsolar_current_max_ac_charging_current
      </>
      ================================
      Here is the AUTOMATION:
      </>
  • id: ‘162702835999’
    alias: inverter Setting max charging Current
    description: ‘’
    trigger:
    • platform: state
      entity_id: input_select.setting_max_charging_current
      condition:
      action:
    • service: esphome.pipsolar_ac_grid_current
      data:
      ACCurent: “{% if is_state("input_select.setting_max_charging_current", "
      2 Amp") %}\n 2 \n{% elif is_state("input_select.setting_max_charging_current"
      , "10 Amp") %}\n 10 \n{% elif is_state("input_select.setting_max_charging_current"
      , "20 Amp") %}\n 20 \n{% elif is_state("input_select.setting_max_charging_current"
      , "30 Amp") %}\n 30 \n{% elif is_state("input_select.setting_max_charging_current"
      , "40 Amp") %}\n 40 \n{% elif is_state("input_select.setting_max_charging_current"
      , "50 Amp") %}\n 50 \n{% elif is_state("input_select.setting_max_charging_current"
      , "60 Amp") %}\n 60 \n{% elif is_state("input_select.setting_max_charging_current"
      , "70 Amp") %}\n 70 \n{% elif is_state("input_select.setting_max_charging_current"
      , "80 Amp") %}\n 80 \n{% elif is_state("input_select.setting_max_charging_current"
      , "90 Amp") %}\n 90 \n{% elif is_state("input_select.setting_max_charging_current"
      , "100 Amp") %}\n 100 \n{% elif is_state("input_select.setting_max_charging_current"
      , "110 Amp") %}\n 110 \n{% elif is_state("input_select.setting_max_charging_current"
      , "120 Amp") %}\n 120 \n{% endif %}\n”
      mode: single
      </>
      ================================

And the Helper:
input_select.setting_max_charging_current with the values of
2 Amp, 10 Amp, 20 Amp, 30 Amp,40 Amp,50 Amp,60 Amp,70 Amp,80 Amp,90 Amp,100 Amp,1100 Amp,120 Amp

Yes, me too.
yes I also have an EASUN hybrid inverter with a broken USB type C port. However I use the RS232 serial port connected to a RS232-TTL adapter (10 pieces for €12) + a few € ESP8266 which gives me Wifi connection.
Not using mqtt but ESPHOME from HA.

1 Like

Nice !
Can you please share your ESPHOME config and RS232-TTL to ESP8266 pinout?

Prova questo (try this)

Have been able to setup “current_max_charging_current” with the same config of my post as per above. Unfortunately till not able to setup “current_max_ac_charging_current”.

After years of experimenting with solutions from this topic, I finally wrote my own. It’s been running great for months, and I’ve shared it in a new topic: Voltronic Solar Inverter to Home Assistant via MQTT with docker-voltronic-mqtt.

Please check it out and share your thoughts!