This application reads pulse counts from S0PCM-2 (2-channel) or S0PCM-5 (5-channel) USB devices and publishes them to Home Assistant via MQTT. It is designed to be a robust "hardware driver" that handles the serial communication and state recovery, leaving high-level logic (like cost calculation) to Home Assistant.
- Add the repository:
https://github.com/darkrain-nl/home-assistant-addon-s0pcm-reader - Install S0PCM Reader from the App Store.
- Start the app. By default, it will auto-detect your connected S0PCM reader. (Optional: To manually select a port, enable "Show unused optional configuration options" in the Configuration tab).
If you are not using Home Assistant OS/Supervisor, you can run this as a standalone container.
1. Create a config/options.json file:
{
"device": "/dev/ttyACM0",
"mqtt": {
"host": "192.168.1.50",
"username": "user",
"password": "password",
"base_topic": "s0pcmreader"
},
"log_level": "info"
}2. Run with Docker Compose:
services:
s0pcm-reader:
image: ghcr.io/darkrain-nl/s0pcm-reader-standalone:latest
container_name: s0pcm-reader
restart: unless-stopped
devices:
- /dev/ttyACM0:/dev/ttyACM0
volumes:
- ./config:/data- Device: (Optional) Path to the USB device (e.g.,
/dev/ttyACM0). If left unconfigured (default), the app will automatically scan and select the connected S0PCM reader (CH340 chip). In the Home Assistant UI, this field is hidden under the "Show unused optional configuration options" toggle by default. - Log Level: (Default:
info) Set logging verbosity (debug,info,warning,error,critical).
- MQTT Host: Internal broker is used by default. Set this for external brokers.
- MQTT Port: Default
1883(or8883if TLS is enabled). - MQTT Username: Username for the broker.
- MQTT Password: Password for the broker.
- MQTT Client ID: (Optional) Custom client ID for the connection.
- MQTT Base Topic: Root topic (Default
s0pcmreader). Changing this creates a new device in Home Assistant. - MQTT Protocol: (Default:
5.0) Select MQTT protocol version (3.1,3.1.1, or5.0). - MQTT Discovery: (Default:
true) Enable Home Assistant auto-discovery. - MQTT Discovery Prefix: (Default:
homeassistant) Prefix for discovery topics. - MQTT Retain: (Default:
true) Retain messages for persistence. - MQTT Split Topic: (Default:
true) Use split topic structure (recommended). - Recovery Wait Time: (Default:
7s) Time to wait for MQTT retained messages on startup. Do not lower this unless you have fast hardware, or you risk data loss.
- MQTT TLS: (Default:
false) Enable TLS encryption. The connection will not fall back to plaintext if TLS fails. - MQTT TLS Port: (Default:
8883) Port to use for TLS connections. - MQTT TLS CA: (Optional) Path to a custom CA certificate file.
- MQTT Check Peer: (Default:
false) Verify the server's certificate. Disabled by default for compatibility with self-signed certs.
Note
When TLS is enabled without a CA certificate, the connection is encrypted but the server's identity is not verified. This is safe on a local Home Assistant OS setup. If you connect to an external broker over an untrusted network, provide a CA certificate and enable MQTT Check Peer.
You can rename meters directly from the Home Assistant UI.
- Go to Settings > Devices & Services > Devices.
- Find S0PCM Reader.
- Change the value in the "Name" text entity (e.g.,
text.1_name->Kitchen Water). - The sensors in HA will automatically update to
sensor.kitchen_water_total.
To sync the app with your physical meter:
- Go to the S0PCM Reader device page.
- Find the "Total Correction" number entity (e.g.,
number.1_total_correction). - Set the correct value and press enter. The
totalsensor will update immediately.
The app provides raw pulse counts (e.g., 12345 pulses). To make this useful, use Home Assistant's native helpers.
Create a Template Sensor to convert raw pulses to your desired unit (e.g., 1000 pulses = 1 m³).
- Settings > Devices & Services > Helpers > Create Helper > Template > Template a sensor.
- Name:
Water Usage - State Template:
{{ (states('sensor.s0pcm_s0pcmreader_1_total') | float(0) / 1000) | round(3) }} - Availability Template:
{{ has_value('sensor.s0pcm_s0pcmreader_1_total') }} - Unit:
m³ - Class:
Water - State Class:
Total increasing
Use the Derivative helper to calculate flow rate (L/min) or power (Watts) from the total counter.
- Settings > Devices & Services > Helpers > Create Helper > Derivative sensor.
- Input Sensor: The Template Sensor you created above (e.g.,
Water Usage). - Time Window:
00:01:00(1 minute smoothing). - Unit:
h(for m³/h) ormin(for L/min).
Once you have created the Template Sensor (Recipe 1) with correct device class (Water or Energy) and state class (Total increasing), it will automatically appear as a selectable source in the Energy Dashboard settings.
Note
This section is only for users who disable MQTT Discovery or prefer manual YAML configuration.
If you disable MQTT Auto-Discovery (set discovery to false under Advanced MQTT Settings), you can manually configure sensors in your configuration.yaml:
mqtt:
sensor:
- state_topic: "s0pcmreader/1/total"
availability_topic: "s0pcmreader/status"
name: "Water Multiplier"
unique_id: "water_multiplier"
# Example: Convert pulses to m3
value_template: "{{ value | float / 1000 }}"
unit_of_measurement: "m³"
state_class: total_increasing
device_class: water- "Connection Refused": Check if MQTT broker is running.
- "Serialport connection failed": Check USB connection and "Hardware" tab in HA OS.
- Available Ports: On the first connection failure, the app will automatically log a list of all detected serial ports to help you find the correct path.
- Exclusive Access: The app requires exclusive access to the port. If another app (e.g. ZHA, Zigbee2MQTT) or Home Assistant integration is using the same USB device, the connection will fail.
- Sensors "Unavailable":
- If the app is disconnected from the MQTT broker (e.g., during a restart), sensors will automatically show as "Unavailable" to prevent stale data. They will recover once reconnected.
- If they never recover, did you change the MQTT Base Topic? This creates a new device.
The app uses a dual-layer recovery system:
- MQTT Retain: Primary recovery source.
- HA API: Fallback if MQTT is empty.
Note: If you wipe both MQTT and restart HA simultaneously, data may be lost. Always backup your MQTT broker.
- Architecture: Asynchronous Python application running on a single-threaded asyncio event loop.
- Discovery: Follows Home Assistant MQTT Discovery standard.
- Topics:
- Data:
s0pcmreader/<ID>/total - Diagnostics:
s0pcmreader/status,s0pcmreader/error
- Data: