| Crates.io | dalybms |
| lib.rs | dalybms |
| version | 0.1.5 |
| created_at | 2025-05-29 21:53:38.501091+00 |
| updated_at | 2025-08-27 19:49:31.592954+00 |
| description | Daly BMS protocol and commandline tool |
| homepage | |
| repository | https://github.com/acpiccolo/Daly-BMS |
| max_upload_size | |
| id | 1694423 |
| size | 398,211 |
This RUST project can read and write a Daly BMS module from the command line.
For those interested in the low-level communication details, the Daly BMS UART/RS485 communication protocol specification (version 1.2) is available in the repository at docs/Daly UART_485 Communications Protocol V1.2.pdf.
Ensure you have the following dependencies installed before proceeding:
git clone https://github.com/acpiccolo/Daly-BMS.git
cd Daly-BMS
cargo build --release
The compiled binary will be available at:
target/release/dalybms
cargo install --path .
This installs dalybms to $HOME/.cargo/bin, making it accessible from anywhere.The dalybms command-line tool allows you to interact with your Daly BMS from the terminal.
To see all available commands and options:
dalybms --help
To get help for a specific subcommand, for example set-soc:
dalybms set-soc --help
Here are some examples of how to use the dalybms tool. Replace /dev/ttyUSB0 with the actual serial port your BMS is connected to, if different.
1. Fetching Basic Information
Get State of Charge (SOC), total voltage, and current:
dalybms --device /dev/ttyUSB0 soc
(Output will be similar to: SOC: Soc { total_voltage: 53.6, current: -0.0, soc_percent: 87.5 })
Get general status information (number of cells, temperature sensors, charger/load status, cycles):
dalybms status
(Assumes default device or you can specify --device)
Get MOSFET status (mode, charging/discharging MOSFET state, BMS cycles, capacity):
dalybms mosfet
Get cell voltage range (highest/lowest cell voltage and which cell):
dalybms voltage-range
Get temperature range (highest/lowest temperature and which sensor):
dalybms temperature-range
Get current error codes:
dalybms errors
(Output will be like: Errors: [] if no errors, or show a list of active errors)
2. Fetching Detailed Information
Important: For commands like cell-voltages, cell-temperatures, and balancing, the BMS needs to know the number of cells/sensors. The dalybms tool automatically calls status first if you haven't, but it's good practice to be aware of this.
Get individual cell voltages:
dalybms cell-voltages
Get individual cell/temperature sensor readings:
dalybms cell-temperatures
Get cell balancing status (shows which cells are currently being balanced):
dalybms balancing
3. Setting Values and Controlling MOSFETs
Set the State of Charge (SOC) to 80.5%:
dalybms set-soc 80.5
Enable the discharge MOSFET:
dalybms set-discharge-mosfet --enable
Disable the discharge MOSFET:
dalybms set-discharge-mosfet
Enable the charge MOSFET:
dalybms set-charge-mosfet --enable
Disable the charge MOSFET:
dalybms set-charge-mosfet
4. Fetching All Information
dalybms all
(This is very useful for a quick overview.)5. Specifying Connection Parameters
Use a different serial device:
dalybms --device /dev/ttyACM0 status
Change the communication timeout (e.g., to 1 second):
dalybms --timeout 1s soc
Change the delay between commands (e.g., to 100 milliseconds):
dalybms --delay 100ms all
(Useful if you experience communication issues with the default delay.)
Set the number of retries for a failed command:
dalybms --retries 5 soc
6. Resetting the BMS
dalybms reset
These examples should help you get started with using the dalybms command-line tool. Always refer to dalybms --help and dalybms <subcommand> --help for the most up-to-date options and parameters.
The dalybms tool includes a daemon mode for continuous monitoring and data export, useful for logging BMS data over time or integrating with monitoring systems like Home Assistant via MQTT.
Daemon mode runs persistently, fetching specified metrics from the BMS at regular intervals and outputting them to the console or an MQTT broker.
The basic command to start daemon mode is:
dalybms daemon [OPTIONS]
Daemon Options:
--output <console|mqtt>: (Required) Specifies where to send the data.
console: Prints data to the standard output.mqtt: Publishes data to an MQTT broker. Requires mqtt.yaml for configuration.--interval <DURATION>: Sets how often to fetch and report data. This is a duration string like "10s", "1m", "2h30m".
--metrics <METRICS>: A comma-separated list of specific metrics to collect.
status, soc, mosfet, voltage-range, temperature-range, cell-voltages, cell-temperatures, balancing, errors, all.all is included, all available metrics will be fetched.Console Output: Fetch SOC and general status every 30 seconds and print to console.
dalybms daemon --output console --interval 30s --metrics soc,status
MQTT Output: Fetch all available metrics every 5 minutes and publish to an MQTT broker (ensure mqtt.yaml is configured).
dalybms daemon --output mqtt --interval 5m --metrics all
(You would also need an mqtt.yaml file in the same directory, for example:)
# mqtt.yaml
uri: "mqtt://localhost:1883"
username: "your_username" # Optional
password: "your_password" # Optional
topic: "dalybms" # Optional
client_id: "dalybms_1" # Optional
mqtt.yaml)When using --output mqtt, the tool requires a configuration file named mqtt.yaml in the root directory where you run the dalybms command.
This file contains details for connecting to your MQTT broker:
uri: (String) MQTT broker server uri (e.g., mqtt://localhost:1883).username: (String, Optional) Username for MQTT authentication.password: (String, Optional) Password for MQTT authentication.topic: (String, Optional) Base MQTT topic to publish data to. Defaults to "dalybms" if not set.qos (Integer, Optional): MQTT Quality of Service level (0, 1, or 2). Defaults to 0 if not set.client_id: (String, Optional) Custom client ID for this connection. If blank or omitted, a default ID (e.g., "dalybms-<random_suffix>") will be generated.Please refer to the example mqtt.yaml file in the repository for exact formatting and more comments.
When using MQTT, you can specify the output format using the --format option:
--format simple (Default): Publishes each data point as a separate value on a sub-topic. This is ideal for systems that expect simple key-value pairs (e.g., Home Assistant MQTT sensors).
dalybms daemon --output mqtt --format simple --metrics all
Example messages published:
dalybms/soc/total_voltage, Payload: 53.6dalybms/soc/current, Payload: 0.0dalybms/soc/soc_percent, Payload: 87.5dalybms/status/cells, Payload: 16--format json: Publishes a single JSON payload to the base topic. This is useful for integrations that can parse complex JSON objects.
dalybms daemon --output mqtt --format json --metrics all
Example payload on topic dalybms:
{
"timestamp": "2023-10-27T10:00:00Z",
"soc": {"total_voltage": 53.6, "current": 0.0, "soc_percent": 87.5},
"status": {"cells": 16, "temperature_sensors": 2, ...}
}
This crate can also be used as a library (dalybms_lib) to interact with Daly BMS programmatically from your own Rust projects.
To use dalybms_lib, add it to your Cargo.toml. Replace "x.y.z" with the desired version of dalybms_lib:
[dependencies]
# For the synchronous client:
dalybms_lib = { version = "x.y.z", features = ["serialport"] }
# For the asynchronous client:
# dalybms_lib = { version = "x.y.z", features = ["tokio-serial-async"] }
You need to specify which client(s) you intend to use via feature flags:
serialport: For the synchronous client.tokio-serial-async: For the asynchronous Tokio-based client.You can enable both if needed: features = ["serialport", "tokio-serial-async"]
The synchronous client uses the serialport crate.
Feature flag required: serialport
use dalybms_lib::serialport::DalyBMS;
use std::time::Duration;
fn main() {
match DalyBMS::new("/dev/ttyUSB0") { // Replace with your serial port
Ok(mut bms) => {
bms.set_timeout(Duration::from_millis(500)).unwrap_or_else(|e| {
eprintln!("Error setting timeout: {:?}", e);
});
match bms.get_soc() {
Ok(soc) => {
println!("SOC: {:.1}%, Voltage: {:.1}V, Current: {:.1}A",
soc.soc_percent, soc.total_voltage, soc.current);
}
Err(e) => {
eprintln!("Error getting SOC: {:?}", e);
}
}
}
Err(e) => {
eprintln!("Failed to connect to BMS: {:?}", e);
}
}
}
The asynchronous client uses tokio and tokio-serial.
Feature flag required: tokio-serial-async
use dalybms_lib::tokio_serial_async::DalyBMS;
use std::time::Duration;
#[tokio::main]
async fn main() {
match DalyBMS::new("/dev/ttyUSB0") { // Replace with your serial port
Ok(mut bms) => {
bms.set_timeout(Duration::from_millis(500)).unwrap_or_else(|e| {
// In async, set_timeout is sync, so direct error handling is fine
eprintln!("Error setting timeout: {:?}", e);
});
match bms.get_soc().await {
Ok(soc) => {
println!("SOC: {:.1}%, Voltage: {:.1}V, Current: {:.1}A",
soc.soc_percent, soc.total_voltage, soc.current);
}
Err(e) => {
eprintln!("Error getting SOC: {:?}", e);
}
}
}
Err(e) => {
eprintln!("Failed to connect to BMS: {:?}", e);
}
}
}
This crate (dalybms_lib) uses a feature-based system to manage optional dependencies and client implementations. This allows users to compile only the parts they need.
default: Enables bin-dependencies, which is intended for compiling the dalybms command-line tool.serialport: Enables the synchronous client using the serialport crate.tokio-serial-async: Enables the asynchronous client using tokio and tokio-serial.serde: Enables serde support for serializing/deserializing data structures.bin-dependencies: Enables all features required by the dalybms binary executable (currently serialport).Licensed under either of
at your option.