diff --git a/src/httpserver/hass.c b/src/httpserver/hass.c index 0c6c1cc86..d1b77d5ea 100644 --- a/src/httpserver/hass.c +++ b/src/httpserver/hass.c @@ -16,36 +16,36 @@ Sensor - https://www.home-assistant.io/integrations/sensor.mqtt/ //CFG_GetShortDeviceName and clientId so it needs to be bigger than them. +64 for light/switch/etc. static char g_hassBuffer[CGF_MQTT_CLIENT_ID_SIZE + 64]; -static char *STATE_TOPIC_KEY = "stat_t"; -static char *COMMAND_TOPIC_KEY = "cmd_t"; +static char* STATE_TOPIC_KEY = "stat_t"; +static char* COMMAND_TOPIC_KEY = "cmd_t"; /// @brief Populates HomeAssistant unique id for the entity. /// @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){ - //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(); - - switch(type){ - case ENTITY_LIGHT_PWM: - sprintf(uniq_id,"%s_%s_%d", longDeviceName, "light", index); - break; +void hass_populate_unique_id(ENTITY_TYPE type, int index, char* uniq_id) { + //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(); - case ENTITY_LIGHT_RGB: - case ENTITY_LIGHT_RGBCW: - sprintf(uniq_id,"%s_%s", longDeviceName, "light"); - break; - - case ENTITY_RELAY: - sprintf(uniq_id,"%s_%s_%d", longDeviceName, "relay", index); - break; + switch (type) { + case ENTITY_LIGHT_PWM: + sprintf(uniq_id, "%s_%s_%d", longDeviceName, "light", index); + break; - case ENTITY_SENSOR: - sprintf(uniq_id,"%s_%s_%d", longDeviceName, "sensor", index); - break; - } + case ENTITY_LIGHT_RGB: + case ENTITY_LIGHT_RGBCW: + sprintf(uniq_id, "%s_%s", longDeviceName, "light"); + break; + + case ENTITY_RELAY: + sprintf(uniq_id, "%s_%s_%d", longDeviceName, "relay", index); + break; + + case ENTITY_SENSOR: + sprintf(uniq_id, "%s_%s_%d", longDeviceName, "sensor", index); + break; + } } /// @brief Prints HomeAssistant unique id for the entity. @@ -53,52 +53,52 @@ 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){ - char uniq_id[HASS_UNIQUE_ID_SIZE]; - hass_populate_unique_id(type, index, uniq_id); - hprintf128(request, fmt, uniq_id); +void hass_print_unique_id(http_request_t* request, const char* fmt, ENTITY_TYPE type, int index) { + char uniq_id[HASS_UNIQUE_ID_SIZE]; + hass_populate_unique_id(type, index, uniq_id); + hprintf128(request, fmt, uniq_id); } /// @brief Populates HomeAssistant device configuration MQTT channel e.g. switch/enbrighten_9de8f9_relay_0/config. /// @param type Entity type /// @param uniq_id Entity unique id /// @param info Device info -void hass_populate_device_config_channel(ENTITY_TYPE type, char *uniq_id, HassDeviceInfo *info){ - switch(type){ - case ENTITY_LIGHT_PWM: - case ENTITY_LIGHT_RGB: - case ENTITY_LIGHT_RGBCW: - sprintf(info->channel, "light/%s/config", uniq_id); - break; - - case ENTITY_RELAY: - sprintf(info->channel, "switch/%s/config", uniq_id); - break; - - case ENTITY_SENSOR: - sprintf(info->channel, "sensor/%s/config", uniq_id); - break; - } +void hass_populate_device_config_channel(ENTITY_TYPE type, char* uniq_id, HassDeviceInfo* info) { + switch (type) { + case ENTITY_LIGHT_PWM: + case ENTITY_LIGHT_RGB: + case ENTITY_LIGHT_RGBCW: + sprintf(info->channel, "light/%s/config", uniq_id); + break; + + case ENTITY_RELAY: + sprintf(info->channel, "switch/%s/config", uniq_id); + break; + + case ENTITY_SENSOR: + sprintf(info->channel, "sensor/%s/config", uniq_id); + break; + } } /// @brief Builds HomeAssistant device discovery info. The caller needs to free the returned pointer. /// @param ids -cJSON *hass_build_device_node(cJSON *ids) { - cJSON *dev = cJSON_CreateObject(); - cJSON_AddItemToObject(dev, "ids", ids); //identifiers - cJSON_AddStringToObject(dev, "name", CFG_GetShortDeviceName()); +cJSON* hass_build_device_node(cJSON* ids) { + cJSON* dev = cJSON_CreateObject(); + cJSON_AddItemToObject(dev, "ids", ids); //identifiers + cJSON_AddStringToObject(dev, "name", CFG_GetShortDeviceName()); - #ifdef USER_SW_VER - cJSON_AddStringToObject(dev, "sw", USER_SW_VER); //sw_version - #endif +#ifdef USER_SW_VER + cJSON_AddStringToObject(dev, "sw", USER_SW_VER); //sw_version +#endif - cJSON_AddStringToObject(dev, "mf", MANUFACTURER); //manufacturer - cJSON_AddStringToObject(dev, "mdl", PLATFORM_MCU_NAME); //Using chipset for model + cJSON_AddStringToObject(dev, "mf", MANUFACTURER); //manufacturer + cJSON_AddStringToObject(dev, "mdl", PLATFORM_MCU_NAME); //Using chipset for model - sprintf(g_hassBuffer,"http://%s/index",HAL_GetMyIPString()); - cJSON_AddStringToObject(dev, "cu", g_hassBuffer); //configuration_url - - return dev; + sprintf(g_hassBuffer, "http://%s/index", HAL_GetMyIPString()); + cJSON_AddStringToObject(dev, "cu", g_hassBuffer); //configuration_url + + return dev; } /// @brief Initializes HomeAssistant device discovery storage with common values. @@ -107,162 +107,162 @@ cJSON *hass_build_device_node(cJSON *ids) { /// @param payload_on /// @param payload_off /// @return -HassDeviceInfo *hass_init_device_info(ENTITY_TYPE type, int index, char *payload_on, char *payload_off){ - HassDeviceInfo *info = os_malloc(sizeof(HassDeviceInfo)); - addLogAdv(LOG_INFO, LOG_FEATURE_HASS, "hass_init_device_info=%p", info); - - hass_populate_unique_id(type, index, info->unique_id); - hass_populate_device_config_channel(type, info->unique_id, info); - - info->ids = cJSON_CreateArray(); - cJSON_AddItemToArray(info->ids, cJSON_CreateString(CFG_GetDeviceName())); +HassDeviceInfo* hass_init_device_info(ENTITY_TYPE type, int index, char* payload_on, char* payload_off) { + HassDeviceInfo* info = os_malloc(sizeof(HassDeviceInfo)); + addLogAdv(LOG_INFO, LOG_FEATURE_HASS, "hass_init_device_info=%p", info); - info->device = hass_build_device_node(info->ids); + hass_populate_unique_id(type, index, info->unique_id); + hass_populate_device_config_channel(type, info->unique_id, info); - info->root = cJSON_CreateObject(); - cJSON_AddItemToObject(info->root, "dev", info->device); //device - - switch(type){ - case ENTITY_LIGHT_PWM: - case ENTITY_RELAY: - sprintf(g_hassBuffer,"%s %i",CFG_GetShortDeviceName(),index); - break; - case ENTITY_LIGHT_RGB: - case ENTITY_LIGHT_RGBCW: - //There can only be one RGB so we can skip including index in the name - sprintf(g_hassBuffer,"%s",CFG_GetShortDeviceName()); - break; - case ENTITY_SENSOR: + info->ids = cJSON_CreateArray(); + cJSON_AddItemToArray(info->ids, cJSON_CreateString(CFG_GetDeviceName())); + + info->device = hass_build_device_node(info->ids); + + info->root = cJSON_CreateObject(); + cJSON_AddItemToObject(info->root, "dev", info->device); //device + + switch (type) { + case ENTITY_LIGHT_PWM: + case ENTITY_RELAY: + sprintf(g_hassBuffer, "%s %i", CFG_GetShortDeviceName(), index); + break; + case ENTITY_LIGHT_RGB: + case ENTITY_LIGHT_RGBCW: + //There can only be one RGB so we can skip including index in the name + sprintf(g_hassBuffer, "%s", CFG_GetShortDeviceName()); + break; + case ENTITY_SENSOR: #ifndef OBK_DISABLE_ALL_DRIVERS - sprintf(g_hassBuffer,"%s %s",CFG_GetShortDeviceName(), sensor_mqttNames[index]); + sprintf(g_hassBuffer, "%s %s", CFG_GetShortDeviceName(), sensor_mqttNames[index]); #endif - break; - } - cJSON_AddStringToObject(info->root, "name", g_hassBuffer); + break; + } + cJSON_AddStringToObject(info->root, "name", g_hassBuffer); - cJSON_AddStringToObject(info->root, "~", CFG_GetMQTTClientId()); //base topic + cJSON_AddStringToObject(info->root, "~", CFG_GetMQTTClientId()); //base topic - cJSON_AddStringToObject(info->root, "avty_t", "~/connected"); //availability_topic, `online` value is broadcasted + cJSON_AddStringToObject(info->root, "avty_t", "~/connected"); //availability_topic, `online` value is broadcasted - cJSON_AddStringToObject(info->root, "pl_on", payload_on); //payload_on - cJSON_AddStringToObject(info->root, "pl_off", payload_off); //payload_off + cJSON_AddStringToObject(info->root, "pl_on", payload_on); //payload_on + cJSON_AddStringToObject(info->root, "pl_off", payload_off); //payload_off - cJSON_AddStringToObject(info->root, "uniq_id", info->unique_id); //unique_id + cJSON_AddStringToObject(info->root, "uniq_id", info->unique_id); //unique_id - addLogAdv(LOG_DEBUG, LOG_FEATURE_HASS, "root=%p", info->root); - return info; + addLogAdv(LOG_DEBUG, LOG_FEATURE_HASS, "root=%p", info->root); + return info; } /// @brief Initializes HomeAssistant relay device discovery storage. /// @param index /// @return -HassDeviceInfo *hass_init_relay_device_info(int index){ - HassDeviceInfo *info = hass_init_device_info(ENTITY_RELAY, index, "1", "0"); - cJSON_AddNumberToObject(info->root, "qos", 1); +HassDeviceInfo* hass_init_relay_device_info(int index) { + HassDeviceInfo* info = hass_init_device_info(ENTITY_RELAY, index, "1", "0"); + cJSON_AddNumberToObject(info->root, "qos", 1); - sprintf(g_hassBuffer,"~/%i/get",index); - cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); //state_topic - sprintf(g_hassBuffer,"~/%i/set",index); - cJSON_AddStringToObject(info->root, COMMAND_TOPIC_KEY, g_hassBuffer); //command_topic + sprintf(g_hassBuffer, "~/%i/get", index); + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); //state_topic + sprintf(g_hassBuffer, "~/%i/set", index); + cJSON_AddStringToObject(info->root, COMMAND_TOPIC_KEY, g_hassBuffer); //command_topic - return info; + return info; } /// @brief Initializes HomeAssistant light device discovery storage. /// @param type /// @param index Ignored for RGB, for sensor this corresponds to sensor_mqttNames. /// @return -HassDeviceInfo *hass_init_light_device_info(ENTITY_TYPE type, int index){ - const char *clientId = CFG_GetMQTTClientId(); - HassDeviceInfo *info = NULL; +HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type, int index) { + const char* clientId = CFG_GetMQTTClientId(); + HassDeviceInfo* info = NULL; - switch(type){ - case ENTITY_LIGHT_RGBCW: - case ENTITY_LIGHT_RGB: - info = hass_init_device_info(type, index, "1", "0"); + switch (type) { + case ENTITY_LIGHT_RGBCW: + case ENTITY_LIGHT_RGB: + info = hass_init_device_info(type, index, "1", "0"); - cJSON_AddStringToObject(info->root, "rgb_cmd_tpl","{{'#%02x%02x%02x0000'|format(red,green,blue)}}"); //rgb_command_template - cJSON_AddStringToObject(info->root, "rgb_val_tpl","{{value[1:3]|int(base=16)}},{{value[3:5]|int(base=16)}},{{value[5:7]|int(base=16)}}"); //rgb_value_template + cJSON_AddStringToObject(info->root, "rgb_cmd_tpl", "{{'#%02x%02x%02x0000'|format(red,green,blue)}}"); //rgb_command_template + cJSON_AddStringToObject(info->root, "rgb_val_tpl", "{{value[1:3]|int(base=16)}},{{value[3:5]|int(base=16)}},{{value[5:7]|int(base=16)}}"); //rgb_value_template - cJSON_AddStringToObject(info->root, "rgb_stat_t", "~/led_basecolor_rgb/get"); //rgb_state_topic - sprintf(g_hassBuffer,"cmnd/%s/led_basecolor_rgb",clientId); - cJSON_AddStringToObject(info->root, "rgb_cmd_t", g_hassBuffer); //rgb_command_topic + cJSON_AddStringToObject(info->root, "rgb_stat_t", "~/led_basecolor_rgb/get"); //rgb_state_topic + sprintf(g_hassBuffer, "cmnd/%s/led_basecolor_rgb", clientId); + cJSON_AddStringToObject(info->root, "rgb_cmd_t", g_hassBuffer); //rgb_command_topic - cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, "~/led_enableAll/get"); //state_topic - sprintf(g_hassBuffer,"cmnd/%s/led_enableAll",clientId); - cJSON_AddStringToObject(info->root, COMMAND_TOPIC_KEY, g_hassBuffer); //command_topic + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, "~/led_enableAll/get"); //state_topic + sprintf(g_hassBuffer, "cmnd/%s/led_enableAll", clientId); + cJSON_AddStringToObject(info->root, COMMAND_TOPIC_KEY, g_hassBuffer); //command_topic - cJSON_AddStringToObject(info->root, "bri_stat_t", "~/led_dimmer/get"); //brightness_state_topic - sprintf(g_hassBuffer,"cmnd/%s/led_dimmer",clientId); - cJSON_AddStringToObject(info->root, "bri_cmd_t", g_hassBuffer); //brightness_command_topic + cJSON_AddStringToObject(info->root, "bri_stat_t", "~/led_dimmer/get"); //brightness_state_topic + sprintf(g_hassBuffer, "cmnd/%s/led_dimmer", clientId); + cJSON_AddStringToObject(info->root, "bri_cmd_t", g_hassBuffer); //brightness_command_topic - cJSON_AddNumberToObject(info->root, "bri_scl", 100); //brightness_scale + cJSON_AddNumberToObject(info->root, "bri_scl", 100); //brightness_scale - if (type == ENTITY_LIGHT_RGBCW){ - sprintf(g_hassBuffer,"cmnd/%s/led_temperature",clientId); - cJSON_AddStringToObject(info->root, "clr_temp_cmd_t", g_hassBuffer); //color_temp_command_topic + if (type == ENTITY_LIGHT_RGBCW) { + sprintf(g_hassBuffer, "cmnd/%s/led_temperature", clientId); + cJSON_AddStringToObject(info->root, "clr_temp_cmd_t", g_hassBuffer); //color_temp_command_topic - cJSON_AddStringToObject(info->root, "clr_temp_stat_t", "~/led_temperature/get"); //color_temp_state_topic - } + cJSON_AddStringToObject(info->root, "clr_temp_stat_t", "~/led_temperature/get"); //color_temp_state_topic + } - break; + break; - case ENTITY_LIGHT_PWM: - info = hass_init_device_info(type, index, "99", "0"); - cJSON_AddStringToObject(info->root, "on_cmd_type", "brightness"); //on_command_type - cJSON_AddNumberToObject(info->root, "bri_scl", 99); //brightness_scale - cJSON_AddBoolToObject(info->root, "opt", cJSON_True); //optimistic - cJSON_AddNumberToObject(info->root, "qos", 1); - - cJSON_AddStringToObject(info->root, "bri_stat_t", "~/led_dimmer/get"); //brightness_state_topic - sprintf(g_hassBuffer,"cmnd/%s/led_dimmer",clientId); - cJSON_AddStringToObject(info->root, "bri_cmd_t", g_hassBuffer); //brightness_command_topic + case ENTITY_LIGHT_PWM: + info = hass_init_device_info(type, index, "99", "0"); + cJSON_AddStringToObject(info->root, "on_cmd_type", "brightness"); //on_command_type + cJSON_AddNumberToObject(info->root, "bri_scl", 99); //brightness_scale + cJSON_AddBoolToObject(info->root, "opt", cJSON_True); //optimistic + cJSON_AddNumberToObject(info->root, "qos", 1); - sprintf(g_hassBuffer,"~/%i/get",index); - cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); //state_topic - sprintf(g_hassBuffer,"~/%i/set",index); - cJSON_AddStringToObject(info->root, COMMAND_TOPIC_KEY, g_hassBuffer); //command_topic + cJSON_AddStringToObject(info->root, "bri_stat_t", "~/led_dimmer/get"); //brightness_state_topic + sprintf(g_hassBuffer, "cmnd/%s/led_dimmer", clientId); + cJSON_AddStringToObject(info->root, "bri_cmd_t", g_hassBuffer); //brightness_command_topic - break; - - case ENTITY_SENSOR: + sprintf(g_hassBuffer, "~/%i/get", index); + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); //state_topic + sprintf(g_hassBuffer, "~/%i/set", index); + cJSON_AddStringToObject(info->root, COMMAND_TOPIC_KEY, g_hassBuffer); //command_topic + + break; + + case ENTITY_SENSOR: #ifndef OBK_DISABLE_ALL_DRIVERS - info = hass_init_device_info(type, index, "1", "0"); + info = hass_init_device_info(type, index, "1", "0"); - //https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes - //device_class automatically assigns unit,icon - cJSON_AddStringToObject(info->root, "dev_cla", sensor_mqttNames[index]); //device_class=voltage,current,power - - sprintf(g_hassBuffer,"%s/%s/get",clientId,sensor_mqttNames[index]); - cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); + //https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes + //device_class automatically assigns unit,icon + cJSON_AddStringToObject(info->root, "dev_cla", sensor_mqttNames[index]); //device_class=voltage,current,power + + sprintf(g_hassBuffer, "%s/%s/get", clientId, sensor_mqttNames[index]); + cJSON_AddStringToObject(info->root, STATE_TOPIC_KEY, g_hassBuffer); #endif - break; + break; - default: - addLogAdv(LOG_ERROR, LOG_FEATURE_HASS, "Unsupported light type %s", type); - } - - return info; + default: + addLogAdv(LOG_ERROR, LOG_FEATURE_HASS, "Unsupported light type %s", type); + } + + return info; } /// @brief Returns the discovery JSON. /// @param info /// @return -char *hass_build_discovery_json(HassDeviceInfo *info){ - cJSON_PrintPreallocated(info->root, info->json, HASS_JSON_SIZE, 0); - return info->json; +char* hass_build_discovery_json(HassDeviceInfo* info) { + cJSON_PrintPreallocated(info->root, info->json, HASS_JSON_SIZE, 0); + return info->json; } /// @brief Release allocated memory. /// @param info -void hass_free_device_info(HassDeviceInfo *info){ - if (info == NULL) return; - addLogAdv(LOG_DEBUG, LOG_FEATURE_HASS, "hass_free_device_info \r\n"); - - if (info->root != NULL){ - cJSON_Delete(info->root); - } +void hass_free_device_info(HassDeviceInfo* info) { + if (info == NULL) return; + addLogAdv(LOG_DEBUG, LOG_FEATURE_HASS, "hass_free_device_info \r\n"); - os_free(info); + if (info->root != NULL) { + cJSON_Delete(info->root); + } + + os_free(info); } diff --git a/src/httpserver/hass.h b/src/httpserver/hass.h index b5a94fc70..c957288fe 100644 --- a/src/httpserver/hass.h +++ b/src/httpserver/hass.h @@ -6,10 +6,10 @@ typedef enum { ENTITY_RELAY = 0, - ENTITY_LIGHT_PWM = 1, - ENTITY_LIGHT_RGB = 2, - ENTITY_LIGHT_RGBCW = 3, - ENTITY_SENSOR = 4, + ENTITY_LIGHT_PWM = 1, + ENTITY_LIGHT_RGB = 2, + ENTITY_LIGHT_RGBCW = 3, + ENTITY_SENSOR = 4, } ENTITY_TYPE; //unique_id is defined in hass_populate_unique_id and is based on CFG_GetDeviceName() whose size is CGF_DEVICE_NAME_SIZE. @@ -24,18 +24,18 @@ typedef enum { #define HASS_JSON_SIZE (MQTT_PUBLISH_ITEM_VALUE_LENGTH - 1) /// @brief HomeAssistant device discovery information -typedef struct HassDeviceInfo_s{ - char unique_id[HASS_UNIQUE_ID_SIZE]; - char channel[HASS_CHANNEL_SIZE]; - char json[HASS_JSON_SIZE]; +typedef struct HassDeviceInfo_s { + char unique_id[HASS_UNIQUE_ID_SIZE]; + char channel[HASS_CHANNEL_SIZE]; + char json[HASS_JSON_SIZE]; - cJSON *root; - cJSON *device; - cJSON *ids; + cJSON* root; + cJSON* device; + cJSON* ids; } HassDeviceInfo; -void hass_print_unique_id(http_request_t *request, const char *fmt, ENTITY_TYPE type, int index); -HassDeviceInfo *hass_init_relay_device_info(int index); -HassDeviceInfo *hass_init_light_device_info(ENTITY_TYPE type, int index); -char *hass_build_discovery_json(HassDeviceInfo *info); -void hass_free_device_info(HassDeviceInfo *info); +void hass_print_unique_id(http_request_t* request, const char* fmt, ENTITY_TYPE type, int index); +HassDeviceInfo* hass_init_relay_device_info(int index); +HassDeviceInfo* hass_init_light_device_info(ENTITY_TYPE type, int index); +char* hass_build_discovery_json(HassDeviceInfo* info); +void hass_free_device_info(HassDeviceInfo* info); diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c index cb59619f9..23b2779a5 100644 --- a/src/httpserver/http_fns.c +++ b/src/httpserver/http_fns.c @@ -17,42 +17,42 @@ #include "../cJSON/cJSON.h" #ifdef WINDOWS - // nothing + // nothing #elif PLATFORM_BL602 #elif PLATFORM_W600 || PLATFORM_W800 #elif PLATFORM_XR809 - #include +#include #elif defined(PLATFORM_BK7231N) - // tuya-iotos-embeded-sdk-wifi-ble-bk7231n/sdk/include/tuya_hal_storage.h - #include "tuya_hal_storage.h" - #include "BkDriverFlash.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 - #include "tuya_hal_storge.h" - #include "BkDriverFlash.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 -static char *UNIQUE_ID_FORMAT = " - unique_id: \"%s\"\n"; -static char *HASS_INDEXED_NAME_CONFIG = " name: \"%s %i\"\n"; -static char *HASS_STATE_TOPIC_CONFIG = " state_topic: \"%s/%i/get\"\n"; -static char *HASS_COMMAND_TOPIC_CONFIG = " command_topic: \"%s/%i/set\"\n"; -static char *HASS_RETAIN_TRUE_CONFIG = " retain: true\n"; -static char *HASS_AVAILABILITY_CONFIG = " availability:\n"; -static char *HASS_CONNECTED_TOPIC_CONFIG = " - topic: \"%s/connected\"\n"; -static char *HASS_QOS_CONFIG = " qos: 1\n"; +static char* UNIQUE_ID_FORMAT = " - unique_id: \"%s\"\n"; +static char* HASS_INDEXED_NAME_CONFIG = " name: \"%s %i\"\n"; +static char* HASS_STATE_TOPIC_CONFIG = " state_topic: \"%s/%i/get\"\n"; +static char* HASS_COMMAND_TOPIC_CONFIG = " command_topic: \"%s/%i/set\"\n"; +static char* HASS_RETAIN_TRUE_CONFIG = " retain: true\n"; +static char* HASS_AVAILABILITY_CONFIG = " availability:\n"; +static char* HASS_CONNECTED_TOPIC_CONFIG = " - topic: \"%s/connected\"\n"; +static char* HASS_QOS_CONFIG = " qos: 1\n"; -static char *HASS_MQTT_NODE = "mqtt:\n"; -static char *HASS_LIGHT_NODE = " light:\n"; +static char* HASS_MQTT_NODE = "mqtt:\n"; +static char* HASS_LIGHT_NODE = " light:\n"; typedef struct template_s { void (*setter)(); - const char *name; + const char* name; } template_t; -template_t g_templates [] = { +template_t g_templates[] = { { Setup_Device_Empty, "Empty"}, // BK7231N devices { Setup_Device_BK7231N_CB2S_QiachipSmartSwitch, "[BK7231N][CB2S] QiaChip Smart Switch"}, @@ -73,49 +73,49 @@ template_t g_templates [] = { { Setup_Device_EmaxHome_EDU8774, "Emax Home EDU8774 SmartPlug 16A"}, { Setup_Device_BK7231N_TuyaLightBulb_RGBCW_5PWMs, "Tuya E27 LED RGBCW 5PWMs BK7231N"}, { Setup_Device_TuyaSmartPFW02G, "Tuya Smart PFW02-G"}, - { Setup_Device_AvatarASL04, "Avatar ASL04 5v LED strip"}, - { Setup_Device_BL602_MagicHome_IR_RGB_LedStrip, "BL602 Magic Home LED RGB IR Strip"}, - { Setup_Device_BL602_MagicHome_CCT_LedStrip, "BL602 Magic Home LED CCT Strip"}, - { Setup_Device_Sonoff_MiniR3, "Sonoff MiniR3"}, - { Setup_Device_WiFi_DIY_Switch_WB2S_ZN268131, "WB2S WiFi DIY Switch ZN268131"}, + { Setup_Device_AvatarASL04, "Avatar ASL04 5v LED strip"}, + { Setup_Device_BL602_MagicHome_IR_RGB_LedStrip, "BL602 Magic Home LED RGB IR Strip"}, + { Setup_Device_BL602_MagicHome_CCT_LedStrip, "BL602 Magic Home LED CCT Strip"}, + { Setup_Device_Sonoff_MiniR3, "Sonoff MiniR3"}, + { Setup_Device_WiFi_DIY_Switch_WB2S_ZN268131, "WB2S WiFi DIY Switch ZN268131"}, { Setup_Device_DS_102_1Gang_WB3S, "DS-102 1 Gang Switch"}, { Setup_Device_DS_102_2Gang_WB3S, "DS-102 2 Gang Switch"}, { Setup_Device_DS_102_3Gang_WB3S, "DS-102 3 Gang Switch"}, - { Setup_Device_TuyaSmartWIFISwith_4Gang_CB3S, "[BK7231N][CB3S] Tuya Smart Wifi Switch 4 Gang"}, - { Setup_Device_BK7231N_CB2S_LSPA9_BL0942, "[BK7231N][CB2S] LSPA9 power metering plug BL0942 version"}, - { Setup_Device_LSC_Smart_Connect_Plug_CB2S, "[BK7231N][CB2S] LSC Smart Connect Plug"}, + { Setup_Device_TuyaSmartWIFISwith_4Gang_CB3S, "[BK7231N][CB3S] Tuya Smart Wifi Switch 4 Gang"}, + { Setup_Device_BK7231N_CB2S_LSPA9_BL0942, "[BK7231N][CB2S] LSPA9 power metering plug BL0942 version"}, + { Setup_Device_LSC_Smart_Connect_Plug_CB2S, "[BK7231N][CB2S] LSC Smart Connect Plug"}, { Setup_Device_BK7231T_Gosund_Switch_SW5_A_V2_1, "BK7231T Gosund Smart Switch SW5-A-V2.1"}, { Setup_Device_13A_Socket_CB2S, "BK7231N CB2S 13A Aliexpress socket"}, - { Setup_Device_Deta_Smart_Double_Power_Point_6922HA_Series2, "BK7231T DETA SMART Double Power Point 6922HA-Series 2"}, - { Setup_Device_ArlecRGBCCTDownlight, "Arlec RGB+CCT LED Downlight ALD092RHA"}, - { Setup_Device_CasaLifeCCTDownlight, "CasaLife CCT LED Downlight SMART-AL2017-TGTS"}, - { Setup_Device_Enbrighten_WFD4103, "Enbrighten WFD4103 WiFi Switch BK7231T WB2S"} , - { Setup_Device_Zemismart_Light_Switch_KS_811_3, "Zemismart Light Switch (Neutral Optional) KS_811_3"} , - { Setup_Device_TeslaSmartPlus_TSL_SPL_1, "Tesla Smart Plug. Model: (TSL-SPL-1)"}, - { Setup_Device_Calex_900011_1_WB2S, "Calex Smart Power Plug 900011.1"} + { Setup_Device_Deta_Smart_Double_Power_Point_6922HA_Series2, "BK7231T DETA SMART Double Power Point 6922HA-Series 2"}, + { Setup_Device_ArlecRGBCCTDownlight, "Arlec RGB+CCT LED Downlight ALD092RHA"}, + { Setup_Device_CasaLifeCCTDownlight, "CasaLife CCT LED Downlight SMART-AL2017-TGTS"}, + { Setup_Device_Enbrighten_WFD4103, "Enbrighten WFD4103 WiFi Switch BK7231T WB2S"} , + { Setup_Device_Zemismart_Light_Switch_KS_811_3, "Zemismart Light Switch (Neutral Optional) KS_811_3"} , + { Setup_Device_TeslaSmartPlus_TSL_SPL_1, "Tesla Smart Plug. Model: (TSL-SPL-1)"}, + { Setup_Device_Calex_900011_1_WB2S, "Calex Smart Power Plug 900011.1"} }; -int g_total_templates = sizeof(g_templates)/sizeof(g_templates[0]); +int g_total_templates = sizeof(g_templates) / sizeof(g_templates[0]); -unsigned char hexdigit( char hex ) { - return (hex <= '9') ? hex - '0' : - toupper((unsigned char)hex) - 'A' + 10 ; +unsigned char hexdigit(char hex) { + return (hex <= '9') ? hex - '0' : + toupper((unsigned char)hex) - 'A' + 10; } -unsigned char hexbyte( const char* hex ) { - return (hexdigit(*hex) << 4) | hexdigit(*(hex+1)) ; +unsigned char hexbyte(const char* hex) { + return (hexdigit(*hex) << 4) | hexdigit(*(hex + 1)); } -int http_fn_empty_url(http_request_t *request) { - poststr(request,"HTTP/1.1 302 OK\nLocation: /index\nConnection: close\n\n"); +int http_fn_empty_url(http_request_t* request) { + poststr(request, "HTTP/1.1 302 OK\nLocation: /index\nConnection: close\n\n"); poststr(request, NULL); - return 0; + return 0; } -void postFormAction(http_request_t *request, char *action, char *value){ - //"
" - hprintf128(request,"
", action, value); +void postFormAction(http_request_t* request, char* action, char* value) { + //"
" + hprintf128(request, "
", action, value); } /// @brief Generate a pair of label and field elements. @@ -124,14 +124,14 @@ void postFormAction(http_request_t *request, char *action, char *value){ /// @param fieldId This also gets used as the field name /// @param value /// @param preContent -void add_label_input(http_request_t *request, char *inputType, char *label, char *fieldId, const char *value, char *preContent){ - if (strlen(preContent) > 0){ - poststr(request, preContent); - } - - //These individual strings should be less than 256 .. yes hprintf128 uses 256 char buffer - hprintf128(request, "
", fieldId, label); - hprintf128(request, "", inputType, fieldId, fieldId, value); +void add_label_input(http_request_t* request, char* inputType, char* label, char* fieldId, const char* value, char* preContent) { + if (strlen(preContent) > 0) { + poststr(request, preContent); + } + + //These individual strings should be less than 256 .. yes hprintf128 uses 256 char buffer + hprintf128(request, "
", fieldId, label); + hprintf128(request, "", inputType, fieldId, fieldId, value); } /// @brief Generates a pair of label and text field elements. @@ -140,8 +140,8 @@ void add_label_input(http_request_t *request, char *inputType, char *label, char /// @param fieldId Field id, this also gets used as the name /// @param value String value /// @param preContent Content before the label -void add_label_text_field(http_request_t *request, char *label, char *fieldId, const char *value, char *preContent){ - add_label_input(request, "text", label, fieldId, value, preContent); +void add_label_text_field(http_request_t* request, char* label, char* fieldId, const char* value, char* preContent) { + add_label_input(request, "text", label, fieldId, value, preContent); } /// @brief Generate a pair of label and numeric field elements. @@ -150,21 +150,21 @@ void add_label_text_field(http_request_t *request, char *label, char *fieldId, c /// @param fieldId Field id, this also gets used as the name /// @param value Integer value /// @param preContent Content before the label -void add_label_numeric_field(http_request_t *request, char *label, char *fieldId, int value, char *preContent){ - char strValue[32]; - sprintf(strValue, "%i", value); - add_label_input(request, "number", label, fieldId, strValue, preContent); +void add_label_numeric_field(http_request_t* request, char* label, char* fieldId, int value, char* preContent) { + char strValue[32]; + sprintf(strValue, "%i", value); + add_label_input(request, "number", label, fieldId, strValue, preContent); } -int http_fn_testmsg(http_request_t *request) { - poststr(request,"This is just a test msg\n\n"); +int http_fn_testmsg(http_request_t* request) { + poststr(request, "This is just a test msg\n\n"); poststr(request, NULL); - return 0; + return 0; } -int http_fn_index(http_request_t *request) { - int j, i; +int http_fn_index(http_request_t* request) { + int j, i; char tmpA[128]; int bRawPWMs; int forceShowRGBCW; @@ -172,1017 +172,1043 @@ int http_fn_index(http_request_t *request) { bRawPWMs = CFG_HasFlag(OBK_FLAG_LED_RAWCHANNELSMODE); forceShowRGBCW = CFG_HasFlag(OBK_FLAG_LED_FORCESHOWRGBCWCONTROLLER); - http_setup(request, httpMimeTypeHTML); //Add mimetype regardless of the request + http_setup(request, httpMimeTypeHTML); //Add mimetype regardless of the request - // use ?state URL parameter to only request current state - if(!http_getArg(request->url, "state", tmpA, sizeof(tmpA))) { - http_html_start(request, NULL); + // use ?state URL parameter to only request current state + if (!http_getArg(request->url, "state", tmpA, sizeof(tmpA))) { + http_html_start(request, NULL); - poststr(request, "
"); - if(http_getArg(request->url,"tgl",tmpA,sizeof(tmpA))) { - j = atoi(tmpA); - if(j == SPECIAL_CHANNEL_LEDPOWER) { - hprintf128(request,"

Toggled LED power!

",j); - } else { - hprintf128(request,"

Toggled %i!

",j); - } - CHANNEL_Toggle(j); - } - if(http_getArg(request->url,"on",tmpA,sizeof(tmpA))) { - j = atoi(tmpA); - hprintf128(request,"

Enabled %i!

",j); - CHANNEL_Set(j,255,1); - } - if(http_getArg(request->url,"rgb",tmpA,sizeof(tmpA))) { - hprintf128(request,"

Set RGB to %s!

",tmpA); - LED_SetBaseColor(0,"led_basecolor",tmpA,0); - } - - if(http_getArg(request->url,"off",tmpA,sizeof(tmpA))) { - j = atoi(tmpA); - hprintf128(request,"

Disabled %i!

",j); - CHANNEL_Set(j,0,1); - } - if(http_getArg(request->url,"pwm",tmpA,sizeof(tmpA))) { - int newPWMValue = atoi(tmpA); - http_getArg(request->url,"pwmIndex",tmpA,sizeof(tmpA)); - j = atoi(tmpA); - if(j == SPECIAL_CHANNEL_TEMPERATURE) { - hprintf128(request,"

Changed Temperature to %i!

",newPWMValue); - } else { - hprintf128(request,"

Changed pwm %i to %i!

",j,newPWMValue); - } - CHANNEL_Set(j,newPWMValue,1); - } - if(http_getArg(request->url,"dim",tmpA,sizeof(tmpA))) { - int newDimmerValue = atoi(tmpA); - http_getArg(request->url,"dimIndex",tmpA,sizeof(tmpA)); - j = atoi(tmpA); - if(j == SPECIAL_CHANNEL_BRIGHTNESS) { - hprintf128(request,"

Changed LED brightness to %i!

",newDimmerValue); - } else { - hprintf128(request,"

Changed dimmer %i to %i!

",j,newDimmerValue); - } - CHANNEL_Set(j,newDimmerValue,1); - } - if(http_getArg(request->url,"set",tmpA,sizeof(tmpA))) { - int newSetValue = atoi(tmpA); - http_getArg(request->url,"setIndex",tmpA,sizeof(tmpA)); - j = atoi(tmpA); - hprintf128(request,"

Changed channel %i to %i!

",j,newSetValue); - CHANNEL_Set(j,newSetValue,1); - } - if(http_getArg(request->url,"restart",tmpA,sizeof(tmpA))) { - poststr(request,"
Module will restart soon
"); - RESET_ScheduleModuleReset(3); - } - poststr(request, "
"); // end div#change - poststr(request, "
"); // replaceable content follows - } + poststr(request, "
"); + if (http_getArg(request->url, "tgl", tmpA, sizeof(tmpA))) { + j = atoi(tmpA); + if (j == SPECIAL_CHANNEL_LEDPOWER) { + hprintf128(request, "

Toggled LED power!

", j); + } + else { + hprintf128(request, "

Toggled %i!

", j); + } + CHANNEL_Toggle(j); + } + if (http_getArg(request->url, "on", tmpA, sizeof(tmpA))) { + j = atoi(tmpA); + hprintf128(request, "

Enabled %i!

", j); + CHANNEL_Set(j, 255, 1); + } + if (http_getArg(request->url, "rgb", tmpA, sizeof(tmpA))) { + hprintf128(request, "

Set RGB to %s!

", tmpA); + LED_SetBaseColor(0, "led_basecolor", tmpA, 0); + } - poststr(request, ""); - for (i = 0; i < CHANNEL_MAX; i++) { - int channelType; + if (http_getArg(request->url, "off", tmpA, sizeof(tmpA))) { + j = atoi(tmpA); + hprintf128(request, "

Disabled %i!

", j); + CHANNEL_Set(j, 0, 1); + } + if (http_getArg(request->url, "pwm", tmpA, sizeof(tmpA))) { + int newPWMValue = atoi(tmpA); + http_getArg(request->url, "pwmIndex", tmpA, sizeof(tmpA)); + j = atoi(tmpA); + if (j == SPECIAL_CHANNEL_TEMPERATURE) { + hprintf128(request, "

Changed Temperature to %i!

", newPWMValue); + } + else { + hprintf128(request, "

Changed pwm %i to %i!

", j, newPWMValue); + } + CHANNEL_Set(j, newPWMValue, 1); + } + if (http_getArg(request->url, "dim", tmpA, sizeof(tmpA))) { + int newDimmerValue = atoi(tmpA); + http_getArg(request->url, "dimIndex", tmpA, sizeof(tmpA)); + j = atoi(tmpA); + if (j == SPECIAL_CHANNEL_BRIGHTNESS) { + hprintf128(request, "

Changed LED brightness to %i!

", newDimmerValue); + } + else { + hprintf128(request, "

Changed dimmer %i to %i!

", j, newDimmerValue); + } + CHANNEL_Set(j, newDimmerValue, 1); + } + if (http_getArg(request->url, "set", tmpA, sizeof(tmpA))) { + int newSetValue = atoi(tmpA); + http_getArg(request->url, "setIndex", tmpA, sizeof(tmpA)); + j = atoi(tmpA); + hprintf128(request, "

Changed channel %i to %i!

", j, newSetValue); + CHANNEL_Set(j, newSetValue, 1); + } + if (http_getArg(request->url, "restart", tmpA, sizeof(tmpA))) { + poststr(request, "
Module will restart soon
"); + RESET_ScheduleModuleReset(3); + } + poststr(request, ""); // end div#change + poststr(request, "
"); // replaceable content follows + } - channelType = CHANNEL_GetType(i); - if (h_isChannelRelay(i) || channelType == ChType_Toggle) { - if (i <= 1) { - hprintf128(request, "
"); - } - if (CHANNEL_Check(i)) { - poststr(request, ""); - } - else { - poststr(request, ""); - } - if (i == CHANNEL_MAX - 1) { - poststr(request, ""); - } - } - } - poststr(request, "
ONOFF
"); - - poststr(request, ""); - for(i = 0; i < CHANNEL_MAX; i++) { - - int channelType; + poststr(request, "
"); + for (i = 0; i < CHANNEL_MAX; i++) { + int channelType; channelType = CHANNEL_GetType(i); - if(channelType == ChType_Temperature) { + if (h_isChannelRelay(i) || channelType == ChType_Toggle) { + if (i <= 1) { + hprintf128(request, ""); + } + if (CHANNEL_Check(i)) { + poststr(request, ""); + } + else { + poststr(request, ""); + } + if (i == CHANNEL_MAX - 1) { + poststr(request, ""); + } + } + } + poststr(request, "
ONOFF
"); + + poststr(request, ""); + for (i = 0; i < CHANNEL_MAX; i++) { + + int channelType; + + channelType = CHANNEL_GetType(i); + if (channelType == ChType_Temperature) { int iValue; iValue = CHANNEL_Get(i); - poststr(request, ""); - - } else if(channelType == ChType_Temperature_div10) { + poststr(request, ""); + + } + else if (channelType == ChType_Temperature_div10) { int iValue; float fValue; iValue = CHANNEL_Get(i); fValue = iValue * 0.1f; - poststr(request, ""); + poststr(request, ""); - } else if(channelType == ChType_Humidity) { + } + else if (channelType == ChType_Humidity) { int iValue; iValue = CHANNEL_Get(i); - poststr(request, ""); + poststr(request, ""); - } else if(channelType == ChType_Humidity_div10) { + } + else if (channelType == ChType_Humidity_div10) { int iValue; float fValue; iValue = CHANNEL_Get(i); fValue = iValue * 0.1f; - poststr(request, ""); + poststr(request, ""); - } else if(channelType == ChType_LowMidHigh) { - const char *types[]={"Low","Mid","High"}; + } + else if (channelType == ChType_LowMidHigh) { + const char* types[] = { "Low","Mid","High" }; int iValue; iValue = CHANNEL_Get(i); - poststr(request, ""); + hprintf128(request, ""); + poststr(request, ""); - } else if(channelType == ChType_OffLowMidHigh || channelType == ChType_OffLowestLowMidHighHighest || channelType == ChType_LowestLowMidHighHighest) { - const char **types; - const char *types4[] = {"Off","Low","Mid","High"}; - const char *types6[] = {"Off", "Lowest", "Low", "Mid", "High", "Highest"}; - const char *types5NoOff[] = { "Lowest", "Low", "Mid", "High", "Highest"}; + } + else if (channelType == ChType_OffLowMidHigh || channelType == ChType_OffLowestLowMidHighHighest || channelType == ChType_LowestLowMidHighHighest) { + const char** types; + const char* types4[] = { "Off","Low","Mid","High" }; + const char* types6[] = { "Off", "Lowest", "Low", "Mid", "High", "Highest" }; + const char* types5NoOff[] = { "Lowest", "Low", "Mid", "High", "Highest" }; int numTypes; int iValue; - - if(channelType == ChType_OffLowMidHigh) { + + if (channelType == ChType_OffLowMidHigh) { types = types4; numTypes = 4; - } else if(channelType == ChType_LowestLowMidHighHighest) { + } + else if (channelType == ChType_LowestLowMidHighHighest) { types = types5NoOff; numTypes = 5; - } else { + } + else { types = types6; numTypes = 6; } iValue = CHANNEL_Get(i); - poststr(request, ""); + hprintf128(request, ""); + poststr(request, ""); - } else if(channelType == ChType_TextField) { + } + else if (channelType == ChType_TextField) { int iValue; iValue = CHANNEL_Get(i); - poststr(request, ""); + poststr(request, ""); - } else if(channelType == ChType_ReadOnly) { + } + else if (channelType == ChType_ReadOnly) { int iValue; iValue = CHANNEL_Get(i); - poststr(request, ""); + poststr(request, ""); - } - else if (h_isChannelRelay(i) || channelType == ChType_Toggle) { - if (i <= 1) { - hprintf128(request, ""); - } - const char *c; - if(CHANNEL_Check(i)) { - c = "bgrn"; - } else { - c = "bred"; - } - poststr(request,"",c,i); - if (i == CHANNEL_MAX-1) { - poststr(request, ""); - } - } - else if((bRawPWMs&&h_isChannelPWM(i)) || (channelType == ChType_Dimmer) || (channelType == ChType_Dimmer256)) { + } + else if (h_isChannelRelay(i) || channelType == ChType_Toggle) { + if (i <= 1) { + hprintf128(request, ""); + } + const char* c; + if (CHANNEL_Check(i)) { + c = "bgrn"; + } + else { + c = "bred"; + } + poststr(request, "", c, i); + if (i == CHANNEL_MAX - 1) { + poststr(request, ""); + } + } + else if ((bRawPWMs && h_isChannelPWM(i)) || (channelType == ChType_Dimmer) || (channelType == ChType_Dimmer256)) { int maxValue; - // PWM and dimmer both use a slider control - const char *inputName = h_isChannelPWM(i) ? "pwm" : "dim"; - int pwmValue; + // PWM and dimmer both use a slider control + const char* inputName = h_isChannelPWM(i) ? "pwm" : "dim"; + int pwmValue; - if(channelType == ChType_Dimmer256) { + if (channelType == ChType_Dimmer256) { maxValue = 255; - } else { + } + else { maxValue = 100; } - pwmValue = CHANNEL_Get(i); - poststr(request, ""); - } - } + pwmValue = CHANNEL_Get(i); + poststr(request, ""); + } + } - if(bRawPWMs == 0 || forceShowRGBCW) { + if (bRawPWMs == 0 || forceShowRGBCW) { int c_pwms; int lm; lm = LED_GetMode(); c_pwms = PIN_CountPinsWithRoleOrRole(IOR_PWM, IOR_PWM_n); - if(forceShowRGBCW) { + if (forceShowRGBCW) { c_pwms = 5; } - if(c_pwms > 0) { - const char *c; - if(CHANNEL_Check(SPECIAL_CHANNEL_LEDPOWER)) { + if (c_pwms > 0) { + const char* c; + if (CHANNEL_Check(SPECIAL_CHANNEL_LEDPOWER)) { c = "bgrn"; - } else { + } + else { c = "bred"; } poststr(request, ""); } - if(c_pwms > 0) { - int pwmValue; - const char *inputName; + if (c_pwms > 0) { + int pwmValue; + const char* inputName; inputName = "dim"; - pwmValue = LED_GetDimmer(); + pwmValue = LED_GetDimmer(); poststr(request, ""); } - if(c_pwms >= 3) { + if (c_pwms >= 3) { char colorValue[16]; - const char *inputName = "rgb"; - const char *activeStr = ""; - if(lm == Light_RGB) { + const char* inputName = "rgb"; + const char* activeStr = ""; + if (lm == Light_RGB) { activeStr = "[ACTIVE]"; } LED_GetBaseColorString(colorValue); poststr(request, ""); } - if(c_pwms == 2 || c_pwms == 5) { + if (c_pwms == 2 || c_pwms == 5) { // TODO: temperature slider int pwmValue; - const char *inputName; - const char *activeStr = ""; - if(lm == Light_Temperature) { + const char* inputName; + const char* activeStr = ""; + if (lm == Light_Temperature) { activeStr = "[ACTIVE]"; } inputName = "pwm"; - pwmValue = LED_GetTemperature(); + pwmValue = LED_GetTemperature(); poststr(request, ""); - } + } } - poststr(request, "
"); - hprintf128(request,"Temperature Channel %i value %i C
",i, iValue); - poststr(request, "
"); + hprintf128(request, "Temperature Channel %i value %i C
", i, iValue); + poststr(request, "
"); - hprintf128(request,"Temperature Channel %i value %f C
",i, fValue); - poststr(request, "
"); + hprintf128(request, "Temperature Channel %i value %f C
", i, fValue); + poststr(request, "
"); - hprintf128(request,"Humidity Channel %i value %i Percent
",i, iValue); - poststr(request, "
"); + hprintf128(request, "Humidity Channel %i value %i Percent
", i, iValue); + poststr(request, "
"); - hprintf128(request,"Humidity Channel %i value %f Percent
",i, fValue); - poststr(request, "
"); + hprintf128(request, "Humidity Channel %i value %f Percent
", i, fValue); + poststr(request, "
"); - hprintf128(request,"

Select speed:

"); - hprintf128(request,"",i); - for(j = 0; j < 3; j++) { - const char *check; - if(j == iValue) + poststr(request, "
"); + hprintf128(request, "

Select speed:

"); + hprintf128(request, "", i); + for (j = 0; j < 3; j++) { + const char* check; + if (j == iValue) check = "checked"; else check = ""; - hprintf128(request,"%s",j,check,types[j]); + hprintf128(request, "%s", j, check, types[j]); } - hprintf128(request,""); - poststr(request, "
"); - hprintf128(request,"

Select speed:

"); - hprintf128(request,"",i); - for(j = 0; j < numTypes; j++) { - const char *check; - if(j == iValue) + poststr(request, "
"); + hprintf128(request, "

Select speed:

"); + hprintf128(request, "", i); + for (j = 0; j < numTypes; j++) { + const char* check; + if (j == iValue) check = "checked"; else check = ""; - hprintf128(request,"%s",j,check,types[j]); + hprintf128(request, "%s", j, check, types[j]); } - hprintf128(request,""); - poststr(request, "
"); - hprintf128(request,"

Change channel %i value:

",i); - hprintf128(request,"",i); - hprintf128(request,"",iValue); - hprintf128(request,"
"); - hprintf128(request,""); - poststr(request, "
"); + hprintf128(request, "

Change channel %i value:

", i); + hprintf128(request, "", i); + hprintf128(request, "", iValue); + hprintf128(request, "
"); + hprintf128(request, ""); + poststr(request, "
"); - hprintf128(request,"Channel %i = %i",i,iValue); - poststr(request, "
"); + hprintf128(request, "Channel %i = %i", i, iValue); + poststr(request, "
"); - hprintf128(request,"",i); - hprintf128(request,"
"); + hprintf128(request, "", i); + hprintf128(request, "
"); - hprintf128(request,"
",i); - hprintf128(request,"",maxValue,inputName,i,pwmValue); - hprintf128(request,"",inputName,i); - hprintf128(request,"
",i); - poststr(request, "
"); + hprintf128(request, "
", i); + hprintf128(request, "", maxValue, inputName, i, pwmValue); + hprintf128(request, "", inputName, i); + hprintf128(request, "
", i); + poststr(request, "
"); - poststr(request,"
"); - hprintf128(request,"",SPECIAL_CHANNEL_LEDPOWER); - hprintf128(request,"
",c); + poststr(request, "
"); + hprintf128(request, "", SPECIAL_CHANNEL_LEDPOWER); + hprintf128(request, "
", c); poststr(request, "
"); - hprintf128(request,"
LED Dimmer/Brightness
"); - hprintf128(request,"
",SPECIAL_CHANNEL_BRIGHTNESS); - hprintf128(request,"",inputName,SPECIAL_CHANNEL_BRIGHTNESS,pwmValue); - hprintf128(request,"",inputName,SPECIAL_CHANNEL_BRIGHTNESS); - hprintf128(request,"
",SPECIAL_CHANNEL_BRIGHTNESS); + hprintf128(request, "
LED Dimmer/Brightness
"); + hprintf128(request, "
", SPECIAL_CHANNEL_BRIGHTNESS); + hprintf128(request, "", inputName, SPECIAL_CHANNEL_BRIGHTNESS, pwmValue); + hprintf128(request, "", inputName, SPECIAL_CHANNEL_BRIGHTNESS); + hprintf128(request, "
", SPECIAL_CHANNEL_BRIGHTNESS); poststr(request, "
"); - hprintf128(request,"
LED RGB Color %s
",activeStr); - hprintf128(request,"
",SPECIAL_CHANNEL_BASECOLOR); - hprintf128(request,"",inputName,SPECIAL_CHANNEL_BASECOLOR,colorValue); - hprintf128(request,"",inputName,SPECIAL_CHANNEL_BASECOLOR); - hprintf128(request,"
"); + hprintf128(request, "
LED RGB Color %s
", activeStr); + hprintf128(request, "
", SPECIAL_CHANNEL_BASECOLOR); + hprintf128(request, "", inputName, SPECIAL_CHANNEL_BASECOLOR, colorValue); + hprintf128(request, "", inputName, SPECIAL_CHANNEL_BASECOLOR); + hprintf128(request, "
"); poststr(request, "
"); - hprintf128(request,"
LED Temperature Slider %s (cur=%i, min=%i, max=%i) (Cold <--- ---> Warm)
",activeStr,pwmValue,HASS_TEMPERATURE_MIN,HASS_TEMPERATURE_MAX); - hprintf128(request,"
",SPECIAL_CHANNEL_TEMPERATURE); - hprintf128(request,"",inputName,SPECIAL_CHANNEL_TEMPERATURE,pwmValue); - hprintf128(request,"",inputName,SPECIAL_CHANNEL_TEMPERATURE); - hprintf128(request,"
",SPECIAL_CHANNEL_TEMPERATURE); + hprintf128(request, "
LED Temperature Slider %s (cur=%i, min=%i, max=%i) (Cold <--- ---> Warm)
", activeStr, pwmValue, HASS_TEMPERATURE_MIN, HASS_TEMPERATURE_MAX); + hprintf128(request, "
", SPECIAL_CHANNEL_TEMPERATURE); + hprintf128(request, "", inputName, SPECIAL_CHANNEL_TEMPERATURE, pwmValue); + hprintf128(request, "", inputName, SPECIAL_CHANNEL_TEMPERATURE); + hprintf128(request, "
", SPECIAL_CHANNEL_TEMPERATURE); poststr(request, "
"); + poststr(request, ""); #ifndef OBK_DISABLE_ALL_DRIVERS DRV_AppendInformationToHTTPIndexPage(request); #endif - if(1) { + if (1) { int bFirst = true; - hprintf128(request,"
"); - for(i = 0; i < CHANNEL_MAX; i++) { - if(CHANNEL_IsInUse(i)) { + hprintf128(request, "
"); + for (i = 0; i < CHANNEL_MAX; i++) { + if (CHANNEL_IsInUse(i)) { int value = CHANNEL_Get(i); - if(bFirst == false) { - hprintf128(request,", "); + if (bFirst == false) { + hprintf128(request, ", "); } - hprintf128(request,"Channel %i = %i",i,value); + hprintf128(request, "Channel %i = %i", i, value); bFirst = false; } } - hprintf128(request,"
"); + hprintf128(request, ""); } - hprintf128(request,"
Cfg size: %i, change counter: %i, ota counter: %i, boot incompletes %i (might change to 0 if you wait to 30 sec)!
", - sizeof(g_cfg),g_cfg.changeCounter,g_cfg.otaCounter,Main_GetLastRebootBootFailures()); + hprintf128(request, "
Cfg size: %i, change counter: %i, ota counter: %i, boot incompletes %i (might change to 0 if you wait to 30 sec)!
", + sizeof(g_cfg), g_cfg.changeCounter, g_cfg.otaCounter, Main_GetLastRebootBootFailures()); - hprintf128(request,"
Ping watchdog - %i lost, %i ok!
", - PingWatchDog_GetTotalLost(),PingWatchDog_GetTotalReceived()); - hprintf128(request,"
MQTT State: %s RES: %d(%s)
", (Main_HasMQTTConnected()==1)?"connected":"disconnected", - MQTT_GetConnectResult(), get_error_name(MQTT_GetConnectResult()) ); - hprintf128(request,"MQTT ErrMsg: %s
", (MQTT_GetStatusMessage()!=NULL)?MQTT_GetStatusMessage():""); - hprintf128(request,"MQTT Stats:CONN: %d PUB: %d RECV: %d ERR: %d
", MQTT_GetConnectEvents(), - MQTT_GetPublishEventCounter(), MQTT_GetReceivedEventCounter(), MQTT_GetPublishErrorCounter()); + hprintf128(request, "
Ping watchdog - %i lost, %i ok!
", + PingWatchDog_GetTotalLost(), PingWatchDog_GetTotalReceived()); + hprintf128(request, "
MQTT State: %s RES: %d(%s)
", (Main_HasMQTTConnected() == 1) ? "connected" : "disconnected", + MQTT_GetConnectResult(), get_error_name(MQTT_GetConnectResult())); + hprintf128(request, "MQTT ErrMsg: %s
", (MQTT_GetStatusMessage() != NULL) ? MQTT_GetStatusMessage() : ""); + hprintf128(request, "MQTT Stats:CONN: %d PUB: %d RECV: %d ERR: %d
", MQTT_GetConnectEvents(), + MQTT_GetPublishEventCounter(), MQTT_GetReceivedEventCounter(), MQTT_GetPublishErrorCounter()); - // for normal page loads, show the rest of the HTML - if(!http_getArg(request->url,"state",tmpA,sizeof(tmpA))) { - poststr(request, "
"); // end div#state + // for normal page loads, show the rest of the HTML + if (!http_getArg(request->url, "state", tmpA, sizeof(tmpA))) { + poststr(request, "
"); // end div#state - // Shared UI elements - poststr(request, "
"); + // Shared UI elements + poststr(request, "
"); - poststr(request, "
" - "" - "" - "
"); + poststr(request, "
" + "" + "" + "
"); - poststr(request, "
"); - poststr(request, "
"); + poststr(request, "
"); + poststr(request, "
"); - poststr(request, htmlFooterRefreshLink); - http_html_end(request); - } + poststr(request, htmlFooterRefreshLink); + http_html_end(request); + } poststr(request, NULL); return 0; } -int http_fn_about(http_request_t *request){ - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "About"); - poststr(request,"

Open source firmware for BK7231N, BK7231T, XR809 and BL602 by OpenSHWProjects

"); - poststr(request,htmlFooterReturnToMenu); - http_html_end(request); +int http_fn_about(http_request_t* request) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "About"); + poststr(request, "

Open source firmware for BK7231N, BK7231T, XR809 and BL602 by OpenSHWProjects

"); + poststr(request, htmlFooterReturnToMenu); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_mqtt(http_request_t *request) { - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "MQTT"); - poststr(request,"

Use this to connect to your MQTT

"); - add_label_text_field(request, "Host", "host", CFG_GetMQTTHost(), "
"); - add_label_numeric_field(request, "Port", "port", CFG_GetMQTTPort(), "
"); - add_label_text_field(request, "Client", "client", CFG_GetMQTTClientId(), "

"); - add_label_text_field(request, "User", "user", CFG_GetMQTTUserName(), "
"); - add_label_text_field(request, "Password", "password", CFG_GetMQTTPass(), "
"); - - poststr(request,"
\ +int http_fn_cfg_mqtt(http_request_t* request) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "MQTT"); + poststr(request, "

Use this to connect to your MQTT

"); + add_label_text_field(request, "Host", "host", CFG_GetMQTTHost(), ""); + add_label_numeric_field(request, "Port", "port", CFG_GetMQTTPort(), "
"); + add_label_text_field(request, "Client", "client", CFG_GetMQTTClientId(), "

"); + add_label_text_field(request, "User", "user", CFG_GetMQTTUserName(), "
"); + add_label_text_field(request, "Password", "password", CFG_GetMQTTPass(), "
"); + + poststr(request, "
\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); - poststr(request, NULL); - return 0; + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); + poststr(request, NULL); + return 0; } -int http_fn_cfg_mqtt_set(http_request_t *request) { +int http_fn_cfg_mqtt_set(http_request_t* request) { char tmpA[128]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Saving MQTT"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Saving MQTT"); - if(http_getArg(request->url,"host",tmpA,sizeof(tmpA))) { - CFG_SetMQTTHost(tmpA); - } - if(http_getArg(request->url,"port",tmpA,sizeof(tmpA))) { - CFG_SetMQTTPort(atoi(tmpA)); - } - if(http_getArg(request->url,"user",tmpA,sizeof(tmpA))) { - CFG_SetMQTTUserName(tmpA); - } - if(http_getArg(request->url,"password",tmpA,sizeof(tmpA))) { - CFG_SetMQTTPass(tmpA); - } - if(http_getArg(request->url,"client",tmpA,sizeof(tmpA))) { - CFG_SetMQTTClientId(tmpA); - } + if (http_getArg(request->url, "host", tmpA, sizeof(tmpA))) { + CFG_SetMQTTHost(tmpA); + } + if (http_getArg(request->url, "port", tmpA, sizeof(tmpA))) { + CFG_SetMQTTPort(atoi(tmpA)); + } + if (http_getArg(request->url, "user", tmpA, sizeof(tmpA))) { + CFG_SetMQTTUserName(tmpA); + } + if (http_getArg(request->url, "password", tmpA, sizeof(tmpA))) { + CFG_SetMQTTPass(tmpA); + } + if (http_getArg(request->url, "client", tmpA, sizeof(tmpA))) { + CFG_SetMQTTClientId(tmpA); + } CFG_Save_SetupTimer(); - poststr(request,"Please wait for module to connect... if there is problem, restart it from Index html page..."); + poststr(request, "Please wait for module to connect... if there is problem, restart it from Index html page..."); - poststr(request,"
"); - poststr(request,"Return to MQTT settings"); - poststr(request,"
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, "
"); + poststr(request, "Return to MQTT settings"); + poststr(request, "
"); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_webapp(http_request_t *request) { - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Set Webapp"); - poststr(request,"

Use this to set the URL of the Webapp

"); - add_label_text_field(request, "Url", "url", CFG_GetWebappRoot(), "
"); - poststr(request,"
\ +int http_fn_cfg_webapp(http_request_t* request) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Set Webapp"); + poststr(request, "

Use this to set the URL of the Webapp

"); + add_label_text_field(request, "Url", "url", CFG_GetWebappRoot(), ""); + poststr(request, "
\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_webapp_set(http_request_t *request) { +int http_fn_cfg_webapp_set(http_request_t* request) { char tmpA[128]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Saving Webapp"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Saving Webapp"); - if(http_getArg(request->url,"url",tmpA,sizeof(tmpA))) { - if(CFG_SetWebappRoot(tmpA)) { - hprintf128(request,"Webapp url set to %s", tmpA); - } else { - hprintf128(request,"Webapp url change error - failed to save to flash."); - } - } else { - poststr(request,"Webapp url not set because you didn't specify the argument."); - } + if (http_getArg(request->url, "url", tmpA, sizeof(tmpA))) { + if (CFG_SetWebappRoot(tmpA)) { + hprintf128(request, "Webapp url set to %s", tmpA); + } + else { + hprintf128(request, "Webapp url change error - failed to save to flash."); + } + } + else { + poststr(request, "Webapp url not set because you didn't specify the argument."); + } - poststr(request,"
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, "
"); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_ping(http_request_t *request) { +int http_fn_cfg_ping(http_request_t* request) { char tmpA[128]; int bChanged; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Set Watchdog"); - bChanged = 0; - poststr(request,"

Ping watchdog (backup reconnect mechanism)

"); - poststr(request,"

By default, all OpenBeken devices automatically tries to reconnect to WiFi when a connection is lost."); - poststr(request," I have tested the reconnect mechanism many times by restarting my router and it always worked reliably."); - poststr(request," However, according to some reports, there are still some edge cases when a device fails to reconnect to WIFi."); - poststr(request," This is why this mechanism has been added.

"); - poststr(request,"

This mechanism keeps pinging certain host and reconnects to WiFi if it doesn't respond at all for a certain amount of seconds.

"); - poststr(request,"

USAGE: For a host, choose the main address of your router and make sure it responds to a pings. Interval is 1 second or so, timeout can be set by user, to eg. 60 sec

"); - if(http_getArg(request->url,"host",tmpA,sizeof(tmpA))) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Set Watchdog"); + bChanged = 0; + poststr(request, "

Ping watchdog (backup reconnect mechanism)

"); + poststr(request, "

By default, all OpenBeken devices automatically tries to reconnect to WiFi when a connection is lost."); + poststr(request, " I have tested the reconnect mechanism many times by restarting my router and it always worked reliably."); + poststr(request, " However, according to some reports, there are still some edge cases when a device fails to reconnect to WIFi."); + poststr(request, " This is why this mechanism has been added.

"); + poststr(request, "

This mechanism keeps pinging certain host and reconnects to WiFi if it doesn't respond at all for a certain amount of seconds.

"); + poststr(request, "

USAGE: For a host, choose the main address of your router and make sure it responds to a pings. Interval is 1 second or so, timeout can be set by user, to eg. 60 sec

"); + if (http_getArg(request->url, "host", tmpA, sizeof(tmpA))) { CFG_SetPingHost(tmpA); - poststr(request,"

New ping host set!

"); - bChanged = 1; - } - /* if(http_getArg(request->url,"interval",tmpA,sizeof(tmpA))) { - CFG_SetPingIntervalSeconds(atoi(tmpA)); - poststr(request,"

New ping interval set!

"); - bChanged = 1; - }*/ - if(http_getArg(request->url,"disconnectTime",tmpA,sizeof(tmpA))) { + poststr(request, "

New ping host set!

"); + bChanged = 1; + } + /* if(http_getArg(request->url,"interval",tmpA,sizeof(tmpA))) { + CFG_SetPingIntervalSeconds(atoi(tmpA)); + poststr(request,"

New ping interval set!

"); + bChanged = 1; + }*/ + if (http_getArg(request->url, "disconnectTime", tmpA, sizeof(tmpA))) { CFG_SetPingDisconnectedSecondsToRestart(atoi(tmpA)); - poststr(request,"

New ping disconnectTime set!

"); - bChanged = 1; - } - if(http_getArg(request->url,"clear",tmpA,sizeof(tmpA))) { + poststr(request, "

New ping disconnectTime set!

"); + bChanged = 1; + } + if (http_getArg(request->url, "clear", tmpA, sizeof(tmpA))) { CFG_SetPingDisconnectedSecondsToRestart(0); CFG_SetPingIntervalSeconds(0); CFG_SetPingHost(""); - poststr(request,"

Ping watchdog disabled!

"); - bChanged = 1; - } - if(bChanged) { - poststr(request,"

Changes will be applied after restarting

"); - } - poststr(request,"
\ + poststr(request, "

Ping watchdog disabled!

"); + bChanged = 1; + } + if (bChanged) { + poststr(request, "

Changes will be applied after restarting

"); + } + poststr(request, "\ \ \
"); - poststr(request,"

Use this to enable pinger

"); - add_label_text_field(request, "Host", "host", CFG_GetPingHost(), "
"); - add_label_numeric_field(request, "Take action after this number of seconds with no reply", "disconnectTime", - CFG_GetPingDisconnectedSecondsToRestart(), "
"); - poststr(request,"

\ + poststr(request, "

Use this to enable pinger

"); + add_label_text_field(request, "Host", "host", CFG_GetPingHost(), ""); + add_label_numeric_field(request, "Take action after this number of seconds with no reply", "disconnectTime", + CFG_GetPingDisconnectedSecondsToRestart(), "
"); + poststr(request, "

\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_wifi(http_request_t *request) { - // for a test, show password as well... +int http_fn_cfg_wifi(http_request_t* request) { + // for a test, show password as well... char tmpA[128]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Set Wifi"); - /*bChanged = 0; - if(http_getArg(recvbuf,"ssid",tmpA,sizeof(tmpA))) { - CFG_SetWiFiSSID(tmpA); - poststr(request,"

WiFi SSID set!

"); - bChanged = 1; - } - if(http_getArg(recvbuf,"pass",tmpA,sizeof(tmpA))) { - CFG_SetWiFiPass(tmpA); - poststr(request,"

WiFi Password set!

"); - bChanged = 1; - } - if(bChanged) { - poststr(request,"

Device will reconnect after restarting

"); - }*/ - poststr(request,"

Check networks reachable by module

This will lag few seconds.
"); - if(http_getArg(request->url,"scan",tmpA,sizeof(tmpA))) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Set Wifi"); + /*bChanged = 0; + if(http_getArg(recvbuf,"ssid",tmpA,sizeof(tmpA))) { + CFG_SetWiFiSSID(tmpA); + poststr(request,"

WiFi SSID set!

"); + bChanged = 1; + } + if(http_getArg(recvbuf,"pass",tmpA,sizeof(tmpA))) { + CFG_SetWiFiPass(tmpA); + poststr(request,"

WiFi Password set!

"); + bChanged = 1; + } + if(bChanged) { + poststr(request,"

Device will reconnect after restarting

"); + }*/ + poststr(request, "

Check networks reachable by module

This will lag few seconds.
"); + if (http_getArg(request->url, "scan", tmpA, sizeof(tmpA))) { #ifdef WINDOWS - poststr(request,"Not available on Windows
"); + poststr(request, "Not available on Windows
"); #elif PLATFORM_XR809 - poststr(request,"TODO XR809
"); + poststr(request, "TODO XR809
"); #elif PLATFORM_W600 || PLATFORM_W800 - poststr(request,"TODO W800
"); + poststr(request, "TODO W800
"); #elif PLATFORM_BL602 - poststr(request,"TODO BL602
"); + poststr(request, "TODO BL602
"); #elif PLATFORM_BK7231T int i; - AP_IF_S *ar; - uint32_t num; + AP_IF_S* ar; + uint32_t num; - bk_printf("Scan begin...\r\n"); - tuya_hal_wifi_all_ap_scan(&ar,&num); - bk_printf("Scan returned %i networks\r\n",num); - for(i = 0; i < num; i++) { - hprintf128(request,"[%i/%i] SSID: %s, Channel: %i, Signal %i
",i,(int)num,ar[i].ssid, ar[i].channel, ar[i].rssi); - } - tuya_hal_wifi_release_ap(ar); + bk_printf("Scan begin...\r\n"); + tuya_hal_wifi_all_ap_scan(&ar, &num); + bk_printf("Scan returned %i networks\r\n", num); + for (i = 0; i < num; i++) { + hprintf128(request, "[%i/%i] SSID: %s, Channel: %i, Signal %i
", i, (int)num, ar[i].ssid, ar[i].channel, ar[i].rssi); + } + tuya_hal_wifi_release_ap(ar); #elif PLATFORM_BK7231N int i; - AP_IF_S *ar; - uint32_t num; + AP_IF_S* ar; + uint32_t num; - bk_printf("Scan begin...\r\n"); - tuya_os_adapt_wifi_all_ap_scan(&ar,&num); - bk_printf("Scan returned %i networks\r\n",num); - for(i = 0; i < num; i++) { - hprintf128(request,"[%i/%i] SSID: %s, Channel: %i, Signal %i
",i + 1,(int)num,ar[i].ssid, ar[i].channel, ar[i].rssi); - } - tuya_os_adapt_wifi_release_ap(ar); + bk_printf("Scan begin...\r\n"); + tuya_os_adapt_wifi_all_ap_scan(&ar, &num); + bk_printf("Scan returned %i networks\r\n", num); + for (i = 0; i < num; i++) { + hprintf128(request, "[%i/%i] SSID: %s, Channel: %i, Signal %i
", i + 1, (int)num, ar[i].ssid, ar[i].channel, ar[i].rssi); + } + tuya_os_adapt_wifi_release_ap(ar); #else #error "Unknown platform" - poststr(request,"Unknown platform
"); + poststr(request, "Unknown platform
"); #endif - } - poststr(request,"
\ + } + poststr(request, "\ \ \
"); - poststr(request,"

Use this to disconnect from your WiFi

"); - poststr(request,"
\ + poststr(request, "

Use this to disconnect from your WiFi

"); + poststr(request, "\ \ \
"); - poststr(request,"

Use this to connect to your WiFi

"); - add_label_text_field(request, "SSID", "ssid", CFG_GetWiFiSSID(), "
"); - add_label_text_field(request, "Password", "pass", CFG_GetWiFiPass(), "
"); - poststr(request,"

\ + poststr(request, "

Use this to connect to your WiFi

"); + add_label_text_field(request, "SSID", "ssid", CFG_GetWiFiSSID(), ""); + add_label_text_field(request, "Password", "pass", CFG_GetWiFiPass(), "
"); + poststr(request, "

\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_name(http_request_t *request) { - // for a test, show password as well... +int http_fn_cfg_name(http_request_t* request) { + // for a test, show password as well... char tmpA[128]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Set name"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Set name"); - poststr(request,"

Change device names for display.

"); - if(http_getArg(request->url,"shortName",tmpA,sizeof(tmpA))) { + poststr(request, "

Change device names for display.

"); + if (http_getArg(request->url, "shortName", tmpA, sizeof(tmpA))) { CFG_SetShortDeviceName(tmpA); - } - if(http_getArg(request->url,"name",tmpA,sizeof(tmpA))) { + } + if (http_getArg(request->url, "name", tmpA, sizeof(tmpA))) { CFG_SetDeviceName(tmpA); - } - poststr(request,"

Use this to change device names

"); - add_label_text_field(request, "ShortName", "shortName", CFG_GetShortDeviceName(), "
"); - add_label_text_field(request, "Full Name", "name", CFG_GetDeviceName(), "
"); - poststr(request,"

"); - poststr(request, ""); - poststr(request, "
"); - //poststr(request,htmlReturnToCfg); - //HTTP_AddBuildFooter(request); - //poststr(request,htmlEnd); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + } + poststr(request, "

Use this to change device names

"); + add_label_text_field(request, "ShortName", "shortName", CFG_GetShortDeviceName(), "
"); + add_label_text_field(request, "Full Name", "name", CFG_GetDeviceName(), "
"); + poststr(request, "

"); + poststr(request, ""); + poststr(request, "
"); + //poststr(request,htmlReturnToCfg); + //HTTP_AddBuildFooter(request); + //poststr(request,htmlEnd); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_wifi_set(http_request_t *request) { +int http_fn_cfg_wifi_set(http_request_t* request) { char tmpA[128]; - addLogAdv(LOG_INFO, LOG_FEATURE_HTTP,"HTTP_ProcessPacket: generating cfg_wifi_set \r\n"); + addLogAdv(LOG_INFO, LOG_FEATURE_HTTP, "HTTP_ProcessPacket: generating cfg_wifi_set \r\n"); - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Saving Wifi"); - if(http_getArg(request->url,"open",tmpA,sizeof(tmpA))) { - CFG_SetWiFiSSID(""); - CFG_SetWiFiPass(""); - poststr(request,"WiFi mode set: open access point."); - } else { - if(http_getArg(request->url,"ssid",tmpA,sizeof(tmpA))) { - CFG_SetWiFiSSID(tmpA); - } - if(http_getArg(request->url,"pass",tmpA,sizeof(tmpA))) { - CFG_SetWiFiPass(tmpA); - } - poststr(request,"WiFi mode set: connect to WLAN."); - } + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Saving Wifi"); + if (http_getArg(request->url, "open", tmpA, sizeof(tmpA))) { + CFG_SetWiFiSSID(""); + CFG_SetWiFiPass(""); + poststr(request, "WiFi mode set: open access point."); + } + else { + if (http_getArg(request->url, "ssid", tmpA, sizeof(tmpA))) { + CFG_SetWiFiSSID(tmpA); + } + if (http_getArg(request->url, "pass", tmpA, sizeof(tmpA))) { + CFG_SetWiFiPass(tmpA); + } + poststr(request, "WiFi mode set: connect to WLAN."); + } CFG_Save_SetupTimer(); - poststr(request,"Please wait for module to reset..."); + poststr(request, "Please wait for module to reset..."); RESET_ScheduleModuleReset(3); - poststr(request,"
"); - poststr(request,"Return to WiFi settings"); - poststr(request,"
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, "
"); + poststr(request, "Return to WiFi settings"); + poststr(request, "
"); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_loglevel_set(http_request_t *request) { +int http_fn_cfg_loglevel_set(http_request_t* request) { char tmpA[128]; - addLogAdv(LOG_INFO, LOG_FEATURE_HTTP,"HTTP_ProcessPacket: generating cfg_loglevel_set \r\n"); + addLogAdv(LOG_INFO, LOG_FEATURE_HTTP, "HTTP_ProcessPacket: generating cfg_loglevel_set \r\n"); - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Set log level"); - if(http_getArg(request->url,"loglevel",tmpA,sizeof(tmpA))) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Set log level"); + if (http_getArg(request->url, "loglevel", tmpA, sizeof(tmpA))) { #if WINDOWS #else - loglevel = atoi(tmpA); + loglevel = atoi(tmpA); #endif - poststr(request,"LOG level changed."); - } + poststr(request, "LOG level changed."); + } - tmpA[0] = 0; + tmpA[0] = 0; #if WINDOWS - add_label_text_field(request, "Loglevel", "loglevel", "", "
"); + add_label_text_field(request, "Loglevel", "loglevel", "", ""); #else - add_label_numeric_field(request, "Loglevel", "loglevel", loglevel, ""); + add_label_numeric_field(request, "Loglevel", "loglevel", loglevel, ""); #endif - poststr(request,"

\ + poststr(request, "

\ \
"); - poststr(request,"
"); - poststr(request,"Return to config settings"); - poststr(request,"
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, "
"); + poststr(request, "Return to config settings"); + poststr(request, "
"); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_mac(http_request_t *request) { - // must be unsigned, else print below prints negatives as e.g. FFFFFFFe - unsigned char mac[6]; +int http_fn_cfg_mac(http_request_t* request) { + // must be unsigned, else print below prints negatives as e.g. FFFFFFFe + unsigned char mac[6]; char tmpA[128]; - int i; + int i; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Set MAC address"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Set MAC address"); - if(http_getArg(request->url,"mac",tmpA,sizeof(tmpA))) { - for( i = 0; i < 6; i++ ) - { - mac[i] = hexbyte( &tmpA[i * 2] ) ; - } - //sscanf(tmpA,"%02X%02X%02X%02X%02X%02X",&mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]); - if(WiFI_SetMacAddress((char*)mac)) { - poststr(request,"

New MAC set!

"); - } else { - poststr(request,"

MAC change error?

"); - } + if (http_getArg(request->url, "mac", tmpA, sizeof(tmpA))) { + for (i = 0; i < 6; i++) + { + mac[i] = hexbyte(&tmpA[i * 2]); + } + //sscanf(tmpA,"%02X%02X%02X%02X%02X%02X",&mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]); + if (WiFI_SetMacAddress((char*)mac)) { + poststr(request, "

New MAC set!

"); + } + else { + poststr(request, "

MAC change error?

"); + } CFG_Save_IfThereArePendingChanges(); - } + } - WiFI_GetMacAddress((char *)mac); + WiFI_GetMacAddress((char*)mac); - poststr(request,"

Here you can change MAC address.

"); + poststr(request, "

Here you can change MAC address.

"); - char macStr[16]; - sprintf(macStr,"%02X%02X%02X%02X%02X%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); - add_label_text_field(request, "MAC", "mac",macStr , "
"); - poststr(request,"

\ + char macStr[16]; + sprintf(macStr, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + add_label_text_field(request, "MAC", "mac", macStr, ""); + poststr(request, "

\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_flash_read_tool(http_request_t *request) { - int len = 16; - int ofs = 1970176; - int res; - int rem; - int now; - int nowOfs; - int hex; - int i; +int http_fn_flash_read_tool(http_request_t* request) { + int len = 16; + int ofs = 1970176; + int res; + int rem; + int now; + int nowOfs; + int hex; + int i; char tmpA[128]; char tmpB[64]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Flash read"); - poststr(request,"

Flash Read Tool

"); - if( http_getArg(request->url,"hex",tmpA,sizeof(tmpA))){ - hex = atoi(tmpA); - } else { - hex = 0; - } + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Flash read"); + poststr(request, "

Flash Read Tool

"); + if (http_getArg(request->url, "hex", tmpA, sizeof(tmpA))) { + hex = atoi(tmpA); + } + else { + hex = 0; + } - if( http_getArg(request->url,"offset",tmpA,sizeof(tmpA)) && - http_getArg(request->url,"len",tmpB,sizeof(tmpB))) { - unsigned char buffer[128]; - len = atoi(tmpB); - ofs = atoi(tmpA); - hprintf128(request,"Memory at %i with len %i reads: ",ofs,len); - poststr(request,"
"); + if (http_getArg(request->url, "offset", tmpA, sizeof(tmpA)) && + http_getArg(request->url, "len", tmpB, sizeof(tmpB))) { + unsigned char buffer[128]; + len = atoi(tmpB); + ofs = atoi(tmpA); + hprintf128(request, "Memory at %i with len %i reads: ", ofs, len); + poststr(request, "
"); - ///res = bekken_hal_flash_read (ofs, buffer,len); - //sprintf(tmpA,"Result %i",res); - // strcat(outbuf,tmpA); - /// strcat(outbuf,"
"); + ///res = bekken_hal_flash_read (ofs, buffer,len); + //sprintf(tmpA,"Result %i",res); + // strcat(outbuf,tmpA); + /// strcat(outbuf,"
"); - nowOfs = ofs; - rem = len; - while(1) { - if(rem > sizeof(buffer)) { - now = sizeof(buffer); - } else { - now = rem; - } + nowOfs = ofs; + rem = len; + while (1) { + if (rem > sizeof(buffer)) { + now = sizeof(buffer); + } + else { + now = rem; + } #if PLATFORM_XR809 - //uint32_t flash_read(uint32_t flash, uint32_t addr,void *buf, uint32_t size) - #define FLASH_INDEX_XR809 0 - res = flash_read(FLASH_INDEX_XR809, nowOfs, buffer, now); + //uint32_t flash_read(uint32_t flash, uint32_t addr,void *buf, uint32_t size) +#define FLASH_INDEX_XR809 0 + res = flash_read(FLASH_INDEX_XR809, nowOfs, buffer, now); #elif PLATFORM_BL602 #elif PLATFORM_W600 || PLATFORM_W800 #else - res = bekken_hal_flash_read (nowOfs, buffer,now); + res = bekken_hal_flash_read(nowOfs, buffer, now); #endif - for(i = 0; i < now; i++) { - unsigned char val = buffer[i]; - if(!hex && isprint(val)) { - hprintf128(request,"'%c' ",val); - } else { - hprintf128(request,"%02X ",val); - } - } - rem -= now; - nowOfs += now; - if(rem <= 0) { - break; - } - } + for (i = 0; i < now; i++) { + unsigned char val = buffer[i]; + if (!hex && isprint(val)) { + hprintf128(request, "'%c' ", val); + } + else { + hprintf128(request, "%02X ", val); + } + } + rem -= now; + nowOfs += now; + if (rem <= 0) { + break; + } + } - poststr(request,"
"); - } - poststr(request,"
"); + poststr(request, "
"); + } + poststr(request, ""); - poststr(request,"
"); + poststr(request, "
"); - add_label_numeric_field(request, "Offset", "offset", ofs, ""); - add_label_numeric_field(request, "Length", "len", len, "
"); - poststr(request,"

\ + add_label_numeric_field(request, "Offset", "offset", ofs, ""); + add_label_numeric_field(request, "Length", "len", len, "
"); + poststr(request, "

\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cmd_tool(http_request_t *request) { - int i; +int http_fn_cmd_tool(http_request_t* request) { + int i; char tmpA[128]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Command tool"); - poststr(request,"

Command Tool

"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Command tool"); + poststr(request, "

Command Tool

"); - if( http_getArg(request->url,"cmd",tmpA,sizeof(tmpA))) { + if (http_getArg(request->url, "cmd", tmpA, sizeof(tmpA))) { i = CMD_ExecuteCommand(tmpA, COMMAND_FLAG_SOURCE_CONSOLE); - if(i == 0) { - poststr(request,"Command not found"); - } else { - poststr(request,"Executed"); + if (i == 0) { + poststr(request, "Command not found"); } - poststr(request,"
"); - } - add_label_text_field(request, "Command", "cmd", tmpA, "
"); - poststr(request,"

\ + else { + poststr(request, "Executed"); + } + poststr(request, "
"); + } + add_label_text_field(request, "Command", "cmd", tmpA, ""); + poststr(request, "

\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_startup_command(http_request_t *request) { +int http_fn_startup_command(http_request_t* request) { char tmpA[512]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Set startup command"); - poststr(request,"

Set/Change/Clear startup command line

"); - poststr(request,"
Startup command is a shorter, smaller alternative to LittleFS autoexec.bat." + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Set startup command"); + poststr(request, "

Set/Change/Clear startup command line

"); + poststr(request, "
Startup command is a shorter, smaller alternative to LittleFS autoexec.bat." "The startup commands are ran at device startup." "You can use them to init peripherals and drivers, like BL0942 energy sensor
"); - if(http_getArg(request->url,"data",tmpA,sizeof(tmpA))) { - // hprintf128(request,"

Set command to %s!

",tmpA); - // tmpA can be longer than 128 bytes and this would crash - hprintf128(request,"

Command changed!

"); + if (http_getArg(request->url, "data", tmpA, sizeof(tmpA))) { + // hprintf128(request,"

Set command to %s!

",tmpA); + // tmpA can be longer than 128 bytes and this would crash + hprintf128(request, "

Command changed!

"); CFG_SetShortStartupCommand(tmpA); CFG_Save_IfThereArePendingChanges(); - } else { + } + else { } - add_label_text_field(request, "Startup command", "data", CFG_GetShortStartupCommand(), "
"); - poststr(request,"

\ + add_label_text_field(request, "Startup command", "data", CFG_GetShortStartupCommand(), ""); + poststr(request, "

\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_uart_tool(http_request_t *request) { +int http_fn_uart_tool(http_request_t* request) { char tmpA[256]; int resultLen = 0; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "UART tool"); - poststr(request,"

UART Tool

"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "UART tool"); + poststr(request, "

UART Tool

"); - if(http_getArg(request->url,"data",tmpA,sizeof(tmpA))) { + if (http_getArg(request->url, "data", tmpA, sizeof(tmpA))) { #ifndef OBK_DISABLE_ALL_DRIVERS byte results[128]; - hprintf128(request,"

Sent %s!

",tmpA); - if(0){ - TuyaMCU_Send((byte *)tmpA, strlen(tmpA)); - // bk_send_string(0,tmpA); - } else { + hprintf128(request, "

Sent %s!

", tmpA); + if (0) { + TuyaMCU_Send((byte*)tmpA, strlen(tmpA)); + // bk_send_string(0,tmpA); + } + else { byte b; - const char *p; + const char* p; p = tmpA; - while(*p) { + while (*p) { b = hexbyte(p); results[resultLen] = b; resultLen++; - p+=2; + p += 2; } TuyaMCU_Send(results, resultLen); } #endif - } else { - strcpy(tmpA,"Hello UART world"); + } + else { + strcpy(tmpA, "Hello UART world"); } - add_label_text_field(request, "Data", "data", tmpA, "
"); - poststr(request,"
\ + add_label_text_field(request, "Data", "data", tmpA, ""); + poststr(request, "
\ \
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_config_dump_table(http_request_t *request) { - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Dump config"); - poststr(request,"Not implemented
"); +int http_fn_config_dump_table(http_request_t* request) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Dump config"); + poststr(request, "Not implemented
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_quick(http_request_t *request) { +int http_fn_cfg_quick(http_request_t* request) { char tmpA[128]; - int j; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Quick Config"); - poststr(request,"

Quick Config

"); + int j; + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Quick Config"); + poststr(request, "

Quick Config

"); - if(http_getArg(request->url,"dev",tmpA,sizeof(tmpA))) { - j = atoi(tmpA); - hprintf128(request,"

Set dev %i!

",j); - g_templates[j].setter(); - } - poststr(request,"
"); - poststr(request, ""); - poststr(request,"
"); + if (http_getArg(request->url, "dev", tmpA, sizeof(tmpA))) { + j = atoi(tmpA); + hprintf128(request, "

Set dev %i!

", j); + g_templates[j].setter(); + } + poststr(request, "
"); + poststr(request, ""); + poststr(request, "
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } /// @brief Computes the Relay and PWM count. /// @param relayCount /// @param pwmCount -void get_Relay_PWM_Count(int *relayCount, int *pwmCount){ - (*relayCount) = 0; - (*pwmCount) = 0; - - for(int 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)++; - } - } +void get_Relay_PWM_Count(int* relayCount, int* pwmCount) { + (*relayCount) = 0; + (*pwmCount) = 0; + + for (int 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)++; + } + } } bool isLedDriverChipRunning() @@ -1197,212 +1223,214 @@ bool isLedDriverChipRunning() /// @brief Sends HomeAssistant discovery MQTT messages. /// @param request /// @return -int http_fn_ha_discovery(http_request_t *request) { - int i; - char topic[32]; - int relayCount = 0; - int pwmCount = 0; +int http_fn_ha_discovery(http_request_t* request) { + int i; + char topic[32]; + int relayCount = 0; + int pwmCount = 0; - http_setup(request, httpMimeTypeText); - get_Relay_PWM_Count(&relayCount, &pwmCount); + http_setup(request, httpMimeTypeText); + get_Relay_PWM_Count(&relayCount, &pwmCount); - if ((relayCount == 0) && (pwmCount == 0)) { - poststr(request, NULL); - return 0; - } + if ((relayCount == 0) && (pwmCount == 0)) { + poststr(request, NULL); + return 0; + } - if (!http_getArg(request->url, "prefix", topic, sizeof(topic))) { - sprintf(topic, "homeassistant"); //default discovery topic is `homeassistant` - } - - struct cJSON_Hooks hooks; - hooks.malloc_fn = os_malloc; - hooks.free_fn = os_free; - cJSON_InitHooks(&hooks); - - if(relayCount > 0) { - for(i = 0; i < CHANNEL_MAX; i++) { - if(h_isChannelRelay(i)) { - HassDeviceInfo *dev_info = hass_init_relay_device_info(i); - MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); - hass_free_device_info(dev_info); - } - } - } + if (!http_getArg(request->url, "prefix", topic, sizeof(topic))) { + sprintf(topic, "homeassistant"); //default discovery topic is `homeassistant` + } + + struct cJSON_Hooks hooks; + hooks.malloc_fn = os_malloc; + hooks.free_fn = os_free; + cJSON_InitHooks(&hooks); + + if (relayCount > 0) { + for (i = 0; i < CHANNEL_MAX; i++) { + if (h_isChannelRelay(i)) { + HassDeviceInfo* dev_info = hass_init_relay_device_info(i); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + } + } + } + + if (pwmCount == 5 || isLedDriverChipRunning()) { + // Enable + RGB control + CW control + HassDeviceInfo* dev_info = hass_init_light_device_info(ENTITY_LIGHT_RGBCW, -1); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + } + else if (pwmCount == 3) { + // Enable + RGB control + HassDeviceInfo* dev_info = hass_init_light_device_info(ENTITY_LIGHT_RGB, -1); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + } + else if (pwmCount > 0) { + for (i = 0; i < CHANNEL_MAX; i++) { + if (h_isChannelPWM(i)) { + HassDeviceInfo* dev_info = hass_init_light_device_info(ENTITY_LIGHT_PWM, i); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + } + } + } - if (pwmCount == 5 || isLedDriverChipRunning()) { - // Enable + RGB control + CW control - HassDeviceInfo *dev_info = hass_init_light_device_info(ENTITY_LIGHT_RGBCW, -1); - MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); - hass_free_device_info(dev_info); - } - else if (pwmCount == 3) { - // Enable + RGB control - HassDeviceInfo *dev_info = hass_init_light_device_info(ENTITY_LIGHT_RGB, -1); - MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); - hass_free_device_info(dev_info); - } - else if(pwmCount > 0) { - for(i = 0; i < CHANNEL_MAX; i++) { - if(h_isChannelPWM(i)) { - HassDeviceInfo *dev_info = hass_init_light_device_info(ENTITY_LIGHT_PWM, i); - MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); - hass_free_device_info(dev_info); - } - } - } - #ifndef OBK_DISABLE_ALL_DRIVERS - if (DRV_IsMeasuringPower()){ - for(i = 0;i < OBK_NUM_MEASUREMENTS;i ++) - { - HassDeviceInfo *dev_info = hass_init_light_device_info(ENTITY_SENSOR, i); - MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); - hass_free_device_info(dev_info); - } - } + if (DRV_IsMeasuringPower()) { + for (i = 0;i < OBK_NUM_MEASUREMENTS;i++) + { + HassDeviceInfo* dev_info = hass_init_light_device_info(ENTITY_SENSOR, i); + MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); + hass_free_device_info(dev_info); + } + } #endif - poststr(request, NULL); - return 0; -} - -void http_generate_rgb_cfg(http_request_t *request, char *clientId){ - hprintf128(request," rgb_command_template: \"{{ '#%%02x%%02x%%02x0000' | format(red, green, blue)}}\"\n"); - hprintf128(request," rgb_value_template: \"{{ value[1:3] | int(base=16) }},{{ value[3:5] | int(base=16) }},{{ value[5:7] | int(base=16) }}\"\n"); - hprintf128(request," rgb_state_topic: \"%s/led_basecolor_rgb/get\"\n",clientId); - hprintf128(request," rgb_command_topic: \"cmnd/%s/led_basecolor_rgb\"\n",clientId); - hprintf128(request," command_topic: \"cmnd/%s/led_enableAll\"\n",clientId); - hprintf128(request," state_topic: \"%s/led_enableAll/get\"\n",clientId); - hprintf128(request," availability_topic: \"%s/connected\"\n",clientId); - hprintf128(request," payload_on: 1\n"); - hprintf128(request," payload_off: 0\n"); - hprintf128(request," brightness_command_topic: \"cmnd/%s/led_dimmer\"\n",clientId); - hprintf128(request," brightness_scale: 100\n"); -} - -int http_fn_ha_cfg(http_request_t *request) { - int relayCount = 0; - int pwmCount = 0; - const char *shortDeviceName; - const char *clientId; - int i; - char mqttAdded = 0; - char switchAdded = 0; - char lightAdded = 0; - - shortDeviceName = CFG_GetShortDeviceName(); - clientId = CFG_GetMQTTClientId(); - - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Home Assistant Setup"); - poststr(request,"

Home Assistant Cfg

"); - hprintf128(request,"

Note that your short device name is: %s

",shortDeviceName); - poststr(request,"

Paste this to configuration yaml

"); - poststr(request,"
Make sure that you have \"switch:\" keyword only once! Home Assistant doesn't like dup keywords.
"); - poststr(request,"
You can also use \"switch MyDeviceName:\" to avoid keyword duplication!
"); - - poststr(request,""); - poststr(request,"
 

"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); - poststr(request, ha_discovery_script); poststr(request, NULL); - return 0; + return 0; +} + +void http_generate_rgb_cfg(http_request_t* request, char* clientId) { + hprintf128(request, " rgb_command_template: \"{{ '#%%02x%%02x%%02x0000' | format(red, green, blue)}}\"\n"); + hprintf128(request, " rgb_value_template: \"{{ value[1:3] | int(base=16) }},{{ value[3:5] | int(base=16) }},{{ value[5:7] | int(base=16) }}\"\n"); + hprintf128(request, " rgb_state_topic: \"%s/led_basecolor_rgb/get\"\n", clientId); + hprintf128(request, " rgb_command_topic: \"cmnd/%s/led_basecolor_rgb\"\n", clientId); + hprintf128(request, " command_topic: \"cmnd/%s/led_enableAll\"\n", clientId); + hprintf128(request, " state_topic: \"%s/led_enableAll/get\"\n", clientId); + hprintf128(request, " availability_topic: \"%s/connected\"\n", clientId); + hprintf128(request, " payload_on: 1\n"); + hprintf128(request, " payload_off: 0\n"); + hprintf128(request, " brightness_command_topic: \"cmnd/%s/led_dimmer\"\n", clientId); + hprintf128(request, " brightness_scale: 100\n"); +} + +int http_fn_ha_cfg(http_request_t* request) { + int relayCount = 0; + int pwmCount = 0; + const char* shortDeviceName; + const char* clientId; + int i; + char mqttAdded = 0; + char switchAdded = 0; + char lightAdded = 0; + + shortDeviceName = CFG_GetShortDeviceName(); + clientId = CFG_GetMQTTClientId(); + + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Home Assistant Setup"); + poststr(request, "

Home Assistant Cfg

"); + hprintf128(request, "

Note that your short device name is: %s

", shortDeviceName); + poststr(request, "

Paste this to configuration yaml

"); + poststr(request, "
Make sure that you have \"switch:\" keyword only once! Home Assistant doesn't like dup keywords.
"); + poststr(request, "
You can also use \"switch MyDeviceName:\" to avoid keyword duplication!
"); + + poststr(request, ""); + poststr(request, "
 

"); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); + poststr(request, ha_discovery_script); + poststr(request, NULL); + return 0; } // https://tasmota.github.io/docs/Commands/#with-mqtt @@ -1415,7 +1443,7 @@ http:///cm?user=admin&password=joker&cmnd=Power%20Toggle // https://www.elektroda.com/rtvforum/viewtopic.php?p=19330027#19330027 // Web browser sends: GET /cm?cmnd=POWER1 // System responds with state -int http_tasmota_json_power(http_request_t *request) { +int http_tasmota_json_power(http_request_t* request) { int numRelays; int numPWMs; int i; @@ -1426,34 +1454,39 @@ int http_tasmota_json_power(http_request_t *request) { numRelays = 0; // LED driver (if has PWMs) - if(numPWMs > 0){ - if(LED_GetEnableAll() == 0) { - poststr(request,"{\"POWER\":\"OFF\"}"); - } else { - poststr(request,"{\"POWER\":\"ON\"}"); + if (numPWMs > 0) { + if (LED_GetEnableAll() == 0) { + poststr(request, "{\"POWER\":\"OFF\"}"); } - } else { + else { + poststr(request, "{\"POWER\":\"ON\"}"); + } + } + else { // relays driver - for(i = 0; i < CHANNEL_MAX; i++) { + for (i = 0; i < CHANNEL_MAX; i++) { if (h_isChannelRelay(i) || CHANNEL_GetType(i) == ChType_Toggle) { numRelays++; lastRelayState = CHANNEL_Get(i); } } - if(numRelays == 1) { - if(lastRelayState) { - poststr(request,"{\"POWER\":\"ON\"}"); - } else { - poststr(request,"{\"POWER\":\"OFF\"}"); + if (numRelays == 1) { + if (lastRelayState) { + poststr(request, "{\"POWER\":\"ON\"}"); } - } else { - for(i = 0; i < CHANNEL_MAX; i++) { + else { + poststr(request, "{\"POWER\":\"OFF\"}"); + } + } + else { + for (i = 0; i < CHANNEL_MAX; i++) { if (h_isChannelRelay(i) || CHANNEL_GetType(i) == ChType_Toggle) { lastRelayState = CHANNEL_Get(i); - if(lastRelayState) { - hprintf128(request,"{\"POWER%i\":\"ON\"}",i); - } else { - hprintf128(request,"{\"POWER%i\":\"OFF\"}",i); + if (lastRelayState) { + hprintf128(request, "{\"POWER%i\":\"ON\"}", i); + } + else { + hprintf128(request, "{\"POWER%i\":\"OFF\"}", i); } } } @@ -1465,7 +1498,7 @@ int http_tasmota_json_power(http_request_t *request) { /* {"StatusSNS":{"Time":"2022-07-30T10:11:26","ENERGY":{"TotalStartTime":"2022-05-12T10:56:31","Total":0.003,"Yesterday":0.003,"Today":0.000,"Power": 0,"ApparentPower": 0,"ReactivePower": 0,"Factor":0.00,"Voltage":236,"Current":0.000}}} */ -int http_tasmota_json_status_SNS(http_request_t *request) { +int http_tasmota_json_status_SNS(http_request_t* request) { float power, factor, voltage, current; #ifndef OBK_DISABLE_ALL_DRIVERS @@ -1474,238 +1507,242 @@ int http_tasmota_json_status_SNS(http_request_t *request) { current = DRV_GetReading(OBK_CURRENT); power = DRV_GetReading(OBK_POWER); #else - factor = 0; + factor = 0; voltage = 0; current = 0; power = 0; #endif - hprintf128(request,"{\"StatusSNS\":{\"ENERGY\":{"); - hprintf128(request,"\"Power\": %f,", power); - hprintf128(request,"\"ApparentPower\": 0,\"ReactivePower\": 0,\"Factor\":%f,", factor); - hprintf128(request,"\"Voltage\":%f,", voltage); - hprintf128(request,"\"Current\":%f}}}", current); + hprintf128(request, "{\"StatusSNS\":{\"ENERGY\":{"); + hprintf128(request, "\"Power\": %f,", power); + hprintf128(request, "\"ApparentPower\": 0,\"ReactivePower\": 0,\"Factor\":%f,", factor); + hprintf128(request, "\"Voltage\":%f,", voltage); + hprintf128(request, "\"Current\":%f}}}", current); return 0; } /* {"Status":{"Module":0,"DeviceName":"Tasmota","FriendlyName":["Tasmota"],"Topic":"tasmota_48E7F3","ButtonTopic":"0","Power":1,"PowerOnState":3,"LedState":1,"LedMask":"FFFF","SaveData":1,"SaveState":1,"SwitchTopic":"0","SwitchMode":[0,0,0,0,0,0,0,0],"ButtonRetain":0,"SwitchRetain":0,"SensorRetain":0,"PowerRetain":0,"InfoRetain":0,"StateRetain":0}} */ -int http_tasmota_json_status_generic(http_request_t *request) { - const char *deviceName; - const char *friendlyName; - const char *clientId; +int http_tasmota_json_status_generic(http_request_t* request) { + const char* deviceName; + const char* friendlyName; + const char* clientId; deviceName = CFG_GetShortDeviceName(); friendlyName = CFG_GetDeviceName(); clientId = CFG_GetMQTTClientId(); - hprintf128(request,"{\"Status\":{\"Module\":0,\"DeviceName\":\"%s\"",deviceName); - hprintf128(request,",\"FriendlyName\":[\"%s\"]",friendlyName); - hprintf128(request,",\"Topic\":\"%s\",\"ButtonTopic\":\"0\"",clientId); - hprintf128(request,",\"Power\":1,\"PowerOnState\":3,\"LedState\":1"); - hprintf128(request,",\"LedMask\":\"FFFF\",\"SaveData\":1,\"SaveState\":1"); - hprintf128(request,",\"SwitchTopic\":\"0\",\"SwitchMode\":[0,0,0,0,0,0,0,0]"); - hprintf128(request,",\"ButtonRetain\":0,\"SwitchRetain\":0,\"SensorRetain\":0"); - hprintf128(request,",\"PowerRetain\":0,\"InfoRetain\":0,\"StateRetain\":0}}"); + hprintf128(request, "{\"Status\":{\"Module\":0,\"DeviceName\":\"%s\"", deviceName); + hprintf128(request, ",\"FriendlyName\":[\"%s\"]", friendlyName); + hprintf128(request, ",\"Topic\":\"%s\",\"ButtonTopic\":\"0\"", clientId); + hprintf128(request, ",\"Power\":1,\"PowerOnState\":3,\"LedState\":1"); + hprintf128(request, ",\"LedMask\":\"FFFF\",\"SaveData\":1,\"SaveState\":1"); + hprintf128(request, ",\"SwitchTopic\":\"0\",\"SwitchMode\":[0,0,0,0,0,0,0,0]"); + hprintf128(request, ",\"ButtonRetain\":0,\"SwitchRetain\":0,\"SensorRetain\":0"); + hprintf128(request, ",\"PowerRetain\":0,\"InfoRetain\":0,\"StateRetain\":0}}"); return 0; } -int http_fn_cm(http_request_t *request) { +int http_fn_cm(http_request_t* request) { char tmpA[128]; - http_setup(request, httpMimeTypeJson); + http_setup(request, httpMimeTypeJson); // exec command - if( http_getArg(request->url,"cmnd",tmpA,sizeof(tmpA))) { - CMD_ExecuteCommand(tmpA,COMMAND_FLAG_SOURCE_HTTP); + if (http_getArg(request->url, "cmnd", tmpA, sizeof(tmpA))) { + CMD_ExecuteCommand(tmpA, COMMAND_FLAG_SOURCE_HTTP); - if(!wal_strnicmp(tmpA,"POWER",5)) { + if (!wal_strnicmp(tmpA, "POWER", 5)) { http_tasmota_json_power(request); - } else if(!wal_strnicmp(tmpA,"STATUS 8",8)) { + } + else if (!wal_strnicmp(tmpA, "STATUS 8", 8)) { http_tasmota_json_status_SNS(request); - } else { + } + else { http_tasmota_json_status_generic(request); } - } + } poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg(http_request_t *request) { - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Config"); - postFormAction(request, "cfg_pins", "Configure Module"); - postFormAction(request, "cfg_generic", "Configure General"); - postFormAction(request, "cfg_startup", "Configure Startup"); - postFormAction(request, "cfg_dgr", "Configure Device Groups"); - postFormAction(request, "cfg_quick","Quick Config"); - postFormAction(request, "cfg_wifi", "Configure WiFi"); - postFormAction(request, "cfg_mqtt", "Configure MQTT"); - postFormAction(request, "cfg_name", "Configure Names"); - postFormAction(request, "cfg_mac", "Change MAC"); - postFormAction(request, "cfg_ping", "Ping Watchdog (Network lost restarter)"); - postFormAction(request, "cfg_webapp", "Configure Webapp"); - postFormAction(request, "ha_cfg", "Generate Home Assistant cfg"); - postFormAction(request, "ota", "OTA (update software by WiFi)"); - postFormAction(request, "cmd_tool", "Execute custom command"); - postFormAction(request, "flash_read_tool" ,"Flash Read Tool"); - postFormAction(request, "uart_tool", "UART Tool"); - postFormAction(request, "startup_command", "Change startup command text"); +int http_fn_cfg(http_request_t* request) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Config"); + postFormAction(request, "cfg_pins", "Configure Module"); + postFormAction(request, "cfg_generic", "Configure General"); + postFormAction(request, "cfg_startup", "Configure Startup"); + postFormAction(request, "cfg_dgr", "Configure Device Groups"); + postFormAction(request, "cfg_quick", "Quick Config"); + postFormAction(request, "cfg_wifi", "Configure WiFi"); + postFormAction(request, "cfg_mqtt", "Configure MQTT"); + postFormAction(request, "cfg_name", "Configure Names"); + postFormAction(request, "cfg_mac", "Change MAC"); + postFormAction(request, "cfg_ping", "Ping Watchdog (Network lost restarter)"); + postFormAction(request, "cfg_webapp", "Configure Webapp"); + postFormAction(request, "ha_cfg", "Generate Home Assistant cfg"); + postFormAction(request, "ota", "OTA (update software by WiFi)"); + postFormAction(request, "cmd_tool", "Execute custom command"); + postFormAction(request, "flash_read_tool", "Flash Read Tool"); + postFormAction(request, "uart_tool", "UART Tool"); + postFormAction(request, "startup_command", "Change startup command text"); #if 0 #if PLATFORM_BK7231T | PLATFORM_BK7231N { - int i,j,k; - k = config_get_tableOffsets(BK_PARTITION_NET_PARAM,&i,&j); - hprintf128(request,"BK_PARTITION_NET_PARAM: bOk %i, at %i, len %i
",k,i,j); - k = config_get_tableOffsets(BK_PARTITION_RF_FIRMWARE,&i,&j); - hprintf128(request,"BK_PARTITION_RF_FIRMWARE: bOk %i, at %i, len %i
",k,i,j); - k = config_get_tableOffsets(BK_PARTITION_OTA,&i,&j); - hprintf128(request,"BK_PARTITION_OTA: bOk %i, at %i, len %i
",k,i,j); + int i, j, k; + k = config_get_tableOffsets(BK_PARTITION_NET_PARAM, &i, &j); + hprintf128(request, "BK_PARTITION_NET_PARAM: bOk %i, at %i, len %i
", k, i, j); + k = config_get_tableOffsets(BK_PARTITION_RF_FIRMWARE, &i, &j); + hprintf128(request, "BK_PARTITION_RF_FIRMWARE: bOk %i, at %i, len %i
", k, i, j); + k = config_get_tableOffsets(BK_PARTITION_OTA, &i, &j); + hprintf128(request, "BK_PARTITION_OTA: bOk %i, at %i, len %i
", k, i, j); } #endif #endif - poststr(request,htmlFooterReturnToMenu); - http_html_end(request); + poststr(request, htmlFooterReturnToMenu); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_pins(http_request_t *request) { - int iChanged = 0; - int iChangedRequested = 0; - int i; +int http_fn_cfg_pins(http_request_t* request) { + int iChanged = 0; + int iChangedRequested = 0; + int i; char tmpA[128]; char tmpB[64]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Pin config"); - poststr(request,"
First textfield is used to enter channel index (relay index), used to support multiple relays and buttons
"); - poststr(request,"
(so, first button and first relay should have channel 1, second button and second relay have channel 2, etc)
"); - poststr(request,"
Second textfield (only for buttons) is used to enter channel to toggle when doing double click
"); - poststr(request,"
(second textfield shows up when you change role to button and save...)
"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Pin config"); + poststr(request, "
First textfield is used to enter channel index (relay index), used to support multiple relays and buttons
"); + poststr(request, "
(so, first button and first relay should have channel 1, second button and second relay have channel 2, etc)
"); + poststr(request, "
Second textfield (only for buttons) is used to enter channel to toggle when doing double click
"); + poststr(request, "
(second textfield shows up when you change role to button and save...)
"); #if PLATFORM_BK7231N || PLATFORM_BK7231T - poststr(request,"
BK7231N/BK7231T supports PWM only on pins 6, 7, 8, 9, 24 and 26!
"); + poststr(request, "
BK7231N/BK7231T supports PWM only on pins 6, 7, 8, 9, 24 and 26!
"); #endif - for(i = 0; i < PLATFORM_GPIO_MAX; i++) { - sprintf(tmpA, "%i",i); - if(http_getArg(request->url,tmpA,tmpB,sizeof(tmpB))) { - int role; - int pr; + for (i = 0; i < PLATFORM_GPIO_MAX; i++) { + sprintf(tmpA, "%i", i); + if (http_getArg(request->url, tmpA, tmpB, sizeof(tmpB))) { + int role; + int pr; - iChangedRequested++; + iChangedRequested++; - role = atoi(tmpB); + role = atoi(tmpB); - pr = PIN_GetPinRoleForPinIndex(i); - if(pr != role) { - PIN_SetPinRoleForPinIndex(i,role); - iChanged++; - } - } - sprintf(tmpA, "r%i",i); - if(http_getArg(request->url,tmpA,tmpB,sizeof(tmpB))) { - int rel; - int prevRel; + pr = PIN_GetPinRoleForPinIndex(i); + if (pr != role) { + PIN_SetPinRoleForPinIndex(i, role); + iChanged++; + } + } + sprintf(tmpA, "r%i", i); + if (http_getArg(request->url, tmpA, tmpB, sizeof(tmpB))) { + int rel; + int prevRel; - iChangedRequested++; + iChangedRequested++; - rel = atoi(tmpB); + rel = atoi(tmpB); - prevRel = PIN_GetPinChannelForPinIndex(i); - if(prevRel != rel) { - PIN_SetPinChannelForPinIndex(i,rel); - iChanged++; - } - } - sprintf(tmpA, "e%i",i); - if(http_getArg(request->url,tmpA,tmpB,sizeof(tmpB))) { - int rel; - int prevRel; + prevRel = PIN_GetPinChannelForPinIndex(i); + if (prevRel != rel) { + PIN_SetPinChannelForPinIndex(i, rel); + iChanged++; + } + } + sprintf(tmpA, "e%i", i); + if (http_getArg(request->url, tmpA, tmpB, sizeof(tmpB))) { + int rel; + int prevRel; - iChangedRequested++; + iChangedRequested++; - rel = atoi(tmpB); + rel = atoi(tmpB); - prevRel = PIN_GetPinChannel2ForPinIndex(i); - if(prevRel != rel) { - PIN_SetPinChannel2ForPinIndex(i,rel); - iChanged++; - } - } - } - if(iChangedRequested>0) { - // Anecdotally, if pins are configured badly, the - // second-timer breaks. To reconfigure, force - // saving the configuration instead of waiting. + prevRel = PIN_GetPinChannel2ForPinIndex(i); + if (prevRel != rel) { + PIN_SetPinChannel2ForPinIndex(i, rel); + iChanged++; + } + } + } + if (iChangedRequested > 0) { + // Anecdotally, if pins are configured badly, the + // second-timer breaks. To reconfigure, force + // saving the configuration instead of waiting. //CFG_Save_SetupTimer(); - CFG_Save_IfThereArePendingChanges(); - hprintf128(request, "Pins update - %i reqs, %i changed!

",iChangedRequested,iChanged); - } -// strcat(outbuf,""); - poststr(request,"
"); - for(i = 0; i < PLATFORM_GPIO_MAX; i++) { - int si, ch, ch2; - int j; - const char *alias; + CFG_Save_IfThereArePendingChanges(); + hprintf128(request, "Pins update - %i reqs, %i changed!

", iChangedRequested, iChanged); + } + // strcat(outbuf,""); + poststr(request, ""); + for (i = 0; i < PLATFORM_GPIO_MAX; i++) { + int si, ch, ch2; + int j; + const char* alias; // On BL602, any GPIO can be mapped to one of 5 PWM channels // But on Beken chips, only certain pins can be PWM int bCanThisPINbePWM; - si = PIN_GetPinRoleForPinIndex(i); - ch = PIN_GetPinChannelForPinIndex(i); - ch2 = PIN_GetPinChannel2ForPinIndex(i); + si = PIN_GetPinRoleForPinIndex(i); + ch = PIN_GetPinChannelForPinIndex(i); + ch2 = PIN_GetPinChannel2ForPinIndex(i); bCanThisPINbePWM = HAL_PIN_CanThisPinBePWM(i); // if available.. alias = HAL_PIN_GetPinNameAlias(i); - poststr(request, "
"); - if(alias) { - poststr(request,alias); - poststr(request," "); - } else { - hprintf128(request, "P%i ",i); + poststr(request, "
"); + if (alias) { + poststr(request, alias); + poststr(request, " "); } - hprintf128(request, "", i); + for (j = 0; j < IOR_Total_Options; j++) { // do not show hardware PWM on non-PWM pin - if(j == IOR_PWM || j == IOR_PWM_n) { - if(bCanThisPINbePWM == 0) { + if (j == IOR_PWM || j == IOR_PWM_n) { + if (bCanThisPINbePWM == 0) { continue; } } - if(j == si) { - hprintf128(request, "",j,htmlPinRoleNames[j]); - } else { - hprintf128(request, "",j,htmlPinRoleNames[j]); - } - } - poststr(request, ""); - hprintf128(request, "",i,ch); + if (j == si) { + hprintf128(request, "", j, htmlPinRoleNames[j]); + } + else { + hprintf128(request, "", j, htmlPinRoleNames[j]); + } + } + poststr(request, ""); + hprintf128(request, "", i, ch); - if(si == IOR_Button || si == IOR_Button_n) + if (si == IOR_Button || si == IOR_Button_n) { // extra param. For button, is relay index to toggle on double click - hprintf128(request, "",i,ch2); + hprintf128(request, "", i, ch2); } - poststr(request,"
"); - } - poststr(request,""); + poststr(request, "
"); + } + poststr(request, ""); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -const char *g_obk_flagNames[] = { +const char* g_obk_flagNames[] = { "[MQTT] Broadcast led params together (send dimmer and color when dimmer or color changes, topic name: YourDevName/led_basecolor_rgb/get, YourDevName/led_dimmer/get)", "[MQTT] Broadcast led final color (topic name: YourDevName/led_finalcolor_rgb/get)", "[MQTT] Broadcast self state every minute (May cause device disconnect's, DONT USE IT YET)", @@ -1723,264 +1760,265 @@ const char *g_obk_flagNames[] = { "error", }; -int http_fn_cfg_generic(http_request_t *request) { - int i; +int http_fn_cfg_generic(http_request_t* request) { + int i; char tmpA[64]; char tmpB[64]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Generic config"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Generic config"); - if( http_getArg(request->url,"boot_ok_delay",tmpA,sizeof(tmpA))) { + if (http_getArg(request->url, "boot_ok_delay", tmpA, sizeof(tmpA))) { i = atoi(tmpA); - if(i <= 0) { - poststr(request,"
Boot ok delay must be at least 1 second
"); + if (i <= 0) { + poststr(request, "
Boot ok delay must be at least 1 second
"); i = 1; } - hprintf128(request,"
Setting boot OK delay to %i
",i); + hprintf128(request, "
Setting boot OK delay to %i
", i); CFG_SetBootOkSeconds(i); - } + } - if( http_getArg(request->url,"setFlags",tmpA,sizeof(tmpA))) { - for(i = 0; i < OBK_TOTAL_FLAGS; i++) { + if (http_getArg(request->url, "setFlags", tmpA, sizeof(tmpA))) { + for (i = 0; i < OBK_TOTAL_FLAGS; i++) { int ni; - sprintf(tmpB,"flag%i",i); + sprintf(tmpB, "flag%i", i); - if( http_getArg(request->url,tmpB,tmpA,sizeof(tmpA))) { + if (http_getArg(request->url, tmpB, tmpA, sizeof(tmpA))) { ni = atoi(tmpA); - } else { + } + else { ni = 0; } - hprintf128(request,"
Setting flag %i to %i
",i,ni); - CFG_SetFlag(i,ni); + hprintf128(request, "
Setting flag %i to %i
", i, ni); + CFG_SetFlag(i, ni); } - } + } CFG_Save_IfThereArePendingChanges(); - hprintf128(request,"
Flags (Current value=%i)
",CFG_GetFlags()); - poststr(request,"
"); + hprintf128(request, "
Flags (Current value=%i)
", CFG_GetFlags()); + poststr(request, ""); - for(i = 0; i < OBK_TOTAL_FLAGS; i++) { - const char *flagName = g_obk_flagNames[i]; -/* -
- -
-*/ - hprintf128(request, "
", - i, i, (CFG_HasFlag(i) ?" checked":"")); //this is less that 128 char + for (i = 0; i < OBK_TOTAL_FLAGS; i++) { + const char* flagName = g_obk_flagNames[i]; + /* +
+ +
+ */ + hprintf128(request, "
", + i, i, (CFG_HasFlag(i) ? " checked" : "")); //this is less that 128 char - hprintf128(request,"
"); + hprintf128(request, "
"); } - poststr(request,""); - poststr(request,""); + poststr(request, ""); + poststr(request, ""); - add_label_numeric_field(request, "Uptime seconds required to mark boot as ok", "boot_ok_delay", - CFG_GetBootOkSeconds(), "
"); - poststr(request,"
"); + add_label_numeric_field(request, "Uptime seconds required to mark boot as ok", "boot_ok_delay", + CFG_GetBootOkSeconds(), "
"); + poststr(request, "
"); - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_startup(http_request_t *request) { +int http_fn_cfg_startup(http_request_t* request) { int channelIndex; int newValue; - int i; + int i; char tmpA[128]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Config startup"); - hprintf128(request,"
Here you can set pin start values
"); - hprintf128(request,"
For relays, simply use 1 or 0
"); - hprintf128(request,"
For 'remember last power state', use -1 as a special value
"); - hprintf128(request,"
For dimmers, range is 0 to 100
"); - hprintf128(request,"
For custom values, you can set any number you want to
"); - hprintf128(request,"
Remember that you can also use short startup command to run commands like led_baseColor #FF0000 and led_enableAll 1 etc
"); - hprintf128(request,"
Remembering last state of LED driver is not yet fully supported, please wait!
"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Config startup"); + hprintf128(request, "
Here you can set pin start values
"); + hprintf128(request, "
For relays, simply use 1 or 0
"); + hprintf128(request, "
For 'remember last power state', use -1 as a special value
"); + hprintf128(request, "
For dimmers, range is 0 to 100
"); + hprintf128(request, "
For custom values, you can set any number you want to
"); + hprintf128(request, "
Remember that you can also use short startup command to run commands like led_baseColor #FF0000 and led_enableAll 1 etc
"); + hprintf128(request, "
Remembering last state of LED driver is not yet fully supported, please wait!
"); - if( http_getArg(request->url,"idx",tmpA,sizeof(tmpA))) { + if (http_getArg(request->url, "idx", tmpA, sizeof(tmpA))) { channelIndex = atoi(tmpA); - if( http_getArg(request->url,"value",tmpA,sizeof(tmpA))) { + if (http_getArg(request->url, "value", tmpA, sizeof(tmpA))) { newValue = atoi(tmpA); - CFG_SetChannelStartupValue(channelIndex,newValue); + CFG_SetChannelStartupValue(channelIndex, newValue); // also save current value if marked as saved Channel_SaveInFlashIfNeeded(channelIndex); - hprintf128(request,"
Setting channel %i start value to %i
",channelIndex,newValue); + hprintf128(request, "
Setting channel %i start value to %i
", channelIndex, newValue); CFG_Save_IfThereArePendingChanges(); } - } + } - for(i = 0; i < CHANNEL_MAX; i++) { - if(CHANNEL_IsInUse(i)) { + for (i = 0; i < CHANNEL_MAX; i++) { + if (CHANNEL_IsInUse(i)) { int startValue; startValue = CFG_GetChannelStartupValue(i); - poststr(request,"
\ + poststr(request, "
\
\ + hprintf128(request, "%i", i); + poststr(request, ":
\ "); - poststr(request,"
"); - poststr(request,"
"); + hprintf128(request, "%i", i); + poststr(request, "\">"); + poststr(request, "
"); + poststr(request, ""); } } - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_cfg_dgr(http_request_t *request) { +int http_fn_cfg_dgr(http_request_t* request) { char tmpA[128]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Device groups"); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Device groups"); - hprintf128(request,"
Here you can configure Tasmota Device Groups
"); + hprintf128(request, "
Here you can configure Tasmota Device Groups
"); - if( http_getArg(request->url,"name",tmpA,sizeof(tmpA))) { + if (http_getArg(request->url, "name", tmpA, sizeof(tmpA))) { int newSendFlags; int newRecvFlags; newSendFlags = 0; newRecvFlags = 0; - if(http_getArgInteger(request->url,"s_pwr")) + if (http_getArgInteger(request->url, "s_pwr")) newSendFlags |= DGR_SHARE_POWER; - if(http_getArgInteger(request->url,"r_pwr")) + if (http_getArgInteger(request->url, "r_pwr")) newRecvFlags |= DGR_SHARE_POWER; - if(http_getArgInteger(request->url,"s_lbr")) + if (http_getArgInteger(request->url, "s_lbr")) newSendFlags |= DGR_SHARE_LIGHT_BRI; - if(http_getArgInteger(request->url,"r_lbr")) + if (http_getArgInteger(request->url, "r_lbr")) newRecvFlags |= DGR_SHARE_LIGHT_BRI; - if(http_getArgInteger(request->url,"s_lcl")) + if (http_getArgInteger(request->url, "s_lcl")) newSendFlags |= DGR_SHARE_LIGHT_COLOR; - if(http_getArgInteger(request->url,"r_lcl")) + if (http_getArgInteger(request->url, "r_lcl")) newRecvFlags |= DGR_SHARE_LIGHT_COLOR; CFG_DeviceGroups_SetName(tmpA); CFG_DeviceGroups_SetSendFlags(newSendFlags); CFG_DeviceGroups_SetRecvFlags(newRecvFlags); - if(tmpA[0] != 0) { + if (tmpA[0] != 0) { #ifndef OBK_DISABLE_ALL_DRIVERS DRV_StartDriver("DGR"); #endif } CFG_Save_IfThereArePendingChanges(); - } + } { int newSendFlags; int newRecvFlags; - const char *groupName = CFG_DeviceGroups_GetName(); + const char* groupName = CFG_DeviceGroups_GetName(); newSendFlags = CFG_DeviceGroups_GetSendFlags(); newRecvFlags = CFG_DeviceGroups_GetRecvFlags(); add_label_text_field(request, "Group name", "name", groupName, "
"); - poststr(request,"
"); + poststr(request, "
NameTasmota CodeReceiveSend
Power1
"); - poststr(request," "); + poststr(request, " "); - poststr(request," "); + poststr(request, " "); - poststr(request," "); + poststr(request, " "); - poststr(request," "); - poststr(request," "); + poststr(request, " "); + poststr(request, " "); - poststr(request,"
NameTasmota CodeReceiveSend
Power1
Light Brightness 2
Light Brightness 2
Light Color 16
Light Color 16
"); + poststr(request, " "); } - poststr(request,htmlFooterReturnToCfgLink); - http_html_end(request); + poststr(request, htmlFooterReturnToCfgLink); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -void XR809_RequestOTAHTTP(const char *s); +void XR809_RequestOTAHTTP(const char* s); -int http_fn_ota_exec(http_request_t *request) { +int http_fn_ota_exec(http_request_t* request) { char tmpA[128]; //char tmpB[64]; - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "OTA request"); - if(http_getArg(request->url,"host",tmpA,sizeof(tmpA))) { - hprintf128(request,"

OTA requested for %s!

",tmpA); - addLogAdv(LOG_INFO, LOG_FEATURE_HTTP,"http_fn_ota_exec: will try to do OTA for %s \r\n",tmpA); + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "OTA request"); + if (http_getArg(request->url, "host", tmpA, sizeof(tmpA))) { + hprintf128(request, "

OTA requested for %s!

", tmpA); + addLogAdv(LOG_INFO, LOG_FEATURE_HTTP, "http_fn_ota_exec: will try to do OTA for %s \r\n", tmpA); #if WINDOWS #elif PLATFORM_BL602 #elif PLATFORM_W600 || PLATFORM_W800 - t_http_fwup(tmpA); + t_http_fwup(tmpA); #elif PLATFORM_XR809 - XR809_RequestOTAHTTP(tmpA); + XR809_RequestOTAHTTP(tmpA); #else - otarequest(tmpA); + otarequest(tmpA); #endif - } - poststr(request,htmlFooterReturnToMenu); - http_html_end(request); + } + poststr(request, htmlFooterReturnToMenu); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_ota(http_request_t *request) { - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "OTA system"); - poststr(request,"

Simple OTA system (you should rather use the OTA from App panel where you can drag and drop file easily without setting up server). Use RBL file for OTA. In the OTA below, you should paste link to RBL file (you need HTTP server).

"); - add_label_text_field(request, "URL for new bin file", "host", "", "
"); - poststr(request,"
\ +int http_fn_ota(http_request_t* request) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "OTA system"); + poststr(request, "

Simple OTA system (you should rather use the OTA from App panel where you can drag and drop file easily without setting up server). Use RBL file for OTA. In the OTA below, you should paste link to RBL file (you need HTTP server).

"); + add_label_text_field(request, "URL for new bin file", "host", "", ""); + poststr(request, "
\ \
"); - poststr(request,htmlFooterReturnToMenu); - http_html_end(request); + poststr(request, htmlFooterReturnToMenu); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } -int http_fn_other(http_request_t *request) { - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "Not found"); - poststr(request,"Not found.
"); - poststr(request,htmlFooterReturnToMenu); - http_html_end(request); +int http_fn_other(http_request_t* request) { + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "Not found"); + poststr(request, "Not found.
"); + poststr(request, htmlFooterReturnToMenu); + http_html_end(request); poststr(request, NULL); - return 0; + return 0; } diff --git a/src/httpserver/http_fns.h b/src/httpserver/http_fns.h index d489fbbee..4dcc33e2d 100644 --- a/src/httpserver/http_fns.h +++ b/src/httpserver/http_fns.h @@ -2,34 +2,34 @@ -int http_fn_about(http_request_t *request); -int http_fn_cfg_mqtt(http_request_t *request); -int http_fn_cfg_mqtt_set(http_request_t *request); -int http_fn_cfg_webapp(http_request_t *request); -int http_fn_config_dump_table(http_request_t *request); -int http_fn_cfg_webapp_set(http_request_t *request); -int http_fn_cfg_wifi_set(http_request_t *request); -int http_fn_cfg_name(http_request_t *request); -int http_fn_cfg_loglevel_set(http_request_t *request); -int http_fn_cfg_wifi(http_request_t *request); -int http_fn_cfg_mac(http_request_t *request); -int http_fn_flash_read_tool(http_request_t *request); -int http_fn_cmd_tool(http_request_t *request); -int http_fn_uart_tool(http_request_t *request); -int http_fn_cfg_quick(http_request_t *request); -int http_fn_ha_cfg(http_request_t *request); -int http_fn_ha_discovery(http_request_t *request); -int http_fn_cfg(http_request_t *request); -int http_fn_cfg_pins(http_request_t *request); -int http_fn_cfg_ping(http_request_t *request); -int http_fn_index(http_request_t *request); -int http_fn_testmsg(http_request_t *request); -int http_fn_ota_exec(http_request_t *request); -int http_fn_ota(http_request_t *request); -int http_fn_empty_url(http_request_t *request); -int http_fn_other(http_request_t *request); -int http_fn_cm(http_request_t *request); -int http_fn_startup_command(http_request_t *request); -int http_fn_cfg_generic(http_request_t *request); -int http_fn_cfg_startup(http_request_t *request); -int http_fn_cfg_dgr(http_request_t *request); +int http_fn_about(http_request_t* request); +int http_fn_cfg_mqtt(http_request_t* request); +int http_fn_cfg_mqtt_set(http_request_t* request); +int http_fn_cfg_webapp(http_request_t* request); +int http_fn_config_dump_table(http_request_t* request); +int http_fn_cfg_webapp_set(http_request_t* request); +int http_fn_cfg_wifi_set(http_request_t* request); +int http_fn_cfg_name(http_request_t* request); +int http_fn_cfg_loglevel_set(http_request_t* request); +int http_fn_cfg_wifi(http_request_t* request); +int http_fn_cfg_mac(http_request_t* request); +int http_fn_flash_read_tool(http_request_t* request); +int http_fn_cmd_tool(http_request_t* request); +int http_fn_uart_tool(http_request_t* request); +int http_fn_cfg_quick(http_request_t* request); +int http_fn_ha_cfg(http_request_t* request); +int http_fn_ha_discovery(http_request_t* request); +int http_fn_cfg(http_request_t* request); +int http_fn_cfg_pins(http_request_t* request); +int http_fn_cfg_ping(http_request_t* request); +int http_fn_index(http_request_t* request); +int http_fn_testmsg(http_request_t* request); +int http_fn_ota_exec(http_request_t* request); +int http_fn_ota(http_request_t* request); +int http_fn_empty_url(http_request_t* request); +int http_fn_other(http_request_t* request); +int http_fn_cm(http_request_t* request); +int http_fn_startup_command(http_request_t* request); +int http_fn_cfg_generic(http_request_t* request); +int http_fn_cfg_startup(http_request_t* request); +int http_fn_cfg_dgr(http_request_t* request); diff --git a/src/httpserver/http_tcp_server.c b/src/httpserver/http_tcp_server.c index 2c7aeb567..e84a9a12b 100644 --- a/src/httpserver/http_tcp_server.c +++ b/src/httpserver/http_tcp_server.c @@ -22,187 +22,187 @@ #endif -static void tcp_server_thread( beken_thread_arg_t arg ); -static void tcp_client_thread( beken_thread_arg_t arg ); +static void tcp_server_thread(beken_thread_arg_t arg); +static void tcp_client_thread(beken_thread_arg_t arg); xTaskHandle g_http_thread = NULL; void HTTPServer_Start() { - OSStatus err = kNoErr; + OSStatus err = kNoErr; - err = rtos_create_thread( &g_http_thread, BEKEN_APPLICATION_PRIORITY, - "TCP_server", - (beken_thread_function_t)tcp_server_thread, - 0x800, - (beken_thread_arg_t)0 ); - if(err != kNoErr) - { - ADDLOG_ERROR(LOG_FEATURE_HTTP, "create \"TCP_server\" thread failed with %i!\r\n",err); - } + err = rtos_create_thread(&g_http_thread, BEKEN_APPLICATION_PRIORITY, + "TCP_server", + (beken_thread_function_t)tcp_server_thread, + 0x800, + (beken_thread_arg_t)0); + if (err != kNoErr) + { + ADDLOG_ERROR(LOG_FEATURE_HTTP, "create \"TCP_server\" thread failed with %i!\r\n", err); + } } -int sendfn(int fd, char * data, int len){ - if (fd){ - return send( fd, data, len, 0 ); - } - return -1; +int sendfn(int fd, char* data, int len) { + if (fd) { + return send(fd, data, len, 0); + } + return -1; } -static void tcp_client_thread( beken_thread_arg_t arg ) +static void tcp_client_thread(beken_thread_arg_t arg) { - OSStatus err = kNoErr; - int fd = (int) arg; - //fd_set readfds, errfds, readfds2; - char *buf = NULL; - char *reply = NULL; + OSStatus err = kNoErr; + int fd = (int)arg; + //fd_set readfds, errfds, readfds2; + char* buf = NULL; + char* reply = NULL; int replyBufferSize = REPLY_BUFFER_SIZE; //int res; //char reply[8192]; //my_fd = fd; - reply = (char*) os_malloc( replyBufferSize ); - buf = (char*) os_malloc( INCOMING_BUFFER_SIZE ); + reply = (char*)os_malloc(replyBufferSize); + buf = (char*)os_malloc(INCOMING_BUFFER_SIZE); - if ( buf == 0 || reply == 0) - { - ADDLOG_ERROR(LOG_FEATURE_HTTP, "TCP Client failed to malloc buffer" ); - goto exit; - } - http_request_t request; - os_memset(&request, 0, sizeof(request)); + if (buf == 0 || reply == 0) + { + ADDLOG_ERROR(LOG_FEATURE_HTTP, "TCP Client failed to malloc buffer"); + goto exit; + } + http_request_t request; + os_memset(&request, 0, sizeof(request)); - request.fd = fd; - request.received = buf; - request.receivedLenmax = INCOMING_BUFFER_SIZE-2; - request.responseCode = HTTP_RESPONSE_OK; - request.receivedLen = recv( fd, request.received, request.receivedLenmax, 0 ); - request.received[request.receivedLen] = 0; + request.fd = fd; + request.received = buf; + request.receivedLenmax = INCOMING_BUFFER_SIZE - 2; + request.responseCode = HTTP_RESPONSE_OK; + request.receivedLen = recv(fd, request.received, request.receivedLenmax, 0); + request.received[request.receivedLen] = 0; - request.reply = reply; - request.replylen = 0; - reply[0] = '\0'; + request.reply = reply; + request.replylen = 0; + reply[0] = '\0'; - request.replymaxlen = replyBufferSize - 1; + request.replymaxlen = replyBufferSize - 1; - if ( request.receivedLen <= 0 ) - { - ADDLOG_ERROR(LOG_FEATURE_HTTP, "TCP Client is disconnected, fd: %d", fd ); - goto exit; - } + if (request.receivedLen <= 0) + { + ADDLOG_ERROR(LOG_FEATURE_HTTP, "TCP Client is disconnected, fd: %d", fd); + goto exit; + } - //addLog( "TCP received string %s\n",buf ); - // returns length to be sent if any - // ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP will process packet of len %i\n", request.receivedLen ); - int lenret = HTTP_ProcessPacket(&request); - if (lenret > 0){ - ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP sending reply len %i\n",lenret ); - send( fd, reply, lenret, 0 ); - } + //addLog( "TCP received string %s\n",buf ); + // returns length to be sent if any + // ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP will process packet of len %i\n", request.receivedLen ); + int lenret = HTTP_ProcessPacket(&request); + if (lenret > 0) { + ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP sending reply len %i\n", lenret); + send(fd, reply, lenret, 0); + } - rtos_delay_milliseconds(10); + rtos_delay_milliseconds(10); exit: - if ( err != kNoErr ) - ADDLOG_ERROR(LOG_FEATURE_HTTP, "TCP client thread exit with err: %d", err ); + if (err != kNoErr) + ADDLOG_ERROR(LOG_FEATURE_HTTP, "TCP client thread exit with err: %d", err); - if ( buf != NULL ) - os_free( buf ); - if ( reply != NULL ) - os_free( reply ); + if (buf != NULL) + os_free(buf); + if (reply != NULL) + os_free(reply); - lwip_close( fd );; + lwip_close(fd);; #if DISABLE_SEPARATE_THREAD_FOR_EACH_TCP_CLIENT #else - rtos_delete_thread( NULL ); + rtos_delete_thread(NULL); #endif } /* TCP server listener thread */ -static void tcp_server_thread( beken_thread_arg_t arg ) +static void tcp_server_thread(beken_thread_arg_t arg) { - (void)( arg ); - OSStatus err = kNoErr; - struct sockaddr_in server_addr, client_addr; - socklen_t sockaddr_t_size = sizeof(client_addr); - char client_ip_str[16]; - int tcp_listen_fd = -1, client_fd = -1; - fd_set readfds; + (void)(arg); + OSStatus err = kNoErr; + struct sockaddr_in server_addr, client_addr; + socklen_t sockaddr_t_size = sizeof(client_addr); + char client_ip_str[16]; + int tcp_listen_fd = -1, client_fd = -1; + fd_set readfds; - tcp_listen_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + tcp_listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = INADDR_ANY;/* Accept conenction request on all network interface */ - server_addr.sin_port = htons( HTTP_SERVER_PORT );/* Server listen on port: 20000 */ - err = bind( tcp_listen_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) ); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY;/* Accept conenction request on all network interface */ + server_addr.sin_port = htons(HTTP_SERVER_PORT);/* Server listen on port: 20000 */ + err = bind(tcp_listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); - err = listen( tcp_listen_fd, 0 ); + err = listen(tcp_listen_fd, 0); - while ( 1 ) - { - FD_ZERO( &readfds ); - FD_SET( tcp_listen_fd, &readfds ); + while (1) + { + FD_ZERO(&readfds); + FD_SET(tcp_listen_fd, &readfds); - select( tcp_listen_fd + 1, &readfds, NULL, NULL, NULL); + select(tcp_listen_fd + 1, &readfds, NULL, NULL, NULL); - if ( FD_ISSET( tcp_listen_fd, &readfds ) ) - { - client_fd = accept( tcp_listen_fd, (struct sockaddr *) &client_addr, &sockaddr_t_size ); - if ( client_fd >= 0 ) - { + if (FD_ISSET(tcp_listen_fd, &readfds)) + { + client_fd = accept(tcp_listen_fd, (struct sockaddr*)&client_addr, &sockaddr_t_size); + if (client_fd >= 0) + { #if PLATFORM_XR809 #if DISABLE_SEPARATE_THREAD_FOR_EACH_TCP_CLIENT #else - OS_Thread_t clientThreadUnused ; + OS_Thread_t clientThreadUnused; #endif #endif - os_strcpy( client_ip_str, inet_ntoa( client_addr.sin_addr ) ); - // ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP Client %s:%d connected, fd: %d", client_ip_str, client_addr.sin_port, client_fd ); + os_strcpy(client_ip_str, inet_ntoa(client_addr.sin_addr)); + // ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP Client %s:%d connected, fd: %d", client_ip_str, client_addr.sin_port, client_fd ); #if DISABLE_SEPARATE_THREAD_FOR_EACH_TCP_CLIENT // Use main server thread (blocking all other clients) // right now, I am getting OS_ThreadCreate everytime on XR809 platform tcp_client_thread((beken_thread_arg_t)client_fd); #else // Create separate thread for client - if ( kNoErr != + if (kNoErr != #if PLATFORM_XR809 OS_ThreadCreate(&clientThreadUnused, - "HTTP Client", - tcp_client_thread, - client_fd, - OS_THREAD_PRIO_CONSOLE, - 0x400) + "HTTP Client", + tcp_client_thread, + client_fd, + OS_THREAD_PRIO_CONSOLE, + 0x400) #else - rtos_create_thread( NULL, BEKEN_APPLICATION_PRIORITY, - "HTTP Client", - (beken_thread_function_t)tcp_client_thread, - 0x800, - (beken_thread_arg_t)client_fd ) + rtos_create_thread(NULL, BEKEN_APPLICATION_PRIORITY, + "HTTP Client", + (beken_thread_function_t)tcp_client_thread, + 0x800, + (beken_thread_arg_t)client_fd) #endif - ) - { - ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP Client %s:%d thread creation failed! fd: %d", client_ip_str, client_addr.sin_port, client_fd ); - lwip_close( client_fd ); - client_fd = -1; - } + ) + { + ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP Client %s:%d thread creation failed! fd: %d", client_ip_str, client_addr.sin_port, client_fd); + lwip_close(client_fd); + client_fd = -1; + } #endif - } - } - } + } + } + } - if ( err != kNoErr ) - ADDLOG_ERROR(LOG_FEATURE_HTTP, "Server listerner thread exit with err: %d", err ); + if (err != kNoErr) + ADDLOG_ERROR(LOG_FEATURE_HTTP, "Server listerner thread exit with err: %d", err); - lwip_close( tcp_listen_fd ); + lwip_close(tcp_listen_fd); - rtos_delete_thread( NULL ); + rtos_delete_thread(NULL); } @@ -211,14 +211,14 @@ static void tcp_server_thread( beken_thread_arg_t arg ) xTaskHandle g_http_thread = NULL; -int sendfn(int fd, char * data, int len){ - if (fd){ - return send( fd, data, len, 0 ); +int sendfn(int fd, char* data, int len) { + if (fd) { + return send(fd, data, len, 0); } return -1; } -static void tcp_client_thread( int fd, char *buf, char *reply ) +static void tcp_client_thread(int fd, char* buf, char* reply) { //OSStatus err = kNoErr; @@ -229,7 +229,7 @@ static void tcp_client_thread( int fd, char *buf, char *reply ) request.received = buf; request.receivedLenmax = INCOMING_BUFFER_SIZE - 1; request.responseCode = HTTP_RESPONSE_OK; - request.receivedLen = recv( fd, request.received, request.receivedLenmax, 0 ); + request.receivedLen = recv(fd, request.received, request.receivedLenmax, 0); request.received[request.receivedLen] = 0; request.reply = reply; @@ -238,88 +238,88 @@ static void tcp_client_thread( int fd, char *buf, char *reply ) request.replymaxlen = REPLY_BUFFER_SIZE - 1; - if ( request.receivedLen <= 0 ) + if (request.receivedLen <= 0) { - ADDLOG_ERROR(LOG_FEATURE_HTTP, "TCP Client is disconnected, fd: %d", fd ); + ADDLOG_ERROR(LOG_FEATURE_HTTP, "TCP Client is disconnected, fd: %d", fd); return; } int lenret = HTTP_ProcessPacket(&request); - if (lenret > 0){ - send( fd, reply, lenret, 0 ); + if (lenret > 0) { + send(fd, reply, lenret, 0); } rtos_delay_milliseconds(10); } /* TCP server listener thread */ -static void tcp_server_thread( beken_thread_arg_t arg ) +static void tcp_server_thread(beken_thread_arg_t arg) { - (void)( arg ); - OSStatus err = kNoErr; - struct sockaddr_in server_addr, client_addr; - socklen_t sockaddr_t_size = sizeof(client_addr); - char client_ip_str[16]; - int tcp_listen_fd = -1, client_fd = -1; - fd_set readfds; - char *buf = NULL; - char *reply = NULL; + (void)(arg); + OSStatus err = kNoErr; + struct sockaddr_in server_addr, client_addr; + socklen_t sockaddr_t_size = sizeof(client_addr); + char client_ip_str[16]; + int tcp_listen_fd = -1, client_fd = -1; + fd_set readfds; + char* buf = NULL; + char* reply = NULL; - tcp_listen_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + tcp_listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = INADDR_ANY;/* Accept conenction request on all network interface */ - server_addr.sin_port = htons( HTTP_SERVER_PORT );/* Server listen on port: 20000 */ - err = bind( tcp_listen_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) ); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY;/* Accept conenction request on all network interface */ + server_addr.sin_port = htons(HTTP_SERVER_PORT);/* Server listen on port: 20000 */ + err = bind(tcp_listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); - err = listen( tcp_listen_fd, 0 ); + err = listen(tcp_listen_fd, 0); - reply = (char*) os_malloc( REPLY_BUFFER_SIZE ); - buf = (char*) os_malloc( INCOMING_BUFFER_SIZE ); + reply = (char*)os_malloc(REPLY_BUFFER_SIZE); + buf = (char*)os_malloc(INCOMING_BUFFER_SIZE); - while ( 1 ) - { - FD_ZERO( &readfds ); - FD_SET( tcp_listen_fd, &readfds ); + while (1) + { + FD_ZERO(&readfds); + FD_SET(tcp_listen_fd, &readfds); - select( tcp_listen_fd + 1, &readfds, NULL, NULL, NULL); + select(tcp_listen_fd + 1, &readfds, NULL, NULL, NULL); - if ( FD_ISSET( tcp_listen_fd, &readfds ) ) - { - client_fd = accept( tcp_listen_fd, (struct sockaddr *) &client_addr, &sockaddr_t_size ); - if ( client_fd >= 0 ) - { - os_strcpy( client_ip_str, inet_ntoa( client_addr.sin_addr ) ); - // ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP Client %s:%d connected, fd: %d", client_ip_str, client_addr.sin_port, client_fd ); + if (FD_ISSET(tcp_listen_fd, &readfds)) + { + client_fd = accept(tcp_listen_fd, (struct sockaddr*)&client_addr, &sockaddr_t_size); + if (client_fd >= 0) + { + os_strcpy(client_ip_str, inet_ntoa(client_addr.sin_addr)); + // ADDLOG_DEBUG(LOG_FEATURE_HTTP, "TCP Client %s:%d connected, fd: %d", client_ip_str, client_addr.sin_port, client_fd ); - tcp_client_thread(client_fd,reply,buf); + tcp_client_thread(client_fd, reply, buf); - lwip_close( client_fd ); - } - } - } + lwip_close(client_fd); + } + } + } - if ( err != kNoErr ) - ADDLOG_ERROR(LOG_FEATURE_HTTP, "Server listerner thread exit with err: %d", err ); + if (err != kNoErr) + ADDLOG_ERROR(LOG_FEATURE_HTTP, "Server listerner thread exit with err: %d", err); - lwip_close( tcp_listen_fd ); + lwip_close(tcp_listen_fd); - rtos_delete_thread( NULL ); + rtos_delete_thread(NULL); } void HTTPServer_Start() { - OSStatus err = kNoErr; + OSStatus err = kNoErr; - err = rtos_create_thread( &g_http_thread, BEKEN_APPLICATION_PRIORITY, - "TCP_server", - (beken_thread_function_t)tcp_server_thread, - 0x800, - (beken_thread_arg_t)0 ); - if(err != kNoErr) - { - ADDLOG_ERROR(LOG_FEATURE_HTTP, "create \"TCP_server\" thread failed with %i!\r\n",err); - } + err = rtos_create_thread(&g_http_thread, BEKEN_APPLICATION_PRIORITY, + "TCP_server", + (beken_thread_function_t)tcp_server_thread, + 0x800, + (beken_thread_arg_t)0); + if (err != kNoErr) + { + ADDLOG_ERROR(LOG_FEATURE_HTTP, "create \"TCP_server\" thread failed with %i!\r\n", err); + } } diff --git a/src/httpserver/new_http.c b/src/httpserver/new_http.c index 4d330e0ed..e43ddcad5 100644 --- a/src/httpserver/new_http.c +++ b/src/httpserver/new_http.c @@ -14,65 +14,65 @@ // define the feature ADDLOGF_XXX will use #define LOG_FEATURE LOG_FEATURE_HTTP -const char httpHeader[] = "HTTP/1.1 %d OK\nContent-type: %s" ; // HTTP header -const char httpMimeTypeHTML[] = "text/html" ; // HTML MIME type -const char httpMimeTypeText[] = "text/plain" ; // TEXT MIME type -const char httpMimeTypeJson[] = "application/json" ; // TEXT MIME type -const char httpMimeTypeBinary[] = "application/octet-stream" ; // binary/file MIME type +const char httpHeader[] = "HTTP/1.1 %d OK\nContent-type: %s"; // HTTP header +const char httpMimeTypeHTML[] = "text/html"; // HTML MIME type +const char httpMimeTypeText[] = "text/plain"; // TEXT MIME type +const char httpMimeTypeJson[] = "application/json"; // TEXT MIME type +const char httpMimeTypeBinary[] = "application/octet-stream"; // binary/file MIME type const char htmlDoctype[] = - ""; +""; const char htmlHeadMain[] = - "" - "" - ""; +"" +"" +""; const char htmlBodyStart[] = - "" - "" - "
" - "

" - ""; +"" +"" +"
" +"

" +""; const char htmlBodyStart2[] = - "

"; -const char htmlBodyEnd[] = "
" ; +"

"; +const char htmlBodyEnd[] = "
"; const char htmlFooterReturnToMenu[] = "Return to menu"; const char htmlFooterRefreshLink[] = "Refresh"; const char htmlFooterReturnToCfgLink[] = "Return to cfg"; const char htmlFooterInfo[] = - "Read more | " - "Support project
"; +"Read more | " +"Support project
"; // make sure that USER_SW_VER is set on all platforms // Automatic Github builds are setting it externally, // but it may not be set while doing a test build on developer PC #ifndef USER_SW_VER - #ifdef WINDOWS - #define USER_SW_VER "Win_Test" - #elif PLATFORM_XR809 - #define USER_SW_VER "XR809_Test" - #elif defined(PLATFORM_BK7231N) - #define USER_SW_VER "BK7231N_Test" - #elif defined(PLATFORM_BK7231T) - #define USER_SW_VER "BK7231T_Test" - #elif defined(PLATFORM_BL602) - #define USER_SW_VER "BL602_Test" - #elif defined(PLATFORM_W600) - #define USER_SW_VER "W600_Test" - #elif defined(PLATFORM_W800) - #define USER_SW_VER "W800_Test" - #else - #define USER_SW_VER "unknown" - #endif +#ifdef WINDOWS +#define USER_SW_VER "Win_Test" +#elif PLATFORM_XR809 +#define USER_SW_VER "XR809_Test" +#elif defined(PLATFORM_BK7231N) +#define USER_SW_VER "BK7231N_Test" +#elif defined(PLATFORM_BK7231T) +#define USER_SW_VER "BK7231T_Test" +#elif defined(PLATFORM_BL602) +#define USER_SW_VER "BL602_Test" +#elif defined(PLATFORM_W600) +#define USER_SW_VER "W600_Test" +#elif defined(PLATFORM_W800) +#define USER_SW_VER "W800_Test" +#else +#define USER_SW_VER "unknown" #endif -const char *g_build_str = "Build on " __DATE__ " " __TIME__ " version " USER_SW_VER; // Show GIT version at Build line; +#endif +const char* g_build_str = "Build on " __DATE__ " " __TIME__ " version " USER_SW_VER; // Show GIT version at Build line; -const char httpCorsHeaders[] = "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept" ; // TEXT MIME type +const char httpCorsHeaders[] = "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"; // TEXT MIME type -const char *methodNames[] = { +const char* methodNames[] = { "GET", "PUT", "POST", @@ -80,36 +80,36 @@ const char *methodNames[] = { }; #if WINDOWS - #define os_free free - #define os_malloc malloc +#define os_free free +#define os_malloc malloc #endif -void misc_formatUpTimeString(int totalSeconds, char *o); +void misc_formatUpTimeString(int totalSeconds, char* o); int Time_getUpTimeSeconds(); typedef struct http_callback_tag { - char *url; - int method; - http_callback_fn callback; + char* url; + int method; + http_callback_fn callback; } http_callback_t; #define MAX_HTTP_CALLBACKS 32 -static http_callback_t *callbacks[MAX_HTTP_CALLBACKS]; +static http_callback_t* callbacks[MAX_HTTP_CALLBACKS]; static int numCallbacks = 0; -int HTTP_RegisterCallback( const char *url, int method, http_callback_fn callback){ - if (!url || !callback){ +int HTTP_RegisterCallback(const char* url, int method, http_callback_fn callback) { + if (!url || !callback) { return -1; } - if (numCallbacks >= MAX_HTTP_CALLBACKS){ + if (numCallbacks >= MAX_HTTP_CALLBACKS) { return -4; } callbacks[numCallbacks] = (http_callback_t*)os_malloc(sizeof(http_callback_t)); - if (!callbacks[numCallbacks]){ + if (!callbacks[numCallbacks]) { return -2; } - callbacks[numCallbacks]->url = (char *)os_malloc(strlen(url)+1); - if (!callbacks[numCallbacks]->url){ + callbacks[numCallbacks]->url = (char*)os_malloc(strlen(url) + 1); + if (!callbacks[numCallbacks]->url) { os_free(callbacks[numCallbacks]); return -3; } @@ -123,9 +123,9 @@ int HTTP_RegisterCallback( const char *url, int method, http_callback_fn callbac return 0; } -int my_strnicmp(char *a, char *b, int len){ +int my_strnicmp(char* a, char* b, int len) { int i; - for (i = 0; i < len; i++){ + for (i = 0; i < len; i++) { char x = *a; char y = *b; if (!x || !y) return 1; @@ -136,11 +136,11 @@ int my_strnicmp(char *a, char *b, int len){ return 0; } -bool http_startsWith(const char *base, const char *substr) { - while(*substr != 0) { - if(*base != *substr) +bool http_startsWith(const char* base, const char* substr) { + while (*substr != 0) { + if (*base != *substr) return false; - if(*base == 0) + if (*base == 0) return false; base++; substr++; @@ -148,29 +148,29 @@ bool http_startsWith(const char *base, const char *substr) { return true; } -bool http_checkUrlBase(const char *base, const char *fileName) { - while(*base != 0 && *base != '?' && *base != ' ') { - if(*base != *fileName) +bool http_checkUrlBase(const char* base, const char* fileName) { + while (*base != 0 && *base != '?' && *base != ' ') { + if (*base != *fileName) return false; - if(*base == 0) + if (*base == 0) return false; base++; fileName++; } - if(*fileName != 0) + if (*fileName != 0) return false; return true; } -void http_setup(http_request_t *request, const char *type){ +void http_setup(http_request_t* request, const char* type) { hprintf128(request, httpHeader, request->responseCode, type); - poststr(request,"\r\n"); // next header - poststr(request,httpCorsHeaders); - poststr(request,"\r\n"); // end headers with double CRLF - poststr(request,"\r\n"); + poststr(request, "\r\n"); // next header + poststr(request, httpCorsHeaders); + poststr(request, "\r\n"); // end headers with double CRLF + poststr(request, "\r\n"); } -void http_html_start(http_request_t *request, const char *pagename) { +void http_html_start(http_request_t* request, const char* pagename) { poststr(request, htmlDoctype); poststr(request, ""); poststr(request, CFG_GetDeviceName()); // todo: check escaping @@ -186,7 +186,7 @@ void http_html_start(http_request_t *request, const char *pagename) { poststr(request, htmlBodyStart2); } -void http_html_end(http_request_t *request) { +void http_html_end(http_request_t* request) { char upTimeStr[128]; unsigned char mac[32]; @@ -197,22 +197,22 @@ void http_html_end(http_request_t *request) { hprintf128(request, "<br>Online for <span id=\"onlineFor\" data-initial=\"%i\">-</span>", Time_getUpTimeSeconds()); - WiFI_GetMacAddress((char *)mac); + WiFI_GetMacAddress((char*)mac); - sprintf(upTimeStr, "<br>Device MAC: %02X:%02X:%02X:%02X:%02X:%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); + sprintf(upTimeStr, "<br>Device MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); poststr(request, upTimeStr); - sprintf(upTimeStr, "<br>Short name: %s, Chipset %s",CFG_GetShortDeviceName(),PLATFORM_MCU_NAME); + sprintf(upTimeStr, "<br>Short name: %s, Chipset %s", CFG_GetShortDeviceName(), PLATFORM_MCU_NAME); poststr(request, upTimeStr); poststr(request, htmlBodyEnd); poststr(request, pageScript); } -const char *http_checkArg(const char *p, const char *n) { - while(1) { - if(*n == 0 && (*p == 0 || *p == '=')) +const char* http_checkArg(const char* p, const char* n) { + while (1) { + if (*n == 0 && (*p == 0 || *p == '=')) return p; - if(*p != *n) + if (*p != *n) return 0; p++; n++; @@ -220,63 +220,65 @@ const char *http_checkArg(const char *p, const char *n) { return p; } -void http_copyCarg(const char *atin, char *to, int maxSize) { +void http_copyCarg(const char* atin, char* to, int maxSize) { int a, b; - const unsigned char *at = (unsigned char *)atin; + const unsigned char* at = (unsigned char*)atin; - while(*at != 0 && *at != '&' && *at != ' ' && maxSize > 1) { + while (*at != 0 && *at != '&' && *at != ' ' && maxSize > 1) { #if 0 - *to = *at; + * to = *at; to++; at++; maxSize--; #else - if ((*at == '%') && - ((a = at[1]) && (b = at[2])) && - (isxdigit(a) && isxdigit(b))) { - if (a >= 'a') - a -= 'a'-'A'; - if (a >= 'A') - a -= ('A' - 10); - else - a -= '0'; - if (b >= 'a') - b -= 'a'-'A'; - if (b >= 'A') - b -= ('A' - 10); - else - b -= '0'; - *to++ = 16*a+b; - at+=3; - } else if (*at == '+') { - *to++ = ' '; - at++; - } else { - *to++ = *at++; - } + if ((*at == '%') && + ((a = at[1]) && (b = at[2])) && + (isxdigit(a) && isxdigit(b))) { + if (a >= 'a') + a -= 'a' - 'A'; + if (a >= 'A') + a -= ('A' - 10); + else + a -= '0'; + if (b >= 'a') + b -= 'a' - 'A'; + if (b >= 'A') + b -= ('A' - 10); + else + b -= '0'; + *to++ = 16 * a + b; + at += 3; + } + else if (*at == '+') { + *to++ = ' '; + at++; + } + else { + *to++ = *at++; + } maxSize--; #endif } *to = 0; } -int http_getArg(const char *base, const char *name, char *o, int maxSize) { +int http_getArg(const char* base, const char* name, char* o, int maxSize) { *o = '\0'; - while(*base != '?') { - if(*base == 0) + while (*base != '?') { + if (*base == 0) return 0; base++; } base++; - while(*base) { - const char *at = http_checkArg(base,name); - if(at) { + while (*base) { + const char* at = http_checkArg(base, name); + if (at) { at++; - http_copyCarg(at,o,maxSize); + http_copyCarg(at, o, maxSize); return 1; } - while(*base != '&') { - if(*base == 0) { + while (*base != '&') { + if (*base == 0) { return 0; } base++; @@ -285,14 +287,14 @@ int http_getArg(const char *base, const char *name, char *o, int maxSize) { } return 0; } -int http_getArgInteger(const char *base, const char *name) { +int http_getArgInteger(const char* base, const char* name) { char tmp[16]; - if(http_getArg(base,name,tmp,sizeof(tmp))==0) + if (http_getArg(base, name, tmp, sizeof(tmp)) == 0) return 0; return atoi(tmp); } -const char *htmlPinRoleNames[] = { +const char* htmlPinRoleNames[] = { " ", "Rel", "Rel_n", @@ -330,52 +332,52 @@ const char *htmlPinRoleNames[] = { "error", }; -int PIN_ParsePinRoleName(const char *name) { +int PIN_ParsePinRoleName(const char* name) { int i; - for(i = 0; i < IOR_Total_Options; i++) { - if(!stricmp(name,htmlPinRoleNames[i])) + for (i = 0; i < IOR_Total_Options; i++) { + if (!stricmp(name, htmlPinRoleNames[i])) return i; } return IOR_Total_Options; } void setupAllWB2SPinsAsButtons() { - PIN_SetPinRoleForPinIndex(6,IOR_Button); - PIN_SetPinChannelForPinIndex(6,1); + PIN_SetPinRoleForPinIndex(6, IOR_Button); + PIN_SetPinChannelForPinIndex(6, 1); - PIN_SetPinRoleForPinIndex(7,IOR_Button); - PIN_SetPinChannelForPinIndex(7,1); + PIN_SetPinRoleForPinIndex(7, IOR_Button); + PIN_SetPinChannelForPinIndex(7, 1); - PIN_SetPinRoleForPinIndex(8,IOR_Button); - PIN_SetPinChannelForPinIndex(8,1); + PIN_SetPinRoleForPinIndex(8, IOR_Button); + PIN_SetPinChannelForPinIndex(8, 1); - PIN_SetPinRoleForPinIndex(23,IOR_Button); - PIN_SetPinChannelForPinIndex(23,1); + PIN_SetPinRoleForPinIndex(23, IOR_Button); + PIN_SetPinChannelForPinIndex(23, 1); - PIN_SetPinRoleForPinIndex(24,IOR_Button); - PIN_SetPinChannelForPinIndex(24,1); + PIN_SetPinRoleForPinIndex(24, IOR_Button); + PIN_SetPinChannelForPinIndex(24, 1); - PIN_SetPinRoleForPinIndex(26,IOR_Button); - PIN_SetPinChannelForPinIndex(26,1); + PIN_SetPinRoleForPinIndex(26, IOR_Button); + PIN_SetPinChannelForPinIndex(26, 1); - PIN_SetPinRoleForPinIndex(27,IOR_Button); - PIN_SetPinChannelForPinIndex(27,1); + PIN_SetPinRoleForPinIndex(27, IOR_Button); + PIN_SetPinChannelForPinIndex(27, 1); } // add some more output safely, sending if necessary. // call with str == NULL to force send. - can be binary. // supply length -int postany(http_request_t *request, const char *str, int len){ +int postany(http_request_t* request, const char* str, int len) { #if PLATFORM_BL602 - send(request->fd,str,len,0); + send(request->fd, str, len, 0); return 0; #else int currentlen; int addlen = len; - if (NULL == str){ - if(request->replylen > 0) { + if (NULL == str) { + if (request->replylen > 0) { send(request->fd, request->reply, request->replylen, 0); } request->reply[0] = 0; @@ -384,25 +386,25 @@ int postany(http_request_t *request, const char *str, int len){ } currentlen = request->replylen; - if (currentlen + addlen >= request->replymaxlen){ + if (currentlen + addlen >= request->replymaxlen) { send(request->fd, request->reply, request->replylen, 0); request->reply[0] = 0; request->replylen = 0; currentlen = 0; } - while (addlen >= request->replymaxlen){ - if(request->replylen > 0) { + while (addlen >= request->replymaxlen) { + if (request->replylen > 0) { send(request->fd, request->reply, request->replylen, 0); request->replylen = 0; } - send(request->fd, str, (request->replymaxlen-1), 0); - addlen -= (request->replymaxlen-1); - str += (request->replymaxlen-1); + send(request->fd, str, (request->replymaxlen - 1), 0); + addlen -= (request->replymaxlen - 1); + str += (request->replymaxlen - 1); rtos_delay_milliseconds(1); } - memcpy( request->reply+request->replylen, str, addlen ); + memcpy(request->reply + request->replylen, str, addlen); request->replylen += addlen; return (currentlen + addlen); #endif @@ -411,16 +413,16 @@ int postany(http_request_t *request, const char *str, int len){ // add some more output safely, sending if necessary. // call with str == NULL to force send. -int poststr(http_request_t *request, const char *str){ - if (str == NULL){ +int poststr(http_request_t* request, const char* str) { + if (str == NULL) { return postany(request, NULL, 0); } return postany(request, str, strlen(str)); } -int hprintf128(http_request_t *request, const char *fmt, ...){ - va_list argList; - //BaseType_t taken; +int hprintf128(http_request_t* request, const char* fmt, ...) { + va_list argList; + //BaseType_t taken; char tmp[256]; va_start(argList, fmt); vsprintf(tmp, fmt, argList); @@ -429,39 +431,40 @@ int hprintf128(http_request_t *request, const char *fmt, ...){ } -int HTTP_ProcessPacket(http_request_t *request) { +int HTTP_ProcessPacket(http_request_t* request) { int i; - char *p; - char *headers; - char *protocol; + char* p; + char* headers; + char* protocol; //int bChanged = 0; - char *urlStr = ""; + char* urlStr = ""; - if (request->received == 0){ + if (request->received == 0) { ADDLOGF_ERROR("You gave request with NULL input"); return 0; } - char *recvbuf = request->received; - for ( i = 0; i < sizeof(methodNames)/sizeof(*methodNames); i++){ - if (http_startsWith(recvbuf, methodNames[i])){ + char* recvbuf = request->received; + for (i = 0; i < sizeof(methodNames) / sizeof(*methodNames); i++) { + if (http_startsWith(recvbuf, methodNames[i])) { urlStr = recvbuf + strlen(methodNames[i]) + 2; // skip method name plus space, plus slash request->method = i; break; } } - if (request->method == -1){ + if (request->method == -1) { ADDLOGF_ERROR("unsupported method %7s", recvbuf); return 0; } - if (request->reply == 0){ + if (request->reply == 0) { ADDLOGF_ERROR("You gave request with NULL buffer"); return 0; } if (request->method == HTTP_GET) { //ADDLOG_INFO(LOG_FEATURE_HTTP, "HTTP request\n"); - } else { + } + else { //ADDLOG_INFO(LOG_FEATURE_HTTP, "Other request\n"); } @@ -492,7 +495,8 @@ int HTTP_ProcessPacket(http_request_t *request) { *p = '\0'; p++; // past \r p++; // past \n - } else { + } + else { ADDLOGF_ERROR("invalid request\n"); return 0; } @@ -501,14 +505,14 @@ int HTTP_ProcessPacket(http_request_t *request) { headers = p; do { p = strchr(headers, '\r'); - if (p != headers){ - if (p){ - if (request->numheaders < 16){ + if (p != headers) { + if (p) { + if (request->numheaders < 16) { request->headers[request->numheaders] = headers; request->numheaders++; } // pick out contentLength - if (!my_strnicmp(headers, "Content-Length:", 15)){ + if (!my_strnicmp(headers, "Content-Length:", 15)) { request->contentLength = atoi(headers + 15); } @@ -516,78 +520,79 @@ int HTTP_ProcessPacket(http_request_t *request) { p++; // past \r p++; // past \n headers = p; - } else { + } + else { break; } } - if (*p == '\r'){ + if (*p == '\r') { // end of headers *p = 0; p++; p++; break; } - } while(1); + } while (1); request->bodystart = p; request->bodylen = request->receivedLen - (p - request->received); #if 0 - postany(request,"test",4); + postany(request, "test", 4); return 0; #elif 0 return http_fn_empty_url(request); #endif // look for a callback with this URL and method, or HTTP_ANY - for (i = 0; i < numCallbacks; i++){ - char *url = callbacks[i]->url; - if (http_startsWith(urlStr, &url[1])){ + for (i = 0; i < numCallbacks; i++) { + char* url = callbacks[i]->url; + if (http_startsWith(urlStr, &url[1])) { int method = callbacks[i]->method; - if(method == HTTP_ANY || method == request->method){ + if (method == HTTP_ANY || method == request->method) { return callbacks[i]->callback(request); } } } - if(http_checkUrlBase(urlStr,"")) return http_fn_empty_url(request); + if (http_checkUrlBase(urlStr, "")) return http_fn_empty_url(request); - if(http_checkUrlBase(urlStr,"testmsg")) return http_fn_testmsg(request); - if(http_checkUrlBase(urlStr,"index")) return http_fn_index(request); + if (http_checkUrlBase(urlStr, "testmsg")) return http_fn_testmsg(request); + if (http_checkUrlBase(urlStr, "index")) return http_fn_index(request); - if(http_checkUrlBase(urlStr,"about")) return http_fn_about(request); + if (http_checkUrlBase(urlStr, "about")) return http_fn_about(request); - if(http_checkUrlBase(urlStr,"cfg_mqtt")) return http_fn_cfg_mqtt(request); - if(http_checkUrlBase(urlStr,"cfg_mqtt_set")) return http_fn_cfg_mqtt_set(request); + if (http_checkUrlBase(urlStr, "cfg_mqtt")) return http_fn_cfg_mqtt(request); + if (http_checkUrlBase(urlStr, "cfg_mqtt_set")) return http_fn_cfg_mqtt_set(request); - if(http_checkUrlBase(urlStr,"cfg_webapp")) return http_fn_cfg_webapp(request); - if(http_checkUrlBase(urlStr,"cfg_webapp_set")) return http_fn_cfg_webapp_set(request); + if (http_checkUrlBase(urlStr, "cfg_webapp")) return http_fn_cfg_webapp(request); + if (http_checkUrlBase(urlStr, "cfg_webapp_set")) return http_fn_cfg_webapp_set(request); - if(http_checkUrlBase(urlStr,"cfg_wifi")) return http_fn_cfg_wifi(request); - if(http_checkUrlBase(urlStr,"cfg_name")) return http_fn_cfg_name(request); - if(http_checkUrlBase(urlStr,"cfg_wifi_set")) return http_fn_cfg_wifi_set(request); + if (http_checkUrlBase(urlStr, "cfg_wifi")) return http_fn_cfg_wifi(request); + if (http_checkUrlBase(urlStr, "cfg_name")) return http_fn_cfg_name(request); + if (http_checkUrlBase(urlStr, "cfg_wifi_set")) return http_fn_cfg_wifi_set(request); - if(http_checkUrlBase(urlStr,"cfg_loglevel_set")) return http_fn_cfg_loglevel_set(request); - if(http_checkUrlBase(urlStr,"cfg_mac")) return http_fn_cfg_mac(request); + if (http_checkUrlBase(urlStr, "cfg_loglevel_set")) return http_fn_cfg_loglevel_set(request); + if (http_checkUrlBase(urlStr, "cfg_mac")) return http_fn_cfg_mac(request); - if(http_checkUrlBase(urlStr,"flash_read_tool")) return http_fn_flash_read_tool(request); - if(http_checkUrlBase(urlStr,"uart_tool")) return http_fn_uart_tool(request); - if(http_checkUrlBase(urlStr,"cmd_tool")) return http_fn_cmd_tool(request); - if(http_checkUrlBase(urlStr,"config_dump_table")) return http_fn_config_dump_table(request); - if(http_checkUrlBase(urlStr,"startup_command")) return http_fn_startup_command(request); - if(http_checkUrlBase(urlStr,"cfg_generic")) return http_fn_cfg_generic(request); - if(http_checkUrlBase(urlStr,"cfg_startup")) return http_fn_cfg_startup(request); - if(http_checkUrlBase(urlStr,"cfg_dgr")) return http_fn_cfg_dgr(request); + if (http_checkUrlBase(urlStr, "flash_read_tool")) return http_fn_flash_read_tool(request); + if (http_checkUrlBase(urlStr, "uart_tool")) return http_fn_uart_tool(request); + if (http_checkUrlBase(urlStr, "cmd_tool")) return http_fn_cmd_tool(request); + if (http_checkUrlBase(urlStr, "config_dump_table")) return http_fn_config_dump_table(request); + if (http_checkUrlBase(urlStr, "startup_command")) return http_fn_startup_command(request); + if (http_checkUrlBase(urlStr, "cfg_generic")) return http_fn_cfg_generic(request); + if (http_checkUrlBase(urlStr, "cfg_startup")) return http_fn_cfg_startup(request); + if (http_checkUrlBase(urlStr, "cfg_dgr")) return http_fn_cfg_dgr(request); - if(http_checkUrlBase(urlStr,"cfg_quick")) return http_fn_cfg_quick(request); - if(http_checkUrlBase(urlStr,"ha_cfg")) return http_fn_ha_cfg(request); - if(http_checkUrlBase(urlStr,"ha_discovery")) return http_fn_ha_discovery(request); - if(http_checkUrlBase(urlStr,"cfg")) return http_fn_cfg(request); + if (http_checkUrlBase(urlStr, "cfg_quick")) return http_fn_cfg_quick(request); + if (http_checkUrlBase(urlStr, "ha_cfg")) return http_fn_ha_cfg(request); + if (http_checkUrlBase(urlStr, "ha_discovery")) return http_fn_ha_discovery(request); + if (http_checkUrlBase(urlStr, "cfg")) return http_fn_cfg(request); - if(http_checkUrlBase(urlStr,"cfg_pins")) return http_fn_cfg_pins(request); - if(http_checkUrlBase(urlStr,"cfg_ping")) return http_fn_cfg_ping(request); + if (http_checkUrlBase(urlStr, "cfg_pins")) return http_fn_cfg_pins(request); + if (http_checkUrlBase(urlStr, "cfg_ping")) return http_fn_cfg_ping(request); - if(http_checkUrlBase(urlStr,"ota")) return http_fn_ota(request); - if(http_checkUrlBase(urlStr,"ota_exec")) return http_fn_ota_exec(request); - if(http_checkUrlBase(urlStr,"cm")) return http_fn_cm(request); + if (http_checkUrlBase(urlStr, "ota")) return http_fn_ota(request); + if (http_checkUrlBase(urlStr, "ota_exec")) return http_fn_ota_exec(request); + if (http_checkUrlBase(urlStr, "cm")) return http_fn_cm(request); return http_fn_other(request); } @@ -603,13 +608,13 @@ And then run `gulp` which will automatically update the fields. */ //region_start htmlHeadStyle -const char htmlHeadStyle[]="<style>div,fieldset,input,select{padding:5px;font-size:1em;margin:0 0 .2em}fieldset{background:#4f4f4f}p{margin:.5em 0}input{width:100%;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;background:#ddd;color:#000}form{margin-bottom:.5em}input[type=checkbox],input[type=radio]{width:1em;margin-right:6px;vertical-align:-1px}input[type=range]{width:99%}select{width:100%;background:#ddd;color:#000}textarea{resize:vertical;width:98%;height:318px;padding:5px;overflow:auto;background:#1f1f1f;color:#65c115}body{text-align:center;font-family:verdana,sans-serif}body,h1 a{background:#21333e;color:#eaeaea}td{padding:0}button,input[type=submit]{border:0;border-radius:.3rem;background:#1fa3ec;color:#faffff;line-height:2.4rem;font-size:1.2rem;cursor:pointer}input[type=submit]{width:100%;transition-duration:.4s}input[type=submit]:hover{background:#0e70a4}.bred{background:#d43535!important}.bred:hover{background:#931f1f!important}.bgrn{background:#47c266!important}.bgrn:hover{background:#5aaf6f!important}a{color:#1fa3ec;text-decoration:none}.p{float:left;text-align:left}.q{float:right;text-align:right}.r{border-radius:.3em;padding:2px;margin:6px 2px}.hf{display:none}.hdiv{width:95%;white-space:nowrap}.hele{width:210px;display:inline-block;margin-left:2px}div#state{padding:0}div#changed{padding:0;height:23px}div#main{text-align:left;display:inline-block;color:#eaeaea;min-width:340px;max-width:800px}table{table-layout:fixed}</style>"; +const char htmlHeadStyle[] = "<style>div,fieldset,input,select{padding:5px;font-size:1em;margin:0 0 .2em}fieldset{background:#4f4f4f}p{margin:.5em 0}input{width:100%;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;background:#ddd;color:#000}form{margin-bottom:.5em}input[type=checkbox],input[type=radio]{width:1em;margin-right:6px;vertical-align:-1px}input[type=range]{width:99%}select{width:100%;background:#ddd;color:#000}textarea{resize:vertical;width:98%;height:318px;padding:5px;overflow:auto;background:#1f1f1f;color:#65c115}body{text-align:center;font-family:verdana,sans-serif}body,h1 a{background:#21333e;color:#eaeaea}td{padding:0}button,input[type=submit]{border:0;border-radius:.3rem;background:#1fa3ec;color:#faffff;line-height:2.4rem;font-size:1.2rem;cursor:pointer}input[type=submit]{width:100%;transition-duration:.4s}input[type=submit]:hover{background:#0e70a4}.bred{background:#d43535!important}.bred:hover{background:#931f1f!important}.bgrn{background:#47c266!important}.bgrn:hover{background:#5aaf6f!important}a{color:#1fa3ec;text-decoration:none}.p{float:left;text-align:left}.q{float:right;text-align:right}.r{border-radius:.3em;padding:2px;margin:6px 2px}.hf{display:none}.hdiv{width:95%;white-space:nowrap}.hele{width:210px;display:inline-block;margin-left:2px}div#state{padding:0}div#changed{padding:0;height:23px}div#main{text-align:left;display:inline-block;color:#eaeaea;min-width:340px;max-width:800px}table{table-layout:fixed}</style>"; //region_end htmlHeadStyle //region_start pageScript -const char pageScript[]="<script type='text/javascript'>var firstTime,lastTime,onlineFor,req=null,onlineForEl=null,getElement=e=>document.getElementById(e);function showState(){clearTimeout(firstTime),clearTimeout(lastTime),null!=req&&req.abort(),(req=new XMLHttpRequest).onreadystatechange=()=>{4==req.readyState&&200==req.status&&((\"INPUT\"!=document.activeElement.tagName||\"number\"!=document.activeElement.type&&\"color\"!=document.activeElement.type)&&(getElement(\"state\").innerHTML=req.responseText),clearTimeout(firstTime),clearTimeout(lastTime),lastTime=setTimeout(showState,3e3))},req.open(\"GET\",\"index?state=1\",!0),req.send(),firstTime=setTimeout(showState,3e3)}function fmtUpTime(e){var t,n,o=Math.floor(e/86400);return e%=86400,t=Math.floor(e/3600),e%=3600,n=Math.floor(e/60),e=e%60,0<o?o+` days, ${t} hours, ${n} minutes and ${e} seconds`:0<t?t+` hours, ${n} minutes and ${e} seconds`:0<n?n+` minutes and ${e} seconds`:`just ${e} seconds`}function updateOnlineFor(){onlineForEl.textContent=fmtUpTime(++onlineFor)}function onLoad(){(onlineForEl=getElement(\"onlineFor\"))&&(onlineFor=parseInt(onlineForEl.dataset.initial,10))&&setInterval(updateOnlineFor,1e3),showState()}window.addEventListener(\"load\",onLoad),history.pushState(null,\"\",\"index\"),setTimeout(()=>{getElement(\"changed\").innerHTML=\"\"},5e3);</script>"; +const char pageScript[] = "<script type='text/javascript'>var firstTime,lastTime,onlineFor,req=null,onlineForEl=null,getElement=e=>document.getElementById(e);function showState(){clearTimeout(firstTime),clearTimeout(lastTime),null!=req&&req.abort(),(req=new XMLHttpRequest).onreadystatechange=()=>{4==req.readyState&&200==req.status&&((\"INPUT\"!=document.activeElement.tagName||\"number\"!=document.activeElement.type&&\"color\"!=document.activeElement.type)&&(getElement(\"state\").innerHTML=req.responseText),clearTimeout(firstTime),clearTimeout(lastTime),lastTime=setTimeout(showState,3e3))},req.open(\"GET\",\"index?state=1\",!0),req.send(),firstTime=setTimeout(showState,3e3)}function fmtUpTime(e){var t,n,o=Math.floor(e/86400);return e%=86400,t=Math.floor(e/3600),e%=3600,n=Math.floor(e/60),e=e%60,0<o?o+` days, ${t} hours, ${n} minutes and ${e} seconds`:0<t?t+` hours, ${n} minutes and ${e} seconds`:0<n?n+` minutes and ${e} seconds`:`just ${e} seconds`}function updateOnlineFor(){onlineForEl.textContent=fmtUpTime(++onlineFor)}function onLoad(){(onlineForEl=getElement(\"onlineFor\"))&&(onlineFor=parseInt(onlineForEl.dataset.initial,10))&&setInterval(updateOnlineFor,1e3),showState()}window.addEventListener(\"load\",onLoad),history.pushState(null,\"\",\"index\"),setTimeout(()=>{getElement(\"changed\").innerHTML=\"\"},5e3);</script>"; //region_end pageScript //region_start ha_discovery_script -const char ha_discovery_script[]="<script type='text/javascript'>function send_ha_disc(){var e=new XMLHttpRequest;e.open(\"GET\",\"/ha_discovery?prefix=\"+document.getElementById(\"ha_disc_topic\").value,!1),e.onload=function(){200===e.status?alert(\"MQTT discovery queued\"):404===e.status&&alert(\"Error invoking ha_discovery\")},e.onerror=function(){alert(\"Error invoking ha_discovery\")},e.send()}</script>"; +const char ha_discovery_script[] = "<script type='text/javascript'>function send_ha_disc(){var e=new XMLHttpRequest;e.open(\"GET\",\"/ha_discovery?prefix=\"+document.getElementById(\"ha_disc_topic\").value,!1),e.onload=function(){200===e.status?alert(\"MQTT discovery queued\"):404===e.status&&alert(\"Error invoking ha_discovery\")},e.onerror=function(){alert(\"Error invoking ha_discovery\")},e.send()}</script>"; //region_end ha_discovery_script \ No newline at end of file diff --git a/src/httpserver/new_http.h b/src/httpserver/new_http.h index ba84fa8a5..fba9ba78a 100644 --- a/src/httpserver/new_http.h +++ b/src/httpserver/new_http.h @@ -12,9 +12,9 @@ extern const char htmlFooterReturnToMenu[]; extern const char htmlFooterRefreshLink[]; extern const char htmlFooterReturnToCfgLink[]; -extern const char *htmlPinRoleNames[]; +extern const char* htmlPinRoleNames[]; -extern const char *g_build_str; +extern const char* g_build_str; extern const char htmlHeadStyle[]; extern const char pageScript[]; @@ -27,58 +27,58 @@ extern const char ha_discovery_script[]; #define MAX_QUERY 16 #define MAX_HEADERS 16 typedef struct http_request_tag { - char *received; // partial or whole received data, up to 1024 - int receivedLen; - int receivedLenmax; // sizeof received + char* received; // partial or whole received data, up to 1024 + int receivedLen; + int receivedLenmax; // sizeof received - // filled by HTTP_ProcessPacket - int method; - char *url; - int numqueryitems; - char *querynames[MAX_QUERY]; - char *queryvalues[MAX_QUERY]; - int numheaders; - char *headers[MAX_HEADERS]; - char *bodystart; /// start start of the body (maybe all of it) - int bodylen; - int contentLength; - int responseCode; + // filled by HTTP_ProcessPacket + int method; + char* url; + int numqueryitems; + char* querynames[MAX_QUERY]; + char* queryvalues[MAX_QUERY]; + int numheaders; + char* headers[MAX_HEADERS]; + char* bodystart; /// start start of the body (maybe all of it) + int bodylen; + int contentLength; + int responseCode; - // used to respond - char *reply; - int replylen; - int replymaxlen; - int fd; + // used to respond + char* reply; + int replylen; + int replymaxlen; + int fd; } http_request_t; -int HTTP_ProcessPacket(http_request_t *request); -void http_setup(http_request_t *request, const char *type); -void http_html_start(http_request_t *request, const char *pagename); -void http_html_end(http_request_t *request); -int poststr(http_request_t *request, const char *str); -int postany(http_request_t *request, const char *str, int len); -void misc_formatUpTimeString(int totalSeconds, char *o); +int HTTP_ProcessPacket(http_request_t* request); +void http_setup(http_request_t* request, const char* type); +void http_html_start(http_request_t* request, const char* pagename); +void http_html_end(http_request_t* request); +int poststr(http_request_t* request, const char* str); +int postany(http_request_t* request, const char* str, int len); +void misc_formatUpTimeString(int totalSeconds, char* o); // void HTTP_AddBuildFooter(http_request_t *request); // void HTTP_AddHeader(http_request_t *request); -int http_getArg(const char *base, const char *name, char *o, int maxSize); -int http_getArgInteger(const char *base, const char *name); +int http_getArg(const char* base, const char* name, char* o, int maxSize); +int http_getArgInteger(const char* base, const char* name); // poststr with format - for results LESS THAN 128 -int hprintf128(http_request_t *request, const char *fmt, ...); +int hprintf128(http_request_t* request, const char* fmt, ...); typedef enum { - HTTP_ANY = -1, - HTTP_GET = 0, - HTTP_PUT = 1, - HTTP_POST = 2, - HTTP_OPTIONS = 3 + HTTP_ANY = -1, + HTTP_GET = 0, + HTTP_PUT = 1, + HTTP_POST = 2, + HTTP_OPTIONS = 3 } METHODS; // callback function for http -typedef int (*http_callback_fn)(http_request_t *request); +typedef int (*http_callback_fn)(http_request_t* request); // url MUST start with '/' // urls must be unique (i.e. you can't have /about and /aboutme or /about/me) -int HTTP_RegisterCallback( const char *url, int method, http_callback_fn callback); +int HTTP_RegisterCallback(const char* url, int method, http_callback_fn callback); #endif diff --git a/src/httpserver/rest_interface.c b/src/httpserver/rest_interface.c index 333239e8f..fc1536f1b 100644 --- a/src/httpserver/rest_interface.c +++ b/src/httpserver/rest_interface.c @@ -13,7 +13,7 @@ #endif #include "lwip/sockets.h" #if PLATFORM_XR809 - #include <image/flash.h> +#include <image/flash.h> #elif PLATFORM_BL602 #else @@ -23,105 +23,105 @@ #include "../cmnds/cmd_public.h" #if PLATFORM_XR809 -uint32_t flash_read(uint32_t flash, uint32_t addr,void *buf, uint32_t size); +uint32_t flash_read(uint32_t flash, uint32_t addr, void* buf, uint32_t size); #define FLASH_INDEX_XR809 0 #elif PLATFORM_BL602 #elif PLATFORM_W600 || PLATFORM_W800 #else -extern UINT32 flash_read(char *user_buf, UINT32 count, UINT32 address); +extern UINT32 flash_read(char* user_buf, UINT32 count, UINT32 address); #endif #define MAX_JSON_VALUE_LENGTH 128 -static int http_rest_error(http_request_t *request, int code, char *msg); +static int http_rest_error(http_request_t* request, int code, char* msg); -static int http_rest_get(http_request_t *request); -static int http_rest_post(http_request_t *request); -static int http_rest_app(http_request_t *request); +static int http_rest_get(http_request_t* request); +static int http_rest_post(http_request_t* request); +static int http_rest_app(http_request_t* request); -static int http_rest_post_pins(http_request_t *request); -static int http_rest_get_pins(http_request_t *request); +static int http_rest_post_pins(http_request_t* request); +static int http_rest_get_pins(http_request_t* request); -static int http_rest_get_seriallog(http_request_t *request); +static int http_rest_get_seriallog(http_request_t* request); -static int http_rest_post_logconfig(http_request_t *request); -static int http_rest_get_logconfig(http_request_t *request); +static int http_rest_post_logconfig(http_request_t* request); +static int http_rest_get_logconfig(http_request_t* request); #ifdef BK_LITTLEFS -static int http_rest_get_lfs_file(http_request_t *request); -static int http_rest_post_lfs_file(http_request_t *request); +static int http_rest_get_lfs_file(http_request_t* request); +static int http_rest_post_lfs_file(http_request_t* request); #endif -static int http_favicon(http_request_t *request); +static int http_favicon(http_request_t* request); -static int http_rest_post_reboot(http_request_t *request); -static int http_rest_post_flash(http_request_t *request, int startaddr); -static int http_rest_get_flash(http_request_t *request, int startaddr, int len); -static int http_rest_get_flash_advanced(http_request_t *request); -static int http_rest_post_flash_advanced(http_request_t *request); +static int http_rest_post_reboot(http_request_t* request); +static int http_rest_post_flash(http_request_t* request, int startaddr); +static int http_rest_get_flash(http_request_t* request, int startaddr, int len); +static int http_rest_get_flash_advanced(http_request_t* request); +static int http_rest_post_flash_advanced(http_request_t* request); -static int http_rest_get_info(http_request_t *request); +static int http_rest_get_info(http_request_t* request); -static int http_rest_get_dumpconfig(http_request_t *request); -static int http_rest_get_testconfig(http_request_t *request); +static int http_rest_get_dumpconfig(http_request_t* request); +static int http_rest_get_testconfig(http_request_t* request); -static int http_rest_post_channels(http_request_t *request); -static int http_rest_get_channels(http_request_t *request); +static int http_rest_post_channels(http_request_t* request); +static int http_rest_get_channels(http_request_t* request); -static int http_rest_get_flash_vars_test(http_request_t *request); +static int http_rest_get_flash_vars_test(http_request_t* request); -static int http_rest_post_cmd(http_request_t *request); +static int http_rest_post_cmd(http_request_t* request); -void init_rest(){ - HTTP_RegisterCallback( "/api/", HTTP_GET, http_rest_get); - HTTP_RegisterCallback( "/api/", HTTP_POST, http_rest_post); - HTTP_RegisterCallback( "/app", HTTP_GET, http_rest_app); - HTTP_RegisterCallback( "/favicon.ico", HTTP_GET, http_favicon); +void init_rest() { + HTTP_RegisterCallback("/api/", HTTP_GET, http_rest_get); + HTTP_RegisterCallback("/api/", HTTP_POST, http_rest_post); + HTTP_RegisterCallback("/app", HTTP_GET, http_rest_app); + HTTP_RegisterCallback("/favicon.ico", HTTP_GET, http_favicon); } -const char *apppage1 = +const char* apppage1 = "<!DOCTYPE html>" "<html>" " <head>" " <script>" " var root = '"; #if WINDOWS -const char *obktype = "windows"; -const char * apppage2 = "';" +const char* obktype = "windows"; +const char* apppage2 = "';" " var obktype = 'windows';" " var device = 'http://"; #elif PLATFORM_XR809 -const char *obktype = "XR809"; -const char * apppage2 = "';" +const char* obktype = "XR809"; +const char* apppage2 = "';" " var obktype = 'XR809';" " var device = 'http://"; #elif PLATFORM_BL602 -const char *obktype = "BL602"; -const char * apppage2 = "';" +const char* obktype = "BL602"; +const char* apppage2 = "';" " var obktype = 'BL602';" " var device = 'http://"; #elif PLATFORM_W600 -const char *obktype = "W600"; -const char * apppage2 = "';" +const char* obktype = "W600"; +const char* apppage2 = "';" " var obktype = 'W600';" " var device = 'http://"; #elif PLATFORM_W800 -const char *obktype = "W800"; -const char * apppage2 = "';" +const char* obktype = "W800"; +const char* apppage2 = "';" " var obktype = 'W800';" " var device = 'http://"; #else -const char *obktype = "beken"; -const char * apppage2 = "';" +const char* obktype = "beken"; +const char* apppage2 = "';" " var obktype = 'beken';" " var device = 'http://"; #endif -const char * apppage3 = "';" +const char* apppage3 = "';" " </script>" " <script src=\""; -const char * apppage4 = "startup.js\"></script>" +const char* apppage4 = "startup.js\"></script>" " </head>" "<body>" "</body>" @@ -129,725 +129,744 @@ const char * apppage4 = "startup.js\"></script>" /* Extracts string token value into outBuffer (128 char). Returns true if the operation was successful. */ -bool tryGetTokenString(const char *json, jsmntok_t *tok, char *outBuffer){ - if (tok == NULL || tok->type != JSMN_STRING){ - return false; - } - - int length = tok->end - tok->start; +bool tryGetTokenString(const char* json, jsmntok_t* tok, char* outBuffer) { + if (tok == NULL || tok->type != JSMN_STRING) { + return false; + } - //Don't have enough buffer - if (length > MAX_JSON_VALUE_LENGTH) { - return false; - } + int length = tok->end - tok->start; - memset(outBuffer, '\0', MAX_JSON_VALUE_LENGTH); //Wipe previous value - strncpy(outBuffer, json + tok->start, length); - return true; + //Don't have enough buffer + if (length > MAX_JSON_VALUE_LENGTH) { + return false; + } + + memset(outBuffer, '\0', MAX_JSON_VALUE_LENGTH); //Wipe previous value + strncpy(outBuffer, json + tok->start, length); + return true; } -static int http_rest_get(http_request_t *request){ - ADDLOG_DEBUG(LOG_FEATURE_API, "GET of %s", request->url); +static int http_rest_get(http_request_t* request) { + ADDLOG_DEBUG(LOG_FEATURE_API, "GET of %s", request->url); - if (!strcmp(request->url, "api/channels")){ - return http_rest_get_channels(request); - } + if (!strcmp(request->url, "api/channels")) { + return http_rest_get_channels(request); + } - if (!strcmp(request->url, "api/pins")){ - return http_rest_get_pins(request); - } - if (!strcmp(request->url, "api/logconfig")){ - return http_rest_get_logconfig(request); - } + if (!strcmp(request->url, "api/pins")) { + return http_rest_get_pins(request); + } + if (!strcmp(request->url, "api/logconfig")) { + return http_rest_get_logconfig(request); + } - if (!strncmp(request->url, "api/seriallog", 13)){ - return http_rest_get_seriallog(request); - } + if (!strncmp(request->url, "api/seriallog", 13)) { + return http_rest_get_seriallog(request); + } #ifdef BK_LITTLEFS - if (!strcmp(request->url, "api/fsblock")){ - return http_rest_get_flash(request, LFS_BLOCKS_START, LFS_BLOCKS_LEN); - } + if (!strcmp(request->url, "api/fsblock")) { + return http_rest_get_flash(request, LFS_BLOCKS_START, LFS_BLOCKS_LEN); + } #endif #ifdef BK_LITTLEFS - if (!strncmp(request->url, "api/lfs/", 8)){ - return http_rest_get_lfs_file(request); - } + if (!strncmp(request->url, "api/lfs/", 8)) { + return http_rest_get_lfs_file(request); + } #endif - if (!strcmp(request->url, "api/info")){ - return http_rest_get_info(request); - } + if (!strcmp(request->url, "api/info")) { + return http_rest_get_info(request); + } - if (!strncmp(request->url, "api/flash/", 10)){ - return http_rest_get_flash_advanced(request); - } + if (!strncmp(request->url, "api/flash/", 10)) { + return http_rest_get_flash_advanced(request); + } - if (!strcmp(request->url, "api/dumpconfig")){ - return http_rest_get_dumpconfig(request); - } + if (!strcmp(request->url, "api/dumpconfig")) { + return http_rest_get_dumpconfig(request); + } - if (!strcmp(request->url, "api/testconfig")){ - return http_rest_get_testconfig(request); - } + if (!strcmp(request->url, "api/testconfig")) { + return http_rest_get_testconfig(request); + } - if (!strncmp(request->url, "api/testflashvars", 17)){ - return http_rest_get_flash_vars_test(request); - } + if (!strncmp(request->url, "api/testflashvars", 17)) { + return http_rest_get_flash_vars_test(request); + } - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "GET REST API"); - poststr(request, "GET of "); - poststr(request, request->url); - http_html_end(request); - poststr(request,NULL); - return 0; + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "GET REST API"); + poststr(request, "GET of "); + poststr(request, request->url); + http_html_end(request); + poststr(request, NULL); + return 0; } -static int http_rest_post(http_request_t *request){ - char tmp[20]; - ADDLOG_DEBUG(LOG_FEATURE_API, "POST to %s", request->url); +static int http_rest_post(http_request_t* request) { + char tmp[20]; + ADDLOG_DEBUG(LOG_FEATURE_API, "POST to %s", request->url); - if (!strcmp(request->url, "api/channels")){ - return http_rest_post_channels(request); - } + if (!strcmp(request->url, "api/channels")) { + return http_rest_post_channels(request); + } - if (!strcmp(request->url, "api/pins")){ - return http_rest_post_pins(request); - } - if (!strcmp(request->url, "api/logconfig")){ - return http_rest_post_logconfig(request); - } + if (!strcmp(request->url, "api/pins")) { + return http_rest_post_pins(request); + } + if (!strcmp(request->url, "api/logconfig")) { + return http_rest_post_logconfig(request); + } - if (!strcmp(request->url, "api/reboot")){ - return http_rest_post_reboot(request); - } - if (!strcmp(request->url, "api/ota")){ + if (!strcmp(request->url, "api/reboot")) { + return http_rest_post_reboot(request); + } + if (!strcmp(request->url, "api/ota")) { #if PLATFORM_BK7231T - return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA); + return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA); #elif PLATFORM_BK7231N - return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA); + return http_rest_post_flash(request, START_ADR_OF_BK_PARTITION_OTA); #else // TODO #endif - } - if (!strncmp(request->url, "api/flash/", 10)){ - return http_rest_post_flash_advanced(request); - } + } + if (!strncmp(request->url, "api/flash/", 10)) { + return http_rest_post_flash_advanced(request); + } - if (!strcmp(request->url, "api/cmnd")){ - return http_rest_post_cmd(request); - } + if (!strcmp(request->url, "api/cmnd")) { + return http_rest_post_cmd(request); + } #ifdef BK_LITTLEFS - if (!strcmp(request->url, "api/fsblock")){ - if (lfs_present()){ - release_lfs(); - } - // we are writing the lfs block - int res = http_rest_post_flash(request, LFS_BLOCKS_START); - // initialise the filesystem, it should be there now. - // don't create if it does not mount - init_lfs(0); - return res; - } - if (!strncmp(request->url, "api/lfs/", 8)){ - return http_rest_post_lfs_file(request); - } + if (!strcmp(request->url, "api/fsblock")) { + if (lfs_present()) { + release_lfs(); + } + // we are writing the lfs block + int res = http_rest_post_flash(request, LFS_BLOCKS_START); + // initialise the filesystem, it should be there now. + // don't create if it does not mount + init_lfs(0); + return res; + } + if (!strncmp(request->url, "api/lfs/", 8)) { + return http_rest_post_lfs_file(request); + } #endif - http_setup(request, httpMimeTypeHTML); - http_html_start(request, "POST REST API"); - poststr(request, "POST to "); - poststr(request, request->url); - poststr(request, "<br/>Content Length:"); - sprintf(tmp, "%d", request->contentLength); - poststr(request, tmp); - poststr(request, "<br/>Content:["); - poststr(request, request->bodystart); - poststr(request, "]<br/>"); - http_html_end(request); - poststr(request,NULL); - return 0; + http_setup(request, httpMimeTypeHTML); + http_html_start(request, "POST REST API"); + poststr(request, "POST to "); + poststr(request, request->url); + poststr(request, "<br/>Content Length:"); + sprintf(tmp, "%d", request->contentLength); + poststr(request, tmp); + poststr(request, "<br/>Content:["); + poststr(request, request->bodystart); + poststr(request, "]<br/>"); + http_html_end(request); + poststr(request, NULL); + return 0; } -static int http_rest_app(http_request_t *request){ - const char *webhost = CFG_GetWebappRoot(); - const char *ourip = HAL_GetMyIPString(); //CFG_GetOurIP(); - http_setup(request, httpMimeTypeHTML); - if (webhost && ourip){ - poststr(request, apppage1); - poststr(request, webhost); - poststr(request, apppage2); - poststr(request, ourip); - poststr(request, apppage3); - poststr(request, webhost); - poststr(request, apppage4); - } else { - http_html_start(request, "Not available"); - poststr(request, htmlFooterReturnToMenu); - poststr(request, "no APP available<br/>"); - http_html_end(request); - } - poststr(request,NULL); - return 0; +static int http_rest_app(http_request_t* request) { + const char* webhost = CFG_GetWebappRoot(); + const char* ourip = HAL_GetMyIPString(); //CFG_GetOurIP(); + http_setup(request, httpMimeTypeHTML); + if (webhost && ourip) { + poststr(request, apppage1); + poststr(request, webhost); + poststr(request, apppage2); + poststr(request, ourip); + poststr(request, apppage3); + poststr(request, webhost); + poststr(request, apppage4); + } + else { + http_html_start(request, "Not available"); + poststr(request, htmlFooterReturnToMenu); + poststr(request, "no APP available<br/>"); + http_html_end(request); + } + poststr(request, NULL); + return 0; } #ifdef BK_LITTLEFS -int EndsWith(const char *str, const char *suffix) +int EndsWith(const char* str, const char* suffix) { - if (!str || !suffix) - return 0; - size_t lenstr = strlen(str); - size_t lensuffix = strlen(suffix); - if (lensuffix > lenstr) - return 0; - return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; + if (!str || !suffix) + return 0; + size_t lenstr = strlen(str); + size_t lensuffix = strlen(suffix); + if (lensuffix > lenstr) + return 0; + return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; } -static int http_rest_get_lfs_file(http_request_t *request){ - char *fpath; - char *buff; - int len; - int lfsres; - int total = 0; - lfs_file_t *file; +static int http_rest_get_lfs_file(http_request_t* request) { + char* fpath; + char* buff; + int len; + int lfsres; + int total = 0; + lfs_file_t* file; - // don't start LFS just because we're trying to read a file - - // it won't exist anyway - if (!lfs_present()){ - request->responseCode = HTTP_RESPONSE_NOT_FOUND; - http_setup(request, httpMimeTypeText); - poststr(request,NULL); - return 0; - } + // don't start LFS just because we're trying to read a file - + // it won't exist anyway + if (!lfs_present()) { + request->responseCode = HTTP_RESPONSE_NOT_FOUND; + http_setup(request, httpMimeTypeText); + poststr(request, NULL); + return 0; + } - fpath = os_malloc(strlen(request->url) - strlen("api/lfs/") + 1); + fpath = os_malloc(strlen(request->url) - strlen("api/lfs/") + 1); - buff = os_malloc(1024); - file = os_malloc(sizeof(lfs_file_t)); - memset(file, 0, sizeof(lfs_file_t)); + buff = os_malloc(1024); + file = os_malloc(sizeof(lfs_file_t)); + memset(file, 0, sizeof(lfs_file_t)); - strcpy(fpath, request->url + strlen("api/lfs/")); + strcpy(fpath, request->url + strlen("api/lfs/")); - ADDLOG_DEBUG(LOG_FEATURE_API, "LFS read of %s", fpath); - lfsres = lfs_file_open(&lfs, file, fpath, LFS_O_RDONLY); + ADDLOG_DEBUG(LOG_FEATURE_API, "LFS read of %s", fpath); + lfsres = lfs_file_open(&lfs, file, fpath, LFS_O_RDONLY); - if (lfsres == -21){ - lfs_dir_t *dir; - ADDLOG_DEBUG(LOG_FEATURE_API, "%s is a folder", fpath); - dir = os_malloc(sizeof(lfs_dir_t)); - os_memset(dir, 0, sizeof(*dir)); - // if the thing is a folder. - lfsres = lfs_dir_open(&lfs, dir, fpath); + if (lfsres == -21) { + lfs_dir_t* dir; + ADDLOG_DEBUG(LOG_FEATURE_API, "%s is a folder", fpath); + dir = os_malloc(sizeof(lfs_dir_t)); + os_memset(dir, 0, sizeof(*dir)); + // if the thing is a folder. + lfsres = lfs_dir_open(&lfs, dir, fpath); - if (lfsres >= 0){ - // this is needed during iteration...? - struct lfs_info info; - int count = 0; - http_setup(request, httpMimeTypeJson); - ADDLOG_DEBUG(LOG_FEATURE_API, "opened folder %s lfs result %d", fpath, lfsres); - hprintf128(request, "{\"dir\":\"%s\",\"content\":[", fpath); - do { - // Read an entry in the directory - // - // Fills out the info structure, based on the specified file or directory. - // Returns a positive value on success, 0 at the end of directory, - // or a negative error code on failure. - lfsres = lfs_dir_read(&lfs, dir, &info); - if (lfsres > 0){ - if (count) poststr(request, ","); - hprintf128(request, "{\"name\":\"%s\",\"type\":%d,\"size\":%d}", - info.name, info.type, info.size); - } else { - if (lfsres < 0){ - if (count) poststr(request, ","); - hprintf128(request, "{\"error\":%d}", lfsres); - } - } - count++; - } while (lfsres > 0); + if (lfsres >= 0) { + // this is needed during iteration...? + struct lfs_info info; + int count = 0; + http_setup(request, httpMimeTypeJson); + ADDLOG_DEBUG(LOG_FEATURE_API, "opened folder %s lfs result %d", fpath, lfsres); + hprintf128(request, "{\"dir\":\"%s\",\"content\":[", fpath); + do { + // Read an entry in the directory + // + // Fills out the info structure, based on the specified file or directory. + // Returns a positive value on success, 0 at the end of directory, + // or a negative error code on failure. + lfsres = lfs_dir_read(&lfs, dir, &info); + if (lfsres > 0) { + if (count) poststr(request, ","); + hprintf128(request, "{\"name\":\"%s\",\"type\":%d,\"size\":%d}", + info.name, info.type, info.size); + } + else { + if (lfsres < 0) { + if (count) poststr(request, ","); + hprintf128(request, "{\"error\":%d}", lfsres); + } + } + count++; + } while (lfsres > 0); - hprintf128(request, "]}"); + hprintf128(request, "]}"); - lfs_dir_close(&lfs, dir); - if (dir) os_free(dir); - dir = NULL; - } else { - if (dir) os_free(dir); - dir = NULL; - request->responseCode = HTTP_RESPONSE_NOT_FOUND; - http_setup(request, httpMimeTypeJson); - ADDLOG_DEBUG(LOG_FEATURE_API, "failed to open %s lfs result %d", fpath, lfsres); - hprintf128(request, "{\"fname\":\"%s\",\"error\":%d}", fpath, lfsres); - } - } else { - ADDLOG_DEBUG(LOG_FEATURE_API, "LFS open [%s] gives %d", fpath, lfsres); - if (lfsres >= 0){ - const char *mimetype = httpMimeTypeBinary; - do { - if (EndsWith(fpath, ".ico")){ - mimetype = "image/x-icon"; - break; - } - if (EndsWith(fpath, ".js")){ - mimetype = "text/javascript"; - break; - } - if (EndsWith(fpath, ".json")){ - mimetype = httpMimeTypeJson; - break; - } - if (EndsWith(fpath, ".html")){ - mimetype = "text/html"; - break; - } - if (EndsWith(fpath, ".vue")){ - mimetype = "application/javascript"; - break; - } - break; - } while (0); + lfs_dir_close(&lfs, dir); + if (dir) os_free(dir); + dir = NULL; + } + else { + if (dir) os_free(dir); + dir = NULL; + request->responseCode = HTTP_RESPONSE_NOT_FOUND; + http_setup(request, httpMimeTypeJson); + ADDLOG_DEBUG(LOG_FEATURE_API, "failed to open %s lfs result %d", fpath, lfsres); + hprintf128(request, "{\"fname\":\"%s\",\"error\":%d}", fpath, lfsres); + } + } + else { + ADDLOG_DEBUG(LOG_FEATURE_API, "LFS open [%s] gives %d", fpath, lfsres); + if (lfsres >= 0) { + const char* mimetype = httpMimeTypeBinary; + do { + if (EndsWith(fpath, ".ico")) { + mimetype = "image/x-icon"; + break; + } + if (EndsWith(fpath, ".js")) { + mimetype = "text/javascript"; + break; + } + if (EndsWith(fpath, ".json")) { + mimetype = httpMimeTypeJson; + break; + } + if (EndsWith(fpath, ".html")) { + mimetype = "text/html"; + break; + } + if (EndsWith(fpath, ".vue")) { + mimetype = "application/javascript"; + break; + } + break; + } while (0); - http_setup(request, mimetype); - do { - len = lfs_file_read(&lfs, file, buff, 1024); - total += len; - if (len){ - //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes read", len); - postany(request, buff, len); - } - } while (len > 0); - lfs_file_close(&lfs, file); - ADDLOG_DEBUG(LOG_FEATURE_API, "%d total bytes read", total); - } else { - request->responseCode = HTTP_RESPONSE_NOT_FOUND; - http_setup(request, httpMimeTypeJson); - ADDLOG_DEBUG(LOG_FEATURE_API, "failed to open %s lfs result %d", fpath, lfsres); - hprintf128(request, "{\"fname\":\"%s\",\"error\":%d}", fpath, lfsres); - } - } - poststr(request,NULL); - if (fpath) os_free(fpath); - if (file) os_free(file); - if (buff) os_free(buff); - return 0; + http_setup(request, mimetype); + do { + len = lfs_file_read(&lfs, file, buff, 1024); + total += len; + if (len) { + //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes read", len); + postany(request, buff, len); + } + } while (len > 0); + lfs_file_close(&lfs, file); + ADDLOG_DEBUG(LOG_FEATURE_API, "%d total bytes read", total); + } + else { + request->responseCode = HTTP_RESPONSE_NOT_FOUND; + http_setup(request, httpMimeTypeJson); + ADDLOG_DEBUG(LOG_FEATURE_API, "failed to open %s lfs result %d", fpath, lfsres); + hprintf128(request, "{\"fname\":\"%s\",\"error\":%d}", fpath, lfsres); + } + } + poststr(request, NULL); + if (fpath) os_free(fpath); + if (file) os_free(file); + if (buff) os_free(buff); + return 0; } -static int http_rest_post_lfs_file(http_request_t *request){ - int len; - int lfsres; - int total = 0; +static int http_rest_post_lfs_file(http_request_t* request) { + int len; + int lfsres; + int total = 0; - // allocated variables - lfs_file_t *file; - char *fpath; - char *folder; + // allocated variables + lfs_file_t* file; + char* fpath; + char* folder; - // create if it does not exist - init_lfs(1); + // create if it does not exist + init_lfs(1); - fpath = os_malloc(strlen(request->url) - strlen("api/lfs/") + 1); - file = os_malloc(sizeof(lfs_file_t)); - memset(file, 0, sizeof(lfs_file_t)); + fpath = os_malloc(strlen(request->url) - strlen("api/lfs/") + 1); + file = os_malloc(sizeof(lfs_file_t)); + memset(file, 0, sizeof(lfs_file_t)); - strcpy(fpath, request->url + strlen("api/lfs/")); - ADDLOG_DEBUG(LOG_FEATURE_API, "LFS write of %s len %d", fpath, request->contentLength); + strcpy(fpath, request->url + strlen("api/lfs/")); + ADDLOG_DEBUG(LOG_FEATURE_API, "LFS write of %s len %d", fpath, request->contentLength); - folder = strchr(fpath, '/'); - if (folder){ - int folderlen = folder - fpath; - folder = os_malloc(folderlen+1); - strncpy(folder, fpath, folderlen); - folder[folderlen] = 0; - ADDLOG_DEBUG(LOG_FEATURE_API, "file is in folder %s try to create", folder); - lfsres = lfs_mkdir(&lfs, folder); - if (lfsres < 0){ - ADDLOG_DEBUG(LOG_FEATURE_API, "mkdir error %d", lfsres); - } - } + folder = strchr(fpath, '/'); + if (folder) { + int folderlen = folder - fpath; + folder = os_malloc(folderlen + 1); + strncpy(folder, fpath, folderlen); + folder[folderlen] = 0; + ADDLOG_DEBUG(LOG_FEATURE_API, "file is in folder %s try to create", folder); + lfsres = lfs_mkdir(&lfs, folder); + if (lfsres < 0) { + ADDLOG_DEBUG(LOG_FEATURE_API, "mkdir error %d", lfsres); + } + } - //ADDLOG_DEBUG(LOG_FEATURE_API, "LFS write of %s len %d", fpath, request->contentLength); + //ADDLOG_DEBUG(LOG_FEATURE_API, "LFS write of %s len %d", fpath, request->contentLength); - lfsres = lfs_file_open(&lfs, file, fpath, LFS_O_RDWR | LFS_O_CREAT); - if (lfsres >= 0){ - //ADDLOG_DEBUG(LOG_FEATURE_API, "opened %s"); - int towrite = request->bodylen; - char *writebuf = request->bodystart; - int writelen = request->bodylen; - if (request->contentLength >= 0){ - towrite = request->contentLength; - } - //ADDLOG_DEBUG(LOG_FEATURE_API, "bodylen %d, contentlen %d", request->bodylen, request->contentLength); + lfsres = lfs_file_open(&lfs, file, fpath, LFS_O_RDWR | LFS_O_CREAT); + if (lfsres >= 0) { + //ADDLOG_DEBUG(LOG_FEATURE_API, "opened %s"); + int towrite = request->bodylen; + char* writebuf = request->bodystart; + int writelen = request->bodylen; + if (request->contentLength >= 0) { + towrite = request->contentLength; + } + //ADDLOG_DEBUG(LOG_FEATURE_API, "bodylen %d, contentlen %d", request->bodylen, request->contentLength); - if (writelen < 0){ - ADDLOG_DEBUG(LOG_FEATURE_API, "ABORTED: %d bytes to write", writelen); - lfs_file_close(&lfs, file); - request->responseCode = HTTP_RESPONSE_SERVER_ERROR; - http_setup(request, httpMimeTypeJson); - hprintf128(request, "{\"fname\":\"%s\",\"error\":%d}", fpath, -20); - goto exit; - } + if (writelen < 0) { + ADDLOG_DEBUG(LOG_FEATURE_API, "ABORTED: %d bytes to write", writelen); + lfs_file_close(&lfs, file); + request->responseCode = HTTP_RESPONSE_SERVER_ERROR; + http_setup(request, httpMimeTypeJson); + hprintf128(request, "{\"fname\":\"%s\",\"error\":%d}", fpath, -20); + goto exit; + } - do { - //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes to write", writelen); - len = lfs_file_write(&lfs, file, writebuf, writelen); - total += len; - if (len > 0){ - //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes written", len); - } - towrite -= len; - if (towrite > 0){ - writebuf = request->received; - writelen = recv(request->fd, writebuf, request->receivedLenmax, 0); - if (writelen < 0){ - ADDLOG_DEBUG(LOG_FEATURE_API, "recv returned %d - end of data - remaining %d", writelen, towrite); - } - } - } while ((towrite > 0) && (writelen >= 0)); + do { + //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes to write", writelen); + len = lfs_file_write(&lfs, file, writebuf, writelen); + total += len; + if (len > 0) { + //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes written", len); + } + towrite -= len; + if (towrite > 0) { + writebuf = request->received; + writelen = recv(request->fd, writebuf, request->receivedLenmax, 0); + if (writelen < 0) { + ADDLOG_DEBUG(LOG_FEATURE_API, "recv returned %d - end of data - remaining %d", writelen, towrite); + } + } + } while ((towrite > 0) && (writelen >= 0)); // no more data - lfs_file_truncate(&lfs, file,total); + lfs_file_truncate(&lfs, file, total); - //ADDLOG_DEBUG(LOG_FEATURE_API, "closing %s", fpath); - lfs_file_close(&lfs, file); - ADDLOG_DEBUG(LOG_FEATURE_API, "%d total bytes written", total); - http_setup(request, httpMimeTypeJson); - hprintf128(request, "{\"fname\":\"%s\",\"size\":%d}", fpath, total); - } else { - request->responseCode = HTTP_RESPONSE_SERVER_ERROR; - http_setup(request, httpMimeTypeJson); - ADDLOG_DEBUG(LOG_FEATURE_API, "failed to open %s err %d", fpath, lfsres); - hprintf128(request, "{\"fname\":\"%s\",\"error\":%d}", fpath, lfsres); - } + //ADDLOG_DEBUG(LOG_FEATURE_API, "closing %s", fpath); + lfs_file_close(&lfs, file); + ADDLOG_DEBUG(LOG_FEATURE_API, "%d total bytes written", total); + http_setup(request, httpMimeTypeJson); + hprintf128(request, "{\"fname\":\"%s\",\"size\":%d}", fpath, total); + } + else { + request->responseCode = HTTP_RESPONSE_SERVER_ERROR; + http_setup(request, httpMimeTypeJson); + ADDLOG_DEBUG(LOG_FEATURE_API, "failed to open %s err %d", fpath, lfsres); + hprintf128(request, "{\"fname\":\"%s\",\"error\":%d}", fpath, lfsres); + } exit: - poststr(request,NULL); - if (folder) os_free(folder); - if (file) os_free(file); - if (fpath) os_free(fpath); - return 0; + poststr(request, NULL); + if (folder) os_free(folder); + if (file) os_free(file); + if (fpath) os_free(fpath); + return 0; } -static int http_favicon(http_request_t *request){ - request->url = "api/lfs/favicon.ico"; - return http_rest_get_lfs_file(request); +static int http_favicon(http_request_t* request) { + request->url = "api/lfs/favicon.ico"; + return http_rest_get_lfs_file(request); } #else -static int http_favicon(http_request_t *request){ - request->responseCode = HTTP_RESPONSE_NOT_FOUND; - http_setup(request, httpMimeTypeHTML); - poststr(request,NULL); - return 0; +static int http_favicon(http_request_t* request) { + request->responseCode = HTTP_RESPONSE_NOT_FOUND; + http_setup(request, httpMimeTypeHTML); + poststr(request, NULL); + return 0; } #endif -static int http_rest_get_seriallog(http_request_t *request){ - if (request->url[strlen(request->url)-1] == '1'){ - direct_serial_log = 1; - } else { - direct_serial_log = 0; - } - http_setup(request, httpMimeTypeJson); - hprintf128(request, "Direct serial logging set to %d", direct_serial_log); - poststr(request, NULL); - return 0; +static int http_rest_get_seriallog(http_request_t* request) { + if (request->url[strlen(request->url) - 1] == '1') { + direct_serial_log = 1; + } + else { + direct_serial_log = 0; + } + http_setup(request, httpMimeTypeJson); + hprintf128(request, "Direct serial logging set to %d", direct_serial_log); + poststr(request, NULL); + return 0; } -static int http_rest_get_pins(http_request_t *request){ - int i; - http_setup(request, httpMimeTypeJson); - poststr(request, "{\"rolenames\":["); - for (i = 0; i < IOR_Total_Options; i++){ - if (i){ - hprintf128(request, ",\"%s\"", htmlPinRoleNames[i]); - } else { - hprintf128(request, "\"%s\"", htmlPinRoleNames[i]); - } - } - poststr(request, "],\"roles\":["); +static int http_rest_get_pins(http_request_t* request) { + int i; + http_setup(request, httpMimeTypeJson); + poststr(request, "{\"rolenames\":["); + for (i = 0; i < IOR_Total_Options; i++) { + if (i) { + hprintf128(request, ",\"%s\"", htmlPinRoleNames[i]); + } + else { + hprintf128(request, "\"%s\"", htmlPinRoleNames[i]); + } + } + poststr(request, "],\"roles\":["); - for (i = 0; i < PLATFORM_GPIO_MAX; i++){ - if (i){ + for (i = 0; i < PLATFORM_GPIO_MAX; i++) { + if (i) { hprintf128(request, ",%d", g_cfg.pins.roles[i]); - } else { - hprintf128(request, "%d", g_cfg.pins.roles[i]); - } - } + } + else { + hprintf128(request, "%d", g_cfg.pins.roles[i]); + } + } // TODO: maybe we should cull futher channels that are not used? // I support many channels because I plan to use 16x relays module with I2C MCP23017 driver - poststr(request, "],\"channels\":["); - for (i = 0; i < CHANNEL_MAX; i++){ - if (i){ - hprintf128(request, ",%d", g_cfg.pins.channels[i]); - } else { - hprintf128(request, "%d", g_cfg.pins.channels[i]); - } - } - poststr(request, "]}"); - poststr(request, NULL); - return 0; + poststr(request, "],\"channels\":["); + for (i = 0; i < CHANNEL_MAX; i++) { + if (i) { + hprintf128(request, ",%d", g_cfg.pins.channels[i]); + } + else { + hprintf128(request, "%d", g_cfg.pins.channels[i]); + } + } + poststr(request, "]}"); + poststr(request, NULL); + return 0; } //////////////////////////// // log config -static int http_rest_get_logconfig(http_request_t *request){ - int i; - http_setup(request, httpMimeTypeJson); - hprintf128(request, "{\"level\":%d,", loglevel); - hprintf128(request, "\"features\":%d,", logfeatures); - poststr(request, "\"levelnames\":["); - for (i = 0; i < LOG_MAX; i++){ - if (i){ - hprintf128(request, ",\"%s\"", loglevelnames[i]); - } else { - hprintf128(request, "\"%s\"", loglevelnames[i]); - } - } - poststr(request, "],\"featurenames\":["); - for (i = 0; i < LOG_FEATURE_MAX; i++){ - if (i){ - hprintf128(request, ",\"%s\"", logfeaturenames[i]); - } else { - hprintf128(request, "\"%s\"", logfeaturenames[i]); - } - } - poststr(request, "]}"); - poststr(request, NULL); - return 0; +static int http_rest_get_logconfig(http_request_t* request) { + int i; + http_setup(request, httpMimeTypeJson); + hprintf128(request, "{\"level\":%d,", loglevel); + hprintf128(request, "\"features\":%d,", logfeatures); + poststr(request, "\"levelnames\":["); + for (i = 0; i < LOG_MAX; i++) { + if (i) { + hprintf128(request, ",\"%s\"", loglevelnames[i]); + } + else { + hprintf128(request, "\"%s\"", loglevelnames[i]); + } + } + poststr(request, "],\"featurenames\":["); + for (i = 0; i < LOG_FEATURE_MAX; i++) { + if (i) { + hprintf128(request, ",\"%s\"", logfeaturenames[i]); + } + else { + hprintf128(request, "\"%s\"", logfeaturenames[i]); + } + } + poststr(request, "]}"); + poststr(request, NULL); + return 0; } -static int http_rest_post_logconfig(http_request_t *request){ - int i; - int r; - char tmp[64]; +static int http_rest_post_logconfig(http_request_t* request) { + int i; + int r; + char tmp[64]; - //https://github.com/zserge/jsmn/blob/master/example/simple.c - //jsmn_parser p; - jsmn_parser *p = os_malloc(sizeof(jsmn_parser)); - //jsmntok_t t[128]; /* We expect no more than 128 tokens */ + //https://github.com/zserge/jsmn/blob/master/example/simple.c + //jsmn_parser p; + jsmn_parser* p = os_malloc(sizeof(jsmn_parser)); + //jsmntok_t t[128]; /* We expect no more than 128 tokens */ #define TOKEN_COUNT 128 - jsmntok_t *t = os_malloc(sizeof(jsmntok_t)*TOKEN_COUNT); - char *json_str = request->bodystart; - int json_len = strlen(json_str); + jsmntok_t* t = os_malloc(sizeof(jsmntok_t) * TOKEN_COUNT); + char* json_str = request->bodystart; + int json_len = strlen(json_str); http_setup(request, httpMimeTypeText); memset(p, 0, sizeof(jsmn_parser)); - memset(t, 0, sizeof(jsmntok_t)*128); + memset(t, 0, sizeof(jsmntok_t) * 128); - jsmn_init(p); - r = jsmn_parse(p, json_str, json_len, t, TOKEN_COUNT); - if (r < 0) { - ADDLOG_ERROR(LOG_FEATURE_API, "Failed to parse JSON: %d", r); - poststr(request, NULL); - os_free(p); - os_free(t); - return 0; - } + jsmn_init(p); + r = jsmn_parse(p, json_str, json_len, t, TOKEN_COUNT); + if (r < 0) { + ADDLOG_ERROR(LOG_FEATURE_API, "Failed to parse JSON: %d", r); + poststr(request, NULL); + os_free(p); + os_free(t); + return 0; + } - /* Assume the top-level element is an object */ - if (r < 1 || t[0].type != JSMN_OBJECT) { - ADDLOG_ERROR(LOG_FEATURE_API, "Object expected", r); - poststr(request, NULL); - os_free(p); - os_free(t); - return 0; - } + /* Assume the top-level element is an object */ + if (r < 1 || t[0].type != JSMN_OBJECT) { + ADDLOG_ERROR(LOG_FEATURE_API, "Object expected", r); + poststr(request, NULL); + os_free(p); + os_free(t); + return 0; + } - //sprintf(tmp,"parsed JSON: %s\n", json_str); - //poststr(request, tmp); - //poststr(request, NULL); + //sprintf(tmp,"parsed JSON: %s\n", json_str); + //poststr(request, tmp); + //poststr(request, NULL); - /* Loop over all keys of the root object */ - for (i = 1; i < r; i++) { - if (jsoneq(json_str, &t[i], "level") == 0) { - if (t[i + 1].type != JSMN_PRIMITIVE) { - continue; /* We expect groups to be an array of strings */ - } - loglevel = atoi(json_str + t[i + 1].start); - i += t[i + 1].size + 1; - } else if (jsoneq(json_str, &t[i], "features") == 0) { - if (t[i + 1].type != JSMN_PRIMITIVE) { - continue; /* We expect groups to be an array of strings */ - } - logfeatures = atoi(json_str + t[i + 1].start);; - i += t[i + 1].size + 1; - } else { - ADDLOG_ERROR(LOG_FEATURE_API, "Unexpected key: %.*s", t[i].end - t[i].start, - json_str + t[i].start); - sprintf(tmp,"Unexpected key: %.*s\n", t[i].end - t[i].start, - json_str + t[i].start); - poststr(request, tmp); - } - } + /* Loop over all keys of the root object */ + for (i = 1; i < r; i++) { + if (jsoneq(json_str, &t[i], "level") == 0) { + if (t[i + 1].type != JSMN_PRIMITIVE) { + continue; /* We expect groups to be an array of strings */ + } + loglevel = atoi(json_str + t[i + 1].start); + i += t[i + 1].size + 1; + } + else if (jsoneq(json_str, &t[i], "features") == 0) { + if (t[i + 1].type != JSMN_PRIMITIVE) { + continue; /* We expect groups to be an array of strings */ + } + logfeatures = atoi(json_str + t[i + 1].start);; + i += t[i + 1].size + 1; + } + else { + ADDLOG_ERROR(LOG_FEATURE_API, "Unexpected key: %.*s", t[i].end - t[i].start, + json_str + t[i].start); + sprintf(tmp, "Unexpected key: %.*s\n", t[i].end - t[i].start, + json_str + t[i].start); + poststr(request, tmp); + } + } - poststr(request, NULL); - os_free(p); - os_free(t); - return 0; + poststr(request, NULL); + os_free(p); + os_free(t); + return 0; } ///////////////////////////////////////////////// -static int http_rest_get_info(http_request_t *request){ - char macstr[3*6+1]; - http_setup(request, httpMimeTypeJson); - hprintf128(request, "{\"uptime_s\":%d,", Time_getUpTimeSeconds()); - hprintf128(request, "\"build\":\"%s\",", g_build_str); - hprintf128(request, "\"sys\":\"%s\",", obktype); - hprintf128(request, "\"ip\":\"%s\",", HAL_GetMyIPString()); - hprintf128(request, "\"mac\":\"%s\",", HAL_GetMACStr(macstr)); - hprintf128(request, "\"mqtthost\":\"%s:%d\",", CFG_GetMQTTHost(), CFG_GetMQTTPort()); - hprintf128(request, "\"mqtttopic\":\"%s\",", CFG_GetMQTTClientId()); - hprintf128(request, "\"chipset\":\"%s\",", PLATFORM_MCU_NAME); - hprintf128(request, "\"webapp\":\"%s\",", CFG_GetWebappRoot()); - hprintf128(request, "\"supportsClientDeviceDB\":true}"); +static int http_rest_get_info(http_request_t* request) { + char macstr[3 * 6 + 1]; + http_setup(request, httpMimeTypeJson); + hprintf128(request, "{\"uptime_s\":%d,", Time_getUpTimeSeconds()); + hprintf128(request, "\"build\":\"%s\",", g_build_str); + hprintf128(request, "\"sys\":\"%s\",", obktype); + hprintf128(request, "\"ip\":\"%s\",", HAL_GetMyIPString()); + hprintf128(request, "\"mac\":\"%s\",", HAL_GetMACStr(macstr)); + hprintf128(request, "\"mqtthost\":\"%s:%d\",", CFG_GetMQTTHost(), CFG_GetMQTTPort()); + hprintf128(request, "\"mqtttopic\":\"%s\",", CFG_GetMQTTClientId()); + hprintf128(request, "\"chipset\":\"%s\",", PLATFORM_MCU_NAME); + hprintf128(request, "\"webapp\":\"%s\",", CFG_GetWebappRoot()); + hprintf128(request, "\"supportsClientDeviceDB\":true}"); - poststr(request, NULL); - return 0; + poststr(request, NULL); + return 0; } -static int http_rest_post_pins(http_request_t *request){ - int i; - int r; - char tmp[64]; - int iChanged = 0; - char tokenStrValue[MAX_JSON_VALUE_LENGTH + 1]; +static int http_rest_post_pins(http_request_t* request) { + int i; + int r; + char tmp[64]; + int iChanged = 0; + char tokenStrValue[MAX_JSON_VALUE_LENGTH + 1]; - //https://github.com/zserge/jsmn/blob/master/example/simple.c - //jsmn_parser p; - jsmn_parser *p = os_malloc(sizeof(jsmn_parser)); - //jsmntok_t t[128]; /* We expect no more than 128 tokens */ + //https://github.com/zserge/jsmn/blob/master/example/simple.c + //jsmn_parser p; + jsmn_parser* p = os_malloc(sizeof(jsmn_parser)); + //jsmntok_t t[128]; /* We expect no more than 128 tokens */ #define TOKEN_COUNT 128 - jsmntok_t *t = os_malloc(sizeof(jsmntok_t)*TOKEN_COUNT); - char *json_str = request->bodystart; - int json_len = strlen(json_str); + jsmntok_t* t = os_malloc(sizeof(jsmntok_t) * TOKEN_COUNT); + char* json_str = request->bodystart; + int json_len = strlen(json_str); memset(p, 0, sizeof(jsmn_parser)); - memset(t, 0, sizeof(jsmntok_t)*TOKEN_COUNT); + memset(t, 0, sizeof(jsmntok_t) * TOKEN_COUNT); - jsmn_init(p); - r = jsmn_parse(p, json_str, json_len, t, TOKEN_COUNT); - if (r < 0) { - ADDLOG_ERROR(LOG_FEATURE_API, "Failed to parse JSON: %d", r); - sprintf(tmp,"Failed to parse JSON: %d\n", r); - os_free(p); - os_free(t); - return http_rest_error(request, 400, tmp); - } + jsmn_init(p); + r = jsmn_parse(p, json_str, json_len, t, TOKEN_COUNT); + if (r < 0) { + ADDLOG_ERROR(LOG_FEATURE_API, "Failed to parse JSON: %d", r); + sprintf(tmp, "Failed to parse JSON: %d\n", r); + os_free(p); + os_free(t); + return http_rest_error(request, 400, tmp); + } - /* Assume the top-level element is an object */ - if (r < 1 || t[0].type != JSMN_OBJECT) { - ADDLOG_ERROR(LOG_FEATURE_API, "Object expected", r); - sprintf(tmp,"Object expected\n"); - os_free(p); - os_free(t); - return http_rest_error(request, 400, tmp); - } + /* Assume the top-level element is an object */ + if (r < 1 || t[0].type != JSMN_OBJECT) { + ADDLOG_ERROR(LOG_FEATURE_API, "Object expected", r); + sprintf(tmp, "Object expected\n"); + os_free(p); + os_free(t); + return http_rest_error(request, 400, tmp); + } - /* Loop over all keys of the root object */ - for (i = 1; i < r; i++) { - if (tryGetTokenString(json_str, &t[i], tokenStrValue) != true){ - ADDLOG_DEBUG(LOG_FEATURE_API, "Parsing failed"); - continue; - } - //ADDLOG_DEBUG(LOG_FEATURE_API, "parsed %s", tokenStrValue); + /* Loop over all keys of the root object */ + for (i = 1; i < r; i++) { + if (tryGetTokenString(json_str, &t[i], tokenStrValue) != true) { + ADDLOG_DEBUG(LOG_FEATURE_API, "Parsing failed"); + continue; + } + //ADDLOG_DEBUG(LOG_FEATURE_API, "parsed %s", tokenStrValue); - if (strcmp(tokenStrValue, "roles") == 0) { - int j; - if (t[i + 1].type != JSMN_ARRAY) { - continue; /* We expect groups to be an array of strings */ - } - for (j = 0; j < t[i + 1].size; j++) { - int roleval, pr; - jsmntok_t *g = &t[i + j + 2]; - roleval = atoi(json_str + g->start); + if (strcmp(tokenStrValue, "roles") == 0) { + int j; + if (t[i + 1].type != JSMN_ARRAY) { + continue; /* We expect groups to be an array of strings */ + } + for (j = 0; j < t[i + 1].size; j++) { + int roleval, pr; + jsmntok_t* g = &t[i + j + 2]; + roleval = atoi(json_str + g->start); pr = PIN_GetPinRoleForPinIndex(j); - if(pr != roleval) { - PIN_SetPinRoleForPinIndex(j,roleval); + if (pr != roleval) { + PIN_SetPinRoleForPinIndex(j, roleval); iChanged++; } - } - i += t[i + 1].size + 1; - } else if (strcmp(tokenStrValue, "channels") == 0) { - int j; - if (t[i + 1].type != JSMN_ARRAY) { - continue; /* We expect groups to be an array of strings */ - } - for (j = 0; j < t[i + 1].size; j++) { - int chanval, pr; - jsmntok_t *g = &t[i + j + 2]; - chanval = atoi(json_str + g->start); + } + i += t[i + 1].size + 1; + } + else if (strcmp(tokenStrValue, "channels") == 0) { + int j; + if (t[i + 1].type != JSMN_ARRAY) { + continue; /* We expect groups to be an array of strings */ + } + for (j = 0; j < t[i + 1].size; j++) { + int chanval, pr; + jsmntok_t* g = &t[i + j + 2]; + chanval = atoi(json_str + g->start); pr = PIN_GetPinChannelForPinIndex(j); - if(pr != chanval) { - PIN_SetPinChannelForPinIndex(j,chanval); + if (pr != chanval) { + PIN_SetPinChannelForPinIndex(j, chanval); iChanged++; } - } - i += t[i + 1].size + 1; - } else if (strcmp(tokenStrValue, "deviceFlag") == 0) { - jsmntok_t *flagTok = &t[i + 1]; - if (flagTok == NULL || flagTok->type != JSMN_PRIMITIVE){ - continue; - } + } + i += t[i + 1].size + 1; + } + else if (strcmp(tokenStrValue, "deviceFlag") == 0) { + jsmntok_t* flagTok = &t[i + 1]; + if (flagTok == NULL || flagTok->type != JSMN_PRIMITIVE) { + continue; + } - int flag = atoi(json_str + flagTok->start); - ADDLOG_DEBUG(LOG_FEATURE_API, "received deviceFlag %d", flag); + int flag = atoi(json_str + flagTok->start); + ADDLOG_DEBUG(LOG_FEATURE_API, "received deviceFlag %d", flag); - if (flag >= 0 && flag <= 10){ - CFG_SetFlag(flag, true); - iChanged++; - } + if (flag >= 0 && flag <= 10) { + CFG_SetFlag(flag, true); + iChanged++; + } - i += t[i + 1].size + 1; - } else if (strcmp(tokenStrValue, "deviceCommand") == 0) { - if (tryGetTokenString(json_str, &t[i + 1], tokenStrValue) == true){ - ADDLOG_DEBUG(LOG_FEATURE_API, "received deviceCommand %s", tokenStrValue); - CFG_SetShortStartupCommand_AndExecuteNow(tokenStrValue); - iChanged++; - } + i += t[i + 1].size + 1; + } + else if (strcmp(tokenStrValue, "deviceCommand") == 0) { + if (tryGetTokenString(json_str, &t[i + 1], tokenStrValue) == true) { + ADDLOG_DEBUG(LOG_FEATURE_API, "received deviceCommand %s", tokenStrValue); + CFG_SetShortStartupCommand_AndExecuteNow(tokenStrValue); + iChanged++; + } - i += t[i + 1].size + 1; - } else { - ADDLOG_ERROR(LOG_FEATURE_API, "Unexpected key: %.*s", t[i].end - t[i].start, - json_str + t[i].start); - } - } - if (iChanged){ + i += t[i + 1].size + 1; + } + else { + ADDLOG_ERROR(LOG_FEATURE_API, "Unexpected key: %.*s", t[i].end - t[i].start, + json_str + t[i].start); + } + } + if (iChanged) { CFG_Save_SetupTimer(); - ADDLOG_DEBUG(LOG_FEATURE_API, "Changed %d - saved to flash", iChanged); - } + ADDLOG_DEBUG(LOG_FEATURE_API, "Changed %d - saved to flash", iChanged); + } - os_free(p); - os_free(t); - return http_rest_error(request, 200, "OK"); - return 0; + os_free(p); + os_free(t); + return http_rest_error(request, 200, "OK"); + return 0; } -static int http_rest_error(http_request_t *request, int code, char *msg){ - request->responseCode = code; - http_setup(request, httpMimeTypeJson); - if (code != 200){ - hprintf128(request, "{\"error\":%d, \"msg\":\"%s\"}", code, msg); - } else { - hprintf128(request, "{\"success\":%d, \"msg\":\"%s\"}", code, msg); - } - poststr(request,NULL); - return 0; +static int http_rest_error(http_request_t* request, int code, char* msg) { + request->responseCode = code; + http_setup(request, httpMimeTypeJson); + if (code != 200) { + hprintf128(request, "{\"error\":%d, \"msg\":\"%s\"}", code, msg); + } + else { + hprintf128(request, "{\"success\":%d, \"msg\":\"%s\"}", code, msg); + } + poststr(request, NULL); + return 0; } -static int http_rest_post_flash(http_request_t *request, int startaddr){ +static int http_rest_post_flash(http_request_t* request, int startaddr) { #if PLATFORM_XR809 #elif PLATFORM_BL602 @@ -855,125 +874,125 @@ static int http_rest_post_flash(http_request_t *request, int startaddr){ #elif PLATFORM_W600 || PLATFORM_W800 #else - int total = 0; - int towrite; - char *writebuf; - int writelen; + int total = 0; + int towrite; + char* writebuf; + int writelen; - ADDLOG_DEBUG(LOG_FEATURE_API, "OTA post len %d", request->contentLength); + ADDLOG_DEBUG(LOG_FEATURE_API, "OTA post len %d", request->contentLength); - init_ota(startaddr); + init_ota(startaddr); - towrite = request->bodylen; - writebuf = request->bodystart; - writelen = request->bodylen; - if (request->contentLength >= 0){ - towrite = request->contentLength; - } + towrite = request->bodylen; + writebuf = request->bodystart; + writelen = request->bodylen; + if (request->contentLength >= 0) { + towrite = request->contentLength; + } - if (writelen < 0 || (startaddr + writelen > 0x200000)){ - ADDLOG_DEBUG(LOG_FEATURE_API, "ABORTED: %d bytes to write", writelen); - return http_rest_error(request, -20, "writelen < 0 or end > 0x200000"); - } + if (writelen < 0 || (startaddr + writelen > 0x200000)) { + ADDLOG_DEBUG(LOG_FEATURE_API, "ABORTED: %d bytes to write", writelen); + return http_rest_error(request, -20, "writelen < 0 or end > 0x200000"); + } - do { - //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes to write", writelen); - add_otadata((unsigned char *)writebuf, writelen); - total += writelen; - towrite -= writelen; - if (towrite > 0){ - writebuf = request->received; - writelen = recv(request->fd, writebuf, request->receivedLenmax, 0); - if (writelen < 0){ - ADDLOG_DEBUG(LOG_FEATURE_API, "recv returned %d - end of data - remaining %d", writelen, towrite); - } - } - } while ((towrite > 0) && (writelen >= 0)); - ADDLOG_DEBUG(LOG_FEATURE_API, "%d total bytes written", total); - http_setup(request, httpMimeTypeJson); - hprintf128(request, "{\"size\":%d}", total); - close_ota(); + do { + //ADDLOG_DEBUG(LOG_FEATURE_API, "%d bytes to write", writelen); + add_otadata((unsigned char*)writebuf, writelen); + total += writelen; + towrite -= writelen; + if (towrite > 0) { + writebuf = request->received; + writelen = recv(request->fd, writebuf, request->receivedLenmax, 0); + if (writelen < 0) { + ADDLOG_DEBUG(LOG_FEATURE_API, "recv returned %d - end of data - remaining %d", writelen, towrite); + } + } + } while ((towrite > 0) && (writelen >= 0)); + ADDLOG_DEBUG(LOG_FEATURE_API, "%d total bytes written", total); + http_setup(request, httpMimeTypeJson); + hprintf128(request, "{\"size\":%d}", total); + close_ota(); - poststr(request,NULL); + poststr(request, NULL); #endif - return 0; + return 0; } -static int http_rest_post_reboot(http_request_t *request){ - http_setup(request, httpMimeTypeJson); - hprintf128(request, "{\"reboot\":%d}", 3); - ADDLOG_DEBUG(LOG_FEATURE_API, "Rebooting in 3 seconds..."); +static int http_rest_post_reboot(http_request_t* request) { + http_setup(request, httpMimeTypeJson); + hprintf128(request, "{\"reboot\":%d}", 3); + ADDLOG_DEBUG(LOG_FEATURE_API, "Rebooting in 3 seconds..."); RESET_ScheduleModuleReset(3); - poststr(request,NULL); - return 0; + poststr(request, NULL); + return 0; } -static int http_rest_get_flash_advanced(http_request_t *request){ - char *params = request->url + 10; - int startaddr = 0; - int len = 0; - int sres; - sres = sscanf(params, "%x-%x", &startaddr, &len); - if (sres == 2) { - return http_rest_get_flash(request, startaddr, len); - } - return http_rest_error(request, -1, "invalid url"); +static int http_rest_get_flash_advanced(http_request_t* request) { + char* params = request->url + 10; + int startaddr = 0; + int len = 0; + int sres; + sres = sscanf(params, "%x-%x", &startaddr, &len); + if (sres == 2) { + return http_rest_get_flash(request, startaddr, len); + } + return http_rest_error(request, -1, "invalid url"); } -static int http_rest_post_flash_advanced(http_request_t *request){ - char *params = request->url + 10; - int startaddr = 0; - int sres; - sres = sscanf(params, "%x", &startaddr); - if (sres == 1 && startaddr >= START_ADR_OF_BK_PARTITION_OTA){ - return http_rest_post_flash(request, startaddr); - } - return http_rest_error(request, -1, "invalid url"); +static int http_rest_post_flash_advanced(http_request_t* request) { + char* params = request->url + 10; + int startaddr = 0; + int sres; + sres = sscanf(params, "%x", &startaddr); + if (sres == 1 && startaddr >= START_ADR_OF_BK_PARTITION_OTA) { + return http_rest_post_flash(request, startaddr); + } + return http_rest_error(request, -1, "invalid url"); } -static int http_rest_get_flash(http_request_t *request, int startaddr, int len){ - char *buffer; - int res; +static int http_rest_get_flash(http_request_t* request, int startaddr, int len) { + char* buffer; + int res; - if (startaddr < 0 || (startaddr + len > 0x200000)){ - return http_rest_error(request, -1, "requested flash read out of range"); - } + if (startaddr < 0 || (startaddr + len > 0x200000)) { + return http_rest_error(request, -1, "requested flash read out of range"); + } - buffer = os_malloc(1024); + buffer = os_malloc(1024); - http_setup(request, httpMimeTypeBinary); - while(len){ - int readlen = len; - if (readlen > 1024){ - readlen = 1024; - } + http_setup(request, httpMimeTypeBinary); + while (len) { + int readlen = len; + if (readlen > 1024) { + readlen = 1024; + } #if PLATFORM_XR809 - //uint32_t flash_read(uint32_t flash, uint32_t addr,void *buf, uint32_t size) - #define FLASH_INDEX_XR809 0 - res = flash_read(FLASH_INDEX_XR809, startaddr, buffer, readlen); + //uint32_t flash_read(uint32_t flash, uint32_t addr,void *buf, uint32_t size) +#define FLASH_INDEX_XR809 0 + res = flash_read(FLASH_INDEX_XR809, startaddr, buffer, readlen); #elif PLATFORM_BL602 res = 0; #elif PLATFORM_W600 || PLATFORM_W800 res = 0; #else - res = flash_read((char *)buffer, readlen, startaddr); + res = flash_read((char*)buffer, readlen, startaddr); #endif - startaddr += readlen; - len -= readlen; - postany(request, buffer, readlen); - } - poststr(request, NULL); - return 0; + startaddr += readlen; + len -= readlen; + postany(request, buffer, readlen); + } + poststr(request, NULL); + return 0; } -static int http_rest_get_dumpconfig(http_request_t *request){ +static int http_rest_get_dumpconfig(http_request_t* request) { - http_setup(request, httpMimeTypeText); - poststr(request, NULL); - return 0; + http_setup(request, httpMimeTypeText); + poststr(request, NULL); + return 0; } @@ -984,151 +1003,151 @@ typedef struct item_new_test_config { INFO_ITEM_ST head; char somename[64]; -}ITEM_NEW_TEST_CONFIG,*ITEM_NEW_TEST_CONFIG_PTR; +}ITEM_NEW_TEST_CONFIG, * ITEM_NEW_TEST_CONFIG_PTR; ITEM_NEW_TEST_CONFIG testconfig; #endif -static int http_rest_get_testconfig(http_request_t *request){ - return http_rest_error(request, 400, "unsupported"); - return 0; +static int http_rest_get_testconfig(http_request_t* request) { + return http_rest_error(request, 400, "unsupported"); + return 0; } -static int http_rest_get_flash_vars_test(http_request_t *request){ -//#if PLATFORM_XR809 -// return http_rest_error(request, 400, "flash vars unsupported"); -//#elif PLATFORM_BL602 -// return http_rest_error(request, 400, "flash vars unsupported"); -//#else -//#ifndef DISABLE_FLASH_VARS_VARS -// char *params = request->url + 17; -// int increment = 0; -// int len = 0; -// int sres; -// int i; -// char tmp[128]; -// FLASH_VARS_STRUCTURE data, *p; -// -// p = &flash_vars; -// -// sres = sscanf(params, "%x-%x", &increment, &len); -// -// ADDLOG_DEBUG(LOG_FEATURE_API, "http_rest_get_flash_vars_test %d %d returned %d", increment, len, sres); -// -// if (increment == 10){ -// flash_vars_read(&data); -// p = &data; -// } else { -// for (i = 0; i < increment; i++){ -// HAL_FlashVars_IncreaseBootCount(); -// } -// for (i = 0; i < len; i++){ -// HAL_FlashVars_SaveBootComplete(); -// } -// } -// -// sprintf(tmp, "offset %d, boot count %d, boot success %d, bootfailures %d", -// flash_vars_offset, -// p->boot_count, -// p->boot_success_count, -// p->boot_count - p->boot_success_count ); -// -// return http_rest_error(request, 200, tmp); -//#else - return http_rest_error(request, 400, "flash test unsupported"); +static int http_rest_get_flash_vars_test(http_request_t* request) { + //#if PLATFORM_XR809 + // return http_rest_error(request, 400, "flash vars unsupported"); + //#elif PLATFORM_BL602 + // return http_rest_error(request, 400, "flash vars unsupported"); + //#else + //#ifndef DISABLE_FLASH_VARS_VARS + // char *params = request->url + 17; + // int increment = 0; + // int len = 0; + // int sres; + // int i; + // char tmp[128]; + // FLASH_VARS_STRUCTURE data, *p; + // + // p = &flash_vars; + // + // sres = sscanf(params, "%x-%x", &increment, &len); + // + // ADDLOG_DEBUG(LOG_FEATURE_API, "http_rest_get_flash_vars_test %d %d returned %d", increment, len, sres); + // + // if (increment == 10){ + // flash_vars_read(&data); + // p = &data; + // } else { + // for (i = 0; i < increment; i++){ + // HAL_FlashVars_IncreaseBootCount(); + // } + // for (i = 0; i < len; i++){ + // HAL_FlashVars_SaveBootComplete(); + // } + // } + // + // sprintf(tmp, "offset %d, boot count %d, boot success %d, bootfailures %d", + // flash_vars_offset, + // p->boot_count, + // p->boot_success_count, + // p->boot_count - p->boot_success_count ); + // + // return http_rest_error(request, 200, tmp); + //#else + return http_rest_error(request, 400, "flash test unsupported"); } -static int http_rest_get_channels(http_request_t *request){ - int i; - int addcomma = 0; - /*typedef struct pinsState_s { - byte roles[32]; - byte channels[32]; - } pinsState_t; +static int http_rest_get_channels(http_request_t* request) { + int i; + int addcomma = 0; + /*typedef struct pinsState_s { + byte roles[32]; + byte channels[32]; + } pinsState_t; - extern pinsState_t g_pins; - */ - http_setup(request, httpMimeTypeJson); - poststr(request, "{"); + extern pinsState_t g_pins; + */ + http_setup(request, httpMimeTypeJson); + poststr(request, "{"); // TODO: maybe we should cull futher channels that are not used? // I support many channels because I plan to use 16x relays module with I2C MCP23017 driver - for (i = 0; i < PLATFORM_GPIO_MAX; i++){ + for (i = 0; i < PLATFORM_GPIO_MAX; i++) { // "i" is a pin index // Get channel index and role - int ch = PIN_GetPinChannelForPinIndex(i); - int role = PIN_GetPinRoleForPinIndex(i); - if (role){ - if (addcomma){ - hprintf128(request, ","); - } - hprintf128(request, "\"%d\":%d", ch, CHANNEL_Get(ch)); - addcomma = 1; - } - } - poststr(request, "}"); - poststr(request, NULL); - return 0; + int ch = PIN_GetPinChannelForPinIndex(i); + int role = PIN_GetPinRoleForPinIndex(i); + if (role) { + if (addcomma) { + hprintf128(request, ","); + } + hprintf128(request, "\"%d\":%d", ch, CHANNEL_Get(ch)); + addcomma = 1; + } + } + poststr(request, "}"); + poststr(request, NULL); + return 0; } // currently crashes the MCU - maybe stack overflow? -static int http_rest_post_channels(http_request_t *request){ - int i; - int r; - char tmp[64]; +static int http_rest_post_channels(http_request_t* request) { + int i; + int r; + char tmp[64]; - //https://github.com/zserge/jsmn/blob/master/example/simple.c - //jsmn_parser p; - jsmn_parser *p = os_malloc(sizeof(jsmn_parser)); - //jsmntok_t t[128]; /* We expect no more than 128 tokens */ + //https://github.com/zserge/jsmn/blob/master/example/simple.c + //jsmn_parser p; + jsmn_parser* p = os_malloc(sizeof(jsmn_parser)); + //jsmntok_t t[128]; /* We expect no more than 128 tokens */ #define TOKEN_COUNT 128 - jsmntok_t *t = os_malloc(sizeof(jsmntok_t)*TOKEN_COUNT); - char *json_str = request->bodystart; - int json_len = strlen(json_str); + jsmntok_t* t = os_malloc(sizeof(jsmntok_t) * TOKEN_COUNT); + char* json_str = request->bodystart; + int json_len = strlen(json_str); memset(p, 0, sizeof(jsmn_parser)); - memset(t, 0, sizeof(jsmntok_t)*128); + memset(t, 0, sizeof(jsmntok_t) * 128); - jsmn_init(p); - r = jsmn_parse(p, json_str, json_len, t, TOKEN_COUNT); - if (r < 0) { - ADDLOG_ERROR(LOG_FEATURE_API, "Failed to parse JSON: %d", r); - sprintf(tmp,"Failed to parse JSON: %d\n", r); - os_free(p); - os_free(t); - return http_rest_error(request, 400, tmp); - } + jsmn_init(p); + r = jsmn_parse(p, json_str, json_len, t, TOKEN_COUNT); + if (r < 0) { + ADDLOG_ERROR(LOG_FEATURE_API, "Failed to parse JSON: %d", r); + sprintf(tmp, "Failed to parse JSON: %d\n", r); + os_free(p); + os_free(t); + return http_rest_error(request, 400, tmp); + } - /* Assume the top-level element is an object */ - if (r < 1 || t[0].type != JSMN_ARRAY) { - ADDLOG_ERROR(LOG_FEATURE_API, "Array expected", r); - sprintf(tmp,"Object expected\n"); - os_free(p); - os_free(t); - return http_rest_error(request, 400, tmp); - } + /* Assume the top-level element is an object */ + if (r < 1 || t[0].type != JSMN_ARRAY) { + ADDLOG_ERROR(LOG_FEATURE_API, "Array expected", r); + sprintf(tmp, "Object expected\n"); + os_free(p); + os_free(t); + return http_rest_error(request, 400, tmp); + } - /* Loop over all keys of the root object */ - for (i = 1; i < r; i++) { - int chanval; - jsmntok_t *g = &t[i]; - chanval = atoi(json_str + g->start); - CHANNEL_Set(i-1, chanval, 0); - ADDLOG_DEBUG(LOG_FEATURE_API, "Set of chan %d to %d", i, - chanval); - } + /* Loop over all keys of the root object */ + for (i = 1; i < r; i++) { + int chanval; + jsmntok_t* g = &t[i]; + chanval = atoi(json_str + g->start); + CHANNEL_Set(i - 1, chanval, 0); + ADDLOG_DEBUG(LOG_FEATURE_API, "Set of chan %d to %d", i, + chanval); + } - os_free(p); - os_free(t); - return http_rest_error(request, 200, "OK"); - return 0; + os_free(p); + os_free(t); + return http_rest_error(request, 200, "OK"); + return 0; } -static int http_rest_post_cmd(http_request_t *request){ - char *cmd = request->bodystart; +static int http_rest_post_cmd(http_request_t* request) { + char* cmd = request->bodystart; CMD_ExecuteCommand(cmd, COMMAND_FLAG_SOURCE_CONSOLE); - return http_rest_error(request, 200, "OK"); + return http_rest_error(request, 200, "OK"); } diff --git a/src/mqtt/new_mqtt.c b/src/mqtt/new_mqtt.c index 090cdf8d9..69c036a1c 100644 --- a/src/mqtt/new_mqtt.c +++ b/src/mqtt/new_mqtt.c @@ -18,37 +18,37 @@ #endif #endif -int wal_stricmp(const char *a, const char *b) { - int ca, cb; - do { - ca = (unsigned char) *a++; - cb = (unsigned char) *b++; - ca = tolower(toupper(ca)); - cb = tolower(toupper(cb)); - } while ((ca == cb) && (ca != '\0')); - return ca - cb; +int wal_stricmp(const char* a, const char* b) { + int ca, cb; + do { + ca = (unsigned char)*a++; + cb = (unsigned char)*b++; + ca = tolower(toupper(ca)); + cb = tolower(toupper(cb)); + } while ((ca == cb) && (ca != '\0')); + return ca - cb; } -int wal_strnicmp(const char *a, const char *b, int count) { - int ca, cb; - do { - ca = (unsigned char) *a++; - cb = (unsigned char) *b++; - ca = tolower(toupper(ca)); - cb = tolower(toupper(cb)); - count--; - } while ((ca == cb) && (ca != '\0') && (count > 0)); - return ca - cb; +int wal_strnicmp(const char* a, const char* b, int count) { + int ca, cb; + do { + ca = (unsigned char)*a++; + cb = (unsigned char)*b++; + ca = tolower(toupper(ca)); + cb = tolower(toupper(cb)); + count--; + } while ((ca == cb) && (ca != '\0') && (count > 0)); + return ca - cb; } #define MQTT_QUEUE_ITEM_IS_REUSABLE(x) (x->topic[0] == 0) #define MQTT_QUEUE_ITEM_SET_REUSABLE(x) (x->topic[0] = 0) -MqttPublishItem_t *g_MqttPublishQueueHead = NULL; +MqttPublishItem_t* g_MqttPublishQueueHead = NULL; int g_MqttPublishItemsQueued = 0; //Items in the queue waiting to be published. This is not the queue length. OBK_Publish_Result PublishQueuedItems(); // from mqtt.c -extern void mqtt_disconnect(mqtt_client_t *client); +extern void mqtt_disconnect(mqtt_client_t* client); static int g_my_reconnect_mqtt_after_time = -1; ip_addr_t mqtt_ip LWIP_MQTT_EXAMPLE_IPADDR_INIT; @@ -63,14 +63,14 @@ static int mqtt_publish_errors = 0; static int mqtt_received_events = 0; typedef struct mqtt_callback_tag { - char *topic; - char *subscriptionTopic; - int ID; - mqtt_callback_fn callback; + char* topic; + char* subscriptionTopic; + int ID; + mqtt_callback_fn callback; } mqtt_callback_t; #define MAX_MQTT_CALLBACKS 32 -static mqtt_callback_t *callbacks[MAX_MQTT_CALLBACKS]; +static mqtt_callback_t* callbacks[MAX_MQTT_CALLBACKS]; static int numCallbacks = 0; // note: only one incomming can be processed at a time. static mqtt_request_t g_mqtt_request; @@ -113,44 +113,45 @@ static SemaphoreHandle_t g_mutex = 0; static bool MQTT_Mutex_Take(int del) { int taken; - if(g_mutex == 0) + if (g_mutex == 0) { - g_mutex = xSemaphoreCreateMutex( ); + g_mutex = xSemaphoreCreateMutex(); } - taken = xSemaphoreTake( g_mutex, del ); - if (taken == pdTRUE) { + taken = xSemaphoreTake(g_mutex, del); + if (taken == pdTRUE) { return true; } return false; } -static void MQTT_Mutex_Free() +static void MQTT_Mutex_Free() { - xSemaphoreGive( g_mutex ); + xSemaphoreGive(g_mutex); } -void MQTT_PublishWholeDeviceState_Internal(bool bAll) +void MQTT_PublishWholeDeviceState_Internal(bool bAll) { - g_bPublishAllStatesNow = 1; - if(bAll) { - g_publishItemIndex = PUBLISHITEM_ALL_INDEX_FIRST; - } else { - g_publishItemIndex = PUBLISHITEM_DYNAMIC_INDEX_FIRST; - } + g_bPublishAllStatesNow = 1; + if (bAll) { + g_publishItemIndex = PUBLISHITEM_ALL_INDEX_FIRST; + } + else { + g_publishItemIndex = PUBLISHITEM_DYNAMIC_INDEX_FIRST; + } } -void MQTT_PublishWholeDeviceState() +void MQTT_PublishWholeDeviceState() { - //Publish all status items once. Publish only dynamic items after that. + //Publish all status items once. Publish only dynamic items after that. MQTT_PublishWholeDeviceState_Internal(g_firstFullBroadcast); } -void MQTT_PublishOnlyDeviceChannelsIfPossible() +void MQTT_PublishOnlyDeviceChannelsIfPossible() { - if(g_bPublishAllStatesNow == 1) - return; - g_bPublishAllStatesNow = 1; - //Start with channels - g_publishItemIndex = 0; + if (g_bPublishAllStatesNow == 1) + return; + g_bPublishAllStatesNow = 1; + //Start with channels + g_publishItemIndex = 0; } static struct mqtt_connect_client_info_t mqtt_client_info = @@ -171,292 +172,293 @@ static struct mqtt_connect_client_info_t mqtt_client_info = // channel set callback int channelSet(mqtt_request_t* request); -static void MQTT_do_connect(mqtt_client_t *client); -static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status); +static void MQTT_do_connect(mqtt_client_t* client); +static void mqtt_connection_cb(mqtt_client_t* client, void* arg, mqtt_connection_status_t status); int MQTT_GetConnectEvents(void) { - return mqtt_connect_events; + return mqtt_connect_events; } int MQTT_GetPublishEventCounter(void) { - return mqtt_published_events; + return mqtt_published_events; } int MQTT_GetPublishErrorCounter(void) { - return mqtt_publish_errors; + return mqtt_publish_errors; } int MQTT_GetReceivedEventCounter(void) { - return mqtt_received_events; + return mqtt_received_events; } int MQTT_GetConnectResult(void) { - return mqtt_connect_result; + return mqtt_connect_result; } -const char *get_error_name(int err) +const char* get_error_name(int err) { - switch(err) - { - case ERR_OK: return "ERR_OK"; - case ERR_MEM: return "ERR_MEM"; - /** Buffer error. */ - case ERR_BUF: return "ERR_BUF"; - /** Timeout. */ - case ERR_TIMEOUT: return "ERR_TIMEOUT"; - /** Routing problem. */ - case ERR_RTE: return "ERR_RTE"; - /** Operation in progress */ - case ERR_INPROGRESS: return "ERR_INPROGRESS"; - /** Illegal value. */ - case ERR_VAL: return "ERR_VAL"; - /** Operation would block. */ - case ERR_WOULDBLOCK: return "ERR_WOULDBLOCK"; - /** Address in use. */ - case ERR_USE: return "ERR_USE"; - #if defined(ERR_ALREADY) - /** Already connecting. */ - case ERR_ALREADY: return "ERR_ALREADY"; - #endif - /** Conn already established.*/ - case ERR_ISCONN: return "ERR_ISCONN"; - /** Not connected. */ - case ERR_CONN: return "ERR_CONN"; - /** Low-level netif error */ - case ERR_IF: return "ERR_IF"; - /** Connection aborted. */ - case ERR_ABRT: return "ERR_ABRT"; - /** Connection reset. */ - case ERR_RST: return "ERR_RST"; - /** Connection closed. */ - case ERR_CLSD: return "ERR_CLSD"; - /** Illegal argument. */ - case ERR_ARG: return "ERR_ARG"; - } - return ""; + switch (err) + { + case ERR_OK: return "ERR_OK"; + case ERR_MEM: return "ERR_MEM"; + /** Buffer error. */ + case ERR_BUF: return "ERR_BUF"; + /** Timeout. */ + case ERR_TIMEOUT: return "ERR_TIMEOUT"; + /** Routing problem. */ + case ERR_RTE: return "ERR_RTE"; + /** Operation in progress */ + case ERR_INPROGRESS: return "ERR_INPROGRESS"; + /** Illegal value. */ + case ERR_VAL: return "ERR_VAL"; + /** Operation would block. */ + case ERR_WOULDBLOCK: return "ERR_WOULDBLOCK"; + /** Address in use. */ + case ERR_USE: return "ERR_USE"; +#if defined(ERR_ALREADY) + /** Already connecting. */ + case ERR_ALREADY: return "ERR_ALREADY"; +#endif + /** Conn already established.*/ + case ERR_ISCONN: return "ERR_ISCONN"; + /** Not connected. */ + case ERR_CONN: return "ERR_CONN"; + /** Low-level netif error */ + case ERR_IF: return "ERR_IF"; + /** Connection aborted. */ + case ERR_ABRT: return "ERR_ABRT"; + /** Connection reset. */ + case ERR_RST: return "ERR_RST"; + /** Connection closed. */ + case ERR_CLSD: return "ERR_CLSD"; + /** Illegal argument. */ + case ERR_ARG: return "ERR_ARG"; + } + return ""; } -char *MQTT_GetStatusMessage(void) +char* MQTT_GetStatusMessage(void) { - return mqtt_status_message; + return mqtt_status_message; } // this can REPLACE callbacks, since we MAY wish to change the root topic.... // in which case we would re-resigster all callbacks? -int MQTT_RegisterCallback( const char *basetopic, const char *subscriptiontopic, int ID, mqtt_callback_fn callback){ - int index; - int i; - int subscribechange = 0; - if (!basetopic || !subscriptiontopic || !callback){ +int MQTT_RegisterCallback(const char* basetopic, const char* subscriptiontopic, int ID, mqtt_callback_fn callback) { + int index; + int i; + int subscribechange = 0; + if (!basetopic || !subscriptiontopic || !callback) { return -1; } - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT_RegisterCallback called for bT %s subT %s", basetopic, subscriptiontopic); + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "MQTT_RegisterCallback called for bT %s subT %s", basetopic, subscriptiontopic); - // find existing to replace - for (index = 0; index < numCallbacks; index++){ - if (callbacks[index]){ - if (callbacks[index]->ID == ID){ - break; - } - } - } + // find existing to replace + for (index = 0; index < numCallbacks; index++) { + if (callbacks[index]) { + if (callbacks[index]->ID == ID) { + break; + } + } + } - // find empty if any (empty by MQTT_RemoveCallback) - if (index == numCallbacks){ - for (index = 0; index < numCallbacks; index++){ - if (!callbacks[index]){ - break; - } - } - } + // find empty if any (empty by MQTT_RemoveCallback) + if (index == numCallbacks) { + for (index = 0; index < numCallbacks; index++) { + if (!callbacks[index]) { + break; + } + } + } - if (index >= MAX_MQTT_CALLBACKS){ + if (index >= MAX_MQTT_CALLBACKS) { return -4; } - if (!callbacks[index]){ - callbacks[index] = (mqtt_callback_t*)os_malloc(sizeof(mqtt_callback_t)); - if(callbacks[index]!=0) { - memset(callbacks[index],0,sizeof(mqtt_callback_t)); - } - } - if (!callbacks[index]){ + if (!callbacks[index]) { + callbacks[index] = (mqtt_callback_t*)os_malloc(sizeof(mqtt_callback_t)); + if (callbacks[index] != 0) { + memset(callbacks[index], 0, sizeof(mqtt_callback_t)); + } + } + if (!callbacks[index]) { return -2; } - if (!callbacks[index]->topic || strcmp(callbacks[index]->topic, basetopic)){ - if (callbacks[index]->topic){ - os_free(callbacks[index]->topic); - } - callbacks[index]->topic = (char *)os_malloc(strlen(basetopic)+1); - if (!callbacks[index]->topic){ - os_free(callbacks[index]); - return -3; - } - strcpy(callbacks[index]->topic, basetopic); - } + if (!callbacks[index]->topic || strcmp(callbacks[index]->topic, basetopic)) { + if (callbacks[index]->topic) { + os_free(callbacks[index]->topic); + } + callbacks[index]->topic = (char*)os_malloc(strlen(basetopic) + 1); + if (!callbacks[index]->topic) { + os_free(callbacks[index]); + return -3; + } + strcpy(callbacks[index]->topic, basetopic); + } - if (!callbacks[index]->subscriptionTopic || strcmp(callbacks[index]->subscriptionTopic, subscriptiontopic)){ - if (callbacks[index]->subscriptionTopic){ - os_free(callbacks[index]->subscriptionTopic); - } - callbacks[index]->subscriptionTopic = (char *)os_malloc(strlen(subscriptiontopic)+1); - callbacks[index]->subscriptionTopic[0] = '\0'; - if (!callbacks[index]->subscriptionTopic){ - os_free(callbacks[index]->topic); - os_free(callbacks[index]); - return -3; - } + if (!callbacks[index]->subscriptionTopic || strcmp(callbacks[index]->subscriptionTopic, subscriptiontopic)) { + if (callbacks[index]->subscriptionTopic) { + os_free(callbacks[index]->subscriptionTopic); + } + callbacks[index]->subscriptionTopic = (char*)os_malloc(strlen(subscriptiontopic) + 1); + callbacks[index]->subscriptionTopic[0] = '\0'; + if (!callbacks[index]->subscriptionTopic) { + os_free(callbacks[index]->topic); + os_free(callbacks[index]); + return -3; + } - // find out if this subscription is new. - for (i = 0; i < numCallbacks; i++){ - if (callbacks[i]){ - if (callbacks[i]->subscriptionTopic && - !strcmp(callbacks[i]->subscriptionTopic, subscriptiontopic)){ - break; - } - } - } - strcpy(callbacks[index]->subscriptionTopic, subscriptiontopic); - // if this subscription is new, must reconnect - if (i == numCallbacks){ - subscribechange++; - } - } + // find out if this subscription is new. + for (i = 0; i < numCallbacks; i++) { + if (callbacks[i]) { + if (callbacks[i]->subscriptionTopic && + !strcmp(callbacks[i]->subscriptionTopic, subscriptiontopic)) { + break; + } + } + } + strcpy(callbacks[index]->subscriptionTopic, subscriptiontopic); + // if this subscription is new, must reconnect + if (i == numCallbacks) { + subscribechange++; + } + } callbacks[index]->callback = callback; - if (index == numCallbacks){ - numCallbacks++; - } + if (index == numCallbacks) { + numCallbacks++; + } - if (subscribechange){ - mqtt_reconnect = 8; - } + if (subscribechange) { + mqtt_reconnect = 8; + } // success return 0; } -int MQTT_RemoveCallback(int ID){ - int index; +int MQTT_RemoveCallback(int ID) { + int index; - for (index = 0; index < numCallbacks; index++){ - if (callbacks[index]){ - if (callbacks[index]->ID == ID){ - if (callbacks[index]->topic) { - os_free(callbacks[index]->topic); - callbacks[index]->topic = NULL; - } - if (callbacks[index]->subscriptionTopic) { - os_free(callbacks[index]->subscriptionTopic); - callbacks[index]->subscriptionTopic = NULL; - } - os_free(callbacks[index]); - callbacks[index] = NULL; - mqtt_reconnect = 8; - return 1; - } - } - } - return 0; + for (index = 0; index < numCallbacks; index++) { + if (callbacks[index]) { + if (callbacks[index]->ID == ID) { + if (callbacks[index]->topic) { + os_free(callbacks[index]->topic); + callbacks[index]->topic = NULL; + } + if (callbacks[index]->subscriptionTopic) { + os_free(callbacks[index]->subscriptionTopic); + callbacks[index]->subscriptionTopic = NULL; + } + os_free(callbacks[index]); + callbacks[index] = NULL; + mqtt_reconnect = 8; + return 1; + } + } + } + return 0; } // this accepts obkXXXXXX/<chan>/set to receive data to set channels -int channelSet(mqtt_request_t* request){ - // we only need a few bytes to receive a decimal number 0-100 - char copy[12]; - int len = request->receivedLen; - char *p = request->topic; - int channel = 0; - int iValue = 0; +int channelSet(mqtt_request_t* request) { + // we only need a few bytes to receive a decimal number 0-100 + char copy[12]; + int len = request->receivedLen; + char* p = request->topic; + int channel = 0; + int iValue = 0; - addLogAdv(LOG_DEBUG,LOG_FEATURE_MQTT,"channelSet topic %i with arg %s", request->topic, request->received); + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "channelSet topic %i with arg %s", request->topic, request->received); - // TODO: better - while(*p != '/') { - if(*p == 0) - return 0; - p++; - } - p++; - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"channelSet part topic %s", p); + // TODO: better + while (*p != '/') { + if (*p == 0) + return 0; + p++; + } + p++; + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "channelSet part topic %s", p); - if ((*p - '0' >= 0) && (*p - '0' <= 9)){ - channel = atoi(p); - } else { - channel = -1; - } + if ((*p - '0' >= 0) && (*p - '0' <= 9)) { + channel = atoi(p); + } + else { + channel = -1; + } - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"channelSet channel %i", channel); + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "channelSet channel %i", channel); - // if channel out of range, stop here. - if ((channel < 0) || (channel > 32)){ - return 0; - } + // if channel out of range, stop here. + if ((channel < 0) || (channel > 32)) { + return 0; + } - // find something after channel - should be <base>/<chan>/set - while(*p != '/') { - if(*p == 0) - return 0; - p++; - } - p++; + // find something after channel - should be <base>/<chan>/set + while (*p != '/') { + if (*p == 0) + return 0; + p++; + } + p++; - // if not /set, then stop here - if (strcmp(p, "set")){ - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"channelSet NOT 'set'"); - return 0; - } + // if not /set, then stop here + if (strcmp(p, "set")) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "channelSet NOT 'set'"); + return 0; + } - if(len > sizeof(copy)-1) { - len = sizeof(copy)-1; - } + if (len > sizeof(copy) - 1) { + len = sizeof(copy) - 1; + } - strncpy(copy, (char *)request->received, len); - // strncpy does not terminate??!!!! - copy[len] = '\0'; + strncpy(copy, (char*)request->received, len); + // strncpy does not terminate??!!!! + copy[len] = '\0'; - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT client in mqtt_incoming_data_cb data is %s for ch %i\n", copy, channel); + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "MQTT client in mqtt_incoming_data_cb data is %s for ch %i\n", copy, channel); - iValue = atoi((char *)copy); - CHANNEL_Set(channel,iValue,0); + iValue = atoi((char*)copy); + CHANNEL_Set(channel, iValue, 0); - // return 1 to stop processing callbacks here. - // return 0 to allow later callbacks to process this topic. - return 1; + // return 1 to stop processing callbacks here. + // return 0 to allow later callbacks to process this topic. + return 1; } // this accepts cmnd/<clientId>/<xxx> to receive data to set channels -int tasCmnd(mqtt_request_t* request){ - // we only need a few bytes to receive a decimal number 0-100 - char copy[64]; - int len = request->receivedLen; - const char *p = request->topic; +int tasCmnd(mqtt_request_t* request) { + // we only need a few bytes to receive a decimal number 0-100 + char copy[64]; + int len = request->receivedLen; + const char* p = request->topic; - // assume a string input here, copy and terminate - if(len > sizeof(copy)-1) { - len = sizeof(copy)-1; - } - strncpy(copy, (char *)request->received, len); - // strncpy does not terminate??!!!! - copy[len] = '\0'; + // assume a string input here, copy and terminate + if (len > sizeof(copy) - 1) { + len = sizeof(copy) - 1; + } + strncpy(copy, (char*)request->received, len); + // strncpy does not terminate??!!!! + copy[len] = '\0'; - // TODO: better - // skip to after second forward slash - while(*p != '/') { if(*p == 0) return 0; p++; } - p++; - while(*p != '/') { if(*p == 0) return 0; p++; } - p++; + // TODO: better + // skip to after second forward slash + while (*p != '/') { if (*p == 0) return 0; p++; } + p++; + while (*p != '/') { if (*p == 0) return 0; p++; } + p++; - // use command executor.... - CMD_ExecuteCommandArgs(p, copy, COMMAND_FLAG_SOURCE_MQTT); + // use command executor.... + CMD_ExecuteCommandArgs(p, copy, COMMAND_FLAG_SOURCE_MQTT); - // return 1 to stop processing callbacks here. - // return 0 to allow later callbacks to process this topic. - return 1; + // return 1 to stop processing callbacks here. + // return 0 to allow later callbacks to process this topic. + return 1; } //void MQTT_GetStats(int *outUsed, int *outMax, int *outFreeMem) { @@ -464,103 +466,107 @@ int tasCmnd(mqtt_request_t* request){ //} // copied here because for some reason renames in sdk? -static void MQTT_disconnect(mqtt_client_t *client) +static void MQTT_disconnect(mqtt_client_t* client) { - if (!client) - return; - // this is what it was renamed to. why? - mqtt_disconnect(client); + if (!client) + return; + // this is what it was renamed to. why? + mqtt_disconnect(client); } /* Called when publish is complete either with sucess or failure */ -static void mqtt_pub_request_cb(void *arg, err_t result) +static void mqtt_pub_request_cb(void* arg, err_t result) { - if(result != ERR_OK) - { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Publish result: %d(%s)\n", result, get_error_name(result)); - mqtt_publish_errors++; - } + if (result != ERR_OK) + { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Publish result: %d(%s)\n", result, get_error_name(result)); + mqtt_publish_errors++; + } } // This publishes value to the specified topic/channel. -static OBK_Publish_Result MQTT_PublishTopicToClient(mqtt_client_t *client, const char *sTopic, const char *sChannel, const char *sVal, int flags, bool appendGet) +static OBK_Publish_Result MQTT_PublishTopicToClient(mqtt_client_t* client, const char* sTopic, const char* sChannel, const char* sVal, int flags, bool appendGet) { - err_t err; - u8_t qos = 2; /* 0 1 or 2, see MQTT specification */ - u8_t retain = 0; /* No don't retain such crappy payload... */ + err_t err; + u8_t qos = 2; /* 0 1 or 2, see MQTT specification */ + u8_t retain = 0; /* No don't retain such crappy payload... */ - if(client==0) - return OBK_PUBLISH_WAS_DISCONNECTED; + if (client == 0) + return OBK_PUBLISH_WAS_DISCONNECTED; - - if(flags & OBK_PUBLISH_FLAG_MUTEX_SILENT) - { - if(MQTT_Mutex_Take(100)==0) - { - return OBK_PUBLISH_MUTEX_FAIL; + + if (flags & OBK_PUBLISH_FLAG_MUTEX_SILENT) + { + if (MQTT_Mutex_Take(100) == 0) + { + return OBK_PUBLISH_MUTEX_FAIL; + } } - } else { - if(MQTT_Mutex_Take(500)==0) - { - addLogAdv(LOG_ERROR,LOG_FEATURE_MQTT,"MQTT_PublishTopicToClient: mutex failed for %s=%s\r\n", sChannel, sVal); - return OBK_PUBLISH_MUTEX_FAIL; + else { + if (MQTT_Mutex_Take(500) == 0) + { + addLogAdv(LOG_ERROR, LOG_FEATURE_MQTT, "MQTT_PublishTopicToClient: mutex failed for %s=%s\r\n", sChannel, sVal); + return OBK_PUBLISH_MUTEX_FAIL; + } + } + if (flags & OBK_PUBLISH_FLAG_RETAIN) + { + retain = 1; + } + // global tool + if (CFG_HasFlag(OBK_FLAG_MQTT_ALWAYSSETRETAIN)) + { + retain = 1; } - } - if(flags & OBK_PUBLISH_FLAG_RETAIN) - { - retain = 1; - } - // global tool - if(CFG_HasFlag(OBK_FLAG_MQTT_ALWAYSSETRETAIN)) - { - retain = 1; - } - if(mqtt_client_is_connected(client)==0) - { - g_my_reconnect_mqtt_after_time = 5; - MQTT_Mutex_Free(); - return OBK_PUBLISH_WAS_DISCONNECTED; - } + if (mqtt_client_is_connected(client) == 0) + { + g_my_reconnect_mqtt_after_time = 5; + MQTT_Mutex_Free(); + return OBK_PUBLISH_WAS_DISCONNECTED; + } - g_timeSinceLastMQTTPublish = 0; - - char *pub_topic = (char *)os_malloc(strlen(sTopic) + 1 + strlen(sChannel) + 5 + 1); //5 for /get - if (pub_topic != NULL) - { - sprintf(pub_topic, "%s/%s%s", sTopic, sChannel, (appendGet == true ? "/get" : "")); - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Publishing val %s to %s retain=%i\n",sVal,pub_topic, retain); + g_timeSinceLastMQTTPublish = 0; - err = mqtt_publish(client, pub_topic, sVal, strlen(sVal), qos, retain, mqtt_pub_request_cb, 0); - os_free(pub_topic); + char* pub_topic = (char*)os_malloc(strlen(sTopic) + 1 + strlen(sChannel) + 5 + 1); //5 for /get + if (pub_topic != NULL) + { + sprintf(pub_topic, "%s/%s%s", sTopic, sChannel, (appendGet == true ? "/get" : "")); + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Publishing val %s to %s retain=%i\n", sVal, pub_topic, retain); - if(err != ERR_OK) - { - if(err == ERR_CONN) - { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Publish err: ERR_CONN aka %d\n", err); - } else if(err == ERR_MEM) { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Publish err: ERR_MEM aka %d\n", err); - g_memoryErrorsThisSession ++; - } else { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Publish err: %d\n", err); - } - } - mqtt_published_events++; - MQTT_Mutex_Free(); - return OBK_PUBLISH_OK; - } else { - MQTT_Mutex_Free(); - return OBK_PUBLISH_MEM_FAIL; - } + err = mqtt_publish(client, pub_topic, sVal, strlen(sVal), qos, retain, mqtt_pub_request_cb, 0); + os_free(pub_topic); + + if (err != ERR_OK) + { + if (err == ERR_CONN) + { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Publish err: ERR_CONN aka %d\n", err); + } + else if (err == ERR_MEM) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Publish err: ERR_MEM aka %d\n", err); + g_memoryErrorsThisSession++; + } + else { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Publish err: %d\n", err); + } + } + mqtt_published_events++; + MQTT_Mutex_Free(); + return OBK_PUBLISH_OK; + } + else { + MQTT_Mutex_Free(); + return OBK_PUBLISH_MEM_FAIL; + } } // This is used to publish channel values in "obk0696FB33/1/get" format with numerical value, // This is also used to publish custom information with string name, // for example, "obk0696FB33/voltage/get" is used to publish voltage from the sensor -static OBK_Publish_Result MQTT_PublishMain(mqtt_client_t *client, const char *sChannel, const char *sVal, int flags, bool appendGet) +static OBK_Publish_Result MQTT_PublishMain(mqtt_client_t* client, const char* sChannel, const char* sVal, int flags, bool appendGet) { - return MQTT_PublishTopicToClient(mqtt_client, CFG_GetMQTTClientId(), sChannel, sVal, flags, appendGet); + return MQTT_PublishTopicToClient(mqtt_client, CFG_GetMQTTClientId(), sChannel, sVal, flags, appendGet); } /// @brief Publish a MQTT message immediately. @@ -569,263 +575,269 @@ static OBK_Publish_Result MQTT_PublishMain(mqtt_client_t *client, const char *sC /// @param sVal /// @param flags /// @return -OBK_Publish_Result MQTT_Publish(char *sTopic, char *sChannel, char *sVal, int flags) +OBK_Publish_Result MQTT_Publish(char* sTopic, char* sChannel, char* sVal, int flags) { - return MQTT_PublishTopicToClient(mqtt_client, sTopic, sChannel, sVal, flags, false); + return MQTT_PublishTopicToClient(mqtt_client, sTopic, sChannel, sVal, flags, false); } -void MQTT_OBK_Printf( char *s) { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,s); +void MQTT_OBK_Printf(char* s) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, s); } -static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags) +static void mqtt_incoming_data_cb(void* arg, const u8_t* data, u16_t len, u8_t flags) { - int i; - // unused - left here as example - //const struct mqtt_connect_client_info_t* client_info = (const struct mqtt_connect_client_info_t*)arg; + int i; + // unused - left here as example + //const struct mqtt_connect_client_info_t* client_info = (const struct mqtt_connect_client_info_t*)arg; - // if we stored a topic in g_mqtt_request, then we found a matching callback, so use it. - if (g_mqtt_request.topic[0]) - { - // note: data is NOT terminated (it may be binary...). - g_mqtt_request.received = data; - g_mqtt_request.receivedLen = len; + // if we stored a topic in g_mqtt_request, then we found a matching callback, so use it. + if (g_mqtt_request.topic[0]) + { + // note: data is NOT terminated (it may be binary...). + g_mqtt_request.received = data; + g_mqtt_request.receivedLen = len; - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT in topic %s", g_mqtt_request.topic); - mqtt_received_events++; + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "MQTT in topic %s", g_mqtt_request.topic); + mqtt_received_events++; - for (i = 0; i < numCallbacks; i++) - { - char *cbtopic = callbacks[i]->topic; - if (!strncmp(g_mqtt_request.topic, cbtopic, strlen(cbtopic))) - { - // note - callback must return 1 to say it ate the mqtt, else further processing can be performed. - // i.e. multiple people can get each topic if required. - if (callbacks[i]->callback(&g_mqtt_request)) - { - return; - } - } - } - } + for (i = 0; i < numCallbacks; i++) + { + char* cbtopic = callbacks[i]->topic; + if (!strncmp(g_mqtt_request.topic, cbtopic, strlen(cbtopic))) + { + // note - callback must return 1 to say it ate the mqtt, else further processing can be performed. + // i.e. multiple people can get each topic if required. + if (callbacks[i]->callback(&g_mqtt_request)) + { + return; + } + } + } + } } -static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len) +static void mqtt_incoming_publish_cb(void* arg, const char* topic, u32_t tot_len) { - //const char *p; - int i; - // unused - left here as example - //const struct mqtt_connect_client_info_t* client_info = (const struct mqtt_connect_client_info_t*)arg; + //const char *p; + int i; + // unused - left here as example + //const struct mqtt_connect_client_info_t* client_info = (const struct mqtt_connect_client_info_t*)arg; - // look for a callback with this URL and method, or HTTP_ANY - g_mqtt_request.topic[0] = '\0'; - for (i = 0; i < numCallbacks; i++) - { - char *cbtopic = callbacks[i]->topic; - if (strncmp(topic, cbtopic, strlen(cbtopic))) - { - strncpy(g_mqtt_request.topic, topic, sizeof(g_mqtt_request.topic) - 1); - g_mqtt_request.topic[sizeof(g_mqtt_request.topic) - 1] = 0; - break; - } - } - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT client in mqtt_incoming_publish_cb topic %s\n",topic); + // look for a callback with this URL and method, or HTTP_ANY + g_mqtt_request.topic[0] = '\0'; + for (i = 0; i < numCallbacks; i++) + { + char* cbtopic = callbacks[i]->topic; + if (strncmp(topic, cbtopic, strlen(cbtopic))) + { + strncpy(g_mqtt_request.topic, topic, sizeof(g_mqtt_request.topic) - 1); + g_mqtt_request.topic[sizeof(g_mqtt_request.topic) - 1] = 0; + break; + } + } + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "MQTT client in mqtt_incoming_publish_cb topic %s\n", topic); } static void -mqtt_request_cb(void *arg, err_t err) +mqtt_request_cb(void* arg, err_t err) { - const struct mqtt_connect_client_info_t* client_info = (const struct mqtt_connect_client_info_t*)arg; + const struct mqtt_connect_client_info_t* client_info = (const struct mqtt_connect_client_info_t*)arg; - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT client \"%s\" request cb: err %d\n", client_info->client_id, (int)err); + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "MQTT client \"%s\" request cb: err %d\n", client_info->client_id, (int)err); } -static void mqtt_sub_request_cb(void *arg, err_t result) +static void mqtt_sub_request_cb(void* arg, err_t result) { - /* Just print the result code here for simplicity, - normal behaviour would be to take some action if subscribe fails like - notifying user, retry subscribe or disconnect from server */ - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Subscribe result: %i\n", result); + /* Just print the result code here for simplicity, + normal behaviour would be to take some action if subscribe fails like + notifying user, retry subscribe or disconnect from server */ + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Subscribe result: %i\n", result); } -static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) +static void mqtt_connection_cb(mqtt_client_t* client, void* arg, mqtt_connection_status_t status) { - int i; + int i; char tmp[CGF_MQTT_CLIENT_ID_SIZE + 16]; - const char *clientId; - err_t err = ERR_OK; - const struct mqtt_connect_client_info_t* client_info = (const struct mqtt_connect_client_info_t*)arg; - LWIP_UNUSED_ARG(client); + const char* clientId; + err_t err = ERR_OK; + const struct mqtt_connect_client_info_t* client_info = (const struct mqtt_connect_client_info_t*)arg; + LWIP_UNUSED_ARG(client); -// addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT client < removed name > connection cb: status %d\n", (int)status); - // addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT client \"%s\" connection cb: status %d\n", client_info->client_id, (int)status); + // addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT client < removed name > connection cb: status %d\n", (int)status); + // addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"MQTT client \"%s\" connection cb: status %d\n", client_info->client_id, (int)status); - if (status == MQTT_CONNECT_ACCEPTED) - { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_connection_cb: Successfully connected\n"); + if (status == MQTT_CONNECT_ACCEPTED) + { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_connection_cb: Successfully connected\n"); - mqtt_set_inpub_callback(mqtt_client, - mqtt_incoming_publish_cb, - mqtt_incoming_data_cb, - LWIP_CONST_CAST(void*, &mqtt_client_info)); + mqtt_set_inpub_callback(mqtt_client, + mqtt_incoming_publish_cb, + mqtt_incoming_data_cb, + LWIP_CONST_CAST(void*, &mqtt_client_info)); - // subscribe to all callback subscription topics - // this makes a BIG assumption that we can subscribe multiple times to the same one? - // TODO - check that subscribing multiple times to the same topic is not BAD - for (i = 0; i < numCallbacks; i++){ - if (callbacks[i]){ - if (callbacks[i]->subscriptionTopic && callbacks[i]->subscriptionTopic[0]){ - err = mqtt_sub_unsub(client, - callbacks[i]->subscriptionTopic, 1, - mqtt_request_cb, LWIP_CONST_CAST(void*, client_info), - 1); - if(err != ERR_OK) { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_subscribe to %s return: %d\n", callbacks[i]->subscriptionTopic, err); - } else { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_subscribed to %s\n", callbacks[i]->subscriptionTopic); - } - } - } - } + // subscribe to all callback subscription topics + // this makes a BIG assumption that we can subscribe multiple times to the same one? + // TODO - check that subscribing multiple times to the same topic is not BAD + for (i = 0; i < numCallbacks; i++) { + if (callbacks[i]) { + if (callbacks[i]->subscriptionTopic && callbacks[i]->subscriptionTopic[0]) { + err = mqtt_sub_unsub(client, + callbacks[i]->subscriptionTopic, 1, + mqtt_request_cb, LWIP_CONST_CAST(void*, client_info), + 1); + if (err != ERR_OK) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_subscribe to %s return: %d\n", callbacks[i]->subscriptionTopic, err); + } + else { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_subscribed to %s\n", callbacks[i]->subscriptionTopic); + } + } + } + } - clientId = CFG_GetMQTTClientId(); + clientId = CFG_GetMQTTClientId(); - sprintf(tmp,"%s/connected",clientId); - err = mqtt_publish(client, tmp, "online", strlen("online"), 2, true, mqtt_pub_request_cb, 0); - if(err != ERR_OK) { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Publish err: %d\n", err); - if(err == ERR_CONN) { - // g_my_reconnect_mqtt_after_time = 5; - } - } + sprintf(tmp, "%s/connected", clientId); + err = mqtt_publish(client, tmp, "online", strlen("online"), 2, true, mqtt_pub_request_cb, 0); + if (err != ERR_OK) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Publish err: %d\n", err); + if (err == ERR_CONN) { + // g_my_reconnect_mqtt_after_time = 5; + } + } - // publish all values on state - if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTSELFSTATEONCONNECT)) { - MQTT_PublishWholeDeviceState(); - } else { - //MQTT_PublishOnlyDeviceChannelsIfPossible(); + // publish all values on state + if (CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTSELFSTATEONCONNECT)) { + MQTT_PublishWholeDeviceState(); + } + else { + //MQTT_PublishOnlyDeviceChannelsIfPossible(); + } + + //mqtt_sub_unsub(client, + // "topic_qos1", 1, + // mqtt_request_cb, LWIP_CONST_CAST(void*, client_info), + // 1); + //mqtt_sub_unsub(client, + // "topic_qos0", 0, + // mqtt_request_cb, LWIP_CONST_CAST(void*, client_info), + // 1); + } + else { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_connection_cb: Disconnected, reason: %d\n", status); + } +} + +static void MQTT_do_connect(mqtt_client_t* client) +{ + const char* mqtt_userName, * mqtt_host, * mqtt_pass, * mqtt_clientID; + int mqtt_port; + int res; + struct hostent* hostEntry; + char will_topic[32]; + + mqtt_host = CFG_GetMQTTHost(); + + if (!mqtt_host[0]) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_host empty, not starting mqtt\r\n"); + sprintf(mqtt_status_message, "mqtt_host empty, not starting mqtt"); + return; } - //mqtt_sub_unsub(client, - // "topic_qos1", 1, - // mqtt_request_cb, LWIP_CONST_CAST(void*, client_info), - // 1); - //mqtt_sub_unsub(client, - // "topic_qos0", 0, - // mqtt_request_cb, LWIP_CONST_CAST(void*, client_info), - // 1); - } else { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_connection_cb: Disconnected, reason: %d\n", status); - } -} - -static void MQTT_do_connect(mqtt_client_t *client) -{ - const char *mqtt_userName, *mqtt_host, *mqtt_pass, *mqtt_clientID; - int mqtt_port; - int res; - struct hostent* hostEntry; - char will_topic[32]; - - mqtt_host = CFG_GetMQTTHost(); - - if (!mqtt_host[0]){ - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_host empty, not starting mqtt\r\n"); - sprintf(mqtt_status_message, "mqtt_host empty, not starting mqtt"); - return; - } - - mqtt_userName = CFG_GetMQTTUserName(); - mqtt_pass = CFG_GetMQTTPass(); - mqtt_clientID = CFG_GetMQTTClientId(); + mqtt_userName = CFG_GetMQTTUserName(); + mqtt_pass = CFG_GetMQTTPass(); + mqtt_clientID = CFG_GetMQTTClientId(); mqtt_port = CFG_GetMQTTPort(); - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_userName %s\r\nmqtt_pass %s\r\nmqtt_clientID %s\r\nmqtt_host %s:%d\r\n", - mqtt_userName, - mqtt_pass, - mqtt_clientID, - mqtt_host, - mqtt_port - ); + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_userName %s\r\nmqtt_pass %s\r\nmqtt_clientID %s\r\nmqtt_host %s:%d\r\n", + mqtt_userName, + mqtt_pass, + mqtt_clientID, + mqtt_host, + mqtt_port + ); - // set pointer, there are no buffers to strcpy - mqtt_client_info.client_id = mqtt_clientID; - mqtt_client_info.client_pass = mqtt_pass; - mqtt_client_info.client_user = mqtt_userName; + // set pointer, there are no buffers to strcpy + mqtt_client_info.client_id = mqtt_clientID; + mqtt_client_info.client_pass = mqtt_pass; + mqtt_client_info.client_user = mqtt_userName; - sprintf(will_topic,"%s/connected",CFG_GetMQTTClientId()); - mqtt_client_info.will_topic = will_topic; - mqtt_client_info.will_msg = "offline"; - mqtt_client_info.will_retain = true, - mqtt_client_info.will_qos = 2, + sprintf(will_topic, "%s/connected", CFG_GetMQTTClientId()); + mqtt_client_info.will_topic = will_topic; + mqtt_client_info.will_msg = "offline"; + mqtt_client_info.will_retain = true, + mqtt_client_info.will_qos = 2, - hostEntry = gethostbyname(mqtt_host); - if (NULL != hostEntry){ - if (hostEntry->h_addr_list && hostEntry->h_addr_list[0]){ - int len = hostEntry->h_length; - if (len > 4){ - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_host resolves to addr len > 4\r\n"); - len = 4; - } - memcpy(&mqtt_ip, hostEntry->h_addr_list[0], len); - } else { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_host resolves no addresses?\r\n"); - sprintf(mqtt_status_message, "mqtt_host resolves no addresses?"); - return; - } + hostEntry = gethostbyname(mqtt_host); + if (NULL != hostEntry) { + if (hostEntry->h_addr_list && hostEntry->h_addr_list[0]) { + int len = hostEntry->h_length; + if (len > 4) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_host resolves to addr len > 4\r\n"); + len = 4; + } + memcpy(&mqtt_ip, hostEntry->h_addr_list[0], len); + } + else { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_host resolves no addresses?\r\n"); + sprintf(mqtt_status_message, "mqtt_host resolves no addresses?"); + return; + } - // host name/ip - //ipaddr_aton(mqtt_host,&mqtt_ip); + // host name/ip + //ipaddr_aton(mqtt_host,&mqtt_ip); - /* Initiate client and connect to server, if this fails immediately an error code is returned - otherwise mqtt_connection_cb will be called with connection result after attempting - to establish a connection with the server. - For now MQTT version 3.1.1 is always used */ + /* Initiate client and connect to server, if this fails immediately an error code is returned + otherwise mqtt_connection_cb will be called with connection result after attempting + to establish a connection with the server. + For now MQTT version 3.1.1 is always used */ - res = mqtt_client_connect(mqtt_client, - &mqtt_ip, mqtt_port, - mqtt_connection_cb, LWIP_CONST_CAST(void*, &mqtt_client_info), - &mqtt_client_info); - mqtt_connect_result = res; - if(res != ERR_OK) - { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Connect error in mqtt_client_connect - code: %d (%s)\n", res, get_error_name(res)); - sprintf(mqtt_status_message, "mqtt_client_connect connect failed"); - if (res == ERR_ISCONN) - { - mqtt_disconnect(mqtt_client); - } - } else { - mqtt_status_message[0] = '\0'; - } - } else { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"mqtt_host %s not found by gethostbyname\r\n", mqtt_host); - sprintf(mqtt_status_message, "mqtt_host %s not found by gethostbyname", mqtt_host); - } + res = mqtt_client_connect(mqtt_client, + &mqtt_ip, mqtt_port, + mqtt_connection_cb, LWIP_CONST_CAST(void*, &mqtt_client_info), + &mqtt_client_info); + mqtt_connect_result = res; + if (res != ERR_OK) + { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Connect error in mqtt_client_connect - code: %d (%s)\n", res, get_error_name(res)); + sprintf(mqtt_status_message, "mqtt_client_connect connect failed"); + if (res == ERR_ISCONN) + { + mqtt_disconnect(mqtt_client); + } + } + else { + mqtt_status_message[0] = '\0'; + } + } + else { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_host %s not found by gethostbyname\r\n", mqtt_host); + sprintf(mqtt_status_message, "mqtt_host %s not found by gethostbyname", mqtt_host); + } } -OBK_Publish_Result MQTT_PublishMain_StringInt(const char *sChannel, int iv) +OBK_Publish_Result MQTT_PublishMain_StringInt(const char* sChannel, int iv) { char valueStr[16]; - sprintf(valueStr,"%i",iv); + sprintf(valueStr, "%i", iv); - return MQTT_PublishMain(mqtt_client,sChannel,valueStr, 0, true); + return MQTT_PublishMain(mqtt_client, sChannel, valueStr, 0, true); } -OBK_Publish_Result MQTT_PublishMain_StringFloat(const char *sChannel, float f) +OBK_Publish_Result MQTT_PublishMain_StringFloat(const char* sChannel, float f) { char valueStr[16]; - sprintf(valueStr,"%f",f); + sprintf(valueStr, "%f", f); - return MQTT_PublishMain(mqtt_client,sChannel,valueStr, 0, true); + return MQTT_PublishMain(mqtt_client, sChannel, valueStr, 0, true); } -OBK_Publish_Result MQTT_PublishMain_StringString(const char *sChannel, const char *valueStr, int flags) +OBK_Publish_Result MQTT_PublishMain_StringString(const char* sChannel, const char* valueStr, int flags) { - return MQTT_PublishMain(mqtt_client,sChannel,valueStr, flags, true); + return MQTT_PublishMain(mqtt_client, sChannel, valueStr, flags, true); } OBK_Publish_Result MQTT_ChannelChangeCallback(int channel, int iVal) @@ -833,56 +845,56 @@ OBK_Publish_Result MQTT_ChannelChangeCallback(int channel, int iVal) char channelNameStr[8]; char valueStr[16]; - addLogAdv(LOG_INFO,LOG_FEATURE_MAIN, "Channel has changed! Publishing change %i with %i \n",channel,iVal); + addLogAdv(LOG_INFO, LOG_FEATURE_MAIN, "Channel has changed! Publishing change %i with %i \n", channel, iVal); - sprintf(channelNameStr,"%i",channel); - sprintf(valueStr,"%i",iVal); + sprintf(channelNameStr, "%i", channel); + sprintf(valueStr, "%i", iVal); - return MQTT_PublishMain(mqtt_client,channelNameStr,valueStr, 0, true); + return MQTT_PublishMain(mqtt_client, channelNameStr, valueStr, 0, true); } OBK_Publish_Result MQTT_ChannelPublish(int channel, int flags) { char channelNameStr[8]; char valueStr[16]; int iValue; - + iValue = CHANNEL_Get(channel); - addLogAdv(LOG_INFO,LOG_FEATURE_MAIN, "Forced channel publish! Publishing val %i with %i \n",channel,iValue); + addLogAdv(LOG_INFO, LOG_FEATURE_MAIN, "Forced channel publish! Publishing val %i with %i \n", channel, iValue); - sprintf(channelNameStr,"%i",channel); - sprintf(valueStr,"%i",iValue); + sprintf(channelNameStr, "%i", channel); + sprintf(valueStr, "%i", iValue); - return MQTT_PublishMain(mqtt_client,channelNameStr,valueStr, flags, true); + return MQTT_PublishMain(mqtt_client, channelNameStr, valueStr, flags, true); } // This console command will trigger a publish of all used variables (channels and extra stuff) -OBK_Publish_Result MQTT_PublishAll(const void *context, const char *cmd, const char *args, int cmdFlags) { - +OBK_Publish_Result MQTT_PublishAll(const void* context, const char* cmd, const char* args, int cmdFlags) { + MQTT_PublishWholeDeviceState_Internal(false); return 1;// TODO make return values consistent for all console commands } // This console command will trigger a publish of runtime variables -OBK_Publish_Result MQTT_PublishChannels(const void *context, const char *cmd, const char *args, int cmdFlags) { - +OBK_Publish_Result MQTT_PublishChannels(const void* context, const char* cmd, const char* args, int cmdFlags) { + MQTT_PublishWholeDeviceState_Internal(true); return 1;// TODO make return values consistent for all console commands } -OBK_Publish_Result MQTT_PublishCommand(const void *context, const char *cmd, const char *args, int cmdFlags) { - const char *topic, *value; +OBK_Publish_Result MQTT_PublishCommand(const void* context, const char* cmd, const char* args, int cmdFlags) { + const char* topic, * value; OBK_Publish_Result ret; Tokenizer_TokenizeString(args); - if(Tokenizer_GetArgsCount() < 2){ - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Publish command requires two arguments (topic and value)"); + if (Tokenizer_GetArgsCount() < 2) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Publish command requires two arguments (topic and value)"); return 0; } topic = Tokenizer_GetArg(0); value = Tokenizer_GetArg(1); - ret = MQTT_PublishMain_StringString(topic,value, 0); + ret = MQTT_PublishMain_StringString(topic, value, 0); return ret; } @@ -890,111 +902,111 @@ OBK_Publish_Result MQTT_PublishCommand(const void *context, const char *cmd, con // called from user_main void MQTT_init() { - char cbtopicbase[64]; - char cbtopicsub[64]; - const char *clientId; + char cbtopicbase[64]; + char cbtopicsub[64]; + const char* clientId; - clientId = CFG_GetMQTTClientId(); + clientId = CFG_GetMQTTClientId(); - // register the main set channel callback - sprintf(cbtopicbase,"%s/",clientId); - sprintf(cbtopicsub,"%s/+/set",clientId); - // note: this may REPLACE an existing entry with the same ID. ID 1 !!! - MQTT_RegisterCallback( cbtopicbase, cbtopicsub, 1, channelSet); + // register the main set channel callback + sprintf(cbtopicbase, "%s/", clientId); + sprintf(cbtopicsub, "%s/+/set", clientId); + // note: this may REPLACE an existing entry with the same ID. ID 1 !!! + MQTT_RegisterCallback(cbtopicbase, cbtopicsub, 1, channelSet); - // register the TAS cmnd callback - sprintf(cbtopicbase,"cmnd/%s/",clientId); - sprintf(cbtopicsub,"cmnd/%s/+",clientId); - // note: this may REPLACE an existing entry with the same ID. ID 2 !!! - MQTT_RegisterCallback( cbtopicbase, cbtopicsub, 2, tasCmnd); + // register the TAS cmnd callback + sprintf(cbtopicbase, "cmnd/%s/", clientId); + sprintf(cbtopicsub, "cmnd/%s/+", clientId); + // note: this may REPLACE an existing entry with the same ID. ID 2 !!! + MQTT_RegisterCallback(cbtopicbase, cbtopicsub, 2, tasCmnd); - mqtt_initialised = 1; + mqtt_initialised = 1; - CMD_RegisterCommand("publish","",MQTT_PublishCommand, "Sqqq", NULL); - CMD_RegisterCommand("publishAll","",MQTT_PublishAll, "Sqqq", NULL); - CMD_RegisterCommand("publishChannels","",MQTT_PublishChannels, "Sqqq", NULL); + CMD_RegisterCommand("publish", "", MQTT_PublishCommand, "Sqqq", NULL); + CMD_RegisterCommand("publishAll", "", MQTT_PublishAll, "Sqqq", NULL); + CMD_RegisterCommand("publishChannels", "", MQTT_PublishChannels, "Sqqq", NULL); } -OBK_Publish_Result MQTT_DoItemPublishString(const char *sChannel, const char *valueStr) +OBK_Publish_Result MQTT_DoItemPublishString(const char* sChannel, const char* valueStr) { - return MQTT_PublishMain(mqtt_client, sChannel, valueStr, OBK_PUBLISH_FLAG_MUTEX_SILENT, false); + return MQTT_PublishMain(mqtt_client, sChannel, valueStr, OBK_PUBLISH_FLAG_MUTEX_SILENT, false); } -OBK_Publish_Result MQTT_DoItemPublish(int idx) +OBK_Publish_Result MQTT_DoItemPublish(int idx) { - char dataStr[3*6+1]; //This is sufficient to hold mac value + char dataStr[3 * 6 + 1]; //This is sufficient to hold mac value - switch(idx) { - case PUBLISHITEM_SELF_STATIC_RESERVED_2: - case PUBLISHITEM_SELF_STATIC_RESERVED_1: - return OBK_PUBLISH_WAS_NOT_REQUIRED; + switch (idx) { + case PUBLISHITEM_SELF_STATIC_RESERVED_2: + case PUBLISHITEM_SELF_STATIC_RESERVED_1: + return OBK_PUBLISH_WAS_NOT_REQUIRED; - case PUBLISHITEM_QUEUED_VALUES: - return PublishQueuedItems(); + case PUBLISHITEM_QUEUED_VALUES: + return PublishQueuedItems(); - case PUBLISHITEM_SELF_DYNAMIC_LIGHTSTATE: - return LED_IsRunningDriver() ? LED_SendEnableAllState() : OBK_PUBLISH_WAS_NOT_REQUIRED; - case PUBLISHITEM_SELF_DYNAMIC_LIGHTMODE: - return LED_IsRunningDriver() ? LED_SendCurrentLightMode() : OBK_PUBLISH_WAS_NOT_REQUIRED; - case PUBLISHITEM_SELF_DYNAMIC_DIMMER: - return LED_IsRunningDriver() ? LED_SendDimmerChange() : OBK_PUBLISH_WAS_NOT_REQUIRED; + case PUBLISHITEM_SELF_DYNAMIC_LIGHTSTATE: + return LED_IsRunningDriver() ? LED_SendEnableAllState() : OBK_PUBLISH_WAS_NOT_REQUIRED; + case PUBLISHITEM_SELF_DYNAMIC_LIGHTMODE: + return LED_IsRunningDriver() ? LED_SendCurrentLightMode() : OBK_PUBLISH_WAS_NOT_REQUIRED; + case PUBLISHITEM_SELF_DYNAMIC_DIMMER: + return LED_IsRunningDriver() ? LED_SendDimmerChange() : OBK_PUBLISH_WAS_NOT_REQUIRED; - case PUBLISHITEM_SELF_HOSTNAME: - return MQTT_DoItemPublishString("host", CFG_GetShortDeviceName()); + case PUBLISHITEM_SELF_HOSTNAME: + return MQTT_DoItemPublishString("host", CFG_GetShortDeviceName()); - case PUBLISHITEM_SELF_BUILD: - return MQTT_DoItemPublishString("build", g_build_str); - - case PUBLISHITEM_SELF_MAC: - return MQTT_DoItemPublishString("mac", HAL_GetMACStr(dataStr)); - - case PUBLISHITEM_SELF_DATETIME: - //Drivers are only built on BK7231 chips - #ifndef OBK_DISABLE_ALL_DRIVERS - if (DRV_IsRunning("NTP")) { - sprintf(dataStr,"%d",NTP_GetCurrentTime()); - return MQTT_DoItemPublishString("datetime", dataStr); - } - else{ - return OBK_PUBLISH_WAS_NOT_REQUIRED; - } - #else - return OBK_PUBLISH_WAS_NOT_REQUIRED; - #endif + case PUBLISHITEM_SELF_BUILD: + return MQTT_DoItemPublishString("build", g_build_str); - case PUBLISHITEM_SELF_SOCKETS: - sprintf(dataStr,"%d",LWIP_GetActiveSockets()); - return MQTT_DoItemPublishString("sockets", dataStr); + case PUBLISHITEM_SELF_MAC: + return MQTT_DoItemPublishString("mac", HAL_GetMACStr(dataStr)); - case PUBLISHITEM_SELF_RSSI: - sprintf(dataStr,"%d",HAL_GetWifiStrength()); - return MQTT_DoItemPublishString("rssi", dataStr); + case PUBLISHITEM_SELF_DATETIME: + //Drivers are only built on BK7231 chips +#ifndef OBK_DISABLE_ALL_DRIVERS + if (DRV_IsRunning("NTP")) { + sprintf(dataStr, "%d", NTP_GetCurrentTime()); + return MQTT_DoItemPublishString("datetime", dataStr); + } + else { + return OBK_PUBLISH_WAS_NOT_REQUIRED; + } +#else + return OBK_PUBLISH_WAS_NOT_REQUIRED; +#endif - case PUBLISHITEM_SELF_UPTIME: - sprintf(dataStr,"%d",Time_getUpTimeSeconds()); - return MQTT_DoItemPublishString("uptime", dataStr); + case PUBLISHITEM_SELF_SOCKETS: + sprintf(dataStr, "%d", LWIP_GetActiveSockets()); + return MQTT_DoItemPublishString("sockets", dataStr); - case PUBLISHITEM_SELF_FREEHEAP: - sprintf(dataStr,"%d",xPortGetFreeHeapSize()); - return MQTT_DoItemPublishString("freeheap", dataStr); + case PUBLISHITEM_SELF_RSSI: + sprintf(dataStr, "%d", HAL_GetWifiStrength()); + return MQTT_DoItemPublishString("rssi", dataStr); - case PUBLISHITEM_SELF_IP: - g_firstFullBroadcast = false; //We published the last status item, disable full broadcast - return MQTT_DoItemPublishString("ip", HAL_GetMyIPString()); + case PUBLISHITEM_SELF_UPTIME: + sprintf(dataStr, "%d", Time_getUpTimeSeconds()); + return MQTT_DoItemPublishString("uptime", dataStr); + + case PUBLISHITEM_SELF_FREEHEAP: + sprintf(dataStr, "%d", xPortGetFreeHeapSize()); + return MQTT_DoItemPublishString("freeheap", dataStr); + + case PUBLISHITEM_SELF_IP: + g_firstFullBroadcast = false; //We published the last status item, disable full broadcast + return MQTT_DoItemPublishString("ip", HAL_GetMyIPString()); + + default: + break; + } - default: - break; - } - // if LED driver is active, do not publish raw channel values - if(LED_IsRunningDriver() == false && idx >= 0) { + if (LED_IsRunningDriver() == false && idx >= 0) { // This is because raw channels are like PWM values, RGBCW has 5 raw channels // (unless it has I2C LED driver) // We do not need raw values for RGBCW lights (or RGB, etc) // because we are using led_basecolor_rgb, led_dimmer, led_enableAll, etc // NOTE: negative indexes are not channels - they are special values - if(CHANNEL_IsInUse(idx)) { - MQTT_ChannelPublish(g_publishItemIndex, OBK_PUBLISH_FLAG_MUTEX_SILENT); + if (CHANNEL_IsInUse(idx)) { + MQTT_ChannelPublish(g_publishItemIndex, OBK_PUBLISH_FLAG_MUTEX_SILENT); } } return OBK_PUBLISH_WAS_NOT_REQUIRED; // didnt publish @@ -1002,56 +1014,57 @@ OBK_Publish_Result MQTT_DoItemPublish(int idx) static int g_secondsBeforeNextFullBroadcast = 30; // called from user timer. -int MQTT_RunEverySecondUpdate() +int MQTT_RunEverySecondUpdate() { if (!mqtt_initialised) return 0; - if (Main_HasWiFiConnected() == 0) - return 0; + if (Main_HasWiFiConnected() == 0) + return 0; // take mutex for connect and disconnect operations - if(MQTT_Mutex_Take(100)==0) - { + if (MQTT_Mutex_Take(100) == 0) + { return 0; } - // reconnect if went into MQTT library ERR_MEM forever loop - if(g_memoryErrorsThisSession >= 5) - { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT, "MQTT will reconnect soon to fix ERR_MEM errors\n"); + // reconnect if went into MQTT library ERR_MEM forever loop + if (g_memoryErrorsThisSession >= 5) + { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "MQTT will reconnect soon to fix ERR_MEM errors\n"); g_memoryErrorsThisSession = 0; mqtt_reconnect = 5; } // if asked to reconnect (e.g. change of topic(s)) if (mqtt_reconnect > 0) - { - mqtt_reconnect --; + { + mqtt_reconnect--; if (mqtt_reconnect == 0) - { + { // then if connected, disconnect, and then it will reconnect automatically in 2s - if (mqtt_client && mqtt_client_is_connected(mqtt_client)) - { + if (mqtt_client && mqtt_client_is_connected(mqtt_client)) + { MQTT_disconnect(mqtt_client); loopsWithDisconnected = 8; } } } - if(mqtt_client == 0 || mqtt_client_is_connected(mqtt_client) == 0) - { + if (mqtt_client == 0 || mqtt_client_is_connected(mqtt_client) == 0) + { //addLogAdv(LOG_INFO,LOG_FEATURE_MAIN, "Timer discovers disconnected mqtt %i\n",loopsWithDisconnected); loopsWithDisconnected++; - if(loopsWithDisconnected > 10) + if (loopsWithDisconnected > 10) { - if(mqtt_client == 0) + if (mqtt_client == 0) { mqtt_client = mqtt_client_new(); - } else { - #if defined(MQTT_CLIENT_CLEANUP) + } + else { +#if defined(MQTT_CLIENT_CLEANUP) mqtt_client_cleanup(mqtt_client); - #endif +#endif } MQTT_do_connect(mqtt_client); mqtt_connect_events++; @@ -1059,7 +1072,8 @@ int MQTT_RunEverySecondUpdate() } MQTT_Mutex_Free(); return 0; - } else { + } + else { MQTT_Mutex_Free(); // below mutex is not required any more @@ -1070,42 +1084,42 @@ int MQTT_RunEverySecondUpdate() // Do it slowly in order not to overload the buffers // The item indexes start at negative values for special items // and then covers Channel indexes up to CHANNEL_MAX - //Handle only queued items. Don't need to do this separately if entire state is being published. - if ((g_MqttPublishItemsQueued > 0) && !g_bPublishAllStatesNow) - { - PublishQueuedItems(); - return 1; - } - else if(g_bPublishAllStatesNow) - { + //Handle only queued items. Don't need to do this separately if entire state is being published. + if ((g_MqttPublishItemsQueued > 0) && !g_bPublishAllStatesNow) + { + PublishQueuedItems(); + return 1; + } + else if (g_bPublishAllStatesNow) + { // Doing step by a step a full publish state - if(g_timeSinceLastMQTTPublish > 2) - { + if (g_timeSinceLastMQTTPublish > 2) + { OBK_Publish_Result publishRes; int g_sent_thisFrame = 0; - while(g_publishItemIndex < CHANNEL_MAX) - { + while (g_publishItemIndex < CHANNEL_MAX) + { publishRes = MQTT_DoItemPublish(g_publishItemIndex); - if(publishRes != OBK_PUBLISH_WAS_NOT_REQUIRED) + if (publishRes != OBK_PUBLISH_WAS_NOT_REQUIRED) { - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT, "[g_bPublishAllStatesNow] item %i result %i\n",g_publishItemIndex,publishRes); + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "[g_bPublishAllStatesNow] item %i result %i\n", g_publishItemIndex, publishRes); } // There are several things that can happen now // OBK_PUBLISH_OK - it was required and was published - if(publishRes == OBK_PUBLISH_OK) - { + if (publishRes == OBK_PUBLISH_OK) + { g_sent_thisFrame++; - if(g_sent_thisFrame>=1) - { + if (g_sent_thisFrame >= 1) + { g_publishItemIndex++; break; } } // OBK_PUBLISH_MUTEX_FAIL - MQTT is busy - if(publishRes == OBK_PUBLISH_MUTEX_FAIL - || publishRes == OBK_PUBLISH_WAS_DISCONNECTED) - { + if (publishRes == OBK_PUBLISH_MUTEX_FAIL + || publishRes == OBK_PUBLISH_WAS_DISCONNECTED) + { // retry the same later break; } @@ -1114,20 +1128,21 @@ int MQTT_RunEverySecondUpdate() g_publishItemIndex++; } - if(g_publishItemIndex >= CHANNEL_MAX) - { + if (g_publishItemIndex >= CHANNEL_MAX) + { // done g_bPublishAllStatesNow = 0; - } + } } - } else { + } + else { // not doing anything - if(CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTSELFSTATEPERMINUTE)) - { + if (CFG_HasFlag(OBK_FLAG_MQTT_BROADCASTSELFSTATEPERMINUTE)) + { // this is called every second g_secondsBeforeNextFullBroadcast--; - if(g_secondsBeforeNextFullBroadcast <= 0) - { + if (g_secondsBeforeNextFullBroadcast <= 0) + { g_secondsBeforeNextFullBroadcast = 60; MQTT_PublishWholeDeviceState(); } @@ -1137,23 +1152,23 @@ int MQTT_RunEverySecondUpdate() return 1; } -MqttPublishItem_t *get_queue_tail(MqttPublishItem_t *head){ - if (head == NULL){ return NULL; } +MqttPublishItem_t* get_queue_tail(MqttPublishItem_t* head) { + if (head == NULL) { return NULL; } - while (head->next != NULL){ - head = head->next; - } - return head; + while (head->next != NULL) { + head = head->next; + } + return head; } -MqttPublishItem_t *find_queue_reusable_item(MqttPublishItem_t *head){ - while (head != NULL){ - if (MQTT_QUEUE_ITEM_IS_REUSABLE(head)){ - return head; - } - head = head->next; - } - return head; +MqttPublishItem_t* find_queue_reusable_item(MqttPublishItem_t* head) { + while (head != NULL) { + if (MQTT_QUEUE_ITEM_IS_REUSABLE(head)) { + return head; + } + head = head->next; + } + return head; } /// @brief Queue an entry for publish. @@ -1161,75 +1176,75 @@ MqttPublishItem_t *find_queue_reusable_item(MqttPublishItem_t *head){ /// @param channel /// @param value /// @param flags -void MQTT_QueuePublish(char *topic, char *channel, char *value, int flags){ - if (g_MqttPublishItemsQueued >= MQTT_MAX_QUEUE_SIZE){ - addLogAdv(LOG_ERROR,LOG_FEATURE_MQTT,"Unable to queue! %i items already present\r\n", g_MqttPublishItemsQueued); - return; - } +void MQTT_QueuePublish(char* topic, char* channel, char* value, int flags) { + if (g_MqttPublishItemsQueued >= MQTT_MAX_QUEUE_SIZE) { + addLogAdv(LOG_ERROR, LOG_FEATURE_MQTT, "Unable to queue! %i items already present\r\n", g_MqttPublishItemsQueued); + return; + } - if ((strlen(topic) > MQTT_PUBLISH_ITEM_TOPIC_LENGTH) || - (strlen(channel) > MQTT_PUBLISH_ITEM_CHANNEL_LENGTH) || - (strlen(value) > MQTT_PUBLISH_ITEM_VALUE_LENGTH)){ - addLogAdv(LOG_ERROR,LOG_FEATURE_MQTT,"Unable to queue! Topic (%i), channel (%i) or value (%i) exceeds size limit\r\n", - strlen(topic), strlen(channel), strlen(value)); - return; - } + if ((strlen(topic) > MQTT_PUBLISH_ITEM_TOPIC_LENGTH) || + (strlen(channel) > MQTT_PUBLISH_ITEM_CHANNEL_LENGTH) || + (strlen(value) > MQTT_PUBLISH_ITEM_VALUE_LENGTH)) { + addLogAdv(LOG_ERROR, LOG_FEATURE_MQTT, "Unable to queue! Topic (%i), channel (%i) or value (%i) exceeds size limit\r\n", + strlen(topic), strlen(channel), strlen(value)); + return; + } - //Queue data for publish. This might be a new item in the queue or an existing item. This is done to prevent - //memory fragmentation. The total queue length is limited to MQTT_MAX_QUEUE_SIZE. - MqttPublishItem_t *newItem; + //Queue data for publish. This might be a new item in the queue or an existing item. This is done to prevent + //memory fragmentation. The total queue length is limited to MQTT_MAX_QUEUE_SIZE. + MqttPublishItem_t* newItem; - if (g_MqttPublishQueueHead == NULL){ - g_MqttPublishQueueHead = newItem = os_malloc(sizeof(MqttPublishItem_t)); - newItem->next=NULL; - } - else{ - newItem = find_queue_reusable_item(g_MqttPublishQueueHead); + if (g_MqttPublishQueueHead == NULL) { + g_MqttPublishQueueHead = newItem = os_malloc(sizeof(MqttPublishItem_t)); + newItem->next = NULL; + } + else { + newItem = find_queue_reusable_item(g_MqttPublishQueueHead); - if (newItem == NULL){ - newItem = os_malloc(sizeof(MqttPublishItem_t)); - newItem->next=NULL; - get_queue_tail(g_MqttPublishQueueHead)->next = newItem; //Append new item - } - } - - //os_strcpy does copy ending null character. - os_strcpy(newItem->topic, topic); - os_strcpy(newItem->channel, channel); - os_strcpy(newItem->value, value); - newItem->flags = flags; - - g_MqttPublishItemsQueued++; - addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"Queued topic=%s/%s %i, items queued", newItem->topic, newItem->channel, g_MqttPublishItemsQueued); + if (newItem == NULL) { + newItem = os_malloc(sizeof(MqttPublishItem_t)); + newItem->next = NULL; + get_queue_tail(g_MqttPublishQueueHead)->next = newItem; //Append new item + } + } + + //os_strcpy does copy ending null character. + os_strcpy(newItem->topic, topic); + os_strcpy(newItem->channel, channel); + os_strcpy(newItem->value, value); + newItem->flags = flags; + + g_MqttPublishItemsQueued++; + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Queued topic=%s/%s %i, items queued", newItem->topic, newItem->channel, g_MqttPublishItemsQueued); } /// @brief Publish MQTT_QUEUED_ITEMS_PUBLISHED_AT_ONCE queued items. /// @return -OBK_Publish_Result PublishQueuedItems(){ - OBK_Publish_Result result = OBK_PUBLISH_WAS_NOT_REQUIRED; +OBK_Publish_Result PublishQueuedItems() { + OBK_Publish_Result result = OBK_PUBLISH_WAS_NOT_REQUIRED; - int count = 0; - MqttPublishItem_t *head = g_MqttPublishQueueHead; - - //The next actionable item might not be at the front. The queue size is limited to MQTT_QUEUED_ITEMS_PUBLISHED_AT_ONCE - //so this traversal is fast. - //addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"PublishQueuedItems g_MqttPublishItemsQueued=%i",g_MqttPublishItemsQueued ); - while ((head != NULL) && (count < MQTT_QUEUED_ITEMS_PUBLISHED_AT_ONCE) && (g_MqttPublishItemsQueued > 0)){ - if (!MQTT_QUEUE_ITEM_IS_REUSABLE(head)){ //Skip reusable entries - count++; - result = MQTT_PublishTopicToClient(mqtt_client, head->topic, head->channel, head->value, head->flags, false); - MQTT_QUEUE_ITEM_SET_REUSABLE(head); //Flag item as reusable - g_MqttPublishItemsQueued--; //decrement queued count + int count = 0; + MqttPublishItem_t* head = g_MqttPublishQueueHead; - //Stop if last publish failed - if (result != OBK_PUBLISH_OK) break; - } - else{ - //addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"PublishQueuedItems item skipped reusable"); - } + //The next actionable item might not be at the front. The queue size is limited to MQTT_QUEUED_ITEMS_PUBLISHED_AT_ONCE + //so this traversal is fast. + //addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"PublishQueuedItems g_MqttPublishItemsQueued=%i",g_MqttPublishItemsQueued ); + while ((head != NULL) && (count < MQTT_QUEUED_ITEMS_PUBLISHED_AT_ONCE) && (g_MqttPublishItemsQueued > 0)) { + if (!MQTT_QUEUE_ITEM_IS_REUSABLE(head)) { //Skip reusable entries + count++; + result = MQTT_PublishTopicToClient(mqtt_client, head->topic, head->channel, head->value, head->flags, false); + MQTT_QUEUE_ITEM_SET_REUSABLE(head); //Flag item as reusable + g_MqttPublishItemsQueued--; //decrement queued count - head = head->next; - } + //Stop if last publish failed + if (result != OBK_PUBLISH_OK) break; + } + else { + //addLogAdv(LOG_INFO,LOG_FEATURE_MQTT,"PublishQueuedItems item skipped reusable"); + } - return result; + head = head->next; + } + + return result; }