Tues 22nd Sep 2026
(21:39) Based on the code at: https://github.com/syssi/esphome-jbd-bms
Got both "SP10S0009-L8S-100A-B-U" and "BR2262e-s" 24V LFP batteries monitored by HA
Happy days!
Tues 22nd Sep 2026
(21:39) Based on the code at: https://github.com/syssi/esphome-jbd-bms
Got both "SP10S0009-L8S-100A-B-U" and "BR2262e-s" 24V LFP batteries monitored by HA
Happy days!
The goal of this project is to repurpose my 3x 24V LFP to a 96V battery for my Sungrow SH3.0RS inverter.
To do this I will need to create a RS485 JK-BMS comms to Sungrow CANBUS comms converter and start by using 32x 18650 3.7V Li-Ion batteries in place of the 24V LFP ones (I will need to buy another 24V LFP battery once I get the comms going.
(Tues 22nd Nov 2026)
Got ESPHome working using ESPHome Device Builder on rhubarb laptop (accessed via http://localhost:6052/)
And successfully got HA to see ESP32-C3 device pulling BMS data over BLE to MQTT and directly to HA.
including the state of all 32 cells..
Must make a dashboard next and test if I can turn CHARGE and DISCHARGE ON and OFF. Yep switches work fine :)
Based on code at https://github.com/syssi/esphome-jk-bms/blob/main/esp32-ble-v19-example.yaml
https://deepwiki.com/syssi/esphome-jk-bms/4.2-basic-uart-configuration
Now. How to make a HA dashboard? And replace BLE with UART connection to BMS
I will try this RS485 example next..
https://github.com/syssi/esphome-jk-bms/blob/main/esp8266-jk-pb-modbus-example.yaml
(Mon 21st Nov 2026)
(16:34) Giving up for now. Will try ESP32-C3 ESPHome project next! Say https://github.com/syssi/esphome-jk-bms
(Backed up Node Red to sionnach_after_jkbms_modbus_mqtt_added_flows.json)
(16:05) Maybe I should just cable the ON/OFF button,_96V and 0V power, UART, RS485 and CAN to the 6 inch pipe lid and then work on unit in the kitchen connected to laptop via USB/RS485 dongle?
Annoys me that some Modbus commands get a response of 0x8604 (error code?) but often nothing. Hanging?
Should I switch to using direct ESP32 to UART port (not RS485 port). Or get PC Windows software running? Cannot see a GPS UART protocol to select from in BLE app. Maybe "4G-GPS Remote module protocol V4.2" or maybe try an ESPhome project
(15:30) Cannot get any robust comms or sensible replies over RS485. Let me check the protocol assigned to UART-21 / UART-2. (Which is the real UART port and which is the RS485 port?)
https://www.gobelpower.com/jkbms-firmware-download_ap88.html
Are all these error code responses? Had to power OFF/ON BMS to get responses MODBUS again.
Last two above examples from http://www.jk-bms.com/en/Upload/2023-12-05/1559153362.pdf
Tried sending Modebus command 01 03 02 58 00 02 44 60 and got response 01 86 04 43 a3.
What does this mean?
Modbus RTU uses 8-bit Serial Communications to send Modbus messages. Format is:
And the response means..
So a success read of register 0x0258 returning 0x8604
http://www.jk-bms.com/en/Upload/2023-12-05/1559153362.pdf
01 03 00 05 00 02 D4 0A
https://koeed.com/pages/modbus-crc-calculator
Cannot get any robust comms or sensible replies over RS485. Let' sme chekc the protocol assigned to UART-21 / UART-2
So added code to NodeRed "Sungrow Inverter" tab at http://192.168.1.153:1880/ to send and receive Modbus messages
But what do I send to get a response?
It looks like the Waveshare converter should work with the Sungrow SH3.0RS inverter once I get the BMS comms going..
https://www.waveshare.com/wiki/ESP32-S3-RS485-CAN-Web
| Sungrow | SH3.0/3.6/4.0/5.0/6.0RS | 1 | ( ⭐⭐ ) | 80 / 460 | BYD protocol |
https://github.com/dalathegreat/Battery-Emulator/discussions/2164
"BYD Protocol" being.. "BYD Battery-Box Premium HVS over CAN bus"
(Sun 20th Sept 2026)
I soldered the RS485 converter to the ESP32-C3 board and made some push connectors for the RS485 A- and B+ wires.
Powering up JK-BMS caused a few messages to be received by the ESP32 monitor (used "IoT MQTT Panel" app to subscribe to MQTT topic "home/solar/esp32c3_jkbms_monitor/#" )
home/solar/esp32c3_jkbms_monitor/RxByte "e0e0" followed by "cf"
(Sat 19th Sept 2026)
I created an Arduino sketch for the BMS comms and burned it into a ESP32-C3. Code in directory:
/home/coderdojo/Arduino/esp32c3/esp32c3_jkbms_monitor
(Fri 18th Sept 2026)
Have code programmed into Waveshare protocol adaptor and added it to the Tola Park SSID WiFi network.
But now need it to talk to the JK-BMS over RS485 and to the Sungrow SH3.0RS hybrid inverter over CAN bus.
Here are the protocols on offer:
So I think I will go with:
1) Set the JK-BMS to use "005 – PYLON_low_voltage_Protocol_RS485_V3.5"
2) The Waveshare converter battery setting to "Pylon /Dryness compatible battery" / RS485 and its Inverter setting to "Pylon HV battery over CAN bus" / CAN (Native)
I should be able to monitor things over the USB-C UART debug connection and, if successful, over MQTT broker
(Thurs 17th Sept 2026)
The Waveshare-ESP32-C3-RS485-CAN DIN module should be ideal to act as the comms converter and the software is available for it at:
https://github.com/dalathegreat/Battery-Emulator
See Sungrow SH3.0RS entry in table at:
https://dalathegreat.github.io/Battery-Emulator-Wiki/inverter/
Vendor Product Name AC Phases Compatibility level Voltage min / max (V) Notes
| Sungrow | SH3.0/3.6/4.0/5.0/6.0RS | 1 | ( ⭐⭐ ) | 80 / 460 | BYD protocol |
https://www.waveshare.com/wiki/ESP32-S3-RS485-CAN
This discussion also helpful
https://github.com/dalathegreat/Battery-Emulator/discussions/2164
I had problems with App not talking to BMS but latest version of App worked fine.
I finished wiring up 32x 18650 3,7V Li-Ion batteries to the 32s JK-BMS and got the BLE app going.
(Weds 26 August 2026)
Well, I got my two ESP32-C3s shipping data from my Sungrow S100 meter via MQTT and Node-Red to my Sungrow SH3.0RS Hybrid Inverter last week. But after a firmware update to the inverter on Monday it stopped working.
So, it looks like my code was marginal and the new inverter has now less than 100 mSec between inverter Modbus transmissions at 9600 baud. So later today I will reflash the ESP32s with a 10 mSec inter-byte time-out but for now I will fix it in Node-Red :)
This means processing MQTT messages received on topic: home/solar/sungrow/esp32c3_s100_emulator/RxBytes to chop and tail inverter messages that have been fused together.
So these rx messages:
fe03003f0001a009
f604101f0001118b
207300000001c370
fe03500000018105
fe03003f0001a009
f604101f0001118b
etc.
Huh? This looks OK. So how is the S100 meter responding? Battery was low so after changing it I got more garbled rx data from the inverter
207300000001c370 got S100 response 20730203275e69
fe03500000018105
fe03003f0001a009
f604101f0001118b
207300000001c370 got S100 response 20730203275e69
030000000d82be20030000000d82be20030000000d82be20030000000d82be20030000000d82be
fe03500000018105
So I will clip the garbled 207300000001c370 message in Node-Red and send the cleaned up one to the S100 ESP32
This caused the S100 meter to eventually respond with:
But the inverter is only seeing these every 30 seconds or so...
(11:24) So I think I need to try fixing the ESP32 firmware next...
Looking at the existing it is crashing! So that needs to be fixed :)
I'll post the code to Github later :)
So lets change
// Changing the Modbus inter-byte timeout to 10 mSec (from 100 mSec)
// Modbus is operating at 9600 baud so a 10-bit transmittion takes about 1 mSec
#define MODBUS_RX_TIMEOUT 10
And take it for a spin..
After turning off serial debug in the code I got the inverter to report in grid power in the iSolarClod app. Job done! :)
12:15:48.963 ->
12:15:48.963 ->
12:15:48.963 ->
12:15:48.963 -> Sungrow esp32c3_s100_emulator.ino v2.1
12:15:48.963 ->
12:15:48.963 ->
12:15:48.963 -> Connecting to Tola Park
12:15:49.527 -> ...
12:15:50.522 -> WiFi connected
12:15:50.522 -> IP address:
12:15:50.522 -> 192.168.1.198
12:15:50.555 -> Attempting MQTT connection...connected
(Mon 27th Jul 2026 21:54)
Created an emulator ESP32 devicewhich is tested by the working monitor ESP32 device (which was tested talking to a Sungrow S100 meter)
2026-07-27T21:53:40+0100{"tst":"2026-07-27T21:53:40.899401+0100","topic":"home/solar/sungrow/MonTxBytes","qos":0,"retain":0,"payloadlen":18,"payload":"20030009000212b8"}
2026-07-27T21:53:51+0100{"tst":"2026-07-27T21:53:51.504754+0100","topic":"home/solar/sungrow/MonTxBytes","qos":0,"retain":0,"payloadlen":18,"payload":"20030009000212b8"}
2026-07-27T21:53:52+0100{"tst":"2026-07-27T21:53:52.199721+0100","topic":"home/solar/sungrow/EmuRxBytes","qos":0,"retain":0,"payloadlen":18,"payload":"20030009000212b8"}
2026-07-27T21:53:52+0100{"tst":"2026-07-27T21:53:52.324962+0100","topic":"home/solar/sungrow/Emulated_power","qos":0,"retain":0,"payloadlen":5,"payload":220}
2026-07-27T21:53:52+0100{"tst":"2026-07-27T21:53:52.334065+0100","topic":"home/solar/sungrow/EmuTxBytes","qos":0,"retain":0,"payloadlen":20,"payload":"20030400000898cd5b"}
2026-07-27T21:53:53+0100{"tst":"2026-07-27T21:53:53.272921+0100","topic":"home/solar/sungrow/Feeder_power","qos":0,"retain":0,"payloadlen":5,"payload":220}
2026-07-27T21:53:53+0100{"tst":"2026-07-27T21:53:53.282750+0100","topic":"home/solar/sungrow/MonRxBytes","qos":0,"retain":0,"payloadlen":22,"payload":"8:20030400000898cd5b"}
2026-07-27T21:54:04+0100{"tst":"2026-07-27T21:54:04.145330+0100","topic":"home/solar/sungrow/MonTxBytes","qos":0,"retain":0,"payloadlen":18,"payload":"20030009000212b8"}
2026-07-27T21:54:04+0100{"tst":"2026-07-27T21:54:04.636205+0100","topic":"home/solar/sungrow/EmuRxBytes","qos":0,"retain":0,"payloadlen":18,"payload":"20030009000212b8"}
2026-07-27T21:54:04+0100{"tst":"2026-07-27T21:54:04.826091+0100","topic":"home/solar/sungrow/Emulated_power","qos":0,"retain":0,"payloadlen":5,"payload":316}
2026-07-27T21:54:04+0100{"tst":"2026-07-27T21:54:04.829405+0100","topic":"home/solar/sungrow/EmuTxBytes","qos":0,"retain":0,"payloadlen":20,"payload":"20030400000c58cfcb"}
^C(base) coderdojo@rhubarb:~$
So every few requests from the Monitor (made once every 10 secs) it sees the response from the Emulator
'2026-07-27T22:00:10+0100{"tst":"2026-07-27T22:00:10.879481+0100","topic":"home/solar/sungrow/Feeder_power","qos":0,"retain":0,"payloadlen":5,"payload":351}
2026-07-27T22:00:23+0100{"tst":"2026-07-27T22:00:23.306534+0100","topic":"home/solar/sungrow/Feeder_power","qos":0,"retain":0,"payloadlen":5,"payload":156}
2026-07-27T22:00:45+0100{"tst":"2026-07-27T22:00:45.020536+0100","topic":"home/solar/sungrow/Feeder_power","qos":0,"retain":0,"payloadlen":5,"payload":268}
2026-07-27T22:01:07+0100{"tst":"2026-07-27T22:01:07.447752+0100","topic":"home/solar/sungrow/Feeder_power","qos":0,"retain":0,"payloadlen":5,"payload":178}
2026-07-27T22:01:19+0100{"tst":"2026-07-27T22:01:19.742903+0100","topic":"home/solar/sungrow/Feeder_power","qos":0,"retain":0,"payloadlen":5,"payload":266}
2026-07-27T22:02:03+0100{"tst":"2026-07-27T22:02:03.681408+0100","topic":"home/solar/sungrow/Feeder_power","qos":0,"retain":0,"payloadlen":5,"payload":247}
2026-07-27T22:02:16+0100{"tst":"2026-07-27T22:02:16.184611+0100","topic":"home/solar/sungrow/Feeder_power","qos":0,"retain":0,"payloadlen":5,"payload":137}
So next is to connect Monitor to S100 near ESB meter and change Emulator to use values posted to topic "home/solar/sungrow/Feeder_power" rather than the random ones :)
(Sat 25th Jul 2026 16:42)
It is working over RS485 to the SH3.0RS over two wires (A,B). But the CT sensor needs to be between the consumer unit and the ESB meter clamped on the live wire the correct way round. Otherwise it won't know how much energy from the inverter is being consumed within the house.
My plan is to relay this information using ESP32 devices.
The first step is to capture th current comms between the inverter and the S100 meter. I'm expecting the inverter to be sending read commands every few seconds to the meter to which it responds.
I have found a blue USB RS485 dongle and a MAX485 board attached to a Heltec CubeCell Board Plus.
So I'd like to get something lik Modbus Poll running on my Rhubarb Linux laptop first. However..
(base) coderdojo@rhubarb:~$ date
Sat 25 Jul 2026 16:49:26 IST
(base) coderdojo@rhubarb:~$ ldd --version
ldd (Ubuntu GLIBC 2.39-0ubuntu8.7) 2.39
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
(base) coderdojo@rhubarb:~$ cd Downloads/
(base) coderdojo@rhubarb:~/Downloads$ ./"Modbus Poll_0.1.5_amd64.AppImage"
modbus-poll: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.43' not found (required by /tmp/.mount_ModbusLFngMe/usr/lib/libglib-2.0.so.0)
modbus-poll: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.43' not found (required by /tmp/.mount_ModbusLFngMe/usr/lib/libwebkit2gtk-4.1.so.0)
modbus-poll: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.42' not found (required by /tmp/.mount_ModbusLFngMe/usr/lib/libwebkit2gtk-4.1.so.0)
modbus-poll: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.43' not found (required by /tmp/.mount_ModbusLFngMe/usr/lib/libjavascriptcoregtk-4.1.so.0)
modbus-poll: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.43' not found (required by /tmp/.mount_ModbusLFngMe/usr/lib/liblcms2.so.2)
modbus-poll: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.43' not found (required by /tmp/.mount_ModbusLFngMe/usr/lib/libjxl.so.0.11)
(base) coderdojo@rhubarb:~/Downloads$
(base) coderdojo@rhubarb:~$ dmesg -w
[ 299.296263] usb 1-3: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.62
[ 299.296281] usb 1-3: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 299.296289] usb 1-3: Product: USB2.0-Serial
[ 299.346087] usbcore: registered new interface driver usbserial_generic
[ 299.346102] usbserial: USB Serial support registered for generic
[ 299.347405] usbcore: registered new interface driver ch341
[ 299.347423] usbserial: USB Serial support registered for ch341-uart
[ 299.347437] ch341 1-3:1.0: ch341-uart converter detected
[ 299.347902] usb 1-3: ch341-uart converter now attached to ttyUSB0
https://github.com/gavinying/modpoll
(base) coderdojo@rhubarb:~$ pip3 install 'modpoll[serial]'
(base) coderdojo@rhubarb:~$ modpoll
Modpoll v1.6.0 - A New Command-line Tool for Modbus and MQTT
usage: modpoll [-h] [-v] -f CONFIG [CONFIG ...] [-d] [-r RATE] [-1] [--interval INTERVAL] [--tcp TCP] [--tcp-port TCP_PORT]
[--udp UDP] [--udp-port UDP_PORT] [--serial SERIAL] [--serial-baud SERIAL_BAUD]
[--serial-parity {none,odd,even}] [--timeout TIMEOUT] [-o EXPORT] [--mqtt-version {3.1.1,5.0}]
[--mqtt-host MQTT_HOST] [--mqtt-port MQTT_PORT] [--mqtt-clientid MQTT_CLIENTID]
[--mqtt-publish-topic-pattern MQTT_PUBLISH_TOPIC_PATTERN]
[--mqtt-subscribe-topic-pattern MQTT_SUBSCRIBE_TOPIC_PATTERN]
[--mqtt-diagnostics-topic-pattern MQTT_DIAGNOSTICS_TOPIC_PATTERN] [--mqtt-qos {0,1,2}]
[--mqtt-user MQTT_USER] [--mqtt-pass MQTT_PASS] [--mqtt-use-tls] [--mqtt-insecure]
[--mqtt-cacerts MQTT_CACERTS] [--mqtt-tls-version {tlsv1.2,tlsv1.1,tlsv1}] [--mqtt-single]
[--diagnostics-rate DIAGNOSTICS_RATE] [--autoremove] [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
[--timestamp] [--delay DELAY] [--framer {default,ascii,rtu,socket}]
modpoll: error: the following arguments are required: -f/--config
(base) coderdojo@rhubarb:~$ modpoll --serial /dev/ttyUSB0
(base) coderdojo@rhubarb:~$ git clone https://github.com/gavinying/modpoll.git
Cloning into 'modpoll'...
remote: Enumerating objects: 1871, done.
remote: Counting objects: 100% (336/336), done.
remote: Compressing objects: 100% (110/110), done.
remote: Total 1871 (delta 267), reused 226 (delta 226), pack-reused 1535 (from 2)
Receiving objects: 100% (1871/1871), 16.17 MiB | 1.71 MiB/s, done.
Resolving deltas: 100% (1093/1093), done.
(base) coderdojo@rhubarb:~$ cat modpoll/contrib/eniwise/scpms6.csv
device,scpm001,1,,,
poll,holding_register,46001,6,BE_BE,
ref,CT_TYPE,46001,uint16,rw,
ref,CT_RATING,46002,uint16,rw,
ref,DATA_SCALAR,46003,uint16,rw,
ref,ReservedA,46004,uint16,rw,
ref,ReservedB,46005,uint16,rw,
ref,SIGNED_MODE,46006,uint16,rw,
poll,holding_register,46011,92,BE_BE,
ref,Hz,46011,int16,r,Hz,1
ref,V,46012,int16,r,V,1
ref,CH1_A,46013,int16,r,A,1
ref,CH2_A,46014,int16,r,A,1
ref,CH3_A,46015,int16,r,A,1
ref,CH4_A,46016,int16,r,A,1
ref,CH5_A,46017,int16,r,A,1
ref,CH6_A,46018,int16,r,A,1
ref,CH1_kWh,46019,uint32,r,kWh,1
ref,CH2_kWh,46021,uint32,r,kWh,1
ref,CH3_kWh,46023,uint32,r,kWh,1
ref,CH4_kWh,46025,uint32,r,kWh,1
ref,CH5_kWh,46027,uint32,r,kWh,1
ref,CH6_kWh,46029,uint32,r,kWh,1
ref,CH1_kWh_P,46031,uint32,r,kWh,1
ref,CH2_kWh_P,46033,uint32,r,kWh,1
ref,CH3_kWh_P,46035,uint32,r,kWh,1
ref,CH4_kWh_P,46037,uint32,r,kWh,1
ref,CH5_kWh_P,46039,uint32,r,kWh,1
ref,CH6_kWh_P,46041,uint32,r,kWh,1
ref,CH1_kWh_N,46043,uint32,r,kWh,1
ref,CH2_kWh_N,46045,uint32,r,kWh,1
ref,CH3_kWh_N,46047,uint32,r,kWh,1
ref,CH4_kWh_N,46049,uint32,r,kWh,1
ref,CH5_kWh_N,46051,uint32,r,kWh,1
ref,CH6_kWh_N,46053,uint32,r,kWh,1
ref,CH1_kVARh,46055,uint32,r,kVARh,1
ref,CH2_kVARh,46057,uint32,r,kVARh,1
ref,CH3_kVARh,46059,uint32,r,kVARh,1
ref,CH4_kVARh,46061,uint32,r,kVARh,1
ref,CH5_kVARh,46063,uint32,r,kVARh,1
ref,CH6_kVARh,46065,uint32,r,kVARh,1
ref,CH1_kVARh_P,46067,uint32,r,kVARh,1
ref,CH2_kVARh_P,46069,uint32,r,kVARh,1
ref,CH3_kVARh_P,46071,uint32,r,kVARh,1
ref,CH4_kVARh_P,46073,uint32,r,kVARh,1
ref,CH5_kVARh_P,46075,uint32,r,kVARh,1
ref,CH6_kVARh_P,46077,uint32,r,kVARh,1
ref,CH1_kVARh_N,46079,uint32,r,kVARh,1
ref,CH2_kVARh_N,46081,uint32,r,kVARh,1
ref,CH3_kVARh_N,46083,uint32,r,kVARh,1
ref,CH4_kVARh_N,46085,uint32,r,kVARh,1
ref,CH5_kVARh_N,46087,uint32,r,kVARh,1
ref,CH6_kVARh_N,46089,uint32,r,kVARh,1
ref,CH1_kVA,46091,int16,r,kVA,1
ref,CH2_kVA,46092,int16,r,kVA,1
ref,CH3_kVA,46093,int16,r,kVA,1
ref,CH4_kVA,46094,int16,r,kVA,1
ref,CH5_kVA,46095,int16,r,kVA,1
ref,CH6_kVA,46096,int16,r,kVA,1
ref,CH1_PF,46097,int16,r,,1
ref,CH2_PF,46098,int16,r,,1
ref,CH3_PF,46099,int16,r,,1
ref,Reserved1,46100,int16,r,
ref,Reserved2,46101,int16,r,
ref,Reserved3,46102,int16,r,
(base) coderdojo@rhubarb:~$ modpoll --serial /dev/ttyUSB0 --serial-baud 9600 --config modpoll/contrib/eniwise/scpms6.csv
Modpoll v1.6.0 - A New Command-line Tool for Modbus and MQTT
2026-07-25 17:00:44,347 | I | modpoll.main | No MQTT host specified, skip MQTT setup.
2026-07-25 17:00:44,347 | I | modpoll.modbus_task | Loading config from: modpoll/contrib/eniwise/scpms6.csv
2026-07-25 17:00:44,348 | I | modpoll.modbus_task | Added 1 device(s)...
2026-07-25 17:00:44,348 | I | modpoll.main | Loaded 1 Modbus config(s).
2026-07-25 17:00:44,348 | I | modpoll.main | === Modpoll is polling at rate:10.0s, actual:10.0s ===
^C2026-07-25 17:00:55,487 | I | modpoll.main | Exiting /home/coderdojo/anaconda3/bin/modpoll
2026-07-25 17:00:56,363 | E | pymodbus.logging | No response received after 3 retries, continue with next request
2026-07-25 17:00:56,363 | E | modpoll.modbus_task | Modbus exception: scpm001 3 46001 6
Device: scpm001
+-------------+-------+-------+
| Reference | Value | Unit |
+-------------+-------+-------+
| CT_TYPE | None | |
| CT_RATING | None | |
| DATA_SCALAR | None | |
| ReservedA | None | |
| ReservedB | None | |
| SIGNED_MODE | None | |
| Hz | None | Hz |
| V | None | V |
| CH1_A | None | A |
| CH2_A | None | A |
| CH3_A | None | A |
| CH4_A | None | A |
| CH5_A | None | A |
| CH6_A | None | A |
| CH1_kWh | None | kWh |
| CH2_kWh | None | kWh |
| CH3_kWh | None | kWh |
| CH4_kWh | None | kWh |
| CH5_kWh | None | kWh |
| CH6_kWh | None | kWh |
| CH1_kWh_P | None | kWh |
| CH2_kWh_P | None | kWh |
| CH3_kWh_P | None | kWh |
| CH4_kWh_P | None | kWh |
| CH5_kWh_P | None | kWh |
| CH6_kWh_P | None | kWh |
| CH1_kWh_N | None | kWh |
| CH2_kWh_N | None | kWh |
| CH3_kWh_N | None | kWh |
| CH4_kWh_N | None | kWh |
| CH5_kWh_N | None | kWh |
| CH6_kWh_N | None | kWh |
| CH1_kVARh | None | kVARh |
| CH2_kVARh | None | kVARh |
| CH3_kVARh | None | kVARh |
| CH4_kVARh | None | kVARh |
| CH5_kVARh | None | kVARh |
| CH6_kVARh | None | kVARh |
| CH1_kVARh_P | None | kVARh |
| CH2_kVARh_P | None | kVARh |
| CH3_kVARh_P | None | kVARh |
| CH4_kVARh_P | None | kVARh |
| CH5_kVARh_P | None | kVARh |
| CH6_kVARh_P | None | kVARh |
| CH1_kVARh_N | None | kVARh |
| CH2_kVARh_N | None | kVARh |
| CH3_kVARh_N | None | kVARh |
| CH4_kVARh_N | None | kVARh |
| CH5_kVARh_N | None | kVARh |
| CH6_kVARh_N | None | kVARh |
| CH1_kVA | None | kVA |
| CH2_kVA | None | kVA |
| CH3_kVA | None | kVA |
| CH4_kVA | None | kVA |
| CH5_kVA | None | kVA |
| CH6_kVA | None | kVA |
| CH1_PF | None | |
| CH2_PF | None | |
| CH3_PF | None | |
| Reserved1 | None | |
| Reserved2 | None | |
| Reserved3 | None | |
+-------------+-------+-------+
(base) coderdojo@rhubarb:~$ ^C
(base) coderdojo@rhubarb:~$ date
Sat 25 Jul 2026 17:00:59 IST
(base) coderdojo@rhubarb:~$
Can I set this up to interoogate my simulation of the Sungrow S100 meter?
https://github.com/Linux-RISC/Sungrow-Meter-cheater/issues/1
(25/7/26 12:38)
/home/coderdojo/Arduino/M5 Stamp/BLE_client_v1_3/BLE_client_v1_3.ino
12:38:15.135 ->
12:38:15.135 -> Looking for BLE device name [BR2262e-s]..
12:38:15.202 -> A BLE Advertised Device named [SP10S009-L8S-100A-B-U] found
12:38:15.235 -> A BLE Advertised Device named [BR2262e-s] found
12:38:15.235 -> Desired BLE Device [BR2262e-s] found
12:38:18.746 -> We are now connected to the BLE Server.
12:38:18.746 -> 0xdd, 0x03, 0x00, 0x19, 0x0a, 0x42, 0x00, 0x00, 0x10, 0x28, 0x27, 0x10, 0x00, 0x7d, 0x2a, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x2b, 0x03, 0x08, 0x01, 0x0b, 0x83, 0xfc, 0xeb, 0x77,
12:38:18.746 -> Battery current= 0.00 I
12:38:18.746 -> Battery balance=0
12:38:18.746 -> (Not being read!)Battery temperature=0.000000
12:38:18.746 -> messageMask=3
12:38:18.779 -> A BLE Advertised Device named [SP10S009-L8S-100A-B-U] found
12:38:18.779 -> A BLE Advertised Device named [BR2262e-s] found
12:38:18.779 -> Desired BLE Device [BR2262e-s] found
12:38:21.823 -> We are now connected to the BLE Server.
12:38:21.823 -> 0xdd, 0x04, 0x00, 0x10, 0x0c, 0xd4, 0x0c, 0xd3, 0x0c, 0xd3, 0x0c, 0xd2, 0x0c, 0xd2, 0x0c, 0xd2, 0x0c, 0xd3, 0x0c, 0xd4, 0xf8, 0xf9, 0x77,
12:38:21.823 -> Cell 1=3284 mV, Cell 2=3283 mV, Cell 3=3283 mV, Cell 4=3282 mV, Cell 5=3282 mV, Cell 6=3282 mV, Cell 7=3283 mV, Cell 8=3284 mV,
12:38:21.823 -> Total volts=26.26 V
12:38:21.823 -> messageMask=7
(25/7/26 10:39)
Just had some success with a M5 Stamp scanning near the batteries..
/home/coderdojo/Arduino/M5 Stamp/Scan/Scan.io
10:49:29.175 -> Advertised Device: Name: SP10S009-L8S-100A-B-U, Address: a4:c1:37:10:00:d2, manufacturer data: d2001037c1a4, serviceUUID: 0000ff00-0000-1000-8000-00805f9b34fb, rssi: -67
10:49:29.175 -> Advertised Device: Name: , Address: 6e:2e:2e:be:f1:fe, manufacturer data: e000086aca8c48f4, serviceUUID: 0000fe9f-0000-1000-8000-00805f9b34fb, rssi: -83, serviceData:
10:49:29.473 -> Advertised Device: Name: BR2262e-s, Address: 04:7f:0e:00:1a:7c, manufacturer data: 02a7dc3855a4, serviceUUID: 0000ff00-0000-1000-8000-00805f9b34fb, serviceUUID: 6e40ff00-b5a3-f393-e0a9-e50e24dcca9e, rssi: -69
10:49:30.536 -> Advertised Device: Name: , Address: 40:00:4d:d3:2d:27, serviceUUID: 0000feed-0000-1000-8000-00805f9b34fb, rssi: -67, serviceData:
10:49:30.669 -> Advertised Device: Name: DL-401804012334, Address: 40:18:04:01:23:34, manufacturer data: 020316401804012334444c, rssi: -84
10:49:32.028 -> Advertised Device: Name: , Address: 55:8d:e4:9f:15:a7, serviceUUID: 0000fef3-0000-1000-8000-00805f9b34fb, rssi: -105, serviceData: J#CN2H2X⸮⸮⸮m⸮gLnc⸮)g⸮aB$
10:49:32.028 -> Advertised Device: Name: , Address: 40:00:59:aa:b7:e0, serviceUUID: 0000feed-0000-1000-8000-00805f9b34fb, rssi: -76, serviceData:
10:49:34.153 -> Devices found: 7
10:49:34.153 -> Scan done!
I will next see if I can get battery info!
(20/7/26)
I have three 24v nominal LFP batteries.
Can I use Python3 code to access each over BLE ?
First, "SP10S009-L8S-100A-B-U" A4:C1:37:10:00:D2
Second, "BR2262e-s" 04:7F:0E:00:1A:7C
Third. "????" xx:xx (daly BMS)
Starting with with First do I write to characteristic 0xFF01 of service 0xFF00 ?
./gatt-python could discover but not connect to "B" or "S"
pi@sionnach:~/gatt-python $ python3 ./discover.py
Discovered [41:3c:6e:a0:75:f1] 41-3C-6E-A0-75-F1
Discovered [40:00:59:aa:b7:e0] 40-00-59-AA-B7-E0
Discovered [a4:c1:37:10:00:d2] SP10S009-L8S-100A-B-U
Discovered [a4:c1:37:10:00:d2] SP10S009-L8S-100A-B-U
Discovered [04:7f:0e:00:1a:7c] BR2262e-s
Discovered [a4:c1:37:10:00:d2] SP10S009-L8S-100A-B-U
Discovered [a4:c1:37:10:00:d2] SP10S009-L8S-100A-B-U
pi@sionnach:~/gatt-python $
pi@sionnach:~/gatt-python $ python3 ./connects_S.py
[a4:c1:37:10:00:d2] Connection failed: Device does not exist, check adapter name and MAC address.
(2026_05_bleak) pi@sionnach:~/2026_05_bleak also failed.
2026_05_bleak) pi@sionnach:~/2026_05_bleak $ nano scanner_S.py
(2026_05_bleak) pi@sionnach:~/2026_05_bleak $
(2026_05_bleak) pi@sionnach:~/2026_05_bleak $ python3 ./scanner_S.py
Traceback (most recent call last):
File "/home/pi/2026_05_bleak/./scanner_S.py", line 37, in <module>
asyncio.run(main(address))
File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
This directory was also no good...
(24v_battery) pi@sionnach:~/24v_battery/bin $ ./gattctl
Module 'dbus' not found
Please run: sudo apt-get install python3-dbus
See also: https://github.com/getsenic/gatt-python#installing-gatt-sdk-for-python
(24v_battery) pi@sionnach:~/24v_battery/bin $
(24v_battery) pi@sionnach:~/jbdtool/build $
(24v_battery) pi@sionnach:~/jbdtool/build $ ls ..
battery.h build.h changelog dsfuncs.h jbd_info.c list.h module.h pack.h README.md utils.h
bt.c can.c config.h ip.c jbd_info.h main.c mqtt.c parson.c serial.c uuid.h
buffer.h cfg.c daemon.c jbd.c LICENSE Makefile mqtt.h parson.h si.h worker.h
build cfg.h debug.h jbd.h list.c module.c mybmm.h r utils.c
(24v_battery) pi@sionnach:~/jbdtool/build $
Also no good
Also no good
(JBD_BMS_BTLE) pi@sionnach:~/JBD_BMS_BTLE $ cd ..
Didn't try aiobmsble as it looks incomplete as no runnable .py script!
Didn't try ANT_BMS as it uses serial port
smart_bms also failed..
docs dumb_test.py examples LICENSE.txt README.md requirements.txt smart_bms test.py
pi@sionnach:~/smart_bms $ vim test.py
pi@sionnach:~/smart_bms $ python3 ./test.py
('A4:C1:37:10:00:D2', 'SP10S009-L8S-100A-B-U', 'Jikong')
WALSH: Running bluetootchctl command <disconnect A4:C1:37:10:00:D2>
WALSH: Running bluetootchctl command <power on>
Traceback (most recent call last):
File "/usr/lib/python3.11/asyncio/tasks.py", line 490, in wait_for
return fut.result()
^^^^^^^^^^^^
File "/home/pi/smart_bms/smart_bms/TransportBLE.py", line 70, in _read_inner
data = [await self._read_queue.get()]
pi@sionnach:~/solar-bt-monitor $ nano solar-bt-monitor.ini
pi@sionnach:~/solar-bt-monitor $ nano solar-bt-monitor.ini.B
pi@sionnach:~/solar-bt-monitor $
pi@sionnach:~/solar-bt-monitor $ python3 ./solar-bt-monitor.py
DEBUG: [CONFIG] mac_addr: A4:C1:37:10:00:D2
DEBUG: [CONFIG] alias: SP10S009-L8S-100A-B-U
DEBUG: [CONFIG] adapter: hci0
DEBUG: [CONFIG] reconnect: True
DEBUG: [CONFIG] continuous_monitor: True
DEBUG: [CONFIG] data_read_interval: 30
DEBUG: [CONFIG] logger_type: prometheus
INFO: Starting Prometheus Server
INFO: Adapter status - Powered: True
INFO: Starting discovery...
INFO: Devices found: 5
INFO: Found bt1 device SP10S009-L8S-100A-B-U [A4:C1:37:10:00:D2]
INFO: Found bt1 device SP10S009-L8S-100A-B-U [a4:c1:37:10:00:d2]
DEBUG: Found. So connecting...
DEBUG: _connect() run manager...
INFO: [a4:c1:37:10:00:d2] Discovered, alias = SP10S009-L8S-100A-B-U
INFO: [A4:C1:37:10:00:D2] Connected
INFO: [a4:c1:37:10:00:d2] Discovered, alias = SP10S009-L8S-100A-B-U
INFO: [A4:C1:37:10:00:D2] Resolved services
DEBUG: resolved services
DEBUG: request_data...
DEBUG: create_read_request 256 => [255, 3, 1, 0, 0, 34, 209, 241]
ERROR: Exception in handler for D-Bus signal:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 218, in maybe_handle_message
self._handler(*args, **kwargs)
File "/home/pi/.local/lib/python3.11/site-packages/gatt/gatt_linux.py", line 398, in properties_changed
self.services_resolved()
File "/home/pi/solar-bt-monitor/SolarDevice.py", line 63, in services_resolved
self.resolved_callback()
File "/home/pi/solar-bt-monitor/BTOneApp.py", line 95, in on_resolved
self.request_data()
File "/home/pi/solar-bt-monitor/BTOneApp.py", line 91, in request_data
self.device.characteristic_write_value(request)
File "/home/pi/solar-bt-monitor/SolarDevice.py", line 79, in characteristic_write_value
self.write_characteristic.write_value(value)
^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'SolarDevice' object has no attribute 'write_characteristic'
INFO: [a4:c1:37:10:00:d2] Discovered, alias = SP10S009-L8S-100A-B-U
^CDEBUG: _connect() keyboard exception...
INFO: gracefully_exit
INFO: Exit: Disconnecting device: SP10S009-L8S-100A-B-U [A4:C1:37:10:00:D2]
pi@sionnach:~/solar-bt-monitor $
pi@sionnach:~/solar-bt-monitor $
pi@sionnach:~/solar-bt-monitor $ date
Mon 20 Jul 17:40:23 IST 2026
pi@sionnach:~/solar-bt-monitor $ # Got further may be worth debugging?
pi@sionnach:~/solar-bt-monitor $
pi@sionnach:~/solar-bt-monitor $
Or should I use a wired connection to each BMS ? Scary
What does Android app make of them ?
daly
jbd
xiaoxiang
Hurrah!!!!
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ vim jbd_bms_bleak2.py
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ vim ./jbd_bms_bleak2.py
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ python3 ./jbd_bms_bleak2.py
INFO:__main__:Found device: SP10S009-L8S-100A-B-U (A4:C1:37:10:00:D2)
INFO:__main__:Updating BMS data...
INFO:__main__:BMS data: {'voltage': 25.99,
'current': 0.0,
'cycle_charge': 0.14,
'design_capacity': 100,
'cycles': 584,
'balancer': 0,
'problem_code': 4096,
'battery_level': 0,
'chrg_mosfet': True,
'dischrg_mosfet': False,
'temp_sensors': 2,
'temp_values': [TempSensor(22.6,
<T.GENERIC: 0>),
TempSensor(22.7,
<T.GENERIC: 0>)],
'cell_voltages': [3.249,
3.25,
3.247,
3.249,
3.248,
3.248,
3.248,
3.253],
'delta_voltage': 0.006,
'cell_count': 8,
'cycle_capacity': 3.639,
'power': 0.0,
'battery_charging': False,
'temperature': 22.65,
'problem': True}
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ date
Mon 20 Jul 2026 19:16:20 IST
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
Now lets try that on a Raspberry Pi!
Pythoin version only 3.11 needs to be at least 3.12
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ python3 ./jbd_S_bms_bleak.py
INFO:__main__:Found device: SP10S009-L8S-100A-B-U (A4:C1:37:10:00:D2)
INFO:__main__:Updating BMS data...
INFO:__main__:BMS data: {'voltage': 25.99,
'current': 0.0,
'cycle_charge': 0.14,
'design_capacity': 100,
'cycles': 584,
'balancer': 0,
'problem_code': 4096,
'battery_level': 0,
'chrg_mosfet': True,
'dischrg_mosfet': False,
'temp_sensors': 2,
'temp_values': [TempSensor(22.6,
<T.GENERIC: 0>),
TempSensor(22.7,
<T.GENERIC: 0>)],
'cell_voltages': [3.249,
3.25,
3.247,
3.249,
3.248,
3.248,
3.248,
3.253],
'delta_voltage': 0.006,
'cell_count': 8,
'cycle_capacity': 3.639,
'power': 0.0,
'battery_charging': False,
'temperature': 22.65,
'problem': True}
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ nano jbd_B_bms_bleak.py
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ vim jbd_B_bms_bleak.py
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ python3 ./jbd_B_bms_bleak.py
ERROR:root:Device 'BR2262e-s' not found.
(jbd_bms_bleak) (base) coderdojo@rhubarb:~/jbd_bms_bleak$ date
Mon 20 Jul 2026 19:27:29 IST
https://raspberrytips.com/install-latest-python-raspberry-pi/
Trying to build Python 3.12.g on sionnach to run aiobmsble!
pi@sionnach:~/Python-3.13.6 $ sudo make
..
e.o Modules/_weakref.o Modules/_abc.o Modules/_functoolsmodule.o Modules/_localemodule.o Modules/_operator.o Modules/_stat.o Modules/symtablemodule.o Modules/pwdmodule.o Modules/getpath.o Python/frozen.o -ldl -lm
sed -e "s,/usr/bin/env python3,/usr/local/bin/python3.13," < ./Tools/scripts/idle3 > build/scripts-3.13/idle3.13
sed -e "s,/usr/bin/env python3,/usr/local/bin/python3.13," < ./Tools/scripts/pydoc3 > build/scripts-3.13/pydoc3.13
The following modules are *disabled* in configure script:
_sqlite3
The necessary bits to build these optional modules were not found:
_bz2 _ctypes _ctypes_test
_curses _curses_panel _dbm
_gdbm _lzma _tkinter
_uuid readline
To find the necessary bits, look in configure.ac and config.log.
Checked 112 modules (33 built-in, 66 shared, 1 n/a on linux-aarch64, 1 disabled, 11 missing, 0 failed on import)
pi@sionnach:~/Python-3.13.6 $
pi@sionnach:~/Python-3.13.6 $ sudo make install
..
Looking in links: /tmp/tmpawanvuou
Processing /tmp/tmpawanvuou/pip-25.2-py3-none-any.whl
Installing collected packages: pip
Successfully installed pip-25.2
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
pi@sionnach:~/Python-3.13.6 $
pi@sionnach:~/Python-3.13.6 $
pi@sionnach:~/Python-3.13.6 $ ls -al python
-rwxr-xr-x 1 root root 32817424 Jul 20 23:07 python
pi@sionnach:~/Python-3.13.6 $ date
Tue 21 Jul 10:06:15 IST 2026
pi@sionnach:~/Python-3.13.6 $ ./python
Fatal Python error: Failed to import encodings module
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'
Current thread 0x0000007f8e77d040 (most recent call first):
<no Python frame>
pi@sionnach:~/Python-3.13.6 $
pi@sionnach:~/Python-3.13.6 $
So still cannot execute it!