Add support for binary sensor (digital input) in Home Assistant discovery (#586)

* Add support for binary sensor in Home Assistant discovery

* Fix broken builds
This commit is contained in:
Alexandre Oliveira
2023-01-07 00:28:37 +01:00
committed by GitHub
parent a5aa068f5e
commit 5f509064f0
5 changed files with 118 additions and 13 deletions

View File

@ -46,6 +46,10 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) {
case ENTITY_SENSOR:
sprintf(uniq_id, "%s_%s_%d", longDeviceName, "sensor", index);
break;
case ENTITY_BINARY_SENSOR:
sprintf(uniq_id, "%s_%s_%d", longDeviceName, "binary_sensor", index);
break;
}
}
@ -80,6 +84,9 @@ void hass_populate_device_config_channel(ENTITY_TYPE type, char* uniq_id, HassDe
case ENTITY_SENSOR:
sprintf(info->channel, "sensor/%s/config", uniq_id);
break;
case ENTITY_BINARY_SENSOR:
sprintf(info->channel, "binary_sensor/%s/config", uniq_id);
}
}
@ -128,6 +135,7 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, char* payload
switch (type) {
case ENTITY_LIGHT_PWM:
case ENTITY_RELAY:
case ENTITY_BINARY_SENSOR:
sprintf(g_hassBuffer, "%s %i", CFG_GetShortDeviceName(), index);
break;
case ENTITY_LIGHT_PWMCW:
@ -236,6 +244,18 @@ HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type) {
return info;
}
/// @brief Initializes HomeAssistant binary sensor device discovery storage.
/// @param index
/// @return
HassDeviceInfo* hass_init_binary_sensor_device_info(int index) {
HassDeviceInfo* info = hass_init_device_info(ENTITY_BINARY_SENSOR, index, "1", "0");
sprintf(g_hassBuffer, "~/%i/get", index);
cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); //state_topic
return info;
}
#ifndef OBK_DISABLE_ALL_DRIVERS
/// @brief Initializes HomeAssistant sensor device discovery storage.

View File

@ -21,7 +21,10 @@ typedef enum {
ENTITY_LIGHT_RGBCW,
/// @brief Sensor (voltage, current, power)
ENTITY_SENSOR
ENTITY_SENSOR,
/// @Brief Binary Sensor
ENTITY_BINARY_SENSOR
} ENTITY_TYPE;
//unique_id is defined in hass_populate_unique_id and is based on CFG_GetDeviceName() whose size is CGF_DEVICE_NAME_SIZE.
@ -50,5 +53,6 @@ void hass_print_unique_id(http_request_t* request, const char* fmt, ENTITY_TYPE
HassDeviceInfo* hass_init_relay_device_info(int index);
HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type);
HassDeviceInfo* hass_init_sensor_device_info(int index);
HassDeviceInfo* hass_init_binary_sensor_device_info(int index);
char* hass_build_discovery_json(HassDeviceInfo* info);
void hass_free_device_info(HassDeviceInfo* info);

View File

