mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-02-11 13:15:37 +00:00
Twin BL0942 mod - Two BL0942 on two UARTs on one power metering device (#1531)
* Twin BL0942 mod * Energy data more checks for index 0 * BL09XX_ResetEnergyCounter reset lastSavedEnergyCounterValue * added ENABLE_BL_TWIN compiler option, default disabled * added more ENABLE_BL_TWIN
This commit is contained in:
@ -32,7 +32,8 @@ const char *g_template_lowMidHigh = "{% if value == '0' %}\n"
|
||||
/// @param type Entity type
|
||||
/// @param index Entity index (Ignored for RGB)
|
||||
/// @param uniq_id Array to populate (should be of size HASS_UNIQUE_ID_SIZE)
|
||||
void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) {
|
||||
/// @param asensdatasetix dataset index for ENERGY_METER_SENSOR, otherwise 0
|
||||
void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id, int asensdatasetix) {
|
||||
//https://developers.home-assistant.io/docs/entity_registry_index/#unique-id-requirements
|
||||
//mentions that mac can be used for unique_id and deviceName contains that.
|
||||
const char* longDeviceName = CFG_GetDeviceName();
|
||||
@ -54,7 +55,7 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) {
|
||||
|
||||
case ENERGY_METER_SENSOR:
|
||||
#ifdef ENABLE_DRIVER_BL0937
|
||||
sprintf(uniq_id, "%s_sensor_%s", longDeviceName, DRV_GetEnergySensorNames(index)->hass_uniq_id_suffix);
|
||||
sprintf(uniq_id, "%s_sensor_%s", longDeviceName, DRV_GetEnergySensorNamesEx(asensdatasetix,index)->hass_uniq_id_suffix);
|
||||
#endif
|
||||
break;
|
||||
case POWER_SENSOR:
|
||||
@ -133,9 +134,10 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) {
|
||||
/// @param fmt
|
||||
/// @param type Entity type
|
||||
/// @param index Entity index
|
||||
void hass_print_unique_id(http_request_t* request, const char* fmt, ENTITY_TYPE type, int index) {
|
||||
/// @param asensdatasetix dataset index for ENERGY_METER_SENSOR, otherwise 0
|
||||
void hass_print_unique_id(http_request_t* request, const char* fmt, ENTITY_TYPE type, int index, int asensdatasetix) {
|
||||
char uniq_id[HASS_UNIQUE_ID_SIZE];
|
||||
hass_populate_unique_id(type, index, uniq_id);
|
||||
hass_populate_unique_id(type, index, uniq_id, asensdatasetix);
|
||||
hprintf255(request, fmt, uniq_id);
|
||||
}
|
||||
|
||||
@ -207,12 +209,13 @@ cJSON* hass_build_device_node(cJSON* ids) {
|
||||
/// For energy sensors, index corresponds to energySensor_t. For regular sensor, index can be be the channel.
|
||||
/// @param payload_on The payload that represents enabled state. This is not added for POWER_SENSOR.
|
||||
/// @param payload_off The payload that represents disabled state. This is not added for POWER_SENSOR.
|
||||
/// @param asensdatasetix dataset index for ENERGY_METER_SENSOR, otherwise 0
|
||||
/// @return
|
||||
HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* payload_on, const char* payload_off) {
|
||||
HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* payload_on, const char* payload_off, int asensdatasetix) {
|
||||
HassDeviceInfo* info = os_malloc(sizeof(HassDeviceInfo));
|
||||
addLogAdv(LOG_DEBUG, LOG_FEATURE_HASS, "hass_init_device_info=%p", info);
|
||||
|
||||
hass_populate_unique_id(type, index, info->unique_id);
|
||||
hass_populate_unique_id(type, index, info->unique_id, asensdatasetix);
|
||||
hass_populate_device_config_channel(type, info->unique_id, info);
|
||||
|
||||
info->ids = cJSON_CreateArray();
|
||||
@ -247,7 +250,7 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* p
|
||||
isSensor = true;
|
||||
#ifdef ENABLE_DRIVER_BL0937
|
||||
if (index <= OBK__LAST)
|
||||
sprintf(g_hassBuffer, "%s", DRV_GetEnergySensorNames(index)->name_friendly);
|
||||
sprintf(g_hassBuffer, "%s", DRV_GetEnergySensorNamesEx(asensdatasetix, index)->name_friendly);
|
||||
else
|
||||
sprintf(g_hassBuffer, "Unknown Energy Meter Sensor");
|
||||
#endif
|
||||
@ -355,10 +358,10 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* p
|
||||
HassDeviceInfo* hass_init_relay_device_info(int index, ENTITY_TYPE type, bool bToggleInv) {
|
||||
HassDeviceInfo* info;
|
||||
if (bToggleInv) {
|
||||
info = hass_init_device_info(type, index, "0", "1");
|
||||
info = hass_init_device_info(type, index, "0", "1", 0);
|
||||
}
|
||||
else {
|
||||
info = hass_init_device_info(type, index, "1", "0");
|
||||
info = hass_init_device_info(type, index, "1", "0", 0);
|
||||
}
|
||||
|
||||
sprintf(g_hassBuffer, "~/%i/get", index);
|
||||
@ -380,7 +383,7 @@ HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type) {
|
||||
|
||||
//We can just use 1 to generate unique_id and name for single PWM.
|
||||
//The payload_on/payload_off have to match the state_topic/command_topic values.
|
||||
info = hass_init_device_info(type, 1, "1", "0");
|
||||
info = hass_init_device_info(type, 1, "1", "0", 0);
|
||||
|
||||
switch (type) {
|
||||
case LIGHT_RGBCW:
|
||||
@ -451,7 +454,7 @@ HassDeviceInfo* hass_init_binary_sensor_device_info(int index, bool bInverse) {
|
||||
payload_off = "1";
|
||||
payload_on = "0";
|
||||
}
|
||||
HassDeviceInfo* info = hass_init_device_info(BINARY_SENSOR, index, payload_on, payload_off);
|
||||
HassDeviceInfo* info = hass_init_device_info(BINARY_SENSOR, index, payload_on, payload_off, 0);
|
||||
|
||||
sprintf(g_hassBuffer, "~/%i/get", index);
|
||||
cJSON_AddStringToObject(info->root, "stat_t", g_hassBuffer); //state_topic
|
||||
@ -464,7 +467,7 @@ HassDeviceInfo* hass_init_binary_sensor_device_info(int index, bool bInverse) {
|
||||
/// @brief Initializes HomeAssistant power sensor device discovery storage.
|
||||
/// @param index Index corresponding to energySensor_t.
|
||||
/// @return
|
||||
HassDeviceInfo* hass_init_energy_sensor_device_info(int index) {
|
||||
HassDeviceInfo* hass_init_energy_sensor_device_info(int index, int asensdatasetix) {
|
||||
HassDeviceInfo* info = 0;
|
||||
|
||||
//https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes
|
||||
@ -472,15 +475,15 @@ HassDeviceInfo* hass_init_energy_sensor_device_info(int index) {
|
||||
if (index > OBK__LAST) return info;
|
||||
if (index >= OBK_CONSUMPTION__DAILY_FIRST && !DRV_IsRunning("NTP")) return info; //include daily stats only when time is valid
|
||||
|
||||
info = hass_init_device_info(ENERGY_METER_SENSOR, index, NULL, NULL);
|
||||
info = hass_init_device_info(ENERGY_METER_SENSOR, index, NULL, NULL, asensdatasetix);
|
||||
|
||||
cJSON_AddStringToObject(info->root, "dev_cla", DRV_GetEnergySensorNames(index)->hass_dev_class); //device_class=voltage,current,power, energy, timestamp
|
||||
cJSON_AddStringToObject(info->root, "dev_cla", DRV_GetEnergySensorNamesEx(asensdatasetix,index)->hass_dev_class); //device_class=voltage,current,power, energy, timestamp
|
||||
//20241024 XJIKKA unit_of_meas is set bellow (was set twice)
|
||||
//cJSON_AddStringToObject(info->root, "unit_of_meas", DRV_GetEnergySensorNames(index)->units); //unit_of_measurement. Sets as empty string if not present. HA doesn't seem to mind
|
||||
sprintf(g_hassBuffer, "~/%s/get", DRV_GetEnergySensorNames(index)->name_mqtt);
|
||||
sprintf(g_hassBuffer, "~/%s/get", DRV_GetEnergySensorNamesEx(asensdatasetix, index)->name_mqtt);
|
||||
cJSON_AddStringToObject(info->root, "stat_t", g_hassBuffer);
|
||||
|
||||
if (!strcmp(DRV_GetEnergySensorNames(index)->hass_dev_class, "energy")) {
|
||||
if (!strcmp(DRV_GetEnergySensorNamesEx(asensdatasetix, index)->hass_dev_class, "energy")) {
|
||||
//state_class can be measurement, total or total_increasing. Energy values should be total_increasing.
|
||||
cJSON_AddStringToObject(info->root, "stat_cla", "total_increasing");
|
||||
cJSON_AddStringToObject(info->root, "unit_of_meas", CFG_HasFlag(OBK_FLAG_MQTT_ENERGY_IN_KWH) ? "kWh" : "Wh");
|
||||
@ -488,14 +491,14 @@ HassDeviceInfo* hass_init_energy_sensor_device_info(int index) {
|
||||
//20241024 XJIKKA skip measurement for timestamp - HASS log:
|
||||
//HASS: energy_clear_date (<class 'homeassistant.components.mqtt.sensor.MqttSensor'>) is using state class 'measurement'
|
||||
// which is impossible considering device class ('timestamp') it is using; expected None;
|
||||
if (strcmp(DRV_GetEnergySensorNames(index)->hass_dev_class,"timestamp")) {
|
||||
if (strcmp(DRV_GetEnergySensorNamesEx(asensdatasetix, index)->hass_dev_class,"timestamp")) {
|
||||
cJSON_AddStringToObject(info->root, "stat_cla", "measurement");
|
||||
}
|
||||
//20241024 XJIKKA if unit is not set (drv_bl_shared.c @ "power_factor"), mqtt value unit_of_meas was empty - HASS log:
|
||||
//HASS: sensor...power_factor is using native unit of measurement '' which is not a valid unit
|
||||
// for the device class ('power_factor') it is using; expected one of ['no unit of measurement', '%'];
|
||||
//solution is to skip empty
|
||||
if (strlen(DRV_GetEnergySensorNames(index)->units)>0) {
|
||||
if (strlen(DRV_GetEnergySensorNamesEx(asensdatasetix, index)->units)>0) {
|
||||
cJSON_AddStringToObject(info->root, "unit_of_meas", DRV_GetEnergySensorNames(index)->units);
|
||||
}
|
||||
}
|
||||
@ -537,7 +540,7 @@ HassDeviceInfo* hass_init_light_singleColor_onChannels(int toggle, int dimmer, i
|
||||
const char* clientId;
|
||||
|
||||
clientId = CFG_GetMQTTClientId();
|
||||
dev_info = hass_init_device_info(LIGHT_PWM, toggle, "1", "0");
|
||||
dev_info = hass_init_device_info(LIGHT_PWM, toggle, "1", "0", 0);
|
||||
|
||||
sprintf(g_hassBuffer, "~/%i/get", toggle);
|
||||
cJSON_AddStringToObject(dev_info->root, "stat_t", g_hassBuffer); //state_topic
|
||||
@ -559,7 +562,7 @@ HassDeviceInfo* hass_init_light_singleColor_onChannels(int toggle, int dimmer, i
|
||||
/// @return
|
||||
HassDeviceInfo* hass_init_sensor_device_info(ENTITY_TYPE type, int channel, int decPlaces, int decOffset, int divider) {
|
||||
//Assuming that there is only one DHT setup per device which keeps uniqueid/names simpler
|
||||
HassDeviceInfo* info = hass_init_device_info(type, channel, NULL, NULL); //using channel as index to generate uniqueId
|
||||
HassDeviceInfo* info = hass_init_device_info(type, channel, NULL, NULL, 0); //using channel as index to generate uniqueId
|
||||
|
||||
//https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes
|
||||
switch (type) {
|
||||
|
||||
@ -120,11 +120,11 @@ typedef struct HassDeviceInfo_s {
|
||||
cJSON* ids;
|
||||
} HassDeviceInfo;
|
||||
|
||||
void hass_print_unique_id(http_request_t* request, const char* fmt, ENTITY_TYPE type, int index);
|
||||
void hass_print_unique_id(http_request_t* request, const char* fmt, ENTITY_TYPE type, int index, int asensdatasetix);
|
||||
HassDeviceInfo* hass_init_relay_device_info(int index, ENTITY_TYPE type, bool bInverse);
|
||||
HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* payload_on, const char* payload_off);
|
||||
HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* payload_on, const char* payload_off, int asensdatasetix);
|
||||
HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type);
|
||||
HassDeviceInfo* hass_init_energy_sensor_device_info(int index);
|
||||
HassDeviceInfo* hass_init_energy_sensor_device_info(int index, int asensdatasetix);
|
||||
HassDeviceInfo* hass_init_light_singleColor_onChannels(int toggle, int dimmer, int brightness_scale);
|
||||
HassDeviceInfo* hass_init_binary_sensor_device_info(int index, bool bInverse);
|
||||
HassDeviceInfo* hass_init_sensor_device_info(ENTITY_TYPE type, int channel, int decPlaces, int decOffset, int divider);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "../cmnds/cmd_public.h"
|
||||
#include "../driver/drv_tuyaMCU.h"
|
||||
#include "../driver/drv_public.h"
|
||||
#include "../driver/drv_bl_shared.h"
|
||||
#include "../hal/hal_wifi.h"
|
||||
#include "../hal/hal_pins.h"
|
||||
#include "../hal/hal_flashConfig.h"
|
||||
@ -1823,13 +1824,30 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
|
||||
if (measuringPower == true) {
|
||||
for (i = OBK__FIRST; i <= OBK__LAST; i++)
|
||||
{
|
||||
dev_info = hass_init_energy_sensor_device_info(i);
|
||||
dev_info = hass_init_energy_sensor_device_info(i, BL_SENSORS_IX_0);
|
||||
if (dev_info) {
|
||||
MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
|
||||
hass_free_device_info(dev_info);
|
||||
discoveryQueued = true;
|
||||
}
|
||||
}
|
||||
#if ENABLE_BL_TWIN
|
||||
//BL_SENSORS_IX_1 - mqtt hass discovery using hass_uniq_id_suffix (_b) from drv_bl_shared.c
|
||||
if (BL_IsMeteringDeviceIndexActive(BL_SENSORS_IX_1)) {
|
||||
for (i = OBK__FIRST; i <= OBK__LAST; i++)
|
||||
{
|
||||
//BL_SENSORS_IX_1 does not have energy yet, just base OBK_VOLTAGE..OBK_POWER_FACTOR
|
||||
if (i < OBK_VOLTAGE) continue;
|
||||
if (i > OBK_POWER_FACTOR) continue;
|
||||
dev_info = hass_init_energy_sensor_device_info(i, BL_SENSORS_IX_1);
|
||||
if (dev_info) {
|
||||
MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
|
||||
hass_free_device_info(dev_info);
|
||||
discoveryQueued = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2264,7 +2282,7 @@ int http_fn_ha_cfg(http_request_t* request) {
|
||||
switchAdded = 1;
|
||||
}
|
||||
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", RELAY, i);
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", RELAY, i, 0);
|
||||
hprintf255(request, " name: %i\n", i);
|
||||
hprintf255(request, " state_topic: \"%s/%i/get\"\n", clientId, i);
|
||||
hprintf255(request, " command_topic: \"%s/%i/set\"\n", clientId, i);
|
||||
@ -2284,7 +2302,7 @@ int http_fn_ha_cfg(http_request_t* request) {
|
||||
switchAdded = 1;
|
||||
}
|
||||
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", BINARY_SENSOR, i);
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", BINARY_SENSOR, i, 0);
|
||||
hprintf255(request, " name: %i\n", i);
|
||||
hprintf255(request, " state_topic: \"%s/%i/get\"\n", clientId, i);
|
||||
hprintf_qos_payload(request, clientId);
|
||||
@ -2303,7 +2321,7 @@ int http_fn_ha_cfg(http_request_t* request) {
|
||||
switchAdded = 1;
|
||||
}
|
||||
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_RGBCW, i);
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_RGBCW, i, 0);
|
||||
hprintf255(request, " name: %i\n", i);
|
||||
http_generate_rgb_cfg(request, clientId);
|
||||
//hprintf255(request, " #brightness_value_template: \"{{ value }}\"\n");
|
||||
@ -2323,7 +2341,7 @@ int http_fn_ha_cfg(http_request_t* request) {
|
||||
switchAdded = 1;
|
||||
}
|
||||
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_RGB, i);
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_RGB, i, 0);
|
||||
hprintf255(request, " name: Light\n");
|
||||
http_generate_rgb_cfg(request, clientId);
|
||||
}
|
||||
@ -2338,7 +2356,7 @@ int http_fn_ha_cfg(http_request_t* request) {
|
||||
switchAdded = 1;
|
||||
}
|
||||
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_PWM, i);
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_PWM, i, 0);
|
||||
hprintf255(request, " name: Light\n");
|
||||
http_generate_singleColor_cfg(request, clientId);
|
||||
}
|
||||
@ -2353,7 +2371,7 @@ int http_fn_ha_cfg(http_request_t* request) {
|
||||
switchAdded = 1;
|
||||
}
|
||||
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_PWMCW, i);
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_PWMCW, i, 0);
|
||||
hprintf255(request, " name: Light\n");
|
||||
http_generate_cw_cfg(request, clientId);
|
||||
}
|
||||
@ -2370,7 +2388,7 @@ int http_fn_ha_cfg(http_request_t* request) {
|
||||
lightAdded = 1;
|
||||
}
|
||||
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_PWM, i);
|
||||
hass_print_unique_id(request, " - unique_id: \"%s\"\n", LIGHT_PWM, i, 0);
|
||||
hprintf255(request, " name: %i\n", i);
|
||||
hprintf255(request, " state_topic: \"%s/%i/get\"\n", clientId, i);
|
||||
hprintf255(request, " command_topic: \"%s/%i/set\"\n", clientId, i);
|
||||
|
||||
Reference in New Issue
Block a user