Ginlong Solis is one of the world's recognised manufacturers of string solar inverters. Almost all of their products have an Modbus RS-485 interface for reading live status and statistics.
Quick start, you'll find here:
- An ESPHome solution to integrate your inverter into Home Assistant, using an ESP8266
- An ESPHome solution to integrate your inverter into Home Assistant, by replacing the firmware of the Solis S3 WiFi stick
- An Arduino solution to push data from your inverter to InfluxDB, using an ESP8266
- A wiring diagram for connecting the inverter to an ESP8266 via ModBus/RS485
The ESPHome solution also has some advanced features such as limiting the inverter output power, synchronising the inverter time via NTP and more.
If in doubt, I recommend choosing the Solis S3 stick with the alternative firmware. You can currently buy the Solis S3 stick for about 20 € and get a rugged, waterproof case, external antenna, etc. For this price you can not buy and assemble the individual parts.
Please do me a favor: 👍 If you use any information or code you find here, please link back to this page. ⭐ Also, please consider to star this project. I really like to keep track of who is using this to do creative things, especially if you are from other parts of the world. 😃 You are welcome to open an issue to report on your personal success project and share it with others.
You need a proprietary Exceedconn EC04681-2014-BF connector (available on Ebay) and an RS485-to-serial adapter (a cheap one without DE/RE pins is sufficient, e.g. the HW-0519
, XY-K485
or XY-017
). Wire all components to e.g. a Wemos D1 mini (also available as 'pro' variant with an SMA connector and external antenna for better reception) as follows:
A bit strange, you have to connect the RX pin of the HW-0519
adapter to the RX pin of the ESP (and the TX pin to the TX pin), so no RX-TX-crossover like normal.
Especially recommended if you use Home Assistant, solis-esphome-esp8266.yaml is an ready-to-use configuration file for ESPHome, using an ESP8266. With the ESPHome dashboard you can easily set up your system with just a few clicks via a user-friendly web interface.
With solis2influx.ino one can read out all inverter data (status and statistics) via Modbus and push it to InfluxDB.
It uses WiFiManager to setup WiFi, so you have to connect to the SOLIS2INFLUX
access point with your mobile phone first.
The reading of the data starts immediately after configuring WiFi. The data is not sent to the InfluxDB server until the inverter's serial number has been read, which may take a moment (the serial number is added as a mandatory tag to distinguish multiple inverters):
DC voltage 1 = 243.70V
DC current 1 = 0.90A
Inverter temperature = 22.50°C
Grid frequency = 49.98Hz
Writing to influxDB: solis,serialnumber=1801020221230123 DC\ voltage\ 1=243.70,DC\ current\ 2=0.90,Inverter\ temperature=22.5,Grid\ frequency=49.98
Energy last month = 234kWh
Energy today = 1.23kWh
Energy last day = 3.45kWh
Writing to influxDB: solis,serialnumber=1801020221230123 Energy\ last\ month=234i,Energy\ today=1.23,Energy\ last\ day=3.45
The WiFi stick is Solis' current solution for connecting the inverter to their 'SolisCloud' platform (which is operated by Alibaba China). You can recognise the 3rd gen stick by the three LEDs on the front and the reset button on the back.
The firmware of the stick offers support for connecting the stick to the home WiFi and displays basic inverter statistics. The firmware (at least the current version 1012F
) is a kind of beta and incomplete, as it lacks important functions that are available in the previous generation WiFi sticks. In particular, support for setting a second remote logging server (called "Server B") is missing.
The web interface is protected by HTTP simple auth with fixed username admin
and password 123456789
. After connecting the stick to your home WiFi the web password changes without notice to your WiFi password. So you need to login to the web admin interface with admin
and your WiFi password.
This somewhat wierd behaviour again shows the immature state of the firmware.
Since the current firmware does not support setting up your own remote logging server, there is solis2influx.pl to read basic statistics from the web interface (/inverter.cgi
) and publish this information in an influx db.
The stick firmware is based on Alibaba's AliOS-Things 3.0.0 embedded operating system
(not sure if some parts of MXCHIPS's MiCO OS were been mixed in).
It uses hardcoded DNS servers (public1.alidns.com
and public2.alidns.com
) and frequently pushes data to *.iot-as-mqtt.*.aliyuncs.com
(this server is chosen depending on your geolocation).
The stick hardware is based on MXCHIP's EMW3080-E MCU
(ARM Cortex-M4F, 2.4G Hz IEEE 802.11 b/g/n WiFi, Suffix -E
denotes IPEX antenna, MX1290 processor
).
Datasheet: V2.2.
✋ Contrary to all available datasheets, the EMW3080-E (at least the one in my Solis S3 stick) does not have 2MB flash installed, but an 8MB flash module.
The EMW3080 is some kind of relabeled (call it the same family) RTL8710BN MCU (Ameba-Z series). One can find more info about the EMW3080 at A_D Electronics and a discussion at esp8266.ru.
The stick is connected to the inverter via a type of proprietary Exceedconn EC04681-2014-BF connector (circular pin arrangement: 1=VCC=5V, 2=GND, 3=RS485+, 4=RS485-) . The external antenna is connected via a standard SMA connector. You can open the case by pressing the notches towards the centre of the stick.
There is a serial interface (LogCLI) on the PCB connected to UART2_Log_TX
and UART2_Log_RX
of the MCU (115200 8N1, 3.3 Volt).
Update: Since end of 2022 there is a new PCB version which contains a hardware watchdog. You can recognize these new boards by the silkscreen '22.34' (which probably corresponds to the year and week of manufacture) .
You get a first impression when you examine the UART2_Log
output:
ROM:[V0.1]
FLASHRATE:4
BOOT TYPE:0 XTAL:40000000
IMG1 DATA[1128:10002000]
IMG1 ENTRY[800053d:100021ef]
IMG1 ENTER
CHIPID[000000ff]
read_mode idx:2, flash_speed idx:2
calibration_result:[1:19:13][3:15]
calibration_result:[2:21:11][1:15]
calibration_result:[3:1:1][1:1]
calibration_ok:[2:21:11]
FLASH CALIB[NEW OK]
OTA2 ADDR[8100000]
OTAx SELE[ffffffff]
OTA1 USE
IMG2 DATA[0x800f1c0:36:0x10005000]
IMG2 SIGN[RTKWin(10005008)]
IMG2 ENTRY[0x10005000:0x800b105]
BOOT_FLASH_RDP RDP enable
RDP bin decryption Failed!
checksum_ipsec = 0x46956286, checksum_rdp_flash = 0x80d838a
2ndboot image start
Press key 'w' to 2ndboot cli menu in 100ms.
122: ota crc cal:0x7a1a param:0xffff
17: ota upg_flag:0xffffcount:0 crc;0xffff
30: No OTA upgrade.
See the full (anonymized) bootlog for more details.
When holding the 'w' key during boot an extremely limited 2ndboot CLI starts:
2ndboot image start
Press key 'w' to 2ndboot cli menu in 100ms.
2ndboot ver: 2ndboot-1.0.0-20210917.200018
Please input 1-2 to select functions
[1] Uart Ymodem Upgrade
[2] System Reboot
[h] Help Info
2ndboot# h
2ndboot ver: 2ndboot-1.0.0-20210917.200018
Please input 1-2 to select functions
2ndboot#
When pulling TX pin 21 (PA_30
) low during boot, the device waits for a xmodem
transfer (UART boot mode
):
ROM:[V0.1]
FLASHRATE:4
UARTIMG_Download 2
Open xModem Transfer on Log UART...
When the device is in this mode, one can download the firmware using RTLtool (depends on Python2) (Update: ltchiptool is now a better option):
$ python2 ./rtltool.py -p /dev/ttyUSB0 gf
Connecting...
Flash Status value: 0x40
$ python2 ./rtltool.py -p /dev/ttyUSB0 rf 0x8000000 0x800000 dump-0x8000000-0x800000.bin
Connecting...
Read Flash data from 0x08000000 to 0x08800000 in file: dump-0x8000000-0x800000.bin ...
Done!
The dump contains all kinds of interesting stuff (AOS-R-3.0.0
and sdk-c-3.0.1
clearly link to AliOS-Things 3.0.0).
With the help of Realtek AmebaZ Memory Layout,
Introduction to Ameba-Z SDK
and mk3080/flash_partitions.c
one can reconstruct the flash partition table found at address 0x800e320
:
DESCRIPTION START_ADDR LENGTH
Bootloader 0x0 0x8000 // = AliOS-Things/platform/mcu/rtl8710bn/bin/boot_all.bin
Recovery 0xb000 0x6000 // 2ndboot
Application 0x19000 0x127000
OTA Storage 0x150000 0x127000
Parameter1 0x2a0000 0x2000
Parameter2 0x2a2000 0x2000 // WiFi credentials @ 0x2a3000
Parameter3 0x2a4000 0x2000 // AliOS PK+PS+DN+DS
Parameter4 0x2a6000 0x2000
Parameter5 0x2a8000 0x10000
Parameter55 0x2b8000 0x1000
Parameter33 0x7fe000 0x1000 // Backup of Parameter3 ?
Offline 0x300000 0x4fe000 // 0x1000 zeros + some noise
Partition 'Parameter3' contains the 'Product Key' (PK) and 'Device Secret' (DS) needed to connect to the Alibaba IOT Platform. The serial number of the stick is used as 'Device Name' (DN). With the Link SDK for Python you can easily impersonate as the inverter and send MQTT data to the SolisCloud.
The main application starts at 0x19000
with a TEXT
segment for
flash in place execution (XIP). It is followed by a DATA
segment for RAM execution. I will refer to this part as 'APP1'.
The complete APP1 in OTA package format (including checksums) starts
at 0x19000
with length 797628 and MD5 checksum 0a88cb5556ab28ffba63a8d56e131d56
.
With decode-alios-ota-firmware.pl one can
view all details and validate the checksums:
$ ./decode-alios-ota-firmware.pl solis-s3-app-1012F_ota.bin
# Segment .text
0x00000000: Signature = 0x3831393538373131 (OK)
0x00000008: Code length = 790112
0x0000000c: Address = 0x00000000 (FLASH XIP)
0x00000010: Reserved = 0xffffffffffffffffffffffffffffffff
0x00000020: Code = (byte code)
# Segment .data
0x000c0e80: Signature = 0x3831393538373131 (OK)
0x000c0e88: Code length = 7420
0x000c0e8c: Address = 0x10005000 (RAM)
0x000c0e90: Reserved = 0xffffffffffffffffffffffffffffffff
0x000c0ea0: Code = (byte code)
# Segments checksum
0x000c2b9c: Checksum = 0x25249404 (OK)
# OTA trailer
0x000c2ba0: Magic = 0xefefefef (OK)
0x000c2ba4: Size = 797600 (OK)
0x000c2ba8: MD5 checksum = 0x85a615f88804cfb7784ffab81c27795b (OK)
0x000c2bb8: Reserved = 0xffffffff
# End of data
0x000c2bbc: Filesize = 0xc2bbc = 797628 (OK)
Somewhat unexpectedly, the APP1 part is followed by a second app ('APP2') starting
with TEXT
at 0xdbbbc
(length 222276) and DATA
at 0x112020
(length 3656).
This APP2 is binary identical to AliOS ate.bin.
It is currently not clear whether it is being used at all, there is a suspicion
that it is an ATE firmware for Automatic test equipment
or to set eFuses/RDP.
With knowledge of the source code it is easy to locate the corresponding byte code in the dump. For example, the Mbed TLS wrapper code
if (ca_crt != NULL) {
mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
corresponds to the binary
0803fb86 ba f1 00 0f cmp.w r10,#0x0
0803fb8a 2f d0 beq LAB_0803fbec
0803fb8c 02 21 movs r1,#0x2 // 0x2 = MBEDTLS_SSL_VERIFY_REQUIRED
0803fb8e 2e e0 b LAB_0803fbee
So, if you change value 02 21
to 00 21
(0x0 = MBEDTLS_SSL_VERIFY_NONE
) at offset 0x3fb8c
,
the destination SSL certificate will not be checked anymore and you can man-in-the-middle or
redirect the SSL traffic (MQTT, HTTP, ... to Alibaba cloud).
When writing to the flash with RTLtool (wf
cmd), make sure to always write
full 4096 bytes aligned data blocks (flash SECTOR_SIZE 0x1000
).
Thanks to the fine folks at LibreTiny, arduino-compatible cores for RTL8710B chips are available. And even better, LibreTiny is now part of ESPHome. With solis-esphome-emw3080.yaml you can read out all relevant status and statistics data from your Solis inverter and push it to Home Assistant.
Install the ESPHome firmware for the S3 stick as follows:
- Install the ESPHome dashboard for Home Assistant (at least version 2023.9.0).
- If you not already have one, add a
secrets.yaml
to the ESPHome addon, containing at leastwifi_ssid
,wifi_password
,wifi_ap_ssid
,wifi_ap_password
,api_encryption_key
andota_password
. - Add solis-esphome-emw3080.yaml to the ESPHome addon.
- Depending on your inverter type, copy one of solis-modbus-inv.yaml or solis-modbus-esinv.yaml as well.
- Within
solis-esphome-emw3080.yaml
edit inverter type (include
statement withinpackages
section). - Click the three-dots button, then "Install" and "Manual Download".
- Wait for the compilation process to finish and download the "UF2 package".
- Set the MCU to
UART boot mode
(pull TX pin low during boot -- you do not need to solder, just inserting some jumper wires is sufficient). Make sure your serial adapter uses 3.3V voltage, read the notes below carefully about possible challenges with these adapters. - Backup the stock firmware with ltchiptool (also available as a Win GUI version):
$ ltchiptool -V ltchiptool v4.10.1 # use at least this version $ ltchiptool flash read -d /dev/ttyUSB0 RTL8710B solis-s3-firmware-1012f.bin I: Connecting to 'Realtek AmebaZ' on /dev/ttyUSB0 @ 1500000 I: Reading Flash (8 MiB) $ ls -l solis-s3-firmware-1012f.bin 8388608 # file size should be exactly this, otherwise something has gone wrong
- Flashing the ESPHome image (replacing stock AliOS 2ndboot and main app altogether) is as simple as
$ ltchiptool flash write -d /dev/ttyUSB0 solis-emw3080.uf2
After flashing, you can reconnect the S3 WiFi stick to the inverter and the status data will magically appear in Home Assistant. For subsequent updates you can simply OTA-upload the firmware via the ESPHome addon.
💡 This integration uses a patched version of the ArduinoCore-API. This workaround is necessary until libretiny-eu/libretiny#154 is fixed.
💡 Matching the EMW3080 datasheet, one should actually use the generic-rtl8710bn-2mb-788k
board profile
for LibreTiny. But since the Solis WiFi stick has a special 8MB version of the MCU with an OTA address of 0x100000, the
not exactly matching profile generic-rtl8710bx-4mb-980k
is used here, manually setting the MCU type and frequency in
the PlatformIO options to the correct value.
Solis products feature (at least) two different Modbus register maps, the
ESINV
(energy storage inverter) map mostly uses registers in the 3xxxx (ten-thousands) range
and the INV
(inverter) map uses the 3xxx (thousands) range.
It is probably a good practice (not thoroughly tested) to query register 35000 ("inverter type definition")
and act according to the first two decimal places of the read value
(the documentation says: "high 8 bit means protocol version, low 8 bit means inverter
model", but I think this is only correct if you interpret it as some kind of 'decimal bits'):
10
: see RS485_MODBUS (INV-3000IDEPM-36000ID) inverter protocol20
: see RS485_MODBUS (ESINV-33000ID) energy storage inverter protocol
For the INV
3xxx Register Map, you'll need to subtract offset 1 from addresses
before transmitting on the bus (see explanation in section 5.3 of the
document).
Dr. Brian Coghlan initially translated the
ESINV
-Modbus inverter communication protocol from chinese to english in 2018,
but it now seems to me to have been superseded by the official versions from Solis linked above.
-
According to Serial Number Naming Rule and Ginlong Solis Serial Number decoder V1.1.pdf Solis inverter serial numbers consist of 12 or 15 digits. Supplemented by helpful comments, the following extended syntax can be derived::
MM-0-YYMDD-SSSS (12 digit style) D-O-0-MM-0-YYMDD-SSSS (15 digit style) D-O-0-MMM-0-YYMDD-SSSS (16 digit style)
-
Curiously, the HTML source files of the Solis S3 WiFi stick can be found in this repository.
-
kuba2k2 for LibreTiny und for patiently helping with problems and patches.
-
jimmyburnworld implemented a similiar approach for Solis ESINV inverters and MalteSchm updated it for Solis INV inverters.
-
incub77 offers a comprehensive solution based on the Raspberry Pi
-
How could it be otherwise than that Tasmota also offers a solution for Modbus inverters.