Add LoRa telemetry, fault counters, and time sync status
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#include "mqtt_client.h"
|
||||
#include <WiFi.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "config.h"
|
||||
#include "json_codec.h"
|
||||
|
||||
static WiFiClient wifi_client;
|
||||
@@ -52,6 +54,97 @@ bool mqtt_publish_state(const MeterData &data) {
|
||||
return mqtt_client.publish(topic.c_str(), payload.c_str());
|
||||
}
|
||||
|
||||
bool mqtt_publish_faults(const char *device_id, const FaultCounters &counters, FaultType last_error, uint32_t last_error_age_sec) {
|
||||
if (!device_id || device_id[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
if (!mqtt_connect()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StaticJsonDocument<192> doc;
|
||||
doc["err_m"] = counters.meter_read_fail;
|
||||
doc["err_d"] = counters.decode_fail;
|
||||
doc["err_tx"] = counters.lora_tx_fail;
|
||||
if (last_error != FaultType::None) {
|
||||
doc["err_last"] = static_cast<uint8_t>(last_error);
|
||||
doc["err_last_age"] = last_error_age_sec;
|
||||
}
|
||||
|
||||
String payload;
|
||||
size_t len = serializeJson(doc, payload);
|
||||
if (len == 0) {
|
||||
return false;
|
||||
}
|
||||
String topic = String("smartmeter/") + device_id + "/faults";
|
||||
return mqtt_client.publish(topic.c_str(), payload.c_str(), true);
|
||||
}
|
||||
|
||||
static bool publish_discovery_sensor(const char *device_id, const char *key, const char *name, const char *unit, const char *device_class,
|
||||
const char *state_topic, const char *value_template) {
|
||||
StaticJsonDocument<256> doc;
|
||||
String unique_id = String("dd3_") + device_id + "_" + key;
|
||||
String sensor_name = String(device_id) + " " + name;
|
||||
|
||||
doc["name"] = sensor_name;
|
||||
doc["state_topic"] = state_topic;
|
||||
doc["unique_id"] = unique_id;
|
||||
if (unit && unit[0] != '\0') {
|
||||
doc["unit_of_measurement"] = unit;
|
||||
}
|
||||
if (device_class && device_class[0] != '\0') {
|
||||
doc["device_class"] = device_class;
|
||||
}
|
||||
doc["value_template"] = value_template;
|
||||
|
||||
JsonObject device = doc.createNestedObject("device");
|
||||
JsonArray identifiers = device.createNestedArray("identifiers");
|
||||
identifiers.add(String("dd3-") + device_id);
|
||||
device["name"] = String("DD3 ") + device_id;
|
||||
device["model"] = "DD3-LoRa-Bridge";
|
||||
device["manufacturer"] = "DD3";
|
||||
|
||||
String payload;
|
||||
size_t len = serializeJson(doc, payload);
|
||||
if (len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String topic = String("homeassistant/sensor/") + device_id + "/" + key + "/config";
|
||||
return mqtt_client.publish(topic.c_str(), payload.c_str(), true);
|
||||
}
|
||||
|
||||
bool mqtt_publish_discovery(const char *device_id) {
|
||||
if (!device_id || device_id[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
if (!mqtt_connect()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String state_topic = String("smartmeter/") + device_id + "/state";
|
||||
bool ok = true;
|
||||
ok = ok && publish_discovery_sensor(device_id, "energy", "Energy", "kWh", "energy", state_topic.c_str(), "{{ value_json.e_kwh }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "power", "Power", "W", "power", state_topic.c_str(), "{{ value_json.p_w }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "v1", "Voltage L1", "V", "voltage", state_topic.c_str(), "{{ value_json.v1_v }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "v2", "Voltage L2", "V", "voltage", state_topic.c_str(), "{{ value_json.v2_v }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "v3", "Voltage L3", "V", "voltage", state_topic.c_str(), "{{ value_json.v3_v }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "p1", "Power L1", "W", "power", state_topic.c_str(), "{{ value_json.p1_w }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "p2", "Power L2", "W", "power", state_topic.c_str(), "{{ value_json.p2_w }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "p3", "Power L3", "W", "power", state_topic.c_str(), "{{ value_json.p3_w }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "bat_v", "Battery Voltage", "V", "voltage", state_topic.c_str(), "{{ value_json.bat_v }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "bat_pct", "Battery", "%", "battery", state_topic.c_str(), "{{ value_json.bat_pct }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "rssi", "LoRa RSSI", "dBm", "signal_strength", state_topic.c_str(), "{{ value_json.rssi }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "snr", "LoRa SNR", "dB", "", state_topic.c_str(), "{{ value_json.snr }}");
|
||||
|
||||
String faults_topic = String("smartmeter/") + device_id + "/faults";
|
||||
ok = ok && publish_discovery_sensor(device_id, "err_m", "Meter Read Errors", "count", "", faults_topic.c_str(), "{{ value_json.err_m }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "err_d", "Decode Errors", "count", "", faults_topic.c_str(), "{{ value_json.err_d }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "err_tx", "LoRa TX Errors", "count", "", faults_topic.c_str(), "{{ value_json.err_tx }}");
|
||||
ok = ok && publish_discovery_sensor(device_id, "err_last_age", "Last Error Age", "s", "", faults_topic.c_str(), "{{ value_json.err_last_age }}");
|
||||
return ok;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TEST_MODE
|
||||
bool mqtt_publish_test(const char *device_id, const String &payload) {
|
||||
if (!mqtt_connect()) {
|
||||
|
||||
Reference in New Issue
Block a user