@ -1543,18 +1543,33 @@ int http_fn_cfg_quick(http_request_t* request) {
/// @brief Computes the Relay and PWM count.
/// @param relayCount Number of relay and LED channels.
/// @param pwmCount Number of PWM channels.
void get_Relay_PWM_Count(int* relayCount, int* pwmCount) {
void get_Relay_PWM_Count(int* relayCount, int* pwmCount, int* dInputCount) {
int i;
(*relayCount) = 0;
(*pwmCount) = 0;
(*dInputCount) = 0;
for (i = 0; i < PLATFORM_GPIO_MAX; i++) {
int role = PIN_GetPinRoleForPinIndex(i);
if (role == IOR_Relay || role == IOR_Relay_n || role == IOR_LED || role == IOR_LED_n) {
(*relayCount)++;
}
else if (role == IOR_PWM || role == IOR_PWM_n) {
(*pwmCount)++;
switch (role) {
case IOR_Relay:
case IOR_Relay_n:
case IOR_LED:
case IOR_LED_n:
(*relayCount)++;
break;
case IOR_PWM:
case IOR_PWM_n:
(*pwmCount)++;
break;
case IOR_DigitalInput:
case IOR_DigitalInput_n:
case IOR_DigitalInput_NoPup:
case IOR_DigitalInput_NoPup_n:
(*dInputCount)++;
break;
default:
break;
}
}
}
@ -1564,6 +1579,7 @@ void doHomeAssistantDiscovery(const char *topic, http_request_t *request) {
int i;
int relayCount;
int pwmCount;
int dInputCount;
bool ledDriverChipRunning;
HassDeviceInfo* dev_info = NULL;
bool measuringPower = false;
@ -1576,14 +1592,14 @@ void doHomeAssistantDiscovery(const char *topic, http_request_t *request) {
measuringPower = DRV_IsMeasuringPower();
#endif
get_Relay_PWM_Count(&relayCount, &pwmCount);
get_Relay_PWM_Count(&relayCount, &pwmCount, &dInputCount);
//Note: PublishChannels should be done for the last MQTT publish except for power measurement which always
//sends out MQTT updates.
ledDriverChipRunning = LED_IsLedDriverChipRunning();
if ((relayCount == 0) && (pwmCount == 0) && !measuringPower && !ledDriverChipRunning) {
const char *msg = "No relay, PWM or power driver running.";
if ((relayCount == 0) && (pwmCount == 0) && (dInputCount == 0) && !measuringPower && !ledDriverChipRunning) {
const char *msg = "No relay, PWM, binary sensor or power driver running.";
if (request) {
poststr(request, msg);
poststr(request, NULL);
@ -1622,6 +1638,30 @@ void doHomeAssistantDiscovery(const char *topic, http_request_t *request) {
}
}
if (dInputCount > 0) {
for (i = 0; i < CHANNEL_MAX; i++) {
if (h_isChannelDigitalInput(i)) {
if (dev_info != NULL) {
MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN);
hass_free_device_info(dev_info);
}
dev_info = hass_init_binary_sensor_device_info(i);
}
}
//Invoke publishChannels after the last topic
if (dev_info != NULL) {
PostPublishCommands ppCommand = PublishChannels;
if (ledDriverChipRunning || (pwmCount > 0)) {
ppCommand = None;
}
MQTT_QueuePublishWithCommand(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN, ppCommand);
hass_free_device_info(dev_info);
}
}
if (pwmCount == 5 || ledDriverChipRunning) {
// Enable + RGB control + CW control
dev_info = hass_init_light_device_info(ENTITY_LIGHT_RGBCW);
@ -1725,6 +1765,7 @@ void http_generate_singleColor_cfg(http_request_t* request, const char* clientId
int http_fn_ha_cfg(http_request_t* request) {
int relayCount;
int pwmCount;
int dInputCount;
const char* shortDeviceName;
const char* clientId;
int i;
@ -1747,7 +1788,7 @@ int http_fn_ha_cfg(http_request_t* request) {
poststr(request, "<textarea rows=\"40\" cols=\"50\">");
get_Relay_PWM_Count(&relayCount, &pwmCount);
get_Relay_PWM_Count(&relayCount, &pwmCount, &dInputCount);
if (relayCount > 0) {
@ -1775,6 +1816,30 @@ int http_fn_ha_cfg(http_request_t* request) {
}
}
}
if (dInputCount > 0) {
for (i = 0; i < CHANNEL_MAX; i++) {
if (h_isChannelDigitalInput(i)) {
if (mqttAdded == 0) {
poststr(request, "mqtt:\n");
mqttAdded = 1;
}
if (switchAdded == 0) {
poststr(request, " binary_sensor:\n");
switchAdded = 1;
}
hass_print_unique_id(request, " - unique_id: \"%s\"\n", ENTITY_BINARY_SENSOR, i);
hprintf255(request, " name: \"%s %i\"\n", shortDeviceName, i);
hprintf255(request, " state_topic: \"%s/%i/get\"\n", clientId, i);
poststr(request, " qos: 1\n");
poststr(request, " payload_on: 1\n");
poststr(request, " payload_off: 0\n");
poststr(request, " retain: true\n");
hprintf255(request, " availability:\n");
hprintf255(request, " - topic: \"%s/connected\"\n", clientId);
}
}
}
if (pwmCount == 5 || LED_IsLedDriverChipRunning()) {
// Enable + RGB control + CW control
if (mqttAdded == 0) {
@ -2170,7 +2235,7 @@ int http_tasmota_json_status_generic(http_request_t* request) {
const char* friendlyName;
const char* clientId;
int powerCode;
int relayCount, pwmCount, i;
int relayCount, pwmCount, dInputCount, i;
bool bRelayIndexingStartsWithZero;
char buff[20];
@ -2190,7 +2255,7 @@ int http_tasmota_json_status_generic(http_request_t* request) {
bRelayIndexingStartsWithZero = CHANNEL_HasChannelPinWithRoleOrRole(0, IOR_Relay, IOR_Relay_n);
get_Relay_PWM_Count(&relayCount, &pwmCount);
get_Relay_PWM_Count(&relayCount, &pwmCount, &dInputCount);
if (LED_IsLEDRunning()) {
powerCode = LED_GetEnableAll();