mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-02-07 13:35:46 +00:00
TCL AC driver progress + LowMidHigh etc channels HA discovery
* Buzzer * Update obk_config.h * Display * uart test stub * unfinished TCL_DoDiscovery * ha * Update drv_tclAC.c * ha mode send * unfinished not working * Update drv_tclAC.c * Update hass.h * better discovery * Update obk_config.h
This commit is contained in:
@ -33,7 +33,7 @@ const char *g_template_lowMidHigh = "{% if value == '0' %}\n"
|
||||
/// @param index Entity index (Ignored for RGB)
|
||||
/// @param uniq_id Array to populate (should be of size HASS_UNIQUE_ID_SIZE)
|
||||
/// @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) {
|
||||
void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id, int asensdatasetix, const char *title) {
|
||||
//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();
|
||||
@ -48,7 +48,13 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id, int ase
|
||||
case LIGHT_RGBCW:
|
||||
sprintf(uniq_id, "%s_%s", longDeviceName, "light");
|
||||
break;
|
||||
|
||||
|
||||
case HASS_FAN:
|
||||
sprintf(uniq_id, "%s_fan", longDeviceName);
|
||||
break;
|
||||
case HASS_HVAC:
|
||||
sprintf(uniq_id, "%s_thermostat", longDeviceName);
|
||||
break;
|
||||
case RELAY:
|
||||
sprintf(uniq_id, "%s_%s_%d", longDeviceName, "relay", index);
|
||||
break;
|
||||
@ -129,6 +135,10 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id, int ase
|
||||
sprintf(uniq_id, "%s_%s_%d", longDeviceName, "sensor", index);
|
||||
break;
|
||||
}
|
||||
if (title) {
|
||||
strcat(uniq_id, "_");
|
||||
strcat(uniq_id, title);
|
||||
}
|
||||
// There can be no spaces in this name!
|
||||
// See: https://www.elektroda.com/rtvforum/topic4000620.html
|
||||
STR_ReplaceWhiteSpacesWithUnderscore(uniq_id);
|
||||
@ -142,7 +152,7 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id, int ase
|
||||
/// @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, asensdatasetix);
|
||||
hass_populate_unique_id(type, index, uniq_id, asensdatasetix, NULL);
|
||||
hprintf255(request, fmt, uniq_id);
|
||||
}
|
||||
|
||||
@ -165,6 +175,12 @@ void hass_populate_device_config_channel(ENTITY_TYPE type, char* uniq_id, HassDe
|
||||
case BINARY_SENSOR:
|
||||
sprintf(info->channel, "binary_sensor/%s/config", uniq_id);
|
||||
break;
|
||||
case HASS_HVAC:
|
||||
sprintf(info->channel, "climate/%s/config", uniq_id);
|
||||
break;
|
||||
case HASS_FAN:
|
||||
sprintf(info->channel, "fan/%s/config", uniq_id);
|
||||
break;
|
||||
case SMOKE_SENSOR:
|
||||
case CO2_SENSOR:
|
||||
case TVOC_SENSOR:
|
||||
@ -208,6 +224,186 @@ cJSON* hass_build_device_node(cJSON* ids) {
|
||||
return dev;
|
||||
}
|
||||
|
||||
// TODO, broken
|
||||
//HassDeviceInfo* hass_createFanWithModes(const char *label, const char *stateTopic, const char *command, const char **options, int numOptions) {
|
||||
// HassDeviceInfo* info = hass_init_device_info(HASS_FAN, 0, NULL, NULL, 0);
|
||||
// if (info == NULL) {
|
||||
// addLogAdv(LOG_ERROR, LOG_FEATURE_HASS, "Failed to initialize HassDeviceInfo for fan");
|
||||
// return NULL;
|
||||
// }
|
||||
//
|
||||
// cJSON_ReplaceItemInObject(info->root, "name", cJSON_CreateString(label));
|
||||
//
|
||||
// char uniq_id[HASS_UNIQUE_ID_SIZE];
|
||||
// snprintf(uniq_id, HASS_UNIQUE_ID_SIZE, "%s_%s", info->unique_id, label);
|
||||
// STR_ReplaceWhiteSpacesWithUnderscore(uniq_id);
|
||||
// cJSON_ReplaceItemInObject(info->root, "uniq_id", cJSON_CreateString(uniq_id));
|
||||
//
|
||||
// sprintf(info->channel, "fan/%s/config", uniq_id);
|
||||
// STR_ReplaceWhiteSpacesWithUnderscore(info->channel);
|
||||
//
|
||||
// cJSON_AddStringToObject(info->root, "pr_mode_stat_t", stateTopic);
|
||||
// sprintf(g_hassBuffer, "cmnd/%s/%s", CFG_GetMQTTClientId(), command);
|
||||
// cJSON_AddStringToObject(info->root, "pr_mode_cmd_t", g_hassBuffer);
|
||||
// cJSON_AddStringToObject(info->root, "dev_cla", "fan");
|
||||
// cJSON_AddItemToObject(info->root, "osc", cJSON_CreateBool(false));
|
||||
// cJSON_AddItemToObject(info->root, "percentage", cJSON_CreateBool(false));
|
||||
// cJSON_AddItemToObject(info->root, "pr_modes", cJSON_CreateStringArray(options, numOptions));
|
||||
//
|
||||
// return info;
|
||||
//}
|
||||
HassDeviceInfo* hass_createSelectEntity(const char* state_topic, const char* command_topic, int numoptions,
|
||||
const char* options[], const char* title) {
|
||||
// Initialize device info for a single select entity
|
||||
HassDeviceInfo* info = hass_init_device_info(HASS_SELECT, 0, NULL, NULL, 0, title);
|
||||
|
||||
// Set entity properties
|
||||
cJSON_AddStringToObject(info->root, "name", title);
|
||||
cJSON_AddStringToObject(info->root, "unique_id", title); // Using title as unique_id for simplicity; adjust if needed
|
||||
cJSON_AddStringToObject(info->root, "state_topic", state_topic);
|
||||
cJSON_AddStringToObject(info->root, "command_topic", command_topic);
|
||||
|
||||
// Create options array from provided options
|
||||
cJSON* select_options = cJSON_CreateArray();
|
||||
for (int i = 0; i < numoptions; i++) {
|
||||
cJSON_AddItemToArray(select_options, cJSON_CreateString(options[i]));
|
||||
}
|
||||
cJSON_AddItemToObject(info->root, "options", select_options);
|
||||
|
||||
// Set availability
|
||||
cJSON_AddStringToObject(info->root, "availability_topic", "~/status");
|
||||
cJSON_AddStringToObject(info->root, "payload_available", "online");
|
||||
cJSON_AddStringToObject(info->root, "payload_not_available", "offline");
|
||||
|
||||
// Set configuration channel for select entity
|
||||
sprintf(info->channel, "select/%s/config", info->unique_id);
|
||||
|
||||
// Update device info
|
||||
cJSON* dev = info->device;
|
||||
cJSON_ReplaceItemInObject(dev, "manufacturer", cJSON_CreateString("Custom"));
|
||||
cJSON_ReplaceItemInObject(dev, "model", cJSON_CreateString("C-Swing-Control"));
|
||||
|
||||
return info;
|
||||
}
|
||||
// Helper function to generate a dictionary string for value_template mapping integers to strings
|
||||
static void generate_value_template(int numoptions, const char* options[], char* buffer, size_t bufsize) {
|
||||
size_t len = 0;
|
||||
len += snprintf(buffer + len, bufsize - len, "{{ {");
|
||||
for (int i = 0; i < numoptions && len < bufsize; i++) {
|
||||
len += snprintf(buffer + len, bufsize - len, "'%d': '%s'%s", i, options[i], i < numoptions - 1 ? ", " : "");
|
||||
}
|
||||
snprintf(buffer + len, bufsize - len, "} [value] }}");
|
||||
}
|
||||
|
||||
// Helper function to generate a dictionary string for command_template mapping strings to integers
|
||||
static void generate_command_template(int numoptions, const char* options[], char* buffer, size_t bufsize) {
|
||||
size_t len = 0;
|
||||
len += snprintf(buffer + len, bufsize - len, "{{ {");
|
||||
for (int i = 0; i < numoptions && len < bufsize; i++) {
|
||||
len += snprintf(buffer + len, bufsize - len, "'%s': '%d'%s", options[i], i, i < numoptions - 1 ? ", " : "");
|
||||
}
|
||||
snprintf(buffer + len, bufsize - len, "} [value] }}");
|
||||
}
|
||||
|
||||
HassDeviceInfo* hass_createSelectEntityIndexed(const char* state_topic, const char* command_topic, int numoptions,
|
||||
const char* options[], const char* title) {
|
||||
HassDeviceInfo* info = hass_init_device_info(HASS_SELECT, 0, NULL, NULL, 0, title);
|
||||
|
||||
cJSON_AddStringToObject(info->root, "name", title);
|
||||
cJSON_AddStringToObject(info->root, "unique_id", title);
|
||||
cJSON_AddStringToObject(info->root, "state_topic", state_topic);
|
||||
cJSON_AddStringToObject(info->root, "command_topic", command_topic);
|
||||
|
||||
cJSON* select_options = cJSON_CreateArray();
|
||||
for (int i = 0; i < numoptions; i++) {
|
||||
cJSON_AddItemToArray(select_options, cJSON_CreateString(options[i]));
|
||||
}
|
||||
cJSON_AddItemToObject(info->root, "options", select_options);
|
||||
|
||||
char value_template[512];
|
||||
generate_value_template(numoptions, options, value_template, sizeof(value_template));
|
||||
cJSON_AddStringToObject(info->root, "value_template", value_template);
|
||||
|
||||
char command_template[512];
|
||||
generate_command_template(numoptions, options, command_template, sizeof(command_template));
|
||||
cJSON_AddStringToObject(info->root, "command_template", command_template);
|
||||
|
||||
cJSON_AddStringToObject(info->root, "availability_topic", "~/status");
|
||||
cJSON_AddStringToObject(info->root, "payload_available", "online");
|
||||
cJSON_AddStringToObject(info->root, "payload_not_available", "offline");
|
||||
|
||||
sprintf(info->channel, "select/%s/config", info->unique_id);
|
||||
|
||||
cJSON* dev = info->device;
|
||||
cJSON_ReplaceItemInObject(dev, "manufacturer", cJSON_CreateString("Custom"));
|
||||
cJSON_ReplaceItemInObject(dev, "model", cJSON_CreateString("C-Swing-Control"));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
HassDeviceInfo* hass_createHVAC(float min, float max, float step, const char **fanOptions, int numFanOptions) {
|
||||
HassDeviceInfo* info = hass_init_device_info(HASS_HVAC, 0, NULL, NULL, 0, 0);
|
||||
|
||||
// Set the name for the HVAC device
|
||||
cJSON_AddStringToObject(info->root, "name", "Smart Thermostat");
|
||||
|
||||
// Set temperature unit
|
||||
cJSON_AddStringToObject(info->root, "temperature_unit", "C");
|
||||
|
||||
// Set temperature topics
|
||||
cJSON_AddStringToObject(info->root, "current_temperature_topic", "~/CurrentTemperature/get");
|
||||
sprintf(g_hassBuffer, "cmnd/%s/TargetTemperature", CFG_GetMQTTClientId());
|
||||
cJSON_AddStringToObject(info->root, "temperature_command_topic", g_hassBuffer);
|
||||
cJSON_AddStringToObject(info->root, "temperature_state_topic", "~/TargetTemperature/get");
|
||||
|
||||
// Set temperature range and step
|
||||
cJSON_AddNumberToObject(info->root, "min_temp", min);
|
||||
cJSON_AddNumberToObject(info->root, "max_temp", max);
|
||||
cJSON_AddNumberToObject(info->root, "temp_step", step);
|
||||
|
||||
// Set mode topics
|
||||
cJSON_AddStringToObject(info->root, "mode_state_topic", "~/ACMode/get");
|
||||
sprintf(g_hassBuffer, "cmnd/%s/ACMode", CFG_GetMQTTClientId());
|
||||
cJSON_AddStringToObject(info->root, "mode_command_topic", g_hassBuffer);
|
||||
|
||||
// Add supported modes
|
||||
cJSON* modes = cJSON_CreateArray();
|
||||
cJSON_AddItemToArray(modes, cJSON_CreateString("off"));
|
||||
cJSON_AddItemToArray(modes, cJSON_CreateString("heat"));
|
||||
cJSON_AddItemToArray(modes, cJSON_CreateString("cool"));
|
||||
cJSON_AddItemToObject(info->root, "modes", modes);
|
||||
|
||||
if (fanOptions && numFanOptions) {
|
||||
// Add fan mode topics
|
||||
cJSON_AddStringToObject(info->root, "fan_mode_state_topic", "~/FanMode/get");
|
||||
sprintf(g_hassBuffer, "cmnd/%s/FanMode", CFG_GetMQTTClientId());
|
||||
cJSON_AddStringToObject(info->root, "fan_mode_command_topic", g_hassBuffer);
|
||||
|
||||
// Add supported fan modes
|
||||
cJSON* fan_modes = cJSON_CreateArray();
|
||||
for (int i = 0; i < numFanOptions; i++) {
|
||||
const char *mode = fanOptions[i];
|
||||
cJSON_AddItemToArray(fan_modes, cJSON_CreateString(mode));
|
||||
}
|
||||
cJSON_AddItemToArray(fan_modes, cJSON_CreateString("high"));
|
||||
cJSON_AddItemToObject(info->root, "fan_modes", fan_modes);
|
||||
}
|
||||
|
||||
// Set availability topic
|
||||
cJSON_AddStringToObject(info->root, "availability_topic", "~/status");
|
||||
cJSON_AddStringToObject(info->root, "payload_available", "online");
|
||||
cJSON_AddStringToObject(info->root, "payload_not_available", "offline");
|
||||
|
||||
// Update device configuration channel for HVAC
|
||||
sprintf(info->channel, "climate/%s/config", info->unique_id);
|
||||
|
||||
// Update device info
|
||||
cJSON* dev = info->device;
|
||||
cJSON_ReplaceItemInObject(dev, "manufacturer", cJSON_CreateString("Custom"));
|
||||
cJSON_ReplaceItemInObject(dev, "model", cJSON_CreateString("C-Thermo"));
|
||||
|
||||
return info;
|
||||
}
|
||||
/// @brief Initializes HomeAssistant device discovery storage with common values.
|
||||
/// @param type
|
||||
/// @param index This is used to generate generate unique_id and name.
|
||||
@ -217,11 +413,11 @@ cJSON* hass_build_device_node(cJSON* ids) {
|
||||
/// @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, int asensdatasetix) {
|
||||
HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* payload_on, const char* payload_off, int asensdatasetix, const char *title) {
|
||||
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, asensdatasetix);
|
||||
hass_populate_unique_id(type, index, info->unique_id, asensdatasetix, title);
|
||||
hass_populate_device_config_channel(type, info->unique_id, info);
|
||||
|
||||
info->ids = cJSON_CreateArray();
|
||||
@ -335,6 +531,10 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* p
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (title) {
|
||||
strcat(g_hassBuffer, "_");
|
||||
strcat(g_hassBuffer, title);
|
||||
}
|
||||
cJSON_AddStringToObject(info->root, "name", g_hassBuffer);
|
||||
cJSON_AddStringToObject(info->root, "~", CFG_GetMQTTClientId()); //base topic
|
||||
// remove availability information for sensor to keep last value visible on Home Assistant
|
||||
@ -362,16 +562,41 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* p
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
HassDeviceInfo* hass_createToggle(const char *label, const char *stateTopic, const char *command) {
|
||||
HassDeviceInfo* info = hass_init_device_info(RELAY, 0, "1", "0", 0, label);
|
||||
if (info == NULL) {
|
||||
addLogAdv(LOG_ERROR, LOG_FEATURE_HASS, "Failed to initialize HassDeviceInfo for toggle");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cJSON_ReplaceItemInObject(info->root, "name", cJSON_CreateString(label));
|
||||
|
||||
char uniq_id[HASS_UNIQUE_ID_SIZE];
|
||||
snprintf(uniq_id, HASS_UNIQUE_ID_SIZE, "%s_%s", info->unique_id, label);
|
||||
STR_ReplaceWhiteSpacesWithUnderscore(uniq_id);
|
||||
cJSON_ReplaceItemInObject(info->root, "uniq_id", cJSON_CreateString(uniq_id));
|
||||
|
||||
// update the discovery channel with the new unique_id
|
||||
sprintf(info->channel, "switch/%s/config", uniq_id);
|
||||
STR_ReplaceWhiteSpacesWithUnderscore(info->channel);
|
||||
|
||||
cJSON_AddStringToObject(info->root, "stat_t", stateTopic);
|
||||
sprintf(g_hassBuffer, "cmnd/%s/%s", CFG_GetMQTTClientId(), command);
|
||||
cJSON_AddStringToObject(info->root, "cmd_t", g_hassBuffer);
|
||||
|
||||
return info;
|
||||
}
|
||||
/// @brief Initializes HomeAssistant relay device discovery storage.
|
||||
/// @param index
|
||||
/// @return
|
||||
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", 0);
|
||||
info = hass_init_device_info(type, index, "0", "1", 0, NULL);
|
||||
}
|
||||
else {
|
||||
info = hass_init_device_info(type, index, "1", "0", 0);
|
||||
info = hass_init_device_info(type, index, "1", "0", 0, NULL);
|
||||
}
|
||||
|
||||
sprintf(g_hassBuffer, "~/%i/get", index);
|
||||
@ -393,7 +618,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", 0);
|
||||
info = hass_init_device_info(type, 1, "1", "0", 0, NULL);
|
||||
|
||||
switch (type) {
|
||||
case LIGHT_RGBCW:
|
||||
@ -464,7 +689,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, 0);
|
||||
HassDeviceInfo* info = hass_init_device_info(BINARY_SENSOR, index, payload_on, payload_off, 0, NULL);
|
||||
|
||||
sprintf(g_hassBuffer, "~/%i/get", index);
|
||||
cJSON_AddStringToObject(info->root, "stat_t", g_hassBuffer); //state_topic
|
||||
@ -490,7 +715,7 @@ HassDeviceInfo* hass_init_energy_sensor_device_info(int index, int asensdataseti
|
||||
//in twin mode, for ix0 is last OBK_CONSUMPTION_YESTERDAY, for ix1 ,OBK_CONSUMPTION_TODAY
|
||||
if ((index > OBK_CONSUMPTION_STORED_LAST[asensdatasetix]) && (index <= OBK_CONSUMPTION__DAILY_LAST)) return info;
|
||||
#endif
|
||||
info = hass_init_device_info(ENERGY_METER_SENSOR, index, NULL, NULL, asensdatasetix);
|
||||
info = hass_init_device_info(ENERGY_METER_SENSOR, index, NULL, NULL, asensdatasetix, NULL);
|
||||
|
||||
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)
|
||||
@ -555,7 +780,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", 0);
|
||||
dev_info = hass_init_device_info(LIGHT_PWM, toggle, "1", "0", 0, NULL);
|
||||
|
||||
sprintf(g_hassBuffer, "~/%i/get", toggle);
|
||||
cJSON_AddStringToObject(dev_info->root, "stat_t", g_hassBuffer); //state_topic
|
||||
@ -577,7 +802,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, 0); //using channel as index to generate uniqueId
|
||||
HassDeviceInfo* info = hass_init_device_info(type, channel, NULL, NULL, 0, NULL); //using channel as index to generate uniqueId
|
||||
|
||||
//https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes
|
||||
switch (type) {
|
||||
|
||||
@ -95,7 +95,9 @@ typedef enum {
|
||||
WATER_QUALITY_TDS,
|
||||
/// @brief Battery level sensor in perc, under channel topic
|
||||
BATTERY_CHANNEL_SENSOR,
|
||||
|
||||
HASS_HVAC,
|
||||
HASS_FAN,
|
||||
HASS_SELECT
|
||||
} ENTITY_TYPE;
|
||||
|
||||
//unique_id is defined in hass_populate_unique_id and is based on CFG_GetDeviceName() whose size is CGF_DEVICE_NAME_SIZE.
|
||||
@ -122,12 +124,21 @@ typedef struct HassDeviceInfo_s {
|
||||
|
||||
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, int asensdatasetix);
|
||||
HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, const char* payload_on, const char* payload_off, int asensdatasetix, const char *title);
|
||||
HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type);
|
||||
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);
|
||||
HassDeviceInfo* hass_createHVAC(float min, float max, float step, const char **fanOptions, int numFanOptions);
|
||||
HassDeviceInfo* hass_createFanWithModes(const char *label, const char *stateTopic,
|
||||
const char *command, const char **options, int numOptions);
|
||||
HassDeviceInfo* hass_createSelectEntity(const char* state_topic, const char* command_topic, int numoptions,
|
||||
const char* options[], const char* title);
|
||||
HassDeviceInfo* hass_createSelectEntityIndexed(const char* state_topic, const char* command_topic, int numoptions,
|
||||
const char* options[], const char* title);
|
||||
|
||||
HassDeviceInfo* hass_createToggle(const char *label, const char *stateTopic, const char *commandTopic);
|
||||
const char* hass_build_discovery_json(HassDeviceInfo* info);
|
||||
void hass_free_device_info(HassDeviceInfo* info);
|
||||
char *hass_generate_multiplyAndRound_template(int decimalPlacesForRounding, int decimalPointOffset, int divider);
|
||||
|
||||
@ -78,6 +78,7 @@ const char* g_typesLowMidHighHighest[] = { "Low","Mid","High","Highest" };
|
||||
const char* g_typesOffOnRemember[] = { "Off", "On", "Remember" };
|
||||
const char* g_typeLowMidHigh[] = { "Low","Mid","High" };
|
||||
const char* g_typesLowestLowMidHighHighest[] = { "Lowest", "Low", "Mid", "High", "Highest" };;
|
||||
const char* g_typeOpenStopClose[] = { "Open","Stop","Close" };
|
||||
|
||||
#define ADD_OPTION(t,a) if(type == t) { *numTypes = sizeof(a)/sizeof(a[0]); return a; }
|
||||
|
||||
@ -89,6 +90,7 @@ const char **Channel_GetOptionsForChannelType(int type, int *numTypes) {
|
||||
ADD_OPTION(ChType_LowMidHighHighest, g_typesLowMidHighHighest);
|
||||
ADD_OPTION(ChType_OffOnRemember, g_typesOffOnRemember);
|
||||
ADD_OPTION(ChType_LowMidHigh, g_typeLowMidHigh);
|
||||
ADD_OPTION(ChType_OpenStopClose, g_typeOpenStopClose);
|
||||
|
||||
*numTypes = 0;
|
||||
return 0;
|
||||
@ -495,6 +497,9 @@ int http_fn_index(http_request_t* request) {
|
||||
if (channelType == ChType_OffOnRemember) {
|
||||
what = "memory";
|
||||
}
|
||||
else if (channelType == ChType_OpenStopClose) {
|
||||
what = "mode";
|
||||
}
|
||||
else {
|
||||
what = "speed";
|
||||
}
|
||||
@ -1800,6 +1805,7 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
|
||||
hooks.free_fn = os_free;
|
||||
cJSON_InitHooks(&hooks);
|
||||
|
||||
DRV_OnHassDiscovery(topic);
|
||||
|
||||
#if ENABLE_ADVANCED_CHANNELTYPES_DISCOVERY
|
||||
// try to pair toggles with dimmers. This is needed only for TuyaMCU,
|
||||
@ -2024,7 +2030,7 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
|
||||
{
|
||||
dev_info = hass_init_sensor_device_info(READONLYLOWMIDHIGH_SENSOR, i, -1, -1, 1);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case ChType_BatteryLevelPercent:
|
||||
{
|
||||
dev_info = hass_init_sensor_device_info(BATTERY_CHANNEL_SENSOR, i, -1, -1, 1);
|
||||
@ -2172,6 +2178,30 @@ void doHomeAssistantDiscovery(const char* topic, http_request_t* request) {
|
||||
dev_info = hass_init_sensor_device_info(WATER_QUALITY_TDS, i, -1, 2, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
int numOptions;
|
||||
const char **options = Channel_GetOptionsForChannelType(type, &numOptions);
|
||||
if (options && numOptions) {
|
||||
// backlog setChannelType 2 LowMidHigh; scheduleHADiscovery 1
|
||||
// backlog setChannelType 3 OpenStopClose; scheduleHADiscovery 1
|
||||
char stateTopic[32];
|
||||
char cmdTopic[32];
|
||||
char title[64];
|
||||
// TODO: lengths
|
||||
strcpy(title, CHANNEL_GetLabel(i));
|
||||
sprintf(stateTopic, "~/%i/get", i);
|
||||
sprintf(cmdTopic, "~/%i/set", i);
|
||||
dev_info = hass_createSelectEntityIndexed(
|
||||
stateTopic,
|
||||
cmdTopic,
|
||||
numOptions,
|
||||
options,
|
||||
title
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (dev_info) {
|
||||
MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
|
||||
|
||||
Reference in New Issue
Block a user