ESPHome custom component for monitoring PYTES LiFePO4 battery systems π via RS232 serial port. This application runs on an ESP32 board π‘, reads the battery console port and integrates automatically with Home Assistant π .
Support for up to 6οΈβ£ individual battery modules with real-time monitoring of voltage β‘, current π, temperature π‘οΈ, SoC π, and status π₯.
- π Real-time monitoring of battery bank and individual battery metrics
- π Multi-battery support (up to 6 battery modules)
- π‘οΈ Temperature monitoring for each battery module
- β‘ Power flow tracking (voltage, current, power)
- π State of Charge (SoC) percentage for bank and individual batteries
- π₯ Status monitoring (operational state, voltage status, alerts)
- π Native Home Assistant integration via ESPHome API
- π Built-in web server for standalone monitoring
- π Configurable polling interval (default 30s)
- π Serial number and firmware tracking for each battery
- π Configurable battery capacity for accurate calculations
- β Pytes V5Β° (48V 5kWh module)
- β Pytes E-Box-48100R (48V 10kWh system)
- β Pytes E-Box-12100 (12V systems)
- β Pytes Pi-LV1 (Low voltage systems)
π‘ Note: This component should work with any Pytes battery system that supports the RS232 console protocol.
- β ESP32-DevKitC
- β ESP32-WROOM-32
- β ESP32-WROVER
- β Any ESP32 board with ESP-IDF framework support (minimum chip revision 3.1)
| Component | Quantity | Description | Example/Notes |
|---|---|---|---|
| π₯οΈ ESP32 DevKit | 1 | ESP32 development board | Minimum chip revision 3.1 |
| π Pytes Battery | 1-6 | LiFePO4 battery system | With RS232 console port |
| π RS232-to-TTL Module | 1 | MAX3232 or equivalent | 3.3V logic level |
| π Dupont Wires | ~10 | Jumper cables | Female-to-female |
| π USB Cable | 1 | For ESP32 power/programming | Micro-USB or USB-C |
| β‘ Power Supply | 1 | 5V power adapter | Optional for standalone operation |
- π¦ Enclosure - To protect the ESP32 and connections
- π DIN rail mount - For professional installation
- π‘ Status LEDs - For visual monitoring
βββββββββββββββββββ ββββββββββββββββββββ
β ESP32 DevKit β β MAX3232 Module β
β π₯οΈ β β (RS232-TTL) β
βββββββββββββββββββ€ ββββββββββββββββββββ€
β GPIO16 (RX) ββββΌβββββββββββββββ€ TX (TTL out) β
β GPIO17 (TX) ββββΌβββββββββββββββ€ RX (TTL in) β
β GND ββββΌβββββββββββββββ€ GND β
β 3.3V ββββΌβββββββββββββββ€ VCC (3.3V) β
βββββββββββββββββββ ββββββββββββββββββββ
β
β π DB9 cable
βΌ
ββββββββββββββββββββ
β Pytes Battery β
β π RS232 Console β
ββββββββββββββββββββ
| ESP32 GPIO | Function | MAX3232 Pin | Pytes Console |
|---|---|---|---|
| π GPIO16 | UART RX | TX (TTL) | TX (RS232) |
| π GPIO17 | UART TX | RX (TTL) | RX (RS232) |
| β« GND | Ground | GND | GND |
| π΄ 3.3V | Power | VCC | - |
- β‘ Baud Rate: 115200
- π Data Bits: 8
- β Parity: None
- π Stop Bits: 1
- π Flow Control: None
Add this to your ESPHome YAML configuration:
external_components:
- source:
type: git
url: https://github.com/s3pt1c0/Pytes_ESP32_RS232
ref: main
components: [ pytes_rs232 ]
refresh: 1d1οΈβ£ Clone or download this repository
2οΈβ£ Copy the Components/pytes_rs232 folder to your ESPHome configuration directory:
mkdir -p /config/esphome/components
cp -r Pytes_ESP32_RS232/Components/pytes_rs232 /config/esphome/components/3οΈβ£ Reference in your YAML:
external_components:
- source:
type: local
path: componentsCreate a file pytes-esp32.yaml:
substitutions:
device_name: pytes-esp32
friendly_name: πPytes Battery Monitorπ
poll_s: "30" # β±οΈ Polling interval in seconds
capacity_ah: "100" # π Battery capacity in Ah
num_batts: "6" # π’ Number of battery modules
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
comment: "Pytes Battery Monitoring via RS232"
esp32:
board: esp32dev
framework:
type: esp-idf
advanced:
minimum_chip_revision: "3.1"
# π Enable logging
logger:
level: INFO
# π Enable Web Server (optional)
web_server:
port: 80
# π Enable Home Assistant API
api:
encryption:
key: "YOUR_ENCRYPTION_KEY_HERE"
# π Enable OTA updates
ota:
- platform: esphome
password: "YOUR_OTA_PASSWORD_HERE"
# π‘ WiFi configuration
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# π Enable fallback hotspot (optional)
ap:
ssid: "${device_name} Fallback"
password: "fallback12345"
# π UART Configuration for Pytes RS232
uart:
id: uart_pytes
tx_pin: GPIO17
rx_pin: GPIO16
baud_rate: 115200
data_bits: 8
parity: NONE
stop_bits: 1
# π Pytes RS232 Component Configuration
pytes_rs232:
uart_id: uart_pytes
num_batteries: ${num_batts}
update_interval: ${poll_s}s
capacity_ah: ${capacity_ah}
# π Summary sensors (entire battery bank)
summary:
voltage: sys_voltage
current: sys_current
temperature: sys_temp_f
coulomb: sys_coulomb
basic_status: sys_basic_status
# π Individual battery sensors (repeat for each battery)
batteries:
- voltage: b1_voltage
current: b1_current
temperature: b1_temp_f
coulomb: b1_coulomb
barcode: b1_barcode
devtype: b1_devtype
firm_version: b1_firmver
basic_status: b1_basic_status
volt_status: b1_volt_status
# ... repeat for batteries 2-6Create or edit secrets.yaml:
wifi_ssid: "YourWiFiSSID"
wifi_password: "YourWiFiPassword"| Sensor Name | Type | Unit | Description |
|---|---|---|---|
β‘ Bank Voltage β οΈ |
Number | V | Total battery bank voltage |
π Bank Currentβ‘ |
Number | A | Total bank current (+ charging, - discharging) |
π‘οΈ Bank Tempπ‘οΈ |
Number | Β°F | Average bank temperature |
π Bank SoCπ |
Number | % | State of Charge (0-100%) |
π₯ Bank Statusπ₯ |
Text | - | Operational status |
| Sensor Name | Type | Unit | Description |
|---|---|---|---|
β‘ B[X] Voltβ οΈ |
Number | V | Individual battery voltage |
π B[X] Currentβ‘ |
Number | A | Individual battery current |
π‘οΈ B[X] Tempπ‘οΈ |
Number | Β°F | Individual battery temperature |
π B[X] SoCπ |
Number | % | Individual State of Charge |
π’ B[X] Serial#οΈβ£ |
Text | - | Battery serial/barcode |
π B[X] Modelπ |
Text | - | Battery model/type |
βοΈ B[X] FirmwareβοΈ |
Text | - | Firmware version |
π₯ B[X] Statusπ₯ |
Text | - | Operational status |
π B[X] Volt Statusπ |
Text | - | Voltage status details |
All sensors are defined as templates in your YAML:
sensor:
# π Summary sensors
- platform: template
name: "Bank Voltage β οΈ"
id: sys_voltage
unit_of_measurement: "V"
accuracy_decimals: 2
- platform: template
name: "Bank Currentβ‘"
id: sys_current
unit_of_measurement: "A"
accuracy_decimals: 2
# π Battery 1 sensors
- platform: template
name: "B1 Voltβ οΈ"
id: b1_voltage
unit_of_measurement: "V"
accuracy_decimals: 2
# ... additional sensors
text_sensor:
# π₯ Summary status
- platform: template
name: "Bank Statusπ₯"
id: sys_basic_status
# π Battery 1 info
- platform: template
name: "B1 Serial#οΈβ£"
id: b1_barcode
# ... additional text sensorsOnce deployed, the device will automatically appear in Home Assistant under:
βοΈ Settings β π Devices & Services β π ESPHome
type: entities
title: π Pytes Battery Bank
entities:
- entity: sensor.pytes_esp32_bank_voltage
name: β‘ Voltage
- entity: sensor.pytes_esp32_bank_current
name: π Current
- entity: sensor.pytes_esp32_bank_soc
name: π State of Charge
- entity: sensor.pytes_esp32_bank_temp
name: π‘οΈ Temperature
- entity: sensor.pytes_esp32_bank_status
name: π₯ Statustype: glance
title: π Individual Battery Status
entities:
- entity: sensor.pytes_esp32_b1_soc
name: Battery 1οΈβ£
- entity: sensor.pytes_esp32_b2_soc
name: Battery 2οΈβ£
- entity: sensor.pytes_esp32_b3_soc
name: Battery 3οΈβ£
- entity: sensor.pytes_esp32_b4_soc
name: Battery 4οΈβ£
- entity: sensor.pytes_esp32_b5_soc
name: Battery 5οΈβ£
- entity: sensor.pytes_esp32_b6_soc
name: Battery 6οΈβ£Create a template sensor in Home Assistant for power calculation:
template:
- sensor:
- name: "Pytes Battery Power"
unique_id: pytes_battery_power
unit_of_measurement: "W"
device_class: power
state: >
{% set v = states('sensor.pytes_esp32_bank_voltage')|float(0) %}
{% set a = states('sensor.pytes_esp32_bank_current')|float(0) %}
{{ (v * a) | round(1) }}To add battery data to the Energy Dashboard:
1οΈβ£ Go to βοΈ Settings β π Dashboards β β‘ Energy 2οΈβ£ Click β Add Battery System 3οΈβ£ Select your power sensor (created above) 4οΈβ£ Configure charge/discharge sensors if available
π΄ Symptom: All sensors show βunavailableβ or βunknownβ
β Solutions:
- β Check physical wiring connections (TX/RX crossed)
- β Verify RS232-TTL module power (3.3V not 5V)
- β Confirm baud rate is 115200
- β Check ESPHome logs for UART errors
- β Verify Pytes console port is active (some models require activation)
π΄ Symptom: Sensors show incorrect values or random characters
β Solutions:
- β Double-check TX/RX wiring (may be swapped)
- β Ensure ground connection between ESP32 and RS232 module
- β Verify 8N1 UART configuration
- β Check for loose connections
- β
Try reducing update interval (increase
poll_s)
π΄ Symptom: ESP32 goes offline periodically
β Solutions:
- β Move ESP32 closer to WiFi router
- β Use stronger WiFi antenna
- β Set static IP in router
- β Enable AP fallback mode
- β Check power supply (use quality 5V 2A adapter)
π΄ Symptom: Summary sensors update but B1-B6 sensors remain unavailable
β Solutions:
- β
Verify
num_batteriesmatches actual battery count - β Check that all battery IDs are defined in configuration
- β Ensure batteries are properly connected in series
- β Review ESPHome logs for parsing errors
π΄ Symptom: Temperature sensors show unusually high values
β Solutions:
- β Check if temperature is in Fahrenheit (default) or Celsius
- β Verify battery ventilation
- β Confirm sensor calibration
- β Check for actual overheating condition
π΄ Symptom: ESPHome fails to compile the configuration
β Solutions:
- β Update ESPHome to version 2025.1 or newer
- β Verify ESP-IDF framework is selected (not Arduino)
- β Check minimum chip revision setting (3.1)
- β Ensure all required IDs are defined in sensor templates
- β Review YAML syntax for errors
To troubleshoot issues, view real-time logs:
# π₯οΈ From ESPHome dashboard
esphome logs pytes-esp32.yaml
# π‘ Or via network
esphome logs pytes-esp32.yaml --device pytes-esp32.localTo monitor ambient temperature near the batteries:
i2c:
sda: GPIO21
scl: GPIO22
scan: true
id: bus_a
sensor:
# ... existing sensors ...
# π‘οΈ BME280 sensors
- platform: bme280
temperature:
name: "π‘οΈ Ambient Temperature"
id: ambient_temp
oversampling: 16x
pressure:
name: "π Ambient Pressure"
id: ambient_pressure
humidity:
name: "π§ Ambient Humidity"
id: ambient_humidity
address: 0x76 # or 0x77
update_interval: 60spytes_rs232:
# ... existing config ...
# β‘ Fast update for critical sensors
update_interval: 10s
# π Slower update for less critical info
text_sensor:
- platform: template
name: "B1 Serial#οΈβ£"
id: b1_barcode
update_interval: 300s # Update every 5 minutesCreate automations in Home Assistant:
automation:
- alias: "β οΈ Battery Low SoC Alert"
trigger:
- platform: numeric_state
entity_id: sensor.pytes_esp32_bank_soc
below: 20
action:
- service: notify.mobile_app
data:
title: "β οΈ Battery Low"
message: "Battery SoC is below 20%"
- alias: "π₯ Battery High Temperature Alert"
trigger:
- platform: numeric_state
entity_id: sensor.pytes_esp32_bank_temp
above: 113 # 45Β°C in Fahrenheit
action:
- service: notify.mobile_app
data:
title: "π₯ Battery Overheating"
message: "Battery temperature exceeds safe limits!"Pytes_ESP32_RS232/
βββ π Components/
β βββ π pytes_rs232/
β βββ π __init__.py
β βββ π pytes_rs232.cpp
β βββ π pytes_rs232.h
β βββ π sensor.py
β βββ π text_sensor.py
βββ π examples/
β βββ π basic-config.yaml
β βββ π 6-battery-system.yaml
β βββ π with-bme280.yaml
βββ π docs/
β βββ πΌοΈ wiring-diagram.png
β βββ π installation-guide.md
β βββ π troubleshooting.md
βββ π LICENSE
βββ π README.md
Contributions are welcome! Hereβs how you can help:
- π΄ Fork the repository
- πΏ Create a feature branch (
git checkout -b feature/amazing-feature) - βοΈ Commit your changes (
git commit -m 'Add amazing feature') - π€ Push to the branch (
git push origin feature/amazing-feature) - π Open a Pull Request
- π Additional documentation and examples
- π Bug fixes and testing
- β¨ New features (Celsius support, additional sensors)
- π Multi-language support
- π¨ Dashboard templates
This project is licensed under the MIT License - see the file for details.
- π Pytes - For manufacturing quality LiFePO4 battery systems
- π ESPHome - For the excellent home automation framework
- π‘ Home Assistant - For the best home automation platform
- π₯οΈ ESP32 Community - For extensive documentation and support
- π¨βπ» chinezbrun - For inspiration from pytes_esp
- π Issues: GitHub Issues
- π¬ Discussions: GitHub Discussions
- β Star this repo if you find it useful!
This is an independent project and is not officially affiliated with or endorsed by Pytes. Use at your own risk. Always follow proper safety procedures when working with battery systems.
- β Initial release
- β Support for up to 6 battery modules
- β RS232 communication via UART
- β Home Assistant integration
- β Web server interface
- β OTA updates
Made with β€οΈ for the Home Assistant and Solar/Battery community
π Enjoy! π
ESPHome component reads the RS232 serial port with configurable frequency (default 30s), parses the battery data and sends it to Home Assistant via the ESPHome API. Home Assistant autodiscovery is built-in, so all sensors will show up automatically.
A signal converter from RS232 to TTL is needed between Pytes serial console port and ESP32 UART pins.
Program creates the following sensors for each battery:
- Bank level: voltage, current, temperature, SoC, status
- Individual batteries (1-6): voltage, current, temperature, SoC, serial#, model, firmware, status, volt_status
ESP32 board ββββββββββββββ tested on ESP32 WROOM 38 pins / ESP32 DevKitC
RS232 to TTL converter ββββββ tested on MAX3232 module
RJ45 to RS232 DB9(male) cable ββββ tested on standard console cable
Simple connection flow:
ESP32 [UART pins GPIO16/17] -> TTL to RS232 converter -> DB09 to RJ45 cable -> Pytes RJ45 console port
Connection with RS232 to TTL converter using RJ45 to RS232 DB9(male) cable - TESTED:
ESP32 Pin: 16 RXD2 ------ RX converter RX DB9 Female ------ DB9 Male console cable RJ45 Pin: 3 TXD
ESP32 Pin: 17 TXD2 ------ TX converter TX DB9 Female ------ DB9 Male console cable RJ45 Pin: 6 RXD
ESP32 PIN: GND ------ GND converter GND DB9 Female ------ DB9 Male console cable RJ45 Pin: 4 GND
ESP32 PIN: 3.3V ------ VCC converter DB9 Female ------ DB9 Male console cable RJ45
UART Configuration:
- Baud Rate: 115200
- Data Bits: 8
- Parity: NONE
- Stop Bits: 1
Important: Both connection types work, but respect the PYTES console port pinout. Main source of issues is incorrect TX/RX connection. If something goes wrong, swap RXD and TXD on one side.
Method 1: Using GitHub external component (Recommended)
Add to your ESPHome YAML configuration:
external_components:
- source:
type: git
url: https://github.com/s3pt1c0/Pytes_ESP32_RS232
ref: main
components: [ pytes_rs232 ]
refresh: 1dMethod 2: Local component
- Clone or download this repository:
git clone https://github.com/s3pt1c0/Pytes_ESP32_RS232.git- Copy
Components/pytes_rs232folder to your ESPHome config directory:
mkdir -p /config/esphome/components
cp -r Pytes_ESP32_RS232/Components/pytes_rs232 /config/esphome/components/- Reference in your YAML:
external_components:
- source:
type: local
path: componentsCreate pytes-esp32.yaml file:
substitutions:
device_name: pytes-esp32
friendly_name: πPytes Battery Monitorπ
poll_s: "30" # Polling interval in seconds
capacity_ah: "100" # Battery capacity in Ah
num_batts: "6" # Number of battery modules (1-6)
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
esp32:
board: esp32dev
framework:
type: esp-idf
advanced:
minimum_chip_revision: "3.1"
logger:
level: INFO
web_server:
port: 80
api:
encryption:
key: "YOUR_ENCRYPTION_KEY"
ota:
- platform: esphome
password: "YOUR_OTA_PASSWORD"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# UART for Pytes RS232
uart:
id: uart_pytes
tx_pin: GPIO17
rx_pin: GPIO16
baud_rate: 115200
data_bits: 8
parity: NONE
stop_bits: 1
# Pytes Component
pytes_rs232:
uart_id: uart_pytes
num_batteries: ${num_batts}
update_interval: ${poll_s}s
capacity_ah: ${capacity_ah}
summary:
voltage: sys_voltage
current: sys_current
temperature: sys_temp_f
coulomb: sys_coulomb
basic_status: sys_basic_status
batteries:
- voltage: b1_voltage
current: b1_current
temperature: b1_temp_f
coulomb: b1_coulomb
barcode: b1_barcode
devtype: b1_devtype
firm_version: b1_firmver
basic_status: b1_basic_status
volt_status: b1_volt_status
# Repeat for batteries 2-6...
# Define template sensors
sensor:
- platform: template
name: "Bank Voltage β οΈ"
id: sys_voltage
unit_of_measurement: "V"
accuracy_decimals: 2
- platform: template
name: "Bank Currentβ‘"
id: sys_current
unit_of_measurement: "A"
accuracy_decimals: 2
# ... more sensors
text_sensor:
- platform: template
name: "Bank Statusπ₯"
id: sys_basic_status
# ... more text sensorsComplete example with all sensors defined can be found in examples/ folder.
When ESP32 is powered and configured:
- Device connects to WiFi
- Establishes UART communication with Pytes battery
- Reads serial data at configured interval (default 30s)
- Automatically creates device and sensors in Home Assistant
- Updates sensor values continuously
After firmware updates it is recommended to delete previous devices in Home Assistant and let them be recreated at next boot.
Bank Level (Summary):
- Bank Voltage (V)
- Bank Current (A)
- Bank Temperature (Β°F)
- Bank SoC (%)
- Bank Status
Individual Batteries (B1-B6):
- Voltage (V)
- Current (A)
- Temperature (Β°F)
- SoC (%)
- Serial Number
- Model/Device Type
- Firmware Version
- Basic Status
- Voltage Status
Device will automatically appear in Home Assistant under Settings β Devices & Services β ESPHome after first connection.
Example dashboard card:
type: entities
title: π Pytes Battery
entities:
- entity: sensor.pytes_esp32_bank_voltage
- entity: sensor.pytes_esp32_bank_current
- entity: sensor.pytes_esp32_bank_soc
- entity: sensor.pytes_esp32_bank_temp
- entity: sensor.pytes_esp32_bank_statusNo data from batteries / All sensors βunavailableβ
- β Check TX/RX wiring (may need to be swapped)
- β Verify RS232-TTL module power (3.3V not 5V)
- β Confirm baud rate is 115200
- β Check ESPHome logs for errors
- β Verify Pytes console port is enabled
Wrong data or garbled output
- β Swap TX/RX connections on one side
- β Ensure ground connection between ESP32 and converter
- β Check for loose connections
- β Try increasing polling interval
WiFi disconnections
- β Move ESP32 closer to router
- β Use quality 5V 2A power supply
- β Set static IP in router
Viewing logs
esphome logs pytes-esp32.yamlPytes_ESP32_RS232/
βββ Components/
β βββ pytes_rs232/
β βββ __init__.py
β βββ pytes_rs232.cpp
β βββ pytes_rs232.h
β βββ sensor.py
β βββ text_sensor.py
βββ examples/
β βββ basic-config.yaml
β βββ 6-battery-system.yaml
βββ docs/
β βββ wiring-diagram.png
β βββ installation-guide.md
βββ LICENSE
βββ README.md
This project is licensed under the MIT License - see the file for details.
- π Issues: GitHub Issues
- π¬ Discussions: GitHub Discussions
- β Star this repo if you find it useful!
- Pytes - For manufacturing quality LiFePO4 battery systems
- ESPHome - For the excellent home automation framework
- Home Assistant - For the best home automation platform
- ESP32 Community - For extensive documentation and support
- chinezbrun - For inspiration from pytes_esp
This is an independent project and is not officially affiliated with or endorsed by Pytes. Use at your own risk. Always follow proper safety procedures when working with battery systems.
Made with β€οΈ for the Home Assistant and Solar/Battery community
enjoy