MQTT - dalathegreat/Battery-Emulator GitHub Wiki
Introduction
v5.0.0 introduces basic MQTT support. The battery emulator can now be configured to publish data to your MQTT broker and then be used in whatever way you choose. You can modify the battery emulator code to publish more data, less data, or other data, as well as subscribing to MQTT topics.
Main purpose for this implementation is better integration with popular home automation platforms such as Home Assistant, in order to for example keep track of battery temperature and cell deviation. If "MQTT" and "Home Assistant" are not familiar words, you will likely not benefit from this until you're up to speed on the current state of home automation.
- Published data
- Subscriptions
- Limitations
- Future improvements
- Inspiration
- Breaking Changes
- References
Enabling MQTT in the software
To start using MQTT, make sure that the line #define MQTT
is set in the USER_SETTINGS.h file. Here you can also specify the IP address for the server on the MQTT_SERVER
line, and the port used on the MQTT_PORT
line.
MQTT settings
The username and password for MQTT can be set in the USER_SETTINGS.cpp file. Incase you want to use no login info, set fields to NULL
Published data
Out of the box, the MQTT implementation publishes to a BE/info
topic that holds SOC, SOH, min/max temperature and min/max cell voltage. On select battery implementations that update cell voltage data, all cell voltages are published in a separate BE/spec_data
topic. Battery emulator events are published to BE/events
topic. By default, all data is published with the retain
flag set, which simplifies having e.g. MQTT Sensors in Home Assistant.
BE/info
example payload (sensor configuration autodiscovery topic is avalilable for each value ):
{
"SOC": 63.300,
"StateOfHealth": 92.000,
"temperature_min": 5.800,
"temperature_max": 7.400,
"cell_max_voltage": 3787,
"cell_min_voltage": 3765
}
BE/spec_data
example payload (has a autodiscovery topic):
{
"cell_voltages": [3779, 3780, 3782, 3767, 3783, 3769, 3782, 3768, 3782, 3777, 3782, 3776, 3781, 3776, 3775, 3765, 3782, 3776, 3782, 3777, 3773, 3765, 3774, 3768, 3773, 3765, 3772, 3771, 3773, 3772, 3772, 3768, 3773, 3772, 3772, 3767, 3772, 3778, 3784, 3778, 3773, 3769, 3773, 3767, 3783, 3769, 3782, 3769, 3779, 3777, 3775, 3777, 3774, 3774, 3780, 3767, 3773, 3770, 3773, 3769, 3775, 3765, 3777, 3777, 3783, 3774, 3787, 3776, 3776, 3775, 3784, 3767, 3778, 3763, 3776, 3763, 3784, 3773, 3778, 3767, 3777, 3771, 3787, 3775, 3783, 3774, 3784, 3772, 3781, 3773, 3780, 3773, 3773, 3766, 3773, 3765]
}
BE/events
example payload (has a autodiscovery topic):
{
"event_type": "RESET_SW",
"severity": "INFO",
"last_event": "9",
"count": "1",
"data": "3",
"message": "Info: The board was reset via software, webserver or OTA. Normal operation",
"milis": "10001"
}
Custom publishing
The SW supports publishing of whatever data you have to whatever topic you want, whenever and where ever you want (with some caveats). To avoid clashes in publications you should only publish from the main/loop() thread, i.e. only from functions that have their origin in the loop() function of Software.ino. This is because the current MQTT implementation uses a common global message buffer, so if you access it from another thread for some reason, it might clash with the recurring publication of general data.
To implement your own publishing code, use the mqtt_publish_retain()
and snprintf()
functions along with the mqtt_msg
global buffer:
float my_float = 1.234f;
snprintf(mqtt_msg, sizeof(mqtt_msg), "{\"some_float_data\": %.3f}", my_float);
mqtt_publish_retain("category/subcategory/topic");
See online documentation for snprintf to understand the details. For one-shot messages there's nothing to consider, but when you need to build your message cumulatively/iteratively (for example with a loop or just line by line for some reason), basically with several calls to snprintf()
you need to be careful with the two first parameters. See mqtt.cpp:publish_cell_data()
, in the else
clause for more info and a tricky example with cell voltages.
Discovery
If you want to implement discovery topics for your data, an example can be found in mqtt.cpp:publish_cell_data()
, in the block below if (mqtt_first_transmission == true)
. The example is a bit complex since it publishes discovery topics for a dynamic amount of cell voltages, but it should sink in after staring at it for a few minutes. The current discovery topic is hardcoded to homeassistant/...
which should probably be configurable in the future.
homeassistant/sensor/BE/cell_voltage96/config example payload:
{
"name": "Battery Cell Voltage 96",
"object_id": "be_battery_voltage_cell96",
"unique_id": "BE_battery_voltage_cell96",
"device_class": "voltage",
"state_class": "measurement",
"state_topic": "BE/spec_data",
"unit_of_measurement": "V",
"enabled_by_default": true,
"expire_after": 240,
"value_template": "{{ value_json.cell_voltages[95] }}",
"device": {
"identifiers": [
"battery-emulator"
],
"manufacturer": "DalaTech",
"model": "BatteryEmulator",
"name": "Battery Emulator"
},
"origin": {
"name": "BatteryEmulator",
"sw": "7.6.0",
"url": "https://github.com/dalathegreat/Battery-Emulator"
}
}
homeassistant/sensor/BE/SOC/config example payload:
{
"name": "SOC (scaled)",
"state_topic": "BE/info",
"unique_id": "BE_SOC",
"object_id": "be_SOC",
"value_template": "{{ value_json.SOC }}",
"unit_of_measurement": "%",
"device_class": "battery",
"state_class": "measurement",
"enabled_by_default": true,
"expire_after": 240,
"device": {
"identifiers": [
"battery-emulator"
],
"manufacturer": "DalaTech",
"model": "BatteryEmulator",
"name": "Battery Emulator"
},
"origin": {
"name": "BatteryEmulator",
"sw": "7.6.0",
"url": "https://github.com/dalathegreat/Battery-Emulator"
}
}
⚠️ NOTE: Entity availability (or rather unavailability) with discovery has not been tested
MQTT Sensor
All data plublished has a discovery topic so you dont have to configure anything on Home assistant. It's recommended your MQTT broker has persistence enabled to ensure the availability is retained when restarting HA.
You can use this for inspiration on how to implement your own MQTT data publishing and integrate it into Home Assistant without using discovery. Also, see the References section.
Subscriptions
Subscriptions are not supported at this time.
Usage
Ideas for usage would be charge/discharge automation (if your inverter supports charge/discharge limits from the battery), manipulating other functionality that the battery emulator has control over, or simply overriding data. Be creative but careful 😺
Limitations
- Publishing is limited to QoS 0
- Subscription is limited to QoS 0 or 1
- Last Will and Testament (LWT) is not supported (Birth could be, but doesn't help much)
Future improvments
- Changing to a more complete MQTT library
- Investigating availability when using discovery without LWT, which might be solved in your MQTT Broker instead
Inspiration
A fairly complex Home Assistant example that uses MQTT for cell voltages, SOC and temperature. Other graphs are based on a mix of MQTT, Fronius Modbus TCP and an internal Fronius API:
Another Battery-Emulator dashboard on Home Assistant:
Breaking Changes
Changes in PRs #566 and #567 introduced on v7.6.0 have introduced updates to the MQTT topic naming conventions for Home Assistant (HA), sensor names, and the addition of a prefix to the cell information. These updates bring consistency across sensor object IDs but may break compatibility for users already using MQTT in HA.
For new installations, the default values are now set in usersettings.cpp as follows:
const char* mqtt_topic_name = "BE";
const char* mqtt_object_id_prefix = "be_";
const char* mqtt_device_name = "Battery Emulator";
To keep previous naming conventions and maintain backward compatibility, you can comment out the following line in user_settings.h:
#define MQTT_MANUAL_TOPIC_OBJECT_NAME
However, please note that the cell voltage sensor IDs will still change, as they now include the prefix to align with other sensors.
If you prefer to maintain the current sensor configurations in HA and avoid any updates, you can disable the autodiscovery feature by commenting out the following line in user_settings.h:
#define HA_AUTODISCOVERY
With HA_AUTODISCOVERY commented out, configuration topics will not be sent to HA, thereby preventing the creation of new sensors.
Summary To retain the existing configuration from installations before v7.6.0 in upcoming updates, comment out the following lines:
#define MQTT_MANUAL_TOPIC_OBJECT_NAME
#define HA_AUTODISCOVERY
References
-
Home Assistant MQTT overview Covers brokers, discovery, various configuration and Home Assistant services related to MQTT
-
Home Assistant MQTT Sensor Explains manual (non-discovery) setup of MQTT related sensors. In a way offers more control over details compared to using Discovery, but requires more work
-
PubSubClient The library currently used for MQTT