diff --git a/src/driver/drv_main.c b/src/driver/drv_main.c index 17a16089a..11640efe3 100644 --- a/src/driver/drv_main.c +++ b/src/driver/drv_main.c @@ -116,9 +116,9 @@ static driver_t g_drivers[] = { { "CHT8305", CHT8305_Init, CHT8305_OnEverySecond, CHT8305_AppendInformationToHTTPIndexPage, NULL, NULL, NULL, false }, { "MAX72XX", DRV_MAX72XX_Init, NULL, NULL, NULL, NULL, NULL, false }, { "SHT3X", SHT3X_Init, NULL, SHT3X_AppendInformationToHTTPIndexPage, NULL, SHT3X_StopDriver, NULL, false }, - { "BATTERY", Batt_Init, Batt_OnEverySecond, Batt_AppendInformationToHTTPIndexPage, NULL, Batt_StopDriver, NULL, false }, + { "Battery", Batt_Init, Batt_OnEverySecond, Batt_AppendInformationToHTTPIndexPage, NULL, Batt_StopDriver, NULL, false }, #endif - { "Bridge", Bridge_driver_Init, NULL, NULL, Bridge_driver_QuickFrame, Bridge_driver_DeInit, Bridge_driver_OnChannelChanged, false } + { "Bridge", Bridge_driver_Init, NULL, NULL, Bridge_driver_QuickFrame, Bridge_driver_DeInit, Bridge_driver_OnChannelChanged, false } }; static const int g_numDrivers = sizeof(g_drivers) / sizeof(g_drivers[0]); diff --git a/src/httpserver/hass.c b/src/httpserver/hass.c index fd8272061..11892b84b 100644 --- a/src/httpserver/hass.c +++ b/src/httpserver/hass.c @@ -4,6 +4,7 @@ #include "../logging/logging.h" #include "../hal/hal_wifi.h" #include "../driver/drv_public.h" +#include "../new_pins.h" /* Abbreviated node names - https://www.home-assistant.io/docs/mqtt/discovery/ @@ -57,6 +58,12 @@ void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) { case HUMIDITY_SENSOR: sprintf(uniq_id, "%s_%s_%d", longDeviceName, "humidity", index); break; + case BATTERY_SENSOR: + sprintf(uniq_id, "%s_%s_%d", longDeviceName, "battery", index); + break; + case BATTERY_VOLTAGE_SENSOR: + sprintf(uniq_id, "%s_%s_%d", longDeviceName, "voltage", index); + break; } } @@ -90,6 +97,8 @@ void hass_populate_device_config_channel(ENTITY_TYPE type, char* uniq_id, HassDe break; case POWER_SENSOR: + case BATTERY_SENSOR: + case BATTERY_VOLTAGE_SENSOR: case TEMPERATURE_SENSOR: case HUMIDITY_SENSOR: sprintf(info->channel, "sensor/%s/config", uniq_id); @@ -177,10 +186,23 @@ HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, char* payload isSensor = true; sprintf(g_hassBuffer, "%s Humidity", CFG_GetShortDeviceName()); break; + case BATTERY_SENSOR: + isSensor = true; + sprintf(g_hassBuffer, "%s Battery", CFG_GetShortDeviceName()); + break; + case BATTERY_VOLTAGE_SENSOR: + isSensor = true; + sprintf(g_hassBuffer, "%s Voltage", CFG_GetShortDeviceName()); + break; } cJSON_AddStringToObject(info->root, "name", g_hassBuffer); cJSON_AddStringToObject(info->root, "~", CFG_GetMQTTClientId()); //base topic - cJSON_AddStringToObject(info->root, "avty_t", "~/connected"); //availability_topic, `online` value is broadcasted + // remove availability information for sensor to keep last value visible on Home Assistant + bool flagavty = false; + flagavty = CFG_HasFlag(OBK_FLAG_NOT_PUBLISH_AVAILABILITY_SENSOR); + if (!isSensor || !flagavty) { + cJSON_AddStringToObject(info->root, "avty_t", "~/connected"); //availability_topic, `online` value is broadcasted + } if (!isSensor) { //Sensors (except binary_sensor) don't use payload cJSON_AddStringToObject(info->root, "pl_on", payload_on); //payload_on @@ -338,19 +360,32 @@ HassDeviceInfo* hass_init_sensor_device_info(ENTITY_TYPE type, int channel) { //https://www.home-assistant.io/integrations/sensor.mqtt/ refers to value_template (val_tpl) //{{ float(value)*0.1 }} for value=12 give 1.2000000000000002, using round() to limit the decimal places cJSON_AddStringToObject(info->root, "val_tpl", "{{ float(value)*0.1|round(2) }}"); + sprintf(g_hassBuffer, "~/%d/get", channel); + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); break; case HUMIDITY_SENSOR: cJSON_AddStringToObject(info->root, "dev_cla", "humidity"); cJSON_AddStringToObject(info->root, "unit_of_meas", "%"); + sprintf(g_hassBuffer, "~/%d/get", channel); + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); + break; + case BATTERY_SENSOR: + cJSON_AddStringToObject(info->root, "dev_cla", "battery"); + cJSON_AddStringToObject(info->root, "unit_of_meas", "%"); + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, "~/battery/get"); + break; + case BATTERY_VOLTAGE_SENSOR: + cJSON_AddStringToObject(info->root, "dev_cla", "voltage"); + cJSON_AddStringToObject(info->root, "unit_of_meas", "mV"); + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, "~/voltage/get"); break; default: + sprintf(g_hassBuffer, "~/%d/get", channel); + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); return NULL; } - sprintf(g_hassBuffer, "~/%d/get", channel); - cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); - cJSON_AddStringToObject(info->root, "stat_cla", "measurement"); return info; } diff --git a/src/httpserver/hass.h b/src/httpserver/hass.h index fa640fa18..9529c8e0b 100644 --- a/src/httpserver/hass.h +++ b/src/httpserver/hass.h @@ -32,7 +32,13 @@ typedef enum { /// @brief Temperature sensor TEMPERATURE_SENSOR, /// @brief Humidity sensor - HUMIDITY_SENSOR + HUMIDITY_SENSOR, + + /// @brief Battery level sensor in perc + BATTERY_SENSOR, + /// @brief Battery votage sensor in mV + BATTERY_VOLTAGE_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. diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c index f93a08ce7..625d4924c 100644 --- a/src/httpserver/http_fns.c +++ b/src/httpserver/http_fns.c @@ -22,7 +22,7 @@ static char SUBMIT_AND_END_FORM[] = "
"; #ifdef WINDOWS - // nothing +// nothing #elif PLATFORM_BL602 #elif PLATFORM_W600 || PLATFORM_W800 @@ -30,12 +30,12 @@ static char SUBMIT_AND_END_FORM[] = "
#elif defined(PLATFORM_BK7231N) - // tuya-iotos-embeded-sdk-wifi-ble-bk7231n/sdk/include/tuya_hal_storage.h +// tuya-iotos-embeded-sdk-wifi-ble-bk7231n/sdk/include/tuya_hal_storage.h #include "tuya_hal_storage.h" #include "BkDriverFlash.h" #else - // REALLY? A typo in Tuya SDK? Storge? - // tuya-iotos-embeded-sdk-wifi-ble-bk7231t/platforms/bk7231t/tuya_os_adapter/include/driver/tuya_hal_storge.h +// REALLY? A typo in Tuya SDK? Storge? +// tuya-iotos-embeded-sdk-wifi-ble-bk7231t/platforms/bk7231t/tuya_os_adapter/include/driver/tuya_hal_storge.h #include "tuya_hal_storge.h" #include "BkDriverFlash.h" #endif @@ -134,10 +134,10 @@ void postFormAction(http_request_t* request, char* action, char* value) { hprintf255(request, "
", action, value); } -void poststr_h2(http_request_t* request, const char *content) { +void poststr_h2(http_request_t* request, const char* content) { hprintf255(request, "

%s

", content); } -void poststr_h4(http_request_t* request, const char *content) { +void poststr_h4(http_request_t* request, const char* content) { hprintf255(request, "

%s

", content); } @@ -374,7 +374,7 @@ int http_fn_index(http_request_t* request) { // DHT pin has two channels - temperature and humidity poststr(request, ""); iValue = CHANNEL_Get(PIN_GetPinChannelForPinIndex(i)); - hprintf255(request, "Sensor %s on pin %i temperature %.2fC", PIN_RoleToString(role), i, (float)(iValue*0.1f)); + hprintf255(request, "Sensor %s on pin %i temperature %.2fC", PIN_RoleToString(role), i, (float)(iValue * 0.1f)); iValue = CHANNEL_Get(PIN_GetPinChannel2ForPinIndex(i)); hprintf255(request, ", humidity %.1f%%
", (float)iValue); poststr(request, ""); @@ -855,12 +855,13 @@ int http_fn_index(http_request_t* request) { hprintf255(request, "
MQTT State: not configured
"); } else { - const char *stateStr; - const char *colorStr; + const char* stateStr; + const char* colorStr; if (mqtt_reconnect > 0) { stateStr = "awaiting reconnect"; colorStr = "orange"; - } else if (Main_HasMQTTConnected() == 1) { + } + else if (Main_HasMQTTConnected() == 1) { stateStr = "connected"; colorStr = "green"; } @@ -869,7 +870,7 @@ int http_fn_index(http_request_t* request) { colorStr = "yellow"; } hprintf255(request, "
MQTT State: %s RES: %d(%s)
", colorStr, - stateStr,MQTT_GetConnectResult(), get_error_name(MQTT_GetConnectResult())); + stateStr, MQTT_GetConnectResult(), get_error_name(MQTT_GetConnectResult())); hprintf255(request, "MQTT ErrMsg: %s
", (MQTT_GetStatusMessage() != NULL) ? MQTT_GetStatusMessage() : ""); hprintf255(request, "MQTT Stats:CONN: %d PUB: %d RECV: %d ERR: %d
", MQTT_GetConnectEvents(), MQTT_GetPublishEventCounter(), MQTT_GetReceivedEventCounter(), MQTT_GetPublishErrorCounter()); @@ -1424,7 +1425,7 @@ int http_fn_flash_read_tool(http_request_t* request) { poststr(request, NULL); return 0; } -const char *CMD_GetResultString(commandResult_t r) { +const char* CMD_GetResultString(commandResult_t r) { if (r == CMD_RES_OK) return "OK"; if (r == CMD_RES_EMPTY_STRING) @@ -1444,9 +1445,9 @@ void LOG_SetCommandHTTPRedirectReply(http_request_t* request); int http_fn_cmd_tool(http_request_t* request) { commandResult_t res; - const char *resStr; + const char* resStr; char tmpA[128]; - char *long_str_alloced = 0; + char* long_str_alloced = 0; int commandLen; http_setup(request, httpMimeTypeHTML); @@ -1608,7 +1609,7 @@ int http_fn_cfg_quick(http_request_t* request) { return 0; } -void doHomeAssistantDiscovery(const char *topic, http_request_t *request) { +void doHomeAssistantDiscovery(const char* topic, http_request_t* request) { int i; int relayCount; int pwmCount; @@ -1616,6 +1617,7 @@ void doHomeAssistantDiscovery(const char *topic, http_request_t *request) { bool ledDriverChipRunning; HassDeviceInfo* dev_info = NULL; bool measuringPower = false; + bool measuringBattery = false; struct cJSON_Hooks hooks; bool discoveryQueued = false; @@ -1626,6 +1628,9 @@ void doHomeAssistantDiscovery(const char *topic, http_request_t *request) { #ifndef OBK_DISABLE_ALL_DRIVERS measuringPower = DRV_IsMeasuringPower(); #endif +#if defined(PLATFORM_BEKEN) || defined(WINDOWS) + measuringBattery = DRV_IsRunning("Battery"); +#endif get_Relay_PWM_Count(&relayCount, &pwmCount, &dInputCount); @@ -1710,6 +1715,18 @@ void doHomeAssistantDiscovery(const char *topic, http_request_t *request) { } #endif + if (measuringBattery == true) { + dev_info = hass_init_sensor_device_info(BATTERY_SENSOR, 0); + 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_sensor_device_info(BATTERY_VOLTAGE_SENSOR, 0); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + + discoveryQueued = true; + } + for (i = 0; i < PLATFORM_GPIO_MAX; i++) { if (IS_PIN_DHT_ROLE(g_cfg.pins.roles[i]) || IS_PIN_TEMP_HUM_SENSOR_ROLE(g_cfg.pins.roles[i])) { dev_info = hass_init_sensor_device_info(TEMPERATURE_SENSOR, PIN_GetPinChannelForPinIndex(i)); @@ -1728,7 +1745,7 @@ void doHomeAssistantDiscovery(const char *topic, http_request_t *request) { MQTT_InvokeCommandAtEnd(PublishChannels); } else { - const char *msg = "No relay, PWM, sensor or power driver running."; + const char* msg = "No relay, PWM, sensor or power driver running."; if (request) { poststr(request, msg); poststr(request, NULL); @@ -1787,7 +1804,7 @@ void http_generate_cw_cfg(http_request_t* request, const char* clientId) { http_generate_singleColor_cfg(request, clientId); } -void hprintf_qos_payload(http_request_t* request, const char *clientId){ +void hprintf_qos_payload(http_request_t* request, const char* clientId) { poststr(request, " qos: 1\n"); poststr(request, " payload_on: 1\n"); poststr(request, " payload_off: 0\n"); @@ -1968,7 +1985,7 @@ int http_fn_ha_cfg(http_request_t* request) { return 0; } -const char *skipToNextWord(const char *p) { +const char* skipToNextWord(const char* p) { while (isWhiteSpace(*p) == false) { if (*p == 0) return p; @@ -1984,7 +2001,7 @@ const char *skipToNextWord(const char *p) { int http_fn_cm(http_request_t* request) { char tmpA[128]; - char *long_str_alloced = 0; + char* long_str_alloced = 0; int commandLen; http_setup(request, httpMimeTypeJson); @@ -2189,7 +2206,7 @@ int http_fn_cfg_pins(http_request_t* request) { } // Secondary linked channel // For button, is relay index to toggle on double click - if (si == IOR_Button || si == IOR_Button_n || IS_PIN_DHT_ROLE(si) || IS_PIN_TEMP_HUM_SENSOR_ROLE(si) ) + if (si == IOR_Button || si == IOR_Button_n || IS_PIN_DHT_ROLE(si) || IS_PIN_TEMP_HUM_SENSOR_ROLE(si)) { hprintf255(request, "", i, ch2); } @@ -2244,7 +2261,7 @@ const char* g_obk_flagNames[] = { "[LED] Use old linear brightness mode, ignore gamma ramp", "[MQTT] Apply channel type multiplier on (if any) on channel value before publishing it", "[MQTT] In HA discovery, add relays as lights", - "error", + "[HASS] Deactivate avty_t flag for sensor when publishing to HASS (permit to keep value)", "error", "error", "error", @@ -2474,7 +2491,7 @@ int http_fn_cfg_dgr(http_request_t* request) { void XR809_RequestOTAHTTP(const char* s); -void OTA_RequestDownloadFromHTTP(const char *s) { +void OTA_RequestDownloadFromHTTP(const char* s) { #if WINDOWS #elif PLATFORM_BL602 diff --git a/src/new_pins.h b/src/new_pins.h index a94e6fd53..0539fe3f3 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -81,8 +81,8 @@ enum IORole { IOR_SM2235_DAT, IOR_SM2235_CLK, - IOR_BridgeForward, - IOR_BridgeReverse, + IOR_BridgeForward, + IOR_BridgeReverse, // Smart LED button // Click = toggle power @@ -181,33 +181,33 @@ typedef enum { #if PLATFORM_W800 typedef struct pinsState_s { - // All above values are indexed by physical pin index - // (so we assume we have maximum of 32 pins) - byte roles[48]; - byte channels[48]; - // extra channels array - this is needed for - // buttons, so button can toggle one relay on single click - // and other relay on double click - byte channels2[48]; - // This single field above, is indexed by CHANNEL INDEX - // (not by pin index) - byte channelTypes[CHANNEL_MAX]; + // All above values are indexed by physical pin index + // (so we assume we have maximum of 32 pins) + byte roles[48]; + byte channels[48]; + // extra channels array - this is needed for + // buttons, so button can toggle one relay on single click + // and other relay on double click + byte channels2[48]; + // This single field above, is indexed by CHANNEL INDEX + // (not by pin index) + byte channelTypes[CHANNEL_MAX]; } pinsState_t; #else typedef struct pinsState_s { - // All above values are indexed by physical pin index - // (so we assume we have maximum of 32 pins) - byte roles[32]; - byte channels[32]; - // extra channels array - this is needed for - // buttons, so button can toggle one relay on single click - // and other relay on double click - byte channels2[32]; - // This single field above, is indexed by CHANNEL INDEX - // (not by pin index) - byte channelTypes[CHANNEL_MAX]; + // All above values are indexed by physical pin index + // (so we assume we have maximum of 32 pins) + byte roles[32]; + byte channels[32]; + // extra channels array - this is needed for + // buttons, so button can toggle one relay on single click + // and other relay on double click + byte channels2[32]; + // This single field above, is indexed by CHANNEL INDEX + // (not by pin index) + byte channelTypes[CHANNEL_MAX]; } pinsState_t; #endif @@ -248,8 +248,9 @@ typedef struct pinsState_s { #define OBK_FLAG_LED_USE_OLD_LINEAR_MODE 32 #define OBK_FLAG_PUBLISH_MULTIPLIED_VALUES 33 #define OBK_FLAG_MQTT_HASS_ADD_RELAYS_AS_LIGHTS 34 +#define OBK_FLAG_NOT_PUBLISH_AVAILABILITY_SENSOR 35 -#define OBK_TOTAL_FLAGS 35 +#define OBK_TOTAL_FLAGS 36 #define CGF_MQTT_CLIENT_ID_SIZE 64 @@ -374,11 +375,11 @@ typedef struct mainConfig_s { // offset 0x000004BC unsigned long LFS_Size; // szie of LFS volume. it's aligned against the end of OTA #if PLATFORM_W800 - byte unusedSectorAB[71]; + byte unusedSectorAB[71]; #else byte unusedSectorAB[119]; #endif - ledRemap_t ledRemap; + ledRemap_t ledRemap; led_corr_t led_corr; // alternate topic name for receiving MQTT commands // offset 0x00000554 @@ -403,7 +404,7 @@ extern char g_enable_pins; #define CHANNEL_SET_FLAG_SKIP_MQTT 2 #define CHANNEL_SET_FLAG_SILENT 4 -void PIN_ticks(void *param); +void PIN_ticks(void* param); void PIN_set_wifi_led(int value); void PIN_AddCommands(void); @@ -449,7 +450,7 @@ bool CHANNEL_IsInUse(int ch); void Channel_SaveInFlashIfNeeded(int ch); int CHANNEL_FindMaxValueForChannel(int ch); // cmd_channels.c -const char *CHANNEL_GetLabel(int ch); +const char* CHANNEL_GetLabel(int ch); //ledRemap_t *CFG_GetLEDRemap(); void get_Relay_PWM_Count(int* relayCount, int* pwmCount, int* dInputCount); @@ -461,9 +462,9 @@ int h_isChannelDigitalInput(int tg_ch); //int PIN_GetPWMIndexForPinIndex(int pin); int PIN_ParsePinRoleName(const char* name); -const char *PIN_RoleToString(int role); +const char* PIN_RoleToString(int role); -extern const char *g_channelTypeNames[]; +extern const char* g_channelTypeNames[]; // from new_builtin.c /*