This is a python script that runs in a container (standalone execution is possible) and reads data from one or multiple V2 / V16 Seplos BMS (also called 10C and 10E) via a remote or local RS485 connection and publishes its/their stats to MQTT.
Home Assistant Sensor auto discovery can be enabled (optional)
NOTE: There is now also a Home Assistant Add-on version. This project will continue to be maintained in parallel for all those who do not use Home Assistant or who want to use and analyze the data elsewhere.
- A remote or local RS485 device (the Waveshare 2-CH RS485 to ETH gateway has been tested)
- For MULTIPLE packs: A self-crimped cable with multiple plugs or one or more splitters (this one works for me) – one of which always needs to be modified (more information below)
- For a SINGLE pack: A regular patch-cable from one of the two RS485-ports of the pack to the terminals of your RS485 device
- One or multiple Seplos BMS V2 / V16
- A configured and running MQTT broker
Carefully check the provided wiring scheme below (the PINK lines). There are two ways to approach the same result:
- A single, self-crimped cable with multiple plugs, crimped as shown in the picture below (recommended).
- Two or more splitters, one of which need to be modified (easier if you don't like crimping) – if you have two packs, you need two splitters, three packs require three splitters and so on.
When using splitters, the first splitter (the one that connects to the Master's CAN-port) needs to be modified like so:
- On one of the two outlets cut all but the three pins of the RS485-part (check the PINK lines in the image below)
- On the other outlet cut all but the two pins of the CAN-part (check the PINK lines in the image below)
Example for four packs:
- Connect the first, modified splitter to the CAN-Port (NOT one of the RS485!) of the Master
- The outlet with only the two CAN-pins connect to your inverter using a regular patch-cable.
- The outlet with only the three RS485-pins connect to the first slave using a regular patch-cable.
- Connect the second, unmodified splitter to the CAN-Port (NOT one of the RS485!) of the first Slave
- Use one outlet to connect the regular patch-cable, coming from the Master
- Use the other outlet to connect a regular patch-cable to the second Slave
- Connect the third, unmodified splitter to the CAN-Port (NOT one of the RS485!) of the second Slave
- Use one outlet to connect the regular patch-cable, coming from the first Slave
- Use the other outlet to connect a regular patch-cable to the third Slave
- Connect the fourth, unmodified splitter to the CAN-Port (NOT one of the RS485!) of the third Slave
- Use one outlet to connect the regular patch-cable, coming from the second Slave
- Use the other outlet to connect a regular patch-cable to your RS485-device (the one that is used to read the data, i.e. the Waveshare 2-CH RS485 to ETH gateway or similar)
1/8=>RS485-B2/7=>RS485-A4=>CAN-H5=>CAN-L3/6=>GND
orange=>RS485-Aorange-white=>RS485-Bgreen-white=>GND
When using a regular patch-cable, cut one of its connectors and take the orange, orange-white and green-white wires to crimp a terminal onto each of them. Then connect it to the waveshare device like so:
orange=>RS485-Aorange-white=>RS485-Bgreen-white=>PE
- Configure and setup an MQTT broker with a user and password
- Configure your RS485 device. For the Waveshare 2-CH RS485 to ETH gateway this would most importantly be
IP Mode: Static(must be a reachable IP within your network),Port: 4196(default),Work Mode: TCP Server,Transfer Protocol: None,Baud Rate: 9600(for MULTIPLE packs) orBaud Rate: 19200(for a SINGLE pack). - Configure and setup something that can run a container (when using the container-image) or python script (when just using the script)
- Set the required ENV-vars
- Run the Docker Image, for example like this:
- For 1 master and 1 slave, i.e. two packs using ENV-vars:
docker run -itd \
--restart unless-stopped \
-e RS485_REMOTE_IP="192.168.1.200" \
-e RS485_REMOTE_PORT="4196" \
-e SERIAL_INTERFACE=/tmp/vcom0 \
-e NUMBER_OF_PACKS=2 \
-e MIN_CELL_VOLTAGE=2.500 \
-e MAX_CELL_VOLTAGE=3.650 \
-e MQTT_HOST=192.168.1.100 \
-e MQTT_PORT=1883 \
-e MQTT_USERNAME=seplos-mqtt \
-e MQTT_PASSWORD=my-secret-password \
-e MQTT_TOPIC=seplos \
-e MQTT_UPDATE_INTERVAL=1 \
-e ENABLE_HA_DISCOVERY_CONFIG=true \
-e INVERT_HA_DIS_CHARGE_MEASUREMENTS=true \
-e HA_DISCOVERY_PREFIX=homeassistant \
-e LOGGING_LEVEL=info \
--name seplos-mqtt-rs485 \
ghcr.io/privatecoder/seplos-mqtt-remote-rs485:v4.0.2- To run the script without socat / remote RS485 but local connections, don't set the
RS485_REMOTE_IPandRS485_REMOTE_PORTENV-vars, i.e:
docker run -itd \
--restart unless-stopped \
-e SERIAL_INTERFACE=/path/to/your/serialport \
-e NUMBER_OF_PACKS=2 \
-e MIN_CELL_VOLTAGE=2.500 \
-e MAX_CELL_VOLTAGE=3.650 \
-e MQTT_HOST=192.168.1.100 \
-e MQTT_PORT=1883 \
-e MQTT_USERNAME=seplos-mqtt \
-e MQTT_PASSWORD=my-secret-password \
-e MQTT_TOPIC=seplos \
-e MQTT_UPDATE_INTERVAL=1 \
-e ENABLE_HA_DISCOVERY_CONFIG=true \
-e INVERT_HA_DIS_CHARGE_MEASUREMENTS=true \
-e HA_DISCOVERY_PREFIX=homeassistant \
-e LOGGING_LEVEL=info \
--name seplos-mqtt-rs485 \
ghcr.io/privatecoder/seplos-mqtt-remote-rs485:v4.0.2Available ENV-vars are:
-
RS485_REMOTE_IP(IP of the remote RS485 device) -
RS485_REMOTE_PORT(Port of the remote RS485 device) -
MQTT_HOST(MQTT Broker IP, default:192.168.1.100) -
MQTT_PORT(MQTT Broker Port, default:1883) -
MQTT_USERNAME(MQTT Broker Username, default:seplos-mqtt) -
MQTT_PASSWORD(MQTT Broker Password, default:my-secret-password) -
MQTT_TOPIC(MQTT Broker Topic to publish to, default:seplos) -
MQTT_UPDATE_INTERVAL(Time to wait (in seconds) in between each circular reading to update stats in MQTT,0=> continuous reading, default:0) -
ENABLE_HA_DISCOVERY_CONFIG(Enable Home Assistant sensor config creation via MQTT for auto-discovery, default:true) -
INVERT_HA_DIS_CHARGE_MEASUREMENTS(Inverts the values of the charging and discharging sensors in Home Assistant, default:false) -
HA_DISCOVERY_PREFIX(Home Assistant Topic to publish the config creations to, default:homeassistant) -
NUMBER_OF_PACKS(Fetch data of n packs, default:1) -
MIN_CELL_VOLTAGE(Min cell voltage as base calculation constant, as this cannot be read from the BMS, default:2.500) -
MAX_CELL_VOLTAGE(Max cell voltage as base calculation constant, as this cannot be read from the BMS, default:3.650) -
SERIAL_INTERFACE(Local RS485 device path, default:/tmp/vcom0) -
LOGGING_LEVEL(Logging level, available modes areinfo,erroranddebug, default:info)
Setting RS485_REMOTE_IP and RS485_REMOTE_PORT starts the docker image with socat, binding your remote RS485 device´s RS485 ports locally to vcom0 (used by default in this script).
Not defining those will just start the script, however SERIAL_INTERFACE must match your existing serial-device – either passed to the container directly or using the privileged-flag (not recommended).
- Clone the project
- Make sure to have Python v3.10 or later installed
- Set ENV-vars to your needs
- Run the script, i.e.
python3 fetch_bms_data.py
- If
ENABLE_HA_DISCOVERY_CONFIGis set toTRUE, it triggers the publishing of auto discovery sensor configs in Home Assistant. The devices should be added automatically.
- The provided
ha-lovelace/lovelace.yamlis using custom add-ons likemushroom-template-card,entity-progress-card,button-card,bar-card,card_modandbrowser_mod(can be installed via HACS) and allows for a first start (value-based colors are based on EVE LF280K datasheets and measurements and personal preferences).