diff --git a/ezlopi-cloud/ezlopi-cloud-constants/ezlopi_cloud_methods_str.c b/ezlopi-cloud/ezlopi-cloud-constants/ezlopi_cloud_methods_str.c index 9d96c780..dca98669 100644 --- a/ezlopi-cloud/ezlopi-cloud-constants/ezlopi_cloud_methods_str.c +++ b/ezlopi-cloud/ezlopi-cloud-constants/ezlopi_cloud_methods_str.c @@ -134,4 +134,12 @@ const char *ezlopi_hub_room_reordered_str = "hub.room.reordered"; const char *ezlopi_hub_modes_changed_str = "hub.modes.changed"; +const char *ezlopi_hub_device_group_created = "hub.device.group.created"; +const char *ezlopi_hub_device_group_deleted = "hub.device.group.deleted"; +const char *ezlopi_hub_device_group_updated = "hub.device.group.updated"; + +const char *ezlopi_hub_item_group_created = "hub.item.group.created"; +const char *ezlopi_hub_item_group_deleted = "hub.item.group.deleted"; +const char *ezlopi_hub_item_group_updated = "hub.item.group.updated"; + #endif // __EZLOPI_METHODS_STR_H__ \ No newline at end of file diff --git a/ezlopi-cloud/ezlopi-cloud-constants/ezlopi_cloud_methods_str.h b/ezlopi-cloud/ezlopi-cloud-constants/ezlopi_cloud_methods_str.h index 7a311de5..ca1b60ac 100644 --- a/ezlopi-cloud/ezlopi-cloud-constants/ezlopi_cloud_methods_str.h +++ b/ezlopi-cloud/ezlopi-cloud-constants/ezlopi_cloud_methods_str.h @@ -134,4 +134,12 @@ extern const char *ezlopi_hub_room_reordered_str; extern const char *ezlopi_hub_modes_changed_str; +extern const char *ezlopi_hub_device_group_created; +extern const char *ezlopi_hub_device_group_deleted; +extern const char *ezlopi_hub_device_group_updated; + +extern const char *ezlopi_hub_item_group_created; +extern const char *ezlopi_hub_item_group_deleted; +extern const char *ezlopi_hub_item_group_updated; + #endif // __EZLOPI_METHODS_STR_H__ \ No newline at end of file diff --git a/ezlopi-cloud/ezlopi-cloud-devices/ezlopi_cloud_devices.c b/ezlopi-cloud/ezlopi-cloud-devices/ezlopi_cloud_devices.c index f9e1cdb9..428fee40 100644 --- a/ezlopi-cloud/ezlopi-cloud-devices/ezlopi_cloud_devices.c +++ b/ezlopi-cloud/ezlopi-cloud-devices/ezlopi_cloud_devices.c @@ -4,10 +4,11 @@ #include "ezlopi_util_trace.h" #include "ezlopi_core_factory_info.h" -#include "ezlopi_core_devices.h" #include "ezlopi_core_devices_list.h" #include "ezlopi_core_api_methods.h" #include "ezlopi_core_sntp.h" +#include "ezlopi_core_nvs.h" +#include "ezlopi_core_device_group.h" #include "ezlopi_cloud_keywords.h" #include "ezlopi_cloud_methods_str.h" @@ -187,3 +188,465 @@ void device_updated(cJSON* cj_request, cJSON* cj_response) } } } + +/////////// device/item group /////// + +//---- device_group_api ------ + +void device_group_create(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON * cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + uint32_t new_device_grp_id = ezlopi_core_device_group_store_nvs_devgrp(cj_params); + TRACE_D("new-device-grp-id: %08x", new_device_grp_id); + + if (new_device_grp_id) + { + char tmp_buff[32]; + snprintf(tmp_buff, sizeof(tmp_buff), "%08x", new_device_grp_id); + cJSON_AddStringToObject(__FUNCTION__, cj_request, ezlopi__id_str, tmp_buff); // this is for (reply) + ezlopi_core_device_group_new_devgrp_populate(cj_params, new_device_grp_id); + } + } + } + } +} + +void device_group_get(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + cJSON* cj_devgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_id_str); + if (cj_devgrp_id && cj_devgrp_id->valuestring) + { + char* devgrp_str = ezlopi_nvs_read_str(cj_devgrp_id->valuestring); + if (devgrp_str) + { + cJSON_AddRawToObject(__FUNCTION__, cj_response, ezlopi_result_str, devgrp_str); + ezlopi_free(__FUNCTION__, devgrp_str); + } + else + { + cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + } + } + } + + } +} + +void device_groups_list(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON* cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + ezlopi_core_device_group_get_list(cJSON_AddArrayToObject(__FUNCTION__, cj_result, "deviceGroups")); + // cJSON* cj_ver_str = cJSON_GetObjectItem(__FUNCTION__, cj_request, "version"); + // if (cj_ver_str && cj_ver_str->valuestring && cj_ver_str->str_value_len) + // { + // cJSON_AddStringToObject(__FUNCTION__, cj_result, "version", cj_ver_str->valuestring); + // } + } + } +} + +void device_group_delete(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON * cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + cJSON* cj_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_id_str); + if (cj_id && cj_id->valuestring) + { + uint32_t dev_grp_id = strtoul(cj_id->valuestring, NULL, 16); + + // 1. check if 'dev_grp' is persistant + l_ezlopi_device_grp_t* curr_devgrp = ezlopi_core_device_group_get_by_id(dev_grp_id); + if (curr_devgrp) + { + if (curr_devgrp->persistent) + { // if 'true' + cJSON * cj_force = cJSON_GetObjectItem(__FUNCTION__, cj_params, "force"); + if (cj_force && cJSON_IsTrue(cj_force)) + { + ezlopi_nvs_delete_stored_data_by_id(dev_grp_id); // from nvs + ezlopi_core_device_group_depopulate_by_id_v2(dev_grp_id); // from ll + ezlopi_core_device_group_remove_id_from_list(dev_grp_id); // from nvs-list + + cJSON_AddStringToObject(__FUNCTION__, cj_request, ezlopi__id_str, cj_id->valuestring); //for (reply_broadcast); if delete is successful + } + else + { + TRACE_E("Error!! , Unable to delete 'device_group_id' : [%d]", dev_grp_id); + } + } + else + { + ezlopi_nvs_delete_stored_data_by_id(dev_grp_id); + ezlopi_core_device_group_depopulate_by_id_v2(dev_grp_id); + ezlopi_core_device_group_remove_id_from_list(dev_grp_id); + } + } + } + } + } + } +} + +void device_group_update(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON * cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + cJSON* cj_devgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_id_str); // "id" + if (cj_devgrp_id && cj_devgrp_id->valuestring) + { + // CJSON_TRACE("dev-grp [new] : ", cj_devgrp_id); + uint32_t req_devgrp_id = strtoul(cj_devgrp_id->valuestring, NULL, 16); + + // edit in nvs and populate again + ezlopi_core_device_group_edit_by_id(req_devgrp_id, cj_params); + } + } + } + } +} + +void device_group_find(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON* cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + ezlopi_core_device_group_find(cJSON_AddArrayToObject(__FUNCTION__, cj_result, "deviceGroups"), cj_params); + } + } + } +} + +void device_group_devitem_expand(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON* cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + // cJSON* cj_show_item = cJSON_GetObjectItem(__FUNCTION__, cj_request, "showItems"); + // if (cj_show_item && cJSON_IsBool(cj_show_item) && (cj_show_item->type == cJSON_True)) + // { + ezlopi_core_device_group_devitem_expand(cJSON_AddArrayToObject(__FUNCTION__, cj_result, "devices"), cj_params); + // } + + // cJSON* cj_ver_str = cJSON_GetObjectItem(__FUNCTION__, cj_request, "version"); + // if (cj_ver_str && cj_ver_str->valuestring && cj_ver_str->str_value_len) + // { + // cJSON_AddStringToObject(__FUNCTION__, cj_result, "version", cj_ver_str->valuestring); + // } + } + } + } +} + +////// updater for device-grps +////// for 'hub.device.group.__' + +void device_group_created(cJSON * cj_request, cJSON * cj_response) +{ + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_sender_str); + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_error_str); + + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_id_str, ezlopi_ui_broadcast_str); + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_msg_subclass_str, ezlopi_hub_device_group_created); + + cJSON* new_devgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi__id_str); + if (new_devgrp_id && new_devgrp_id->valuestring) + { + char* new_devgrp = ezlopi_nvs_read_str(new_devgrp_id->valuestring); + if (new_devgrp) + { + cJSON_AddRawToObject(__FUNCTION__, cj_response, ezlopi_result_str, new_devgrp); + ezlopi_free(__FUNCTION__, new_devgrp); + } + } +} + +void device_group_deleted(cJSON * cj_request, cJSON * cj_response) +{ + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_sender_str); + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_error_str); + + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_id_str, ezlopi_ui_broadcast_str); + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_msg_subclass_str, ezlopi_hub_device_group_deleted); + + cJSON* cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* deleted_devgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi__id_str); // if delete was successful + if (deleted_devgrp_id && deleted_devgrp_id->valuestring) + { + cJSON_AddStringToObject(__FUNCTION__, cj_result, ezlopi__id_str, deleted_devgrp_id->valuestring); + } + } +} + +void device_group_updated(cJSON * cj_request, cJSON * cj_response) +{ + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_sender_str); + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_error_str); + + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_id_str, ezlopi_ui_broadcast_str); + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_msg_subclass_str, ezlopi_hub_device_group_updated); + + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + cJSON* cj_devgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_id_str); + if (cj_devgrp_id && cj_devgrp_id->valuestring) + { + char* devgrp_str = ezlopi_nvs_read_str(cj_devgrp_id->valuestring); + if (devgrp_str) + { + cJSON_AddRawToObject(__FUNCTION__, cj_response, ezlopi_result_str, devgrp_str); + ezlopi_free(__FUNCTION__, devgrp_str); + } + } + } +} + + + + +//---- item_group_api ------ + +void item_group_create(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON * cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + uint32_t new_item_grp_id = ezlopi_core_item_group_store_nvs_itemgrp(cj_params); + TRACE_D("new-item-grp-id: %08x", new_item_grp_id); + + if (new_item_grp_id) + { + char tmp_buff[32]; + snprintf(tmp_buff, sizeof(tmp_buff), "%08x", new_item_grp_id); + cJSON_AddStringToObject(__FUNCTION__, cj_request, ezlopi__id_str, tmp_buff); // this is for (reply) + ezlopi_core_item_group_new_itemgrp_populate(cj_params, new_item_grp_id); + } + } + } + } +} + +void item_group_get(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + cJSON* cj_itemgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_id_str); + if (cj_itemgrp_id && cj_itemgrp_id->valuestring) + { + char* devgrp_str = ezlopi_nvs_read_str(cj_itemgrp_id->valuestring); + if (devgrp_str) + { + cJSON_AddRawToObject(__FUNCTION__, cj_response, ezlopi_result_str, devgrp_str); + ezlopi_free(__FUNCTION__, devgrp_str); + } + else + { + cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + } + } + } + } +} + +void item_groups_list(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON* cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + ezlopi_core_item_group_get_list(cJSON_AddArrayToObject(__FUNCTION__, cj_result, "itemGroups")); + // cJSON* cj_ver_str = cJSON_GetObjectItem(__FUNCTION__, cj_request, "version"); + // if (cj_ver_str && cj_ver_str->valuestring && cj_ver_str->str_value_len) + // { + // cJSON_AddStringToObject(__FUNCTION__, cj_result, "version", cj_ver_str->valuestring); + // } + } + } +} + +void item_group_delete(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON * cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + cJSON* cj_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_id_str); + if (cj_id && cj_id->valuestring) + { + uint32_t item_grp_id = strtoul(cj_id->valuestring, NULL, 16); + + // 1. check if 'item_grp' is persistant + l_ezlopi_item_grp_t* curr_itemgrp = ezlopi_core_item_group_get_by_id(item_grp_id); + if (curr_itemgrp) + { + if (curr_itemgrp->persistent) + { // if 'true' + cJSON * cj_force = cJSON_GetObjectItem(__FUNCTION__, cj_params, "force"); + if (cj_force && cJSON_IsTrue(cj_force)) + { + ezlopi_nvs_delete_stored_data_by_id(item_grp_id); // from nvs + ezlopi_core_item_group_depopulate_by_id_v2(item_grp_id); // from ll + ezlopi_core_item_group_remove_id_from_list(item_grp_id); // from nvs-list + + cJSON_AddStringToObject(__FUNCTION__, cj_request, ezlopi__id_str, cj_id->valuestring); //for (reply_broadcast); if delete is successful + } + else + { + TRACE_E("Error!! , Unable to delete 'item_group_id' : [%d]", item_grp_id); + } + } + else + { + ezlopi_nvs_delete_stored_data_by_id(item_grp_id); + ezlopi_core_item_group_depopulate_by_id_v2(item_grp_id); + ezlopi_core_item_group_remove_id_from_list(item_grp_id); + } + } + } + } + } + } +} + +void item_group_update(cJSON* cj_request, cJSON* cj_response) +{ + if (cj_request && cj_response) + { + cJSON * cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + cJSON* cj_itemgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_id_str); + if (cj_itemgrp_id && cj_itemgrp_id->valuestring) + { + // CJSON_TRACE("dev-grp [new] : ", cj_itemgrp_id); + uint32_t req_devgrp_id = strtoul(cj_itemgrp_id->valuestring, NULL, 16); + + // edit in nvs and populate again + ezlopi_core_item_group_edit_by_id(req_devgrp_id, cj_params); + } + } + } + } +} + +////// updater for item-grps +////// for 'hub.item.group.__' + +void item_group_created(cJSON * cj_request, cJSON * cj_response) +{ + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_sender_str); + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_error_str); + + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_id_str, ezlopi_ui_broadcast_str); + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_msg_subclass_str, ezlopi_hub_item_group_created); + + cJSON* new_itemgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi__id_str); + if (new_itemgrp_id && new_itemgrp_id->valuestring) + { + char* new_itemgrp = ezlopi_nvs_read_str(new_itemgrp_id->valuestring); + if (new_itemgrp) + { + cJSON_AddRawToObject(__FUNCTION__, cj_response, ezlopi_result_str, new_itemgrp); + ezlopi_free(__FUNCTION__, new_itemgrp); + } + } +} + +void item_group_deleted(cJSON * cj_request, cJSON * cj_response) +{ + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_sender_str); + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_error_str); + + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_id_str, ezlopi_ui_broadcast_str); + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_msg_subclass_str, ezlopi_hub_item_group_deleted); + + cJSON* cj_result = cJSON_AddObjectToObject(__FUNCTION__, cj_response, ezlopi_result_str); + if (cj_result) + { + cJSON* deleted_itemgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi__id_str); // if delete was successful + if (deleted_itemgrp_id && deleted_itemgrp_id->valuestring) + { + cJSON_AddStringToObject(__FUNCTION__, cj_result, ezlopi__id_str, deleted_itemgrp_id->valuestring); + } + } +} + +void item_group_updated(cJSON * cj_request, cJSON * cj_response) +{ + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_sender_str); + cJSON_DeleteItemFromObject(__FUNCTION__, cj_response, ezlopi_error_str); + + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_id_str, ezlopi_ui_broadcast_str); + cJSON_AddStringToObject(__FUNCTION__, cj_response, ezlopi_msg_subclass_str, ezlopi_hub_item_group_updated); + + cJSON* cj_params = cJSON_GetObjectItem(__FUNCTION__, cj_request, ezlopi_params_str); + if (cj_params) + { + cJSON* cj_itemgrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_id_str); + if (cj_itemgrp_id && cj_itemgrp_id->valuestring) + { + char* devgrp_str = ezlopi_nvs_read_str(cj_itemgrp_id->valuestring); + if (devgrp_str) + { + cJSON_AddRawToObject(__FUNCTION__, cj_response, ezlopi_result_str, devgrp_str); + ezlopi_free(__FUNCTION__, devgrp_str); + } + } + } +} diff --git a/ezlopi-cloud/ezlopi-cloud-devices/ezlopi_cloud_devices.h b/ezlopi-cloud/ezlopi-cloud-devices/ezlopi_cloud_devices.h index 4a482e49..9858b942 100644 --- a/ezlopi-cloud/ezlopi-cloud-devices/ezlopi_cloud_devices.h +++ b/ezlopi-cloud/ezlopi-cloud-devices/ezlopi_cloud_devices.h @@ -19,6 +19,36 @@ extern "C" // char *devices_settings_list(const char *payload, uint32_t len, struct json_token *method, uint32_t msg_count); // char *devices_name_set(const char *payload, uint32_t len, struct json_token *method, uint32_t msg_count); + + + //--------- device-groups------- + void device_group_create(cJSON* cj_request, cJSON* cj_response); + void device_group_get(cJSON* cj_request, cJSON* cj_response); + void device_group_delete(cJSON* cj_request, cJSON* cj_response); + void device_group_update(cJSON* cj_request, cJSON* cj_response); + void device_groups_list(cJSON* cj_request, cJSON* cj_response); + void device_group_find(cJSON* cj_request, cJSON* cj_response); + void device_group_devitem_expand(cJSON* cj_request, cJSON* cj_response); + + ///////////// device-grp updaters + void device_group_created(cJSON * cj_request, cJSON * cj_response); + void device_group_deleted(cJSON * cj_request, cJSON * cj_response); + void device_group_updated(cJSON * cj_request, cJSON * cj_response); + + + //--------- item-groups------- + void item_group_create(cJSON* cj_request, cJSON* cj_response); + void item_group_get(cJSON* cj_request, cJSON* cj_response); + void item_group_delete(cJSON* cj_request, cJSON* cj_response); + void item_group_update(cJSON* cj_request, cJSON* cj_response); + void item_groups_list(cJSON* cj_request, cJSON* cj_response); + ///////////// item-grp updaters + void item_group_created(cJSON * cj_request, cJSON * cj_response); + void item_group_deleted(cJSON * cj_request, cJSON * cj_response); + void item_group_updated(cJSON * cj_request, cJSON * cj_response); + + + #ifdef __cplusplus } #endif diff --git a/ezlopi-cloud/ezlopi-cloud-scenes/ezlopi_cloud_scenes.c b/ezlopi-cloud/ezlopi-cloud-scenes/ezlopi_cloud_scenes.c index f47a5e8e..b0c1afbf 100755 --- a/ezlopi-cloud/ezlopi-cloud-scenes/ezlopi_cloud_scenes.c +++ b/ezlopi-cloud/ezlopi-cloud-scenes/ezlopi_cloud_scenes.c @@ -44,7 +44,7 @@ void scenes_create(cJSON* cj_request, cJSON* cj_response) { char tmp_buff[32]; snprintf(tmp_buff, sizeof(tmp_buff), "%08x", new_scene_id); - cJSON_AddStringToObject(__FUNCTION__, cj_request, ezlopi__id_str, tmp_buff); + cJSON_AddStringToObject(__FUNCTION__, cj_request, ezlopi__id_str, tmp_buff);// this is for (reply_broadcast) ezlopi_scenes_new_scene_populate(cj_params, new_scene_id); } } @@ -105,8 +105,8 @@ void scenes_delete(cJSON* cj_request, cJSON* cj_response) { uint32_t u_id = strtoul(cj_id->valuestring, NULL, 16); ezlopi_nvs_delete_stored_data_by_id(u_id); - ezlopi_scenes_depopulate_by_id_v2(u_id); ezlopi_scenes_remove_id_from_list_v2(u_id); + ezlopi_scenes_depopulate_by_id_v2(u_id); } } } @@ -533,11 +533,11 @@ void scenes_block_status_reset(cJSON * cj_request, cJSON * cj_response) cJSON *cj_block_id = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_blockId_str); if (cj_block_id && (NULL != cj_block_id->valuestring)) { - ezlopi_core_scene_reset_block_status(cj_scene_id->valuestring, cj_block_id->valuestring); + ezlopi_core_scene_reset_when_block(cj_scene_id->valuestring, cj_block_id->valuestring); } else { - ezlopi_core_scene_reset_block_status(cj_scene_id->valuestring, NULL); + ezlopi_core_scene_reset_when_block(cj_scene_id->valuestring, NULL); } } } diff --git a/ezlopi-core/ezlopi-core-api/ezlopi_core_api_macros.h b/ezlopi-core/ezlopi-core-api/ezlopi_core_api_macros.h index f6227961..684f8878 100644 --- a/ezlopi-core/ezlopi-core-api/ezlopi_core_api_macros.h +++ b/ezlopi-core/ezlopi-core-api/ezlopi_core_api_macros.h @@ -9,6 +9,20 @@ CLOUD_METHOD("hub.device.name.set", device_name_set, device_updated) CLOUD_METHOD("hub.device.armed.set", device_armed_set, device_updated) CLOUD_METHOD("hub.device.room.set", device_room_set, device_updated) +CLOUD_METHOD("hub.device.group.create", device_group_create, device_group_created) +CLOUD_METHOD("hub.device.group.delete", device_group_delete, device_group_deleted) +CLOUD_METHOD("hub.device.group.update", device_group_update, device_group_updated) +CLOUD_METHOD("hub.device.group.get", device_group_get, NULL) +CLOUD_METHOD("hub.device.groups.list", device_groups_list, NULL) +CLOUD_METHOD("hub.device.group.find", device_group_find, NULL) +CLOUD_METHOD("hub.device.item.group.expand", device_group_devitem_expand, NULL) + +CLOUD_METHOD("hub.item.group.create", item_group_create, item_group_created) +CLOUD_METHOD("hub.item.group.delete", item_group_delete, item_group_deleted) +CLOUD_METHOD("hub.item.group.update", item_group_update, item_group_updated) +CLOUD_METHOD("hub.item.group.get", item_group_get, NULL) +CLOUD_METHOD("hub.item.groups.list", item_groups_list, NULL) + #ifdef CONFIG_EZPI_UTIL_TRACE_EN CLOUD_METHOD("hub.log.set", ezlopi_hub_cloud_log_set, NULL) CLOUD_METHOD("hub.log.local.set", ezlopi_hub_serial_log_set, ezlopi_hub_serial_log_set_updater) @@ -70,7 +84,7 @@ CLOUD_METHOD("hub.scenes.list", scenes_list, NULL) CLOUD_METHOD("hub.scenes.create", scenes_create, scene_added) #warning "firmware crashes due to this method 'hub.scenes.run', need to fix this" -// CLOUD_METHOD("hub.scenes.run", scenes_run, NULL) // firmware crashes due to this method, need to fix this +CLOUD_METHOD("hub.scenes.run", scenes_run, NULL) // firmware crashes due to this method, need to fix this CLOUD_METHOD("hub.scenes.get", scenes_get, NULL) CLOUD_METHOD("hub.scenes.edit", scenes_edit, scene_changed) diff --git a/ezlopi-core/ezlopi-core-buffer/ezlopi_core_buffer.c b/ezlopi-core/ezlopi-core-buffer/ezlopi_core_buffer.c index da4694f7..eb6d4fb2 100644 --- a/ezlopi-core/ezlopi-core-buffer/ezlopi_core_buffer.c +++ b/ezlopi-core/ezlopi-core-buffer/ezlopi_core_buffer.c @@ -116,6 +116,6 @@ void ezlopi_core_buffer_release(void) } else { - // TRACE_E("buffer release failed!"); + TRACE_E("buffer release failed!"); } } diff --git a/ezlopi-core/ezlopi-core-cloud/ezlopi_core_cloud.c b/ezlopi-core/ezlopi-core-cloud/ezlopi_core_cloud.c index 9e335059..c02b8d89 100644 --- a/ezlopi-core/ezlopi-core-cloud/ezlopi_core_cloud.c +++ b/ezlopi-core/ezlopi-core-cloud/ezlopi_core_cloud.c @@ -14,6 +14,9 @@ const uint32_t EXPRESSION_ID_START = 0x80000000; const uint32_t MODES_ID_START = 0x90000000; const uint32_t SCENE_GROUP_ID_START = 0xA0000000; const uint32_t SCENE_WHEN_BLOCKID_START = 0xB0000000; +const uint32_t DEVICE_GROUPID_START = 0xC0000000; +const uint32_t ITEM_GROUPID_START = 0xD0000000; + static uint32_t g_device_id = 0; static uint32_t g_item_id = 0; @@ -25,6 +28,8 @@ static uint32_t g_script_id = 0; static uint32_t g_expression_id = 0; static uint32_t g_scene_group_id = 0; static uint32_t g_scene_when_blockId = 0; +static uint32_t g_device_group_id = 0; +static uint32_t g_item_group_id = 0; static uint32_t ezlopi_get_mac_crc(void) { @@ -138,7 +143,6 @@ void ezlopi_cloud_update_script_id(uint32_t a_script_id) g_script_id = (a_script_id > g_script_id) ? a_script_id : g_script_id; } - uint32_t ezlopi_cloud_generate_script_id(void) { g_script_id = (0 == g_script_id) ? (SCRIPT_ID_START + ezlopi_get_mac_crc()) : (g_script_id + 1); @@ -173,8 +177,29 @@ uint32_t ezlopi_cloud_generate_scene_group_id(void) return g_scene_group_id; } -void ezlopi_cloud_update_group_id(uint32_t a_group_id) +void ezlopi_cloud_update_group_id(uint32_t a_device_id) { - g_scene_group_id = (a_group_id > g_scene_group_id) ? a_group_id : g_scene_group_id; + g_scene_group_id = (a_device_id > g_scene_group_id) ? a_device_id : g_scene_group_id; } +uint32_t ezlopi_cloud_generate_device_group_id(void) +{ + g_device_group_id = (0 == g_device_group_id) ? (DEVICE_GROUPID_START + ezlopi_get_mac_crc()) : (g_device_group_id + 1); + return g_device_group_id; +} + +void ezlopi_cloud_update_device_group_id(uint32_t a_device_group_id) +{ + g_device_group_id = (a_device_group_id > g_device_group_id) ? a_device_group_id : g_device_group_id; +} + +uint32_t ezlopi_cloud_generate_item_group_id(void) +{ + g_item_group_id = (0 == g_item_group_id) ? (ITEM_GROUPID_START + ezlopi_get_mac_crc()) : (g_item_group_id + 1); + return g_item_group_id; +} + +void ezlopi_cloud_update_item_group_id(uint32_t a_item_group_id) +{ + g_item_group_id = (a_item_group_id > g_item_group_id) ? a_item_group_id : g_item_group_id; +} diff --git a/ezlopi-core/ezlopi-core-cloud/ezlopi_core_cloud.h b/ezlopi-core/ezlopi-core-cloud/ezlopi_core_cloud.h index 8a5a92a2..3de85d55 100644 --- a/ezlopi-core/ezlopi-core-cloud/ezlopi_core_cloud.h +++ b/ezlopi-core/ezlopi-core-cloud/ezlopi_core_cloud.h @@ -90,6 +90,8 @@ extern const uint32_t EXPRESSION_ID_START; extern const uint32_t MODES_ID_START; extern const uint32_t SCENE_GROUP_ID_START; extern const uint32_t SCENE_WHEN_BLOCKID_START; +extern const uint32_t DEVICE_GROUPID_START; + uint32_t ezlopi_cloud_generate_device_id(void); void ezlopi_cloud_update_device_id(uint32_t device_id); @@ -121,6 +123,12 @@ void ezlopi_cloud_update_room_id(uint32_t a_room_id); uint32_t ezlopi_cloud_generate_scene_group_id(void); void ezlopi_cloud_update_group_id(uint32_t a_group_id); +uint32_t ezlopi_cloud_generate_device_group_id(void); +void ezlopi_cloud_update_device_group_id(uint32_t a_device_group_id); + +uint32_t ezlopi_cloud_generate_item_group_id(void); +void ezlopi_cloud_update_item_group_id(uint32_t a_item_group_id); + // uint32_t ezlopi_cloud_get_modes_initial_id(void); #endif // _EZLOPI_CORE_CLOUD_H_ diff --git a/ezlopi-core/ezlopi-core-devices/CMakeLists.txt b/ezlopi-core/ezlopi-core-devices/CMakeLists.txt index 727872a5..c0a400f4 100644 --- a/ezlopi-core/ezlopi-core-devices/CMakeLists.txt +++ b/ezlopi-core/ezlopi-core-devices/CMakeLists.txt @@ -91,7 +91,7 @@ set(EZLOPI_SENSOR_DEVICE_COMPONENTS ) -idf_component_register(SRCS "ezlopi_core_devices_list.c" "ezlopi_core_devices.c" "ezlopi_core_device_value_updated.c" "${config_src}" +idf_component_register(SRCS "ezlopi_core_device_group.c" "ezlopi_core_devices_list.c" "ezlopi_core_devices.c" "ezlopi_core_device_value_updated.c" "${config_src}" INCLUDE_DIRS "." REQUIRES ${EZLOPI_CORE_COMPONENTS} ${EZLOPI_HAL_COMPONENTS} diff --git a/ezlopi-core/ezlopi-core-devices/ezlopi_core_device_group.c b/ezlopi-core/ezlopi-core-devices/ezlopi_core_device_group.c new file mode 100644 index 00000000..98a0f7d7 --- /dev/null +++ b/ezlopi-core/ezlopi-core-devices/ezlopi_core_device_group.c @@ -0,0 +1,1816 @@ + +#include "ezlopi_core_nvs.h" +#include "ezlopi_core_device_group.h" + +#include "ezlopi_cloud_constants.h" + +#include "EZLOPI_USER_CONFIG.h" + +//-------------------------------------------------------------------------------- +static l_ezlopi_device_grp_t* l_device_grp_head = NULL; +static l_ezlopi_item_grp_t* l_item_grp_head = NULL; + +enum e_devicGrp_vs_itemGrp_choice +{ + DEVICE_GROUP_SELECTED = 0, + ITEM_GROUP_SELECTED = 1 +}; +//-------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------- +// Static functions +//-------------------------------------------------------------------------------- +static void __ezlopi_core_device_group_print(l_ezlopi_device_grp_t* device_grp_node) +{ +#if (1 == ENABLE_TRACE) + if (device_grp_node) + { + TRACE_D("\t-------------------- DEVICE-GROUP --------------------"); + TRACE_D("\t|-- Group_id: %08x", device_grp_node->_id); + TRACE_D("\t|-- Group_name: %s", device_grp_node->name); + CJSON_TRACE("\t|-- Categories", device_grp_node->categories); + CJSON_TRACE("\t|-- Devices", device_grp_node->devices); + CJSON_TRACE("\t|-- Exceptions", device_grp_node->exceptions); + TRACE_D("\t|-- Persistent: %s", device_grp_node->persistent ? "True" : "False"); + TRACE_D("\t|-- Entry_Delay: %s", (EZLOPI_DEVICE_GRP_ENTRYDELAY_NORMAL == device_grp_node->entry_delay) ? "normal" + : (EZLOPI_DEVICE_GRP_ENTRYDELAY_LONG_EXTENDED == device_grp_node->entry_delay) ? "long_extended" + : (EZLOPI_DEVICE_GRP_ENTRYDELAY_EXTENDED == device_grp_node->entry_delay) ? "extended" + : (EZLOPI_DEVICE_GRP_ENTRYDELAY_INSTANT == device_grp_node->entry_delay) ? "instant" + : "none"); + TRACE_D("\t|-- Follow_Entry: %s", device_grp_node->follow_entry ? "True" : "False"); + TRACE_D("\t|-- Role: %s", (EZLOPI_DEVICE_GRP_ROLE_HOUSE_MODES == device_grp_node->role) ? "house_modes" : "user"); + TRACE_D("\t|-- Package_Id: %s", device_grp_node->package_id); + TRACE_D("\t|-- ----------------- ----------- --------------------"); + } +#endif +} +static void __ezlopi_core_item_group_print(l_ezlopi_item_grp_t* item_grp_node) +{ +#if (1 == ENABLE_TRACE) + if (item_grp_node) + { + TRACE_D("\t|------------------- ITEM-GROUP --------------------"); + TRACE_D("\t|-- Group_id: %08x", item_grp_node->_id); + TRACE_D("\t|-- Group_name: %s", item_grp_node->name); + TRACE_D("\t|-- Has_Getter: %s", item_grp_node->has_getter ? "True" : "False"); + TRACE_D("\t|-- Has_Setter: %s", item_grp_node->has_setter ? "True" : "False"); + TRACE_D("\t|-- Persistent: %s", item_grp_node->persistent ? "True" : "False"); + CJSON_TRACE("\t|-- Item_Names", item_grp_node->item_names); + TRACE_D("\t|-- Value_Type: %s", item_grp_node->value_type); + CJSON_TRACE("\t|-- Enum", item_grp_node->enum_values); + TRACE_D("\t|-- Value_Type_Family: %s", item_grp_node->value_type_family); + TRACE_D("\t|-- Role: %s", (EZLOPI_ITEM_GRP_ROLE_HOUSE_MODES == item_grp_node->role) ? "house_modes" : (EZLOPI_ITEM_GRP_ROLE_LIFE_SAFETY == item_grp_node->role) ? "lifeSafety" : "empty"); + CJSON_TRACE("\t|-- Info", item_grp_node->info); + TRACE_D("\t|-- ----------------- ----------- --------------------"); + } +#endif +} + +/** + * @brief This function edits "req_devgrp_node" using "cj_devgrp_new" + * + * @param req_devgrp_node target 'devgrp_node' + * @param cj_devgrp_new new cjson + */ +static void __edit_devgrp_from_ll(l_ezlopi_device_grp_t* req_devgrp_node, cJSON* cj_devgrp_new) +{ + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, ezlopi_name_str)) ? + (CJSON_GET_VALUE_STRING_BY_COPY(cj_devgrp_new, ezlopi_name_str, req_devgrp_node->name)) : + ((req_devgrp_node->name) ? cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, ezlopi_name_str, req_devgrp_node->name) : NULL); + + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, ezlopi_persistent_str)) ? + (CJSON_GET_VALUE_BOOL(cj_devgrp_new, ezlopi_persistent_str, req_devgrp_node->persistent)) : + cJSON_AddBoolToObject(__FUNCTION__, cj_devgrp_new, ezlopi_persistent_str, req_devgrp_node->persistent); + + + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, "followEntry")) ? + (CJSON_GET_VALUE_BOOL(cj_devgrp_new, "followEntry", req_devgrp_node->follow_entry)) : + cJSON_AddBoolToObject(__FUNCTION__, cj_devgrp_new, "followEntry", req_devgrp_node->follow_entry); + + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, "packageId")) ? + (CJSON_GET_VALUE_STRING_BY_COPY(cj_devgrp_new, "packageId", req_devgrp_node->package_id)) : + ((req_devgrp_node->package_id) ? cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, "packageId", req_devgrp_node->package_id) : NULL); + + + // ------------- categories ------------- + { + cJSON * cj_categories = cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, "categories"); + if (cj_categories && cJSON_IsArray(cj_categories)) + { + cJSON_Delete(__FUNCTION__, req_devgrp_node->categories); + req_devgrp_node->categories = cJSON_Duplicate(__FUNCTION__, cj_categories, cJSON_True); + } + else + { + if (req_devgrp_node->categories) + { + cJSON_AddItemToObject(__FUNCTION__, cj_devgrp_new, "categories", cJSON_Duplicate(__FUNCTION__, cj_categories, cJSON_True)); + } + } + } + + // ------------- devices ------------- + { + cJSON * cj_devices = cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, "devices"); + if (cj_devices && cJSON_IsArray(cj_devices)) + { + cJSON_Delete(__FUNCTION__, req_devgrp_node->devices); + req_devgrp_node->devices = cJSON_Duplicate(__FUNCTION__, cj_devices, cJSON_True); + } + else + { + if (req_devgrp_node->devices) + { + cJSON_AddItemToObject(__FUNCTION__, cj_devgrp_new, "devices", cJSON_Duplicate(__FUNCTION__, cj_devices, cJSON_True)); + } + } + } + + // ------------- exceptions ------------- + { + cJSON * cj_exceptions = cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, "exceptions"); + if (cj_exceptions && cJSON_IsArray(cj_exceptions)) + { + cJSON_Delete(__FUNCTION__, req_devgrp_node->exceptions); + req_devgrp_node->exceptions = cJSON_Duplicate(__FUNCTION__, cj_exceptions, cJSON_True); + } + else + { + if (req_devgrp_node->exceptions) + { + cJSON_AddItemToObject(__FUNCTION__, cj_devgrp_new, "exceptions", cJSON_Duplicate(__FUNCTION__, cj_exceptions, cJSON_True)); + } + } + } + + // ------------- entryDelay ------------- + { + cJSON *cj_entry_delay = cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, "entryDelay"); + if (cj_entry_delay && cj_entry_delay->valuestring && cj_entry_delay->str_value_len) + { + req_devgrp_node->entry_delay = ((0 == strncmp(cj_entry_delay->valuestring, "normal", 7)) ? EZLOPI_DEVICE_GRP_ENTRYDELAY_NORMAL + : (0 == strncmp(cj_entry_delay->valuestring, "long_extended", 14)) ? EZLOPI_DEVICE_GRP_ENTRYDELAY_LONG_EXTENDED + : (0 == strncmp(cj_entry_delay->valuestring, "extended", 9)) ? EZLOPI_DEVICE_GRP_ENTRYDELAY_EXTENDED + : (0 == strncmp(cj_entry_delay->valuestring, "instant", 8)) ? EZLOPI_DEVICE_GRP_ENTRYDELAY_INSTANT + : EZLOPI_DEVICE_GRP_ENTRYDELAY_NONE); + } + else + { + switch (req_devgrp_node->entry_delay) + { + case EZLOPI_DEVICE_GRP_ENTRYDELAY_NORMAL: + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, "entryDelay", "normal"); + break; + case EZLOPI_DEVICE_GRP_ENTRYDELAY_LONG_EXTENDED: + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, "entryDelay", "long_extended"); + break; + case EZLOPI_DEVICE_GRP_ENTRYDELAY_EXTENDED: + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, "entryDelay", "extended"); + break; + case EZLOPI_DEVICE_GRP_ENTRYDELAY_INSTANT: + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, "entryDelay", "instant"); + break; + case EZLOPI_DEVICE_GRP_ENTRYDELAY_NONE: + default: + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, "entryDelay", "none"); + break; + } + } + } + + // ------------- role ------------- + { + // req_devgrp_node->role = EZLOPI_DEVICE_GRP_ROLE_USER; + cJSON *cj_role = cJSON_GetObjectItem(__FUNCTION__, cj_devgrp_new, "role"); + if (cj_role && cj_role->valuestring && cj_role->str_value_len) + { + req_devgrp_node->role = ((0 == strncmp(cj_role->valuestring, "house_modes", 12)) ? EZLOPI_DEVICE_GRP_ROLE_HOUSE_MODES : EZLOPI_DEVICE_GRP_ROLE_USER); + } + else + { + switch (req_devgrp_node->role) + { + case EZLOPI_DEVICE_GRP_ROLE_HOUSE_MODES: + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, "role", "house_modes"); + break; + case EZLOPI_DEVICE_GRP_ROLE_USER: + default: + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp_new, "role", "user"); + break; + } + } + } + __ezlopi_core_device_group_print(req_devgrp_node); +} +static void __edit_itemgrp_from_ll(l_ezlopi_item_grp_t* req_itemgrp_node, cJSON* cj_itemgrp_new) +{ + + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, ezlopi_name_str)) ? + (CJSON_GET_VALUE_STRING_BY_COPY(cj_itemgrp_new, ezlopi_name_str, req_itemgrp_node->name)) : + ((req_itemgrp_node->name) ? cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp_new, ezlopi_name_str, req_itemgrp_node->name) : NULL); + + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, "hasGetter")) ? + (CJSON_GET_VALUE_BOOL(cj_itemgrp_new, "hasGetter", req_itemgrp_node->has_getter)) : + cJSON_AddBoolToObject(__FUNCTION__, cj_itemgrp_new, "hasGetter", req_itemgrp_node->has_getter); + + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, "hasSetter")) ? + (CJSON_GET_VALUE_BOOL(cj_itemgrp_new, "hasSetter", req_itemgrp_node->has_setter)) : + cJSON_AddBoolToObject(__FUNCTION__, cj_itemgrp_new, "hasSetter", req_itemgrp_node->has_setter); + + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, ezlopi_persistent_str)) ? + (CJSON_GET_VALUE_BOOL(cj_itemgrp_new, ezlopi_persistent_str, req_itemgrp_node->persistent)) : + cJSON_AddBoolToObject(__FUNCTION__, cj_itemgrp_new, ezlopi_persistent_str, req_itemgrp_node->persistent); + + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, "valueType")) ? + (CJSON_GET_VALUE_STRING_BY_COPY(cj_itemgrp_new, "valueType", req_itemgrp_node->value_type)) : + ((req_itemgrp_node->value_type) ? cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp_new, "valueType", req_itemgrp_node->value_type) : NULL); + + if (req_itemgrp_node->value_type && strlen(req_itemgrp_node->value_type)) + { + (NULL != cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, "valueTypeFamily")) ? + (CJSON_GET_VALUE_STRING_BY_COPY(cj_itemgrp_new, "valueTypeFamily", req_itemgrp_node->value_type_family)) : + ((req_itemgrp_node->value_type_family) ? cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp_new, "valueTypeFamily", req_itemgrp_node->value_type_family) : NULL); + } + + // ------------- itemNames ------------- + { + cJSON * cj_item_names = cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, "itemNames"); + if (cj_item_names && cJSON_IsArray(cj_item_names)) + { + cJSON_Delete(__FUNCTION__, req_itemgrp_node->item_names); + req_itemgrp_node->item_names = cJSON_Duplicate(__FUNCTION__, cj_item_names, cJSON_True); + } + else + { + if (req_itemgrp_node->item_names) + { + cJSON_AddItemToObject(__FUNCTION__, cj_itemgrp_new, "itemNames", cJSON_Duplicate(__FUNCTION__, req_itemgrp_node->item_names, cJSON_True)); + } + } + } + + // ------------- enums ------------- + { + cJSON * cj_enums = cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, ezlopi_enum_str); + if (cj_enums && cJSON_IsArray(cj_enums)) + { + cJSON_Delete(__FUNCTION__, req_itemgrp_node->enum_values); + req_itemgrp_node->enum_values = cJSON_Duplicate(__FUNCTION__, cj_enums, cJSON_True); + } + else + { + if (req_itemgrp_node->enum_values) + { + cJSON_AddItemToObject(__FUNCTION__, cj_itemgrp_new, ezlopi_enum_str, cJSON_Duplicate(__FUNCTION__, req_itemgrp_node->enum_values, cJSON_True)); + } + } + } + + // ------------- role ------------- + { + // req_itemgrp_node->role = EZLOPI_ITEM_GRP_ROLE_EMPTY; + cJSON *cj_role = cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, "role"); + if (cj_role && cj_role->valuestring && cj_role->str_value_len) + { + req_itemgrp_node->role = ((0 == strncmp(cj_role->valuestring, "house_modes", 12)) ? EZLOPI_ITEM_GRP_ROLE_HOUSE_MODES + : (0 == strncmp(cj_role->valuestring, "lifeSafety", 12)) ? EZLOPI_ITEM_GRP_ROLE_LIFE_SAFETY + : EZLOPI_ITEM_GRP_ROLE_EMPTY); + } + else + { + switch (req_itemgrp_node->role) + { + case EZLOPI_ITEM_GRP_ROLE_HOUSE_MODES: + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp_new, "role", "house_modes"); + break; + case EZLOPI_ITEM_GRP_ROLE_LIFE_SAFETY: + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp_new, "role", "lifeSafety"); + break; + case EZLOPI_ITEM_GRP_ROLE_EMPTY: + default: + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp_new, "role", "empty"); + break; + } + } + } + + // ------------- info ------------- + { + cJSON * cj_info = cJSON_GetObjectItem(__FUNCTION__, cj_itemgrp_new, ezlopi_info_str); + if (cj_info && cJSON_IsArray(cj_info)) + { + cJSON_Delete(__FUNCTION__, req_itemgrp_node->info); + req_itemgrp_node->info = cJSON_Duplicate(__FUNCTION__, cj_info, cJSON_True); + } + else + { + if (req_itemgrp_node->info) + { + cJSON_AddItemToObject(__FUNCTION__, cj_itemgrp_new, ezlopi_info_str, cJSON_Duplicate(__FUNCTION__, req_itemgrp_node->info, cJSON_True)); + } + } + } + __ezlopi_core_item_group_print(req_itemgrp_node); +} + +/** + * @brief This function edits the populated 'devgrp_id' within linkedlist + * + * @param devgrp_id target 'devgrp_id' + * @param cj_devgrp_new new cjson to replace old. + * @return int + */ +static int __edit_and_update_ll_devgrp_by_id(uint32_t devgrp_id, cJSON* cj_devgrp_new) +{ + int ret = 0; + // CJSON_TRACE("cj_updated_devgrp_node :", cj_devgrp_new); + + if (devgrp_id && cj_devgrp_new) + { + l_ezlopi_device_grp_t* req_devgrp_node = ezlopi_core_device_group_get_by_id(devgrp_id); + if (req_devgrp_node) + { + __edit_devgrp_from_ll(req_devgrp_node, cj_devgrp_new); + ret = 1; + } + } + return ret; +} +static int __edit_and_update_ll_itemgrp_by_id(uint32_t itemgrp_id, cJSON* cj_itemgrp_new) +{ + int ret = 0; + CJSON_TRACE("cj_updated_itemgrp_node :", cj_itemgrp_new); + + if (itemgrp_id && cj_itemgrp_new) + { + l_ezlopi_item_grp_t* req_itemgrp_node = ezlopi_core_item_group_get_by_id(itemgrp_id); + if (req_itemgrp_node) + { + __edit_itemgrp_from_ll(req_itemgrp_node, cj_itemgrp_new); + ret = 1; + } + } + return ret; +} + +/** + * @brief This function replaces old with 'new_dev/item_grp' + * + * @param cj_grp_new 'new_grp' in cjson format + * @param _id Target nvs '_id'. + * @return int + */ +static int __edit_group_and_store_updated_to_nvs(uint32_t _id, cJSON* cj_grp_new) +{ + int ret = 0; + if (cj_grp_new && _id) + { + char grp_id_str[32]; + snprintf(grp_id_str, sizeof(grp_id_str), "%08x", _id); + if (cJSON_AddStringToObject(__FUNCTION__, cj_grp_new, ezlopi__id_str, grp_id_str)) // since we need to replace 'id' with '_id' ; before storing in nvs . + { + cJSON_DeleteItemFromObject(__FUNCTION__, cj_grp_new, "id"); + } + + char* update_grp_str = cJSON_PrintBuffered(__FUNCTION__, cj_grp_new, 1024, false); + TRACE_D("length of 'update_grp_str': %d", strlen(update_grp_str)); + + if (update_grp_str) + { + ezlopi_nvs_delete_stored_data_by_name(grp_id_str); // delete --> '0x0..grp ' : '{}' + ret = ezlopi_nvs_write_str(update_grp_str, strlen(update_grp_str), grp_id_str); // write --> '0x0..grp ' : '{}' + + ezlopi_free(__FUNCTION__, update_grp_str); + } + } + return ret; +} + +/** + * @brief This function de-links a specific node having req '_id' + * + * @param _id Target 'device_group_id' + * @return l_ezlopi_device_grp_t* + */ +static l_ezlopi_device_grp_t* __device_group_pop_by_id(uint32_t _id) +{ + l_ezlopi_device_grp_t* ret_devgrp = NULL; + + if (_id == l_device_grp_head->_id) + { + ret_devgrp = l_device_grp_head; + l_device_grp_head = l_device_grp_head->next; + ret_devgrp->next = NULL; + } + else + { + l_ezlopi_device_grp_t* curr_devgrp = l_device_grp_head; + while (curr_devgrp->next) + { + if (_id == curr_devgrp->next->_id) + { + ret_devgrp = curr_devgrp->next; + curr_devgrp->next = curr_devgrp->next->next; + ret_devgrp->next = NULL; + break; + } + curr_devgrp = curr_devgrp->next; + } + } + + return ret_devgrp; +} +static l_ezlopi_item_grp_t* __item_group_pop_by_id(uint32_t _id) +{ + l_ezlopi_item_grp_t* ret_itemgrp = NULL; + + if (_id == l_item_grp_head->_id) + { + ret_itemgrp = l_item_grp_head; + l_item_grp_head = l_item_grp_head->next; + ret_itemgrp->next = NULL; + } + else + { + l_ezlopi_item_grp_t* curr_itemgrp = l_item_grp_head; + while (curr_itemgrp->next) + { + if (_id == curr_itemgrp->next->_id) + { + ret_itemgrp = curr_itemgrp->next; + curr_itemgrp->next = curr_itemgrp->next->next; + ret_itemgrp->next = NULL; + break; + } + curr_itemgrp = curr_itemgrp->next; + } + } + + return ret_itemgrp; +} + +static void __device_group_delete_node(l_ezlopi_device_grp_t* devgrp_node) +{ + if (devgrp_node) + { + if (NULL != devgrp_node->categories) + { + cJSON_Delete(__FUNCTION__, devgrp_node->categories); + devgrp_node->categories = NULL; + } + + if (NULL != devgrp_node->devices) + { + cJSON_Delete(__FUNCTION__, devgrp_node->devices); + devgrp_node->devices = NULL; + } + + if (NULL != devgrp_node->exceptions) + { + cJSON_Delete(__FUNCTION__, devgrp_node->exceptions); + devgrp_node->exceptions = NULL; + } + + __device_group_delete_node(devgrp_node->next); + devgrp_node->next = NULL; + ezlopi_free(__FUNCTION__, devgrp_node); + } +} +static void __item_group_delete_node(l_ezlopi_item_grp_t* itemgrp_node) +{ + if (itemgrp_node) + { + if (NULL != itemgrp_node->item_names) + { + cJSON_Delete(__FUNCTION__, itemgrp_node->item_names); + itemgrp_node->item_names = NULL; + } + + // if (NULL != itemgrp_node->value_type_family) + // { + // cJSON_Delete(__FUNCTION__, itemgrp_node->value_type_family); + // itemgrp_node->value_type_family = NULL; + // } + + if (NULL != itemgrp_node->enum_values) + { + cJSON_Delete(__FUNCTION__, itemgrp_node->enum_values); + itemgrp_node->enum_values = NULL; + } + + if (NULL != itemgrp_node->info) + { + cJSON_Delete(__FUNCTION__, itemgrp_node->info); + itemgrp_node->info = NULL; + } + + __item_group_delete_node(itemgrp_node->next); + itemgrp_node->next = NULL; + ezlopi_free(__FUNCTION__, itemgrp_node); + } +} + +static l_ezlopi_device_grp_t* ____device_grp_create_node(cJSON* cj_device_grp, uint32_t device_grp_id) +{ + l_ezlopi_device_grp_t* new_device_grp_node = NULL; + if (cj_device_grp) + { + new_device_grp_node = ezlopi_malloc(__FUNCTION__, sizeof(l_ezlopi_device_grp_t)); + if (new_device_grp_node) + { + memset(new_device_grp_node, 0, sizeof(l_ezlopi_device_grp_t)); + + new_device_grp_node->_id = device_grp_id; + + CJSON_GET_VALUE_STRING_BY_COPY(cj_device_grp, ezlopi_name_str, new_device_grp_node->name); + CJSON_GET_VALUE_BOOL(cj_device_grp, ezlopi_persistent_str, new_device_grp_node->persistent); + CJSON_GET_VALUE_BOOL(cj_device_grp, "followEntry", new_device_grp_node->follow_entry); + CJSON_GET_VALUE_STRING_BY_COPY(cj_device_grp, "packageId", new_device_grp_node->package_id); + + { + cJSON * cj_categories = cJSON_GetObjectItem(__FUNCTION__, cj_device_grp, "categories"); + if (cj_categories && cJSON_IsArray(cj_categories)) + { + new_device_grp_node->categories = cJSON_Duplicate(__FUNCTION__, cj_categories, cJSON_True); + } + } + + { + cJSON * cj_devices = cJSON_GetObjectItem(__FUNCTION__, cj_device_grp, "devices"); + if (cj_devices && cJSON_IsArray(cj_devices)) + { + new_device_grp_node->devices = cJSON_Duplicate(__FUNCTION__, cj_devices, cJSON_True); + } + } + + { + cJSON * cj_exceptions = cJSON_GetObjectItem(__FUNCTION__, cj_device_grp, "exceptions"); + if (cj_exceptions && cJSON_IsArray(cj_exceptions)) + { + new_device_grp_node->exceptions = cJSON_Duplicate(__FUNCTION__, cj_exceptions, cJSON_True); + } + } + + { + cJSON *cj_entry_delay = cJSON_GetObjectItem(__FUNCTION__, cj_device_grp, "entryDelay"); + if (cj_entry_delay && cj_entry_delay->valuestring && cj_entry_delay->str_value_len) + { + new_device_grp_node->entry_delay = ((0 == strncmp(cj_entry_delay->valuestring, "normal", 7)) ? EZLOPI_DEVICE_GRP_ENTRYDELAY_NORMAL + : (0 == strncmp(cj_entry_delay->valuestring, "long_extended", 14)) ? EZLOPI_DEVICE_GRP_ENTRYDELAY_LONG_EXTENDED + : (0 == strncmp(cj_entry_delay->valuestring, "extended", 9)) ? EZLOPI_DEVICE_GRP_ENTRYDELAY_EXTENDED + : (0 == strncmp(cj_entry_delay->valuestring, "instant", 8)) ? EZLOPI_DEVICE_GRP_ENTRYDELAY_INSTANT + : EZLOPI_DEVICE_GRP_ENTRYDELAY_NONE); + } + } + + { + cJSON *cj_role = cJSON_GetObjectItem(__FUNCTION__, cj_device_grp, "role"); + if (cj_role && cj_role->valuestring && cj_role->str_value_len) + { + new_device_grp_node->role = ((0 == strncmp(cj_role->valuestring, "house_modes", 12)) ? EZLOPI_DEVICE_GRP_ROLE_HOUSE_MODES : EZLOPI_DEVICE_GRP_ROLE_USER); + } + } + + // __ezlopi_core_device_group_print(new_device_grp_node); + } + } + return new_device_grp_node; +} +static l_ezlopi_item_grp_t* ____item_grp_create_node(cJSON* cj_item_grp, uint32_t item_grp_id) +{ + l_ezlopi_item_grp_t* new_item_grp_node = NULL; + if (cj_item_grp) + { + new_item_grp_node = ezlopi_malloc(__FUNCTION__, sizeof(l_ezlopi_item_grp_t)); + if (new_item_grp_node) + { + memset(new_item_grp_node, 0, sizeof(l_ezlopi_item_grp_t)); + + new_item_grp_node->_id = item_grp_id; + + CJSON_GET_VALUE_STRING_BY_COPY(cj_item_grp, ezlopi_name_str, new_item_grp_node->name); + CJSON_GET_VALUE_BOOL(cj_item_grp, "hasGetter", new_item_grp_node->has_getter); + CJSON_GET_VALUE_BOOL(cj_item_grp, "hasSetter", new_item_grp_node->has_setter); + CJSON_GET_VALUE_BOOL(cj_item_grp, ezlopi_persistent_str, new_item_grp_node->persistent); + CJSON_GET_VALUE_STRING_BY_COPY(cj_item_grp, ezlopi_valueType_str, new_item_grp_node->value_type); + + { + cJSON * cj_item_names = cJSON_GetObjectItem(__FUNCTION__, cj_item_grp, "itemNames"); + if (cj_item_names && cJSON_IsArray(cj_item_names)) + { + new_item_grp_node->item_names = cJSON_Duplicate(__FUNCTION__, cj_item_names, cJSON_True); + } + } + + { + cJSON * cj_enum = cJSON_GetObjectItem(__FUNCTION__, cj_item_grp, ezlopi_enum_str); + if (cj_enum && cJSON_IsArray(cj_enum)) + { + new_item_grp_node->enum_values = cJSON_Duplicate(__FUNCTION__, cj_enum, cJSON_True); + } + } + + { // Add ('value_type' is abscent) valueType_Family [cjson] + if (NULL == new_item_grp_node->value_type) + { + CJSON_GET_VALUE_STRING_BY_COPY(cj_item_grp, "valueTypeFamily", new_item_grp_node->value_type_family); + } + } + + { + cJSON *cj_role = cJSON_GetObjectItem(__FUNCTION__, cj_item_grp, "role"); + if (cj_role && cj_role->valuestring && cj_role->str_value_len) + { + new_item_grp_node->role = ((0 == strncmp(cj_role->valuestring, "house_modes", 12)) ? EZLOPI_ITEM_GRP_ROLE_HOUSE_MODES + : (0 == strncmp(cj_role->valuestring, "lifeSafety", 12)) ? EZLOPI_ITEM_GRP_ROLE_LIFE_SAFETY + : EZLOPI_ITEM_GRP_ROLE_EMPTY); + } + } + + { + cJSON * cj_info = cJSON_GetObjectItem(__FUNCTION__, cj_item_grp, ezlopi_info_str); + if (cj_info && cJSON_IsObject(cj_info)) + { + new_item_grp_node->info = cJSON_Duplicate(__FUNCTION__, cj_info, cJSON_True); + } + } + + // __ezlopi_core_item_group_print(new_item_grp_node); + } + } + return new_item_grp_node; +} + +static l_ezlopi_device_grp_t* __device_group_populate(cJSON* cj_device_grp, uint32_t device_grp_id) +{ + l_ezlopi_device_grp_t* new_device_grp_node = NULL; + if (l_device_grp_head) + { + l_ezlopi_device_grp_t* current_device_grp = l_device_grp_head; + while (current_device_grp->next) + { + current_device_grp = current_device_grp->next; + } + + current_device_grp->next = ____device_grp_create_node(cj_device_grp, device_grp_id); + new_device_grp_node = current_device_grp->next; + } + else + { + // CJSON_TRACE("new-device-group", cj_device_grp); + l_device_grp_head = ____device_grp_create_node(cj_device_grp, device_grp_id); + new_device_grp_node = l_device_grp_head; + } + + return new_device_grp_node; +} +static l_ezlopi_item_grp_t* __item_group_populate(cJSON* cj_item_grp, uint32_t item_grp_id) +{ + l_ezlopi_item_grp_t* new_item_grp_node = NULL; + if (l_item_grp_head) + { + l_ezlopi_item_grp_t* current_item_grp = l_item_grp_head; + while (current_item_grp->next) + { + current_item_grp = current_item_grp->next; + } + + current_item_grp->next = ____item_grp_create_node(cj_item_grp, item_grp_id); + new_item_grp_node = current_item_grp->next; + } + else + { + // CJSON_TRACE("new-item-group", cj_item_grp); + l_item_grp_head = ____item_grp_create_node(cj_item_grp, item_grp_id); + new_item_grp_node = l_item_grp_head; + } + + return new_item_grp_node; +} + + +//-------------------------------------------------------------------------------- +// Device-Group Functions +//-------------------------------------------------------------------------------- +l_ezlopi_device_grp_t* ezlopi_core_device_group_get_head(void) +{ + return l_device_grp_head; +} +l_ezlopi_item_grp_t* ezlopi_core_item_group_get_head(void) +{ + return l_item_grp_head; +} + + +//---------------------------------------------------------------------------------------------------------------------------------- +l_ezlopi_device_grp_t* ezlopi_core_device_group_get_by_id(uint32_t _id) +{ + l_ezlopi_device_grp_t* ret_devgrp_node = NULL; + l_ezlopi_device_grp_t* curr_devgrp = l_device_grp_head; + while (curr_devgrp) + { + if (_id == curr_devgrp->_id) + { + ret_devgrp_node = curr_devgrp; + break; + } + curr_devgrp = curr_devgrp->next; + } + + return ret_devgrp_node; +} +l_ezlopi_item_grp_t* ezlopi_core_item_group_get_by_id(uint32_t _id) +{ + l_ezlopi_item_grp_t* ret_itemgrp_node = NULL; + l_ezlopi_item_grp_t* curr_itemgrp = l_item_grp_head; + while (curr_itemgrp) + { + if (_id == curr_itemgrp->_id) + { + ret_itemgrp_node = curr_itemgrp; + break; + } + curr_itemgrp = curr_itemgrp->next; + } + + return ret_itemgrp_node; +} +//---------------------------------------------------------------------------------------------------------------------------------- + +//---------------------------------------------------------------------------------------------------------------------------------- +cJSON* ezlopi_core_device_group_create_cjson(l_ezlopi_device_grp_t* devgrp_node) +{ + cJSON* cj_devgrp = NULL; + if (devgrp_node) + { + cj_devgrp = cJSON_CreateObject(__FUNCTION__); + if (cj_devgrp) + { + char tmp_str[16] = { 0 }; + snprintf(tmp_str, sizeof(tmp_str), "%08x", devgrp_node->_id); + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, ezlopi__id_str, tmp_str); + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, ezlopi_name_str, devgrp_node->name); + + cJSON_AddItemToObject(__FUNCTION__, cj_devgrp, "categories", cJSON_Duplicate(__FUNCTION__, devgrp_node->categories, cJSON_True)); + cJSON_AddItemToObject(__FUNCTION__, cj_devgrp, "devices", cJSON_Duplicate(__FUNCTION__, devgrp_node->devices, cJSON_True)); + cJSON_AddItemToObject(__FUNCTION__, cj_devgrp, "exceptions", cJSON_Duplicate(__FUNCTION__, devgrp_node->exceptions, cJSON_True)); + + { // add 'entryDelay' + switch (devgrp_node->entry_delay) + { + case EZLOPI_DEVICE_GRP_ENTRYDELAY_NORMAL: + { + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, "entryDelay", "normal"); + break; + } + case EZLOPI_DEVICE_GRP_ENTRYDELAY_LONG_EXTENDED: + { + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, "entryDelay", "long_extended"); + break; + } + case EZLOPI_DEVICE_GRP_ENTRYDELAY_EXTENDED: + { + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, "entryDelay", "extended"); + break; + } + case EZLOPI_DEVICE_GRP_ENTRYDELAY_INSTANT: + { + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, "entryDelay", "instant"); + break; + } + case EZLOPI_DEVICE_GRP_ENTRYDELAY_NONE: + default: + { + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, "entryDelay", "none"); + break; + } + } + } + { // add 'role' + switch (devgrp_node->role) + { + case EZLOPI_DEVICE_GRP_ROLE_HOUSE_MODES: + { + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, "role", "house_modes"); + break; + } + case EZLOPI_DEVICE_GRP_ROLE_USER: + default: + { + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, "role", "user"); + break; + } + } + } + + cJSON_AddBoolToObject(__FUNCTION__, cj_devgrp, ezlopi_persistent_str, devgrp_node->persistent); + cJSON_AddBoolToObject(__FUNCTION__, cj_devgrp, "followEntry", devgrp_node->follow_entry); + cJSON_AddStringToObject(__FUNCTION__, cj_devgrp, "packageId", devgrp_node->package_id); + } + } + + return cj_devgrp; +} +cJSON* ezlopi_core_item_group_create_cjson(l_ezlopi_item_grp_t* itemgrp_node) +{ + cJSON* cj_itemgrp = NULL; + if (itemgrp_node) + { + cj_itemgrp = cJSON_CreateObject(__FUNCTION__); + if (cj_itemgrp) + { + char tmp_str[16] = { 0 }; + snprintf(tmp_str, sizeof(tmp_str), "%08x", itemgrp_node->_id); + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp, ezlopi__id_str, tmp_str); + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp, ezlopi_name_str, itemgrp_node->name); + cJSON_AddBoolToObject(__FUNCTION__, cj_itemgrp, ezlopi_hasGetter_str, itemgrp_node->has_getter); + cJSON_AddBoolToObject(__FUNCTION__, cj_itemgrp, ezlopi_hasSetter_str, itemgrp_node->has_setter); + cJSON_AddBoolToObject(__FUNCTION__, cj_itemgrp, ezlopi_persistent_str, itemgrp_node->persistent); + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp, ezlopi_valueType_str, itemgrp_node->value_type); + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp, "valueTypeFamily", itemgrp_node->value_type_family); + // cJSON_AddItemToObject(__FUNCTION__, cj_itemgrp, "valueTypeFamily", cJSON_Duplicate(__FUNCTION__, itemgrp_node->value_type_family, cJSON_True)); + + + cJSON_AddItemToObject(__FUNCTION__, cj_itemgrp, "itemNames", cJSON_Duplicate(__FUNCTION__, itemgrp_node->item_names, cJSON_True)); + cJSON_AddItemToObject(__FUNCTION__, cj_itemgrp, ezlopi_enum_str, cJSON_Duplicate(__FUNCTION__, itemgrp_node->enum_values, cJSON_True)); + cJSON_AddItemToObject(__FUNCTION__, cj_itemgrp, ezlopi_info_str, cJSON_Duplicate(__FUNCTION__, itemgrp_node->info, cJSON_True)); + + { // add 'role' + switch (itemgrp_node->role) + { + case EZLOPI_ITEM_GRP_ROLE_LIFE_SAFETY: + { + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp, "role", "lifeSafety"); + break; + } + case EZLOPI_ITEM_GRP_ROLE_HOUSE_MODES: + { + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp, "role", "house_modes"); + break; + } + case EZLOPI_ITEM_GRP_ROLE_EMPTY: + default: + { + cJSON_AddStringToObject(__FUNCTION__, cj_itemgrp, "role", "empty"); + break; + } + } + } + } + } + + return cj_itemgrp; +} +//---------------------------------------------------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------------------------------------------------- +int ezlopi_core_device_group_edit_by_id(uint32_t devgrp_id, cJSON* cj_devgrp_new) +{ + int ret = 0; + + cJSON * tmp_updated_cj = cJSON_Duplicate(__FUNCTION__, cj_devgrp_new, cJSON_True); + if (tmp_updated_cj) + { + if (1 == __edit_and_update_ll_devgrp_by_id(devgrp_id, tmp_updated_cj)) // modifies the ll-node with, 'devgrp_id' + { + if (1 == __edit_group_and_store_updated_to_nvs(devgrp_id, tmp_updated_cj)) + { + ret = 1; + } + } + + cJSON_Delete(__FUNCTION__, tmp_updated_cj); + } + + return ret; +} +int ezlopi_core_item_group_edit_by_id(uint32_t itemgrp_id, cJSON* cj_itemgrp_new) +{ + int ret = 0; + + cJSON * tmp_updated_cj = cJSON_Duplicate(__FUNCTION__, cj_itemgrp_new, cJSON_True); + if (tmp_updated_cj) + { + if (1 == __edit_and_update_ll_itemgrp_by_id(itemgrp_id, cj_itemgrp_new)) // modifies the ll-node with, 'itemgrp_id' + { + if (1 == __edit_group_and_store_updated_to_nvs(itemgrp_id, tmp_updated_cj)) + { + ret = 1; + } + } + cJSON_Delete(__FUNCTION__, tmp_updated_cj); + } + + return ret; +} +//---------------------------------------------------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------------------------------------------------- +static void ____remove_id_from_group_list(uint32_t _id, bool choice_of_trigger) // 0 => devGrp ; 1 => itemGrp +{ + char* grp_id_list = (choice_of_trigger) ? ezlopi_nvs_read_item_groups() : ezlopi_nvs_read_device_groups(); + if (grp_id_list) + { + cJSON* cj_grp_id_list = cJSON_Parse(__FUNCTION__, grp_id_list); + if (cj_grp_id_list) + { + uint32_t idx = 0; + cJSON* cj_id = NULL; + while (NULL != (cj_id = cJSON_GetArrayItem(cj_grp_id_list, idx))) // since all the elements are all-ready in 'cJSON_Number' + { + if (cj_id->valuedouble == _id) + { + cJSON_DeleteItemFromArray(__FUNCTION__, cj_grp_id_list, idx); + } + // iterate upto the last element (incase --> for redundant value ) + idx++; + } + + // Now to rewrite the group list into NVS + char* updated_grp_id_list_str = cJSON_PrintBuffered(__FUNCTION__, cj_grp_id_list, 1024, false); + TRACE_D("length of 'updated_grp_id_list_str': %d", strlen(updated_grp_id_list_str)); + + if (updated_grp_id_list_str) + { + (choice_of_trigger) ? ezlopi_nvs_write_item_groups(updated_grp_id_list_str) : ezlopi_nvs_write_device_groups(updated_grp_id_list_str); + ezlopi_free(__FUNCTION__, updated_grp_id_list_str); + } + + cJSON_Delete(__FUNCTION__, cj_grp_id_list); + } + ezlopi_free(__FUNCTION__, grp_id_list); + } + +} +void ezlopi_core_device_group_remove_id_from_list(uint32_t _id) +{ + ____remove_id_from_group_list(_id, DEVICE_GROUP_SELECTED); +} +void ezlopi_core_item_group_remove_id_from_list(uint32_t _id) +{ + ____remove_id_from_group_list(_id, ITEM_GROUP_SELECTED); +} +//---------------------------------------------------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------------------------------------------------- +void ezlopi_core_device_group_depopulate_by_id_v2(uint32_t _id) +{ + __device_group_delete_node(__device_group_pop_by_id(_id)); +} +void ezlopi_core_item_group_depopulate_by_id_v2(uint32_t _id) +{ + __item_group_delete_node(__item_group_pop_by_id(_id)); +} +//---------------------------------------------------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------------------------------------------------- +static uint32_t __grp_get_list(cJSON * cj_grp_array, bool choice_of_trigger)// 0 => devGrp ; 1 => itemGrp +{ + uint32_t ret = 0; + char* grp_id_list = (choice_of_trigger) ? ezlopi_nvs_read_item_groups() : ezlopi_nvs_read_device_groups(); + if (grp_id_list) + { + cJSON* cj_grp_id_list = cJSON_Parse(__FUNCTION__, grp_id_list); + if (cj_grp_id_list) + { + CJSON_TRACE("In-cjson :", cj_grp_id_list); + int array_size = cJSON_GetArraySize(cj_grp_id_list); + for (int i = 0; i < array_size; i++) + { + cJSON* cj_grp_id = cJSON_GetArrayItem(cj_grp_id_list, i); + if (cj_grp_id && cj_grp_id->valuedouble) + { + char grp_id_str[32]; + snprintf(grp_id_str, sizeof(grp_id_str), "%08x", (uint32_t)cj_grp_id->valuedouble); + char* grp_str = ezlopi_nvs_read_str(grp_id_str); + if (grp_str) + { + cJSON* cj_grp_node = cJSON_Parse(__FUNCTION__, grp_str); + if (cj_grp_node) + { + cJSON_AddStringToObject(__FUNCTION__, cj_grp_node, ezlopi__id_str, grp_id_str); + + if (!cJSON_AddItemToArray(cj_grp_array, cj_grp_node)) + { + cJSON_Delete(__FUNCTION__, cj_grp_node); + } + else + { + ret += 1; // return total number of grps added + } + } + + ezlopi_free(__FUNCTION__, grp_str); + } + } + } + + cJSON_Delete(__FUNCTION__, cj_grp_id_list); + } + + ezlopi_free(__FUNCTION__, grp_id_list); + } + + return ret; +} +uint32_t ezlopi_core_device_group_get_list(cJSON* cj_devgrp_array) +{ + return __grp_get_list(cj_devgrp_array, DEVICE_GROUP_SELECTED); +} +uint32_t ezlopi_core_item_group_get_list(cJSON* cj_itemgrp_array) +{ + return __grp_get_list(cj_itemgrp_array, ITEM_GROUP_SELECTED); +} +//---------------------------------------------------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------------------------------------------------- +static uint32_t __store_new_grp_in_nvs(cJSON* cj_new_grp, bool choice_of_trigger)// 0 => devGrp ; 1 => itemGrp +{ + uint32_t new_grp_id = 0; + + if (cj_new_grp) + { + new_grp_id = (choice_of_trigger) ? ezlopi_cloud_generate_item_group_id() : ezlopi_cloud_generate_device_group_id(); + char grp_id_str[32]; + snprintf(grp_id_str, sizeof(grp_id_str), "%08x", new_grp_id); // convert (uint32_t) to (0xC002e....) + cJSON_AddStringToObject(__FUNCTION__, cj_new_grp, ezlopi__id_str, grp_id_str); // "_id" in nvs + + char* new_grp_str = cJSON_PrintBuffered(__FUNCTION__, cj_new_grp, 1024, false); + TRACE_D("length of 'new_grp_str': %d", strlen(new_grp_str)); + + if (new_grp_str) + { + if (ezlopi_nvs_write_str(new_grp_str, strlen(new_grp_str) + 1, grp_id_str)) // writes to nvs as --> '0xC002e....' + { + bool free_Grp_id_list_str = 1; + char* grp_id_list_str = (choice_of_trigger) ? ezlopi_nvs_read_item_groups() : ezlopi_nvs_read_device_groups(); + if (NULL == grp_id_list_str) + { + grp_id_list_str = "[]"; + free_Grp_id_list_str = 0; + TRACE_W("_dev/item_ Group ids-list not found in NVS"); + } + + cJSON* cj_grp_id_list = cJSON_Parse(__FUNCTION__, grp_id_list_str); + if (cj_grp_id_list) + { + cJSON* cj_grp_id_str = cJSON_CreateNumber(__FUNCTION__, new_grp_id); // adds to nvs as --> '32220910...' + if (cj_grp_id_str) + { + if (!cJSON_AddItemToArray(cj_grp_id_list, cj_grp_id_str)) + { // if 'new_grp_id' doesnot exist, then erase the falsly store 'new_grp_str' in nvs. + cJSON_Delete(__FUNCTION__, cj_grp_id_str); + ezlopi_nvs_delete_stored_data_by_id(new_grp_id); + new_grp_id = 0; + } + else + { + char* updated_grp_id_list_str = cJSON_PrintBuffered(__FUNCTION__, cj_grp_id_list, 1024, false); + TRACE_D("length of 'updated_grp_id_list_str': %d", strlen(updated_grp_id_list_str)); + + if (updated_grp_id_list_str) + { + TRACE_D("updated_grp_id_list_str: %s", updated_grp_id_list_str); + if ((choice_of_trigger) ? ezlopi_nvs_write_item_groups(updated_grp_id_list_str) : ezlopi_nvs_write_device_groups(updated_grp_id_list_str)) + { + TRACE_S("Group list updated."); + } + else + { + TRACE_E("Group list update failed!"); + } + + ezlopi_free(__FUNCTION__, updated_grp_id_list_str); + } + } + } + + cJSON_Delete(__FUNCTION__, cj_grp_id_list); + } + if (free_Grp_id_list_str) + { + ezlopi_free(__FUNCTION__, grp_id_list_str); + } + } + else + { + new_grp_id = 0; + } + + ezlopi_free(__FUNCTION__, new_grp_str); + } + else + { + new_grp_id = 0; + } + } + + return new_grp_id; +} +uint32_t ezlopi_core_device_group_store_nvs_devgrp(cJSON* cj_new_device_grp) +{ + return __store_new_grp_in_nvs(cj_new_device_grp, DEVICE_GROUP_SELECTED); +} +uint32_t ezlopi_core_item_group_store_nvs_itemgrp(cJSON* cj_new_item_grp) +{ + return __store_new_grp_in_nvs(cj_new_item_grp, ITEM_GROUP_SELECTED); +} +//---------------------------------------------------------------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------------------------------------------------------------- +l_ezlopi_device_grp_t * ezlopi_core_device_group_new_devgrp_populate(cJSON *cj_new_dev_grp, uint32_t new_device_grp_id) +{ + return __device_group_populate(cj_new_dev_grp, new_device_grp_id); +} +l_ezlopi_item_grp_t * ezlopi_core_item_group_new_itemgrp_populate(cJSON *cj_new_item_grp, uint32_t new_item_grp_id) +{ + return __item_group_populate(cj_new_item_grp, new_item_grp_id); +} +//---------------------------------------------------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------------------------------------------------- +static uint8_t ____check_for_category_in_devGrp(cJSON * cj_curr_devGrp_node, const char * req_category_name) +{ + uint8_t flags = 0; + if (cj_curr_devGrp_node && req_category_name) + { + cJSON * cj_categories_arr = cJSON_GetObjectItem(__FUNCTION__, cj_curr_devGrp_node, "categories"); + if (cj_categories_arr && cJSON_IsArray(cj_categories_arr)) + { + int idx = 0; + cJSON * cj_cat_element = NULL; + while (NULL != (cj_cat_element = cJSON_GetArrayItem(cj_categories_arr, idx))) // object + { + // 1. compare category {string} + cJSON * cj_category = cJSON_GetObjectItem(__FUNCTION__, cj_cat_element, ezlopi_category_str); // string + if (cj_category && cj_category->valuestring) + { + if (EZPI_STRNCMP_IF_EQUAL(cj_category->valuestring, req_category_name, strlen(cj_category->valuestring), strlen(req_category_name))) + { + flags |= (1 << 0); + // TRACE_S("found Category --> '%s'", req_category_name); + } + } + + // Break if the condition is valid. + if (flags && (1 << 0)) + { + // TRACE_S("Category criteria completed... ; flags -> [%#x]", flags); + break; + } + else + { + // TRACE_E(" flags -> [%#x]", flags); + flags = 0; + } + idx++; + } + } + } + return flags; +} +static uint8_t ____check_for_subcategory_in_devGrp(cJSON * cj_curr_devGrp_node, const char * req_subcategory_name) +{ + uint8_t flags = 0; + if (cj_curr_devGrp_node && req_subcategory_name) + { + cJSON * cj_categories_arr = cJSON_GetObjectItem(__FUNCTION__, cj_curr_devGrp_node, "categories"); + if (cj_categories_arr && cJSON_IsArray(cj_categories_arr)) + { + int idx = 0; + cJSON * cj_cat_element = NULL; + while (NULL != (cj_cat_element = cJSON_GetArrayItem(cj_categories_arr, idx))) // object + { + // 2 compare sub-category {array} + cJSON * cj_sub_category_arr = cJSON_GetObjectItem(__FUNCTION__, cj_cat_element, ezlopi_subcategory_str); // arr-object + if (cj_sub_category_arr && cJSON_IsArray(cj_sub_category_arr)) + { + int count = 0; + cJSON * cj_subcat_element = NULL; + while (NULL != (cj_subcat_element = cJSON_GetArrayItem(cj_sub_category_arr, count))) // string + { + if (EZPI_STRNCMP_IF_EQUAL(cj_subcat_element->valuestring, req_subcategory_name, strlen(cj_subcat_element->valuestring), strlen(req_subcategory_name))) + { + flags |= (1 << 1); + // TRACE_S("found Sub-Category --> '%s'", req_subcategory_name); + break; + } + count++; + } + } + + // Break if the condition is valid. + if (flags && (1 << 1)) + { + // TRACE_S("Sub-Category criteria completed... ; flags -> [%#x]", flags); + break; + } + else + { + // TRACE_E(" flags -> [%#x]", flags); + flags = 0; + } + idx++; + } + } + } + return flags; +} +static uint8_t ____check_for_device_id_in_devGrp(cJSON * cj_curr_devGrp_node, const char * req_device_id_str) +{ + uint8_t flags = 0; + if (cj_curr_devGrp_node && req_device_id_str) + { + cJSON * cj_devices_arr = cJSON_GetObjectItem(__FUNCTION__, cj_curr_devGrp_node, ezlopi_devices_str); // arr-obj + if (cj_devices_arr && cJSON_IsArray(cj_devices_arr)) + { + int idx = 0; + cJSON * cj_device = NULL; + while (NULL != (cj_device = cJSON_GetArrayItem(cj_devices_arr, idx))) // string + { + // 3. compare devices string-elements {string} + if (EZPI_STRNCMP_IF_EQUAL(cj_device->valuestring, req_device_id_str, strlen(cj_device->valuestring), strlen(req_device_id_str))) + { + flags |= (1 << 2); + // TRACE_S("found Device-Id : %s", req_device_id_str); + break; + } + + idx++; + } + // Break if the condition is valid. + if (flags && (1 << 2)) + { + // TRACE_S("DeviceGroupId criteria completed... ; flags -> [%#x]", flags); + } + else + { + // TRACE_E(" flags -> [%#x]", flags); + flags = 0; + } + } + } + return flags; +} +static uint8_t ____check_for_deviceGroupIds_list(cJSON * cj_curr_devGrp_node, cJSON * deviceGroupIds_list) +{ + uint8_t flags = 0; + if (cj_curr_devGrp_node && deviceGroupIds_list) + { + cJSON * cj_curr_devGrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_curr_devGrp_node, "id"); // "c02ea004" + if (cj_curr_devGrp_id && cj_curr_devGrp_id->valuestring) + { + // 5. compare 'cj_curr_devGrp_id' match with the one in "deviceGroupIds_list". + int idx = 0; + cJSON * cj_devId_element = NULL; + while (NULL != (cj_devId_element = cJSON_GetArrayItem(deviceGroupIds_list, idx))) // string [ "c02ea002" , "c02ea003" ...] + { + if (EZPI_STRNCMP_IF_EQUAL(cj_curr_devGrp_id->valuestring, cj_devId_element->valuestring, strlen(cj_curr_devGrp_id->valuestring), strlen(cj_devId_element->valuestring))) + { + flags |= (1 << 3); + // TRACE_S("found list Device-Id matched : %s", cj_curr_devGrp_id->valuestring); + break; + } + idx++; + } + + // Break if the condition is valid. + if (flags && (1 << 3)) + { + // TRACE_S("DeviceGroupIds criteria completed... ; flags -> [%#x]", flags); + } + else + { + // TRACE_E(" flags -> [%#x]", flags); + flags = 0; + } + } + } + return flags; +} +static uint8_t ____check_for_deviceGroupId(cJSON * cj_curr_devGrp_node, const char * req_deviceGroupId) +{ + uint8_t flags = 0; + if (cj_curr_devGrp_node && req_deviceGroupId) + { + cJSON * cj_curr_devGrp_id = cJSON_GetObjectItem(__FUNCTION__, cj_curr_devGrp_node, "id"); // string // "c02ea004" + if (cj_curr_devGrp_id && cj_curr_devGrp_id->valuestring) + { + // 5. compare devices string-elements {string} + if (EZPI_STRNCMP_IF_EQUAL(cj_curr_devGrp_id->valuestring, req_deviceGroupId, strlen(cj_curr_devGrp_id->valuestring), strlen(req_deviceGroupId))) + { + flags |= (1 << 4); + // TRACE_S("found Device-Id : %s", req_deviceGroupId); + } + + // Break if the condition is valid. + if (flags && (1 << 4)) + { + // TRACE_S("DeviceGroupId criteria completed... ; flags -> [%#x]", flags); + } + else + { + // TRACE_E(" flags -> [%#x]", flags); + flags = 0; + } + } + } + return flags; +} +static bool __check_devgroup_validity(cJSON * cj_curr_devgrp_node, cJSON * cj_params) +{ + bool validity_success = true; + + // 1. Check the condition from "cj_params" + for (int i = 0; i < 5; i++) + { + switch (1 << i) + { + case (1 << 0): // cat_flag + { + cJSON * cj_category_param = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_category_str); + if (cj_category_param && cj_category_param->valuestring) + { + if (false == ((1 << 0) && (____check_for_category_in_devGrp(cj_curr_devgrp_node, cj_category_param->valuestring)))) + { + validity_success = false; + } + } + break; + } + case (1 << 1): // subcat_flag + { + cJSON * cj_subcategory_param = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_subcategory_str); + if (cj_subcategory_param && cj_subcategory_param->valuestring) + { + if (false == ((1 << 1) && (____check_for_subcategory_in_devGrp(cj_curr_devgrp_node, cj_subcategory_param->valuestring)))) + { + validity_success = false; + } + } + break; + } + case (1 << 2): // deviceId_flag + { + cJSON * cj_deviceId_param = cJSON_GetObjectItem(__FUNCTION__, cj_params, ezlopi_deviceId_str); + if (cj_deviceId_param && cj_deviceId_param->valuestring) + { + if (false == ((1 << 2) && (____check_for_device_id_in_devGrp(cj_curr_devgrp_node, cj_deviceId_param->valuestring)))) + { + validity_success = false; + } + } + break; + } + case (1 << 3): // deviceGroupIds_flag + { + cJSON * cj_deviceGroupIds_param = cJSON_GetObjectItem(__FUNCTION__, cj_params, "deviceGroupIds"); + if (cj_deviceGroupIds_param && cJSON_IsArray(cj_deviceGroupIds_param)) + { + if (false == ((1 << 3) && (____check_for_deviceGroupIds_list(cj_curr_devgrp_node, cj_deviceGroupIds_param)))) + { + validity_success = false; + } + } + break; + } + case (1 << 4): // deviceGroup_flag + { + cJSON * cj_deviceGroupId_param = cJSON_GetObjectItem(__FUNCTION__, cj_params, "deviceGroupId"); + if (cj_deviceGroupId_param && cj_deviceGroupId_param->valuestring) + { + if (false == ((1 << 4) && (____check_for_deviceGroupId(cj_curr_devgrp_node, cj_deviceGroupId_param->valuestring)))) + { + validity_success = false; + } + } + break; + } + } + + // break immediately --> if one gives invalid + if (!validity_success) + { + TRACE_E(" error at --> [%#x]", (1 << i)); + break; + } + } + + return validity_success; +} +uint32_t ezlopi_core_device_group_find(cJSON* cj_destination_array, cJSON* cj_params) +{ + int ret = 0; + char* devgrp_id_list = ezlopi_nvs_read_device_groups(); + if (devgrp_id_list) + { + cJSON* cj_devgrp_id_list = cJSON_Parse(__FUNCTION__, devgrp_id_list); + if (cj_devgrp_id_list) + { + int idx = 0; + cJSON* cj_devgrp_id = NULL; + while (NULL != (cj_devgrp_id = cJSON_GetArrayItem(cj_devgrp_id_list, idx)))// the list elements are in 'cJSON_number' + { + char devgrp_id_str[32]; + snprintf(devgrp_id_str, sizeof(devgrp_id_str), "%08x", (uint32_t)cj_devgrp_id->valuedouble); // convert to "0xc02e00.." + + char* devgrp_str = ezlopi_nvs_read_str(devgrp_id_str); // to exxtract the dev_grp from nvs ; if exists + if (devgrp_str) + { + cJSON* cj_curr_devgrp_node = cJSON_Parse(__FUNCTION__, devgrp_str); + if (cj_curr_devgrp_node) + { + CJSON_TRACE(" Checking ---> ", cj_curr_devgrp_node); + bool validity_success = __check_devgroup_validity(cj_curr_devgrp_node, cj_params); // deciding flag + //------------------------------------------------------------------------------------------------ + // 2. if Yes create add object with fields "_id" & "name" + if (validity_success) + { + cJSON * cj_add_valid_devGrp = cJSON_CreateObject(__FUNCTION__); + if (cj_add_valid_devGrp) + { + // 1. add : _id + cJSON_AddStringToObject(__FUNCTION__, cj_add_valid_devGrp, ezlopi__id_str, devgrp_id_str); + + // 2. add : name + cJSON * cj_name = cJSON_GetObjectItem(__FUNCTION__, cj_curr_devgrp_node, ezlopi_name_str); + if (cj_name && cj_name->valuestring) + { + cJSON_AddStringToObject(__FUNCTION__, cj_add_valid_devGrp, ezlopi_name_str, cj_name->valuestring); + } + else + { + cJSON_AddStringToObject(__FUNCTION__, cj_add_valid_devGrp, ezlopi_name_str, ezlopi__str); + } + + // 3. delete if not added + if (!cJSON_AddItemToArray(cj_destination_array, cj_add_valid_devGrp)) + { + // TRACE_I(" --- DISCARD [%s] --- ", devgrp_id_str); + cJSON_Delete(__FUNCTION__, cj_add_valid_devGrp); + } + else + { + // TRACE_I(" --- ADDING [%s] --- ", devgrp_id_str); + ret += 1; // return total number of device-grp added + } + } + } + + cJSON_Delete(__FUNCTION__, cj_curr_devgrp_node); + } + + ezlopi_free(__FUNCTION__, devgrp_str); + } + idx++; + } + + + cJSON_Delete(__FUNCTION__, cj_devgrp_id_list); + } + + ezlopi_free(__FUNCTION__, devgrp_id_list); + } + + return ret; +} +//-------------------------------------------------------------------------------------------------------------------------------- + + +//-------------------------------------------------------------------------------------------------------------------------------- +static void ______add_items_list_to_dest_array(cJSON* cj_main_device_list, l_ezlopi_device_t * curr_dev_node) +{ + cJSON * cj_items_arr = cJSON_AddArrayToObject(__FUNCTION__, cj_main_device_list, ezlopi_items_str); + if (cj_items_arr) + { + // Iterate through the items within "curr_device" + l_ezlopi_item_t* curr_item = curr_dev_node->items; + while (curr_item) + { + cJSON* cj_add_curr_item = cJSON_CreateObject(__FUNCTION__); + if (cj_add_curr_item) + { + // 1. add : item_id + char item_id_str[32]; + snprintf(item_id_str, sizeof(item_id_str), "%08x", curr_item->cloud_properties.item_id); + cJSON_AddStringToObject(__FUNCTION__, cj_add_curr_item, "itemId", item_id_str); + + // 2. add : item_name + cJSON_AddStringToObject(__FUNCTION__, cj_add_curr_item, ezlopi_name_str, curr_item->cloud_properties.item_name); + + // 3. delete if not added + if (!cJSON_AddItemToArray(cj_items_arr, cj_add_curr_item)) + { + cJSON_Delete(__FUNCTION__, cj_add_curr_item); + } + } + + curr_item = curr_item->next; + } + } +} +static void ____compare_when_itemgrpid_is_given(cJSON * cj_main_device_list, l_ezlopi_device_t * curr_dev_node, const char * device_id_str, const char * itemgrp_id_str) +{ + if (cj_main_device_list && curr_dev_node && device_id_str && itemgrp_id_str) + { + uint32_t get_itemgrp_id = strtoul(itemgrp_id_str, NULL, 16); // "itemGroupId" : "2002ce001" + + l_ezlopi_item_grp_t* curr_itemgrp_ll = ezlopi_core_item_group_get_by_id(get_itemgrp_id); // node <--- itemgrp_ll + if (curr_itemgrp_ll && (NULL != curr_itemgrp_ll->item_names)) // item_names --> cj_arr + { + int req_count = 0; // total_count of "item_name" condition we must fullfill + int num_of_dev_items = 0; + int num_of_matched_items = 0; + + l_ezlopi_item_t* curr_items_ll_node = curr_dev_node->items; // get items_ll <--- device_ll + while (curr_items_ll_node) + { + num_of_dev_items++; // total_count of items within --> perticular device + + // B1 . Compare :- devce_ll_[items] -- with -- itemGrpId_[itemNames] + cJSON * cj_item_name_compare = NULL; // holds "item_name" [i.e.list_member] <----- [itemGroupId] + while (NULL != (cj_item_name_compare = cJSON_GetArrayItem(curr_itemgrp_ll->item_names, req_count)))// [ "temp" , "humidity" , ...] + { + req_count++; // increase the count on items checked + + if (EZPI_STRNCMP_IF_EQUAL(curr_items_ll_node->cloud_properties.item_name, // items_ll <---- device_ll + cj_item_name_compare->valuestring, // cj_item_name_compare ("temp") <--- itemNames[] <--- ll_itemgrp + strlen(curr_items_ll_node->cloud_properties.item_name), + strlen(cj_item_name_compare->valuestring))) + { + num_of_matched_items++; + break; + } + } + + curr_items_ll_node = curr_items_ll_node->next; + } + + // C1 . Check validity and Add --> "device" with "Items". + if ((num_of_dev_items >= num_of_matched_items) && (req_count == num_of_matched_items)) + { + cJSON_AddStringToObject(__FUNCTION__, cj_main_device_list, "deviceId", device_id_str); + cJSON_AddStringToObject(__FUNCTION__, cj_main_device_list, ezlopi_name_str, curr_dev_node->cloud_properties.device_name); + + // D1 . Add item of this valid "[device_id]" + ______add_items_list_to_dest_array(cj_main_device_list, curr_dev_node); + } + } + } +} +static void __generate_device_list_with_specific_itemgroup_id(cJSON* cj_destination_array, cJSON* cj_devices_arr, cJSON* cj_params) +{ + if (cj_destination_array && cj_devices_arr && cj_params) + { + int idx = 0; + cJSON * cj_device = NULL; + + while (NULL != (cj_device = cJSON_GetArrayItem(cj_devices_arr, idx))) // extract string device_id ---> "102ce001 .." + { + if (cj_device->valuestring) + { + // TRACE_S("Inspecting --> [%s]", cj_device->valuestring); + + uint32_t curr_dev_id = strtoul(cj_device->valuestring, NULL, 16); + l_ezlopi_device_t * curr_dev_node = ezlopi_device_get_by_id(curr_dev_id); + if (curr_dev_node) + { + cJSON * cj_main_device_list = cJSON_CreateObject(__FUNCTION__); + if (cj_main_device_list) + { + + cJSON * cj_itemGroupId_str = cJSON_GetObjectItem(__FUNCTION__, cj_params, "itemGroupId"); + if (cj_itemGroupId_str && cj_itemGroupId_str->valuestring) + { + // A1 . If the itemGroupId condition is given ---> add only those devices to list, containing items that matches with 'ITEM_GROUP->[items_list]' + ____compare_when_itemgrpid_is_given(cj_main_device_list, curr_dev_node, cj_device->valuestring, cj_itemGroupId_str->valuestring); + } + else + { + // A2 . When ItemGroupId is abscent ; include all the devices & its items. + cJSON_AddStringToObject(__FUNCTION__, cj_main_device_list, "deviceId", cj_device->valuestring); + cJSON_AddStringToObject(__FUNCTION__, cj_main_device_list, ezlopi_name_str, curr_dev_node->cloud_properties.device_name); + + // B2 . Proceed only if "showItems == True" + cJSON * cj_showitems = cJSON_GetObjectItem(__FUNCTION__, cj_params, "showItems"); + if (cj_showitems && (cj_showitems->type == cJSON_True)) + { + TRACE_E("Since, [showItems==TRUE] ; attaching items_list "); + + // C2 . add "items" : [...] + ______add_items_list_to_dest_array(cj_main_device_list, curr_dev_node); + } + } + + // Add array # "devices" : [ {}, + <--"{ ... }" ] + if (!cJSON_AddItemToArray(cj_destination_array, cj_main_device_list)) + { + cJSON_Delete(__FUNCTION__, cj_main_device_list); + } + } + } + } + idx++; + } + } +} +uint32_t ezlopi_core_device_group_devitem_expand(cJSON* cj_destination_array, cJSON* cj_params) +{ + int ret = 0; + if (cj_destination_array && cj_params) + { + cJSON * cj_deviceGroupId_param = cJSON_GetObjectItem(__FUNCTION__, cj_params, "deviceGroupId"); + if (cj_deviceGroupId_param && cj_deviceGroupId_param->valuestring) + { + // Get the required device_group from NVS. + char* devgrp_str = ezlopi_nvs_read_str(cj_deviceGroupId_param->valuestring); + if (devgrp_str) + { + cJSON* cj_curr_devgrp_node = cJSON_Parse(__FUNCTION__, devgrp_str); + if (cj_curr_devgrp_node) + { + //------------------------------------------------------------------------------------------------ + // 2. if Yes create add object with fields "_id" & "name" + + cJSON * cj_devices_arr = cJSON_GetObjectItem(__FUNCTION__, cj_curr_devgrp_node, ezlopi_devices_str); // array + if (cj_devices_arr && cJSON_IsArray(cj_devices_arr)) + { + // Generate dev-item expansion list according to 'cj_params' + __generate_device_list_with_specific_itemgroup_id(cj_destination_array, cj_devices_arr, cj_params); + } + + cJSON_Delete(__FUNCTION__, cj_curr_devgrp_node); + } + + ezlopi_free(__FUNCTION__, devgrp_str); + } + } + } + return ret; +} +//-------------------------------------------------------------------------------------------------------------------------------- + + +//------------------------------------------- Main Init_Function ----------------------------------------------------------------- +/** + * @brief This function (if present) removes any unwanted residue-IDs from the nvs_list + * + * @param choice_of_trigger // 0 => devGrp ; 1 => itemGrp + */ +static void __remove_residue_ids_from_list(bool choice_of_trigger) // 0 => devGrp ; 1 => itemGrp +{ + TRACE_D("---------- # Removing [%s_Group] residue-Ids # ----------", (choice_of_trigger) ? "Item" : "Device"); + // check --> nvs_devgrp_list for unncessary "residue-IDs" & update the list + uint32_t invalid_nvs_grp_id = 0; + bool grp_list_has_residue = false; // this indicates absence of residue-IDs // those IDs which are still in the "nvs-list" but doesnot not exists in "nvs-body" + char * list_ptr = NULL; + + do + { + if (grp_list_has_residue) + { + if (0 != invalid_nvs_grp_id) + { + (choice_of_trigger) ? ezlopi_core_item_group_remove_id_from_list(invalid_nvs_grp_id) : ezlopi_core_device_group_remove_id_from_list(invalid_nvs_grp_id); + } + grp_list_has_residue = false; + } + + list_ptr = (choice_of_trigger) ? ezlopi_nvs_read_item_groups() : ezlopi_nvs_read_device_groups(); + if (list_ptr) + { + cJSON* cj_id_list = cJSON_Parse(__FUNCTION__, list_ptr); + if (cj_id_list) + { + int array_size = cJSON_GetArraySize(cj_id_list); + for (int i = 0; i < array_size; i++) + { + cJSON* cj_id = cJSON_GetArrayItem(cj_id_list, i); + if (cj_id && cj_id->valuedouble) + { + char tmp_buffer[32]; + snprintf(tmp_buffer, sizeof(tmp_buffer), "%08x", (uint32_t)cj_id->valuedouble); + + if (NULL == ezlopi_nvs_read_str(tmp_buffer)) + { + invalid_nvs_grp_id = (uint32_t)cj_id->valuedouble; // A residue_id is found.. + grp_list_has_residue = true; // this will trigger a removal of "invalid_nvs_devgrp_id" . + break; // get out of for + } + } + } + } + } + } while (grp_list_has_residue); + TRACE_D("---------- # --------------------------------- # ----------"); +} +void ezlopi_device_group_init(void) +{ + __remove_residue_ids_from_list(DEVICE_GROUP_SELECTED); + + char* devgrp_id_list_str = ezlopi_nvs_read_device_groups(); + if (devgrp_id_list_str) + { + TRACE_D("devGrp_id_list_str : %s", devgrp_id_list_str); + cJSON* cj_devgrp_ids = cJSON_Parse(__FUNCTION__, devgrp_id_list_str); + if (cj_devgrp_ids) + { + int array_size = cJSON_GetArraySize(cj_devgrp_ids); + for (int i = 0; i < array_size; i++) + { + cJSON* cj_devgrp_id = cJSON_GetArrayItem(cj_devgrp_ids, i); + if (cj_devgrp_id && cj_devgrp_id->valuedouble) + { + uint32_t tmp_devgrp_id = (uint32_t)cj_devgrp_id->valuedouble; + + char tmp_buffer[32]; + snprintf(tmp_buffer, sizeof(tmp_buffer), "%08x", tmp_devgrp_id); + ezlopi_cloud_update_device_group_id((uint32_t)tmp_devgrp_id); + + char* devgrp_str = ezlopi_nvs_read_str(tmp_buffer); + if (devgrp_str) + { + cJSON* cj_devgrp = cJSON_Parse(__FUNCTION__, devgrp_str); + if (cj_devgrp) + { + l_ezlopi_device_grp_t* new_devgrp_node = __device_group_populate(cj_devgrp, tmp_devgrp_id); + cJSON_Delete(__FUNCTION__, cj_devgrp); + + if (new_devgrp_node) + { + cJSON* cj_new_devgrp_node = ezlopi_core_device_group_create_cjson(new_devgrp_node); + // CJSON_TRACE("new_devgrp_node", cj_new_devgrp_node); + cJSON_Delete(__FUNCTION__, cj_new_devgrp_node); + } + } + ezlopi_free(__FUNCTION__, devgrp_str); + } + } + } + cJSON_Delete(__FUNCTION__, cj_devgrp_ids); + } + + ezlopi_free(__FUNCTION__, devgrp_id_list_str); + } +} +void ezlopi_item_group_init(void) +{ + __remove_residue_ids_from_list(ITEM_GROUP_SELECTED); + + char* itemgrp_id_list_str = ezlopi_nvs_read_item_groups(); + if (itemgrp_id_list_str) + { + TRACE_D("itemGrp_id_list_str : %s", itemgrp_id_list_str); + cJSON* cj_itemgrp_ids = cJSON_Parse(__FUNCTION__, itemgrp_id_list_str); + if (cj_itemgrp_ids) + { + int array_size = cJSON_GetArraySize(cj_itemgrp_ids); + for (int i = 0; i < array_size; i++) + { + cJSON* cj_itemgrp_id = cJSON_GetArrayItem(cj_itemgrp_ids, i); + if (cj_itemgrp_id && cj_itemgrp_id->valuedouble) + { + uint32_t tmp_itemgrp_id = (uint32_t)cj_itemgrp_id->valuedouble; + + char tmp_buffer[32]; + snprintf(tmp_buffer, sizeof(tmp_buffer), "%08x", tmp_itemgrp_id); + ezlopi_cloud_update_item_group_id((uint32_t)tmp_itemgrp_id); + + char* itemgrp_str = ezlopi_nvs_read_str(tmp_buffer); + if (itemgrp_str) + { + cJSON* cj_itemgrp = cJSON_Parse(__FUNCTION__, itemgrp_str); + if (cj_itemgrp) + { + l_ezlopi_item_grp_t* new_itemgrp_node = __item_group_populate(cj_itemgrp, tmp_itemgrp_id); + cJSON_Delete(__FUNCTION__, cj_itemgrp); + + if (new_itemgrp_node) + { + cJSON* cj_new_itemgrp_node = ezlopi_core_item_group_create_cjson(new_itemgrp_node); + // CJSON_TRACE("new_itemgrp_node", cj_new_itemgrp_node); + cJSON_Delete(__FUNCTION__, cj_new_itemgrp_node); + } + } + + ezlopi_free(__FUNCTION__, itemgrp_str); + } + } + + } + + cJSON_Delete(__FUNCTION__, cj_itemgrp_ids); + } + + ezlopi_free(__FUNCTION__, itemgrp_id_list_str); + } +} +//-------------------------------------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/ezlopi-core/ezlopi-core-devices/ezlopi_core_device_group.h b/ezlopi-core/ezlopi-core-devices/ezlopi_core_device_group.h new file mode 100644 index 00000000..c48dd460 --- /dev/null +++ b/ezlopi-core/ezlopi-core-devices/ezlopi_core_device_group.h @@ -0,0 +1,170 @@ +#ifndef EZLOPI_CORE_DEVICES_GROUP_H +#define EZLOPI_CORE_DEVICES_GROUP_H + +#include "ezlopi_core_devices.h" + +typedef enum e_ezlopi_device_grp_entrydelay_type +{ + EZLOPI_DEVICE_GRP_ENTRYDELAY_UNDEFINED = 0, + EZLOPI_DEVICE_GRP_ENTRYDELAY_NONE, + EZLOPI_DEVICE_GRP_ENTRYDELAY_NORMAL, + EZLOPI_DEVICE_GRP_ENTRYDELAY_LONG_EXTENDED, + EZLOPI_DEVICE_GRP_ENTRYDELAY_EXTENDED, + EZLOPI_DEVICE_GRP_ENTRYDELAY_INSTANT, + EZLOPI_DEVICE_GRP_ENTRYDELAY_MAX +}e_ezlopi_device_grp_entrydelay_type_t; + +typedef enum e_ezlopi_device_grp_role_type +{ + EZLOPI_DEVICE_GRP_ROLE_NONE = 0, + EZLOPI_DEVICE_GRP_ROLE_USER, + EZLOPI_DEVICE_GRP_ROLE_HOUSE_MODES, + EZLOPI_DEVICE_GRP_ROLE_MAX +}e_ezlopi_device_grp_role_type_t; + +typedef enum e_ezlopi_item_grp_role_type +{ + EZLOPI_ITEM_GRP_ROLE_EMPTY = 0, + EZLOPI_ITEM_GRP_ROLE_LIFE_SAFETY, + EZLOPI_ITEM_GRP_ROLE_HOUSE_MODES, + EZLOPI_ITEM_GRP_ROLE_MAX +}e_ezlopi_item_grp_role_type_t; + +typedef struct l_ezlopi_device_grp +{ + uint32_t _id; // perticular device_group_id + char name[128]; // device_group_name + cJSON * categories; // array containing required categories/sub-categories + cJSON * devices; // array containing DeviceIds to be added + cJSON * exceptions; // array of DeviceIds to exclude from this group + bool persistent; + e_ezlopi_device_grp_entrydelay_type_t entry_delay; + bool follow_entry; + e_ezlopi_device_grp_role_type_t role; + char package_id[40]; + struct l_ezlopi_device_grp* next; +}l_ezlopi_device_grp_t; + +typedef struct l_ezlopi_item_grp +{ + uint32_t _id; + char name[128]; + bool has_getter; + bool has_setter; + bool persistent; + cJSON * item_names; // array containing 'Item_names' as filters + char value_type[64]; // 'valueType' -> https://api.ezlo.com/hub/items_api/index.html, // ezlopi-cloud/constants/values_str.h + char value_type_family[32]; // [yes, if there is no valueType field] 'valueType_family' :- one of ["numeric" / "string" / "valuesWithLess" / "valuesWithoutLess"] + cJSON * enum_values; // array of strings ; used to filter specifice 'tokens' [from valueType -> token] + e_ezlopi_item_grp_role_type_t role; // default : empty + cJSON * info; // Description of an item group. + struct l_ezlopi_item_grp* next; +}l_ezlopi_item_grp_t; + + +// ---------------------------------------------------- + +/** + * @brief This function return 'device_group_head' node from ll + */ +l_ezlopi_device_grp_t* ezlopi_core_device_group_get_head(void); +l_ezlopi_item_grp_t* ezlopi_core_item_group_get_head(void); + +/** + * @brief Returns the node associated with required 'device_group_id' + * + * @param _id 'device_group_id' + * @return l_ezlopi_device_grp_t* + */ +l_ezlopi_device_grp_t* ezlopi_core_device_group_get_by_id(uint32_t _id); +l_ezlopi_item_grp_t* ezlopi_core_item_group_get_by_id(uint32_t _id); + +/** + * @brief This function generates equivalent 'cjson' object of the input 'l_ezlopi_device_grp_t*' + * + * @param devgrp_node The node to be converted + * @return cJSON* : ( NOTE!! Must be freed after use ) + */ +cJSON* ezlopi_core_device_group_create_cjson(l_ezlopi_device_grp_t* devgrp_node); +cJSON* ezlopi_core_item_group_create_cjson(l_ezlopi_item_grp_t* itemgrp_node); + +/** + * @brief This function handles editing of req_id in ll & nvs + * + * @param devgrp_id required 'devgrp_id' + * @param cj_devgrp_new cjson of 'new_devgrp' + * @return int + */ +int ezlopi_core_device_group_edit_by_id(uint32_t devgrp_id, cJSON* cj_devgrp_new); +int ezlopi_core_item_group_edit_by_id(uint32_t itemgrp_id, cJSON* cj_itemgrp_new); + +/** + * @brief This function removes perticular 'devgrp_id' from nvs list + * + * @param _id + */ +void ezlopi_core_device_group_remove_id_from_list(uint32_t _id); +void ezlopi_core_item_group_remove_id_from_list(uint32_t _id); + +/** + * @brief Depopulate perticular node with 'device-group-id' + * + * @param _id 'device-group-id' + */ +void ezlopi_core_device_group_depopulate_by_id_v2(uint32_t _id); +void ezlopi_core_item_group_depopulate_by_id_v2(uint32_t _id); + +/** + * @brief This function returns all the 'device_groups' stored in nvs + * + * @param cj_devgrp_array This will contain all the 'dev_grps' in cjson format + * @return uint32_t -> Total devGrps in nvs + */ +uint32_t ezlopi_core_device_group_get_list(cJSON* cj_devgrp_array); +uint32_t ezlopi_core_item_group_get_list(cJSON* cj_itemgrp_array); + +/** + * @brief This function is responsible for storing 'new_device_group_node' in nvs + * + * @param cj_new_device_grp New_dev_grp in cjson format + * @return uint32_t + */ +uint32_t ezlopi_core_device_group_store_nvs_devgrp(cJSON* cj_new_device_grp); +uint32_t ezlopi_core_item_group_store_nvs_itemgrp(cJSON* cj_new_item_grp); + +/** + * @brief This function populates/links the 'new_device_grp' into ll_head + * + * @param cj_new_dev_grp This contains 'new_dev_grp' in cjson format. + * @param new_device_grp_id This 'devgrp_id' indentifies the 'new_dev_grp_node' + * @return l_ezlopi_device_grp_t* + */ +l_ezlopi_device_grp_t * ezlopi_core_device_group_new_devgrp_populate(cJSON *cj_new_dev_grp, uint32_t new_device_grp_id); +l_ezlopi_item_grp_t * ezlopi_core_item_group_new_itemgrp_populate(cJSON *cj_new_item_grp, uint32_t new_item_grp_id); + +/** + * @brief This function returns list of valid dev_groups + * + * @param cj_devgrp_array constains the array of valid dev_groups + * @param params cjson with Conditions to be checked + * @return uint32_t Total count of valid device_groups returned + */ +uint32_t ezlopi_core_device_group_find(cJSON* cj_devgrp_array, cJSON* params); + +/** + * @brief This function return list of device, that contains desired items + * + * @param cj_request The array to be written to. + * @param cj_response contains conditions to be validated. + * @return uint32_t + */ +uint32_t ezlopi_core_device_group_devitem_expand(cJSON* cj_destination_array, cJSON* cj_params); + +/** + * @brief main functions to initialize the device-groups + */ +void ezlopi_device_group_init(void); +void ezlopi_item_group_init(void); + + +#endif//EZLOPI_CORE_DEVICES_GROUP_H \ No newline at end of file diff --git a/ezlopi-core/ezlopi-core-devices/ezlopi_core_devices.c b/ezlopi-core/ezlopi-core-devices/ezlopi_core_devices.c index 6b5315a5..eecab17e 100644 --- a/ezlopi-core/ezlopi-core-devices/ezlopi_core_devices.c +++ b/ezlopi-core/ezlopi-core-devices/ezlopi_core_devices.c @@ -11,6 +11,7 @@ #include "../../build/config/sdkconfig.h" static l_ezlopi_device_t* l_device_head = NULL; + static volatile uint32_t g_store_dev_config_with_id = 0; static s_ezlopi_cloud_controller_t s_controller_information; diff --git a/ezlopi-core/ezlopi-core-ezlopi/ezlopi_core_broadcast.c b/ezlopi-core/ezlopi-core-ezlopi/ezlopi_core_broadcast.c index 23c6a9cc..bfcbc69a 100644 --- a/ezlopi-core/ezlopi-core-ezlopi/ezlopi_core_broadcast.c +++ b/ezlopi-core/ezlopi-core-ezlopi/ezlopi_core_broadcast.c @@ -90,7 +90,7 @@ int ezlopi_core_broadcast_cjson(cJSON* cj_data) TRACE_I("%d -> -----------------------------> buffer acquired!", xTaskGetTickCount()); memset(data_buffer, 0, buffer_len); - TRACE_D("buffer_len = [%d]", buffer_len); + // TRACE_D("buffer_len = [%d]", buffer_len); if (true == cJSON_PrintPreallocated(__FUNCTION__, cj_data, data_buffer, buffer_len, false)) { diff --git a/ezlopi-core/ezlopi-core-ezlopi/ezlopi_core_ezlopi.c b/ezlopi-core/ezlopi-core-ezlopi/ezlopi_core_ezlopi.c index d47977dc..0597c936 100644 --- a/ezlopi-core/ezlopi-core-ezlopi/ezlopi_core_ezlopi.c +++ b/ezlopi-core/ezlopi-core-ezlopi/ezlopi_core_ezlopi.c @@ -17,6 +17,7 @@ #include "ezlopi_core_event_queue.h" #include "ezlopi_core_event_group.h" #include "ezlopi_core_factory_info.h" +#include "ezlopi_core_device_group.h" #include "ezlopi_core_devices_list.h" #include "ezlopi_core_scenes_scripts.h" #include "ezlopi_core_scenes_expressions.h" @@ -60,6 +61,11 @@ void ezlopi_init(void) // Init devices ezlopi_device_prepare(); vTaskDelay(10); + // Init device_groups + ezlopi_device_group_init(); + // Init item_groups + ezlopi_item_group_init(); + vTaskDelay(10); ezlopi_initialize_devices_v3(); vTaskDelay(10); diff --git a/ezlopi-core/ezlopi-core-nvs/ezlopi_core_nvs.c b/ezlopi-core/ezlopi-core-nvs/ezlopi_core_nvs.c index d2d8ecbf..e683e9d6 100644 --- a/ezlopi-core/ezlopi-core-nvs/ezlopi_core_nvs.c +++ b/ezlopi-core/ezlopi-core-nvs/ezlopi_core_nvs.c @@ -23,6 +23,8 @@ static const char* ezlopi_scripts_nvs_ids = "ezlopi_scripts"; static const char* config_info_update_time_name = "config_time"; static const char* config_info_version_number = "conf_ver_no"; static const char* ezlopi_scenes_expression_ids = "ezlopi_exp"; +static const char* ezlopi_device_groups_ids = "dev_grp_list"; +static const char* ezlopi_item_groups_ids = "item_grp_list"; static const char* ezlopi_room_ids_nvs_name = "ezlopi_room"; static const char* ezlopi_time_location_nvs_name = "time.local"; static const char* ezlopi_modes_nvs_name = "ezlopi_modes"; @@ -175,6 +177,26 @@ char* ezlopi_nvs_read_scenes_expressions(void) return ezlopi_nvs_read_str(ezlopi_scenes_expression_ids); } +int ezlopi_nvs_write_device_groups(char* data) +{ + return ezlopi_nvs_write_str(data, strlen(data) + 1, ezlopi_device_groups_ids); +} + +char* ezlopi_nvs_read_device_groups(void) +{ + return ezlopi_nvs_read_str(ezlopi_device_groups_ids); +} + +int ezlopi_nvs_write_item_groups(char* data) +{ + return ezlopi_nvs_write_str(data, strlen(data) + 1, ezlopi_item_groups_ids); +} + +char* ezlopi_nvs_read_item_groups(void) +{ + return ezlopi_nvs_read_str(ezlopi_item_groups_ids); +} + char* ezlopi_nvs_read_rooms(void) { return ezlopi_nvs_read_str(ezlopi_room_ids_nvs_name); diff --git a/ezlopi-core/ezlopi-core-nvs/ezlopi_core_nvs.h b/ezlopi-core/ezlopi-core-nvs/ezlopi_core_nvs.h index 87963a0a..a1f474c6 100644 --- a/ezlopi-core/ezlopi-core-nvs/ezlopi_core_nvs.h +++ b/ezlopi-core/ezlopi-core-nvs/ezlopi_core_nvs.h @@ -75,6 +75,12 @@ extern "C" char* ezlopi_nvs_read_scenes_expressions(void); int ezlopi_nvs_write_scenes_expressions(char* data); + char* ezlopi_nvs_read_device_groups(void); + int ezlopi_nvs_write_device_groups(char* data); + + char* ezlopi_nvs_read_item_groups(void); + int ezlopi_nvs_write_item_groups(char* data); + char* ezlopi_nvs_read_rooms(void); int ezlopi_nvs_write_rooms(char* data); diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_cjson.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_cjson.c index a137407d..25744899 100755 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_cjson.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_cjson.c @@ -445,7 +445,7 @@ static void __cjson_add_fields(cJSON* cj_block, l_fields_v2_t* fields) } case EZLOPI_VALUE_TYPE_BLOCKS: { - TRACE_S(" adding : __ EZLOPI_VALUE_TYPE_BLOCKS __"); + TRACE_D(" adding : __ EZLOPI_VALUE_TYPE_BLOCKS __"); cJSON* vlaue_block_array = cJSON_AddArrayToObject(__FUNCTION__, cj_field, ezlopi_value_str); if (vlaue_block_array) { diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_delete.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_delete.c index af1d9b18..36edb8fd 100755 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_delete.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_delete.c @@ -140,6 +140,16 @@ void ezlopi_scenes_delete_field_value(l_fields_v2_t* field) } break; } + case VALUE_TYPE_HOUSE_MODE_ID_ARRAY: + { + if (field->field_value.u_value.house_modes) + { + TRACE_S("here : free house_mode_arr"); + ezlopi_scenes_delete_house_modes(field->field_value.u_value.house_modes); + field->field_value.u_value.house_modes = NULL; + } + break; + } default: { break; diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_edit.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_edit.c index 63c9ecd4..f0ec2eaf 100644 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_edit.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_edit.c @@ -9,6 +9,7 @@ #include "ezlopi_core_scenes_edit.h" #include "ezlopi_core_cjson_macros.h" #include "ezlopi_core_scenes_populate.h" +#include "ezlopi_core_cloud.h" #include "ezlopi_service_meshbot.h" @@ -19,6 +20,16 @@ int ezlopi_core_scene_edit_store_updated_to_nvs(cJSON* cj_updated_scene) int ret = 0; if (cj_updated_scene) { + if (ezlopi_core_scene_add_when_blockId_if_reqd(cj_updated_scene)) + { + TRACE_S("==> Added new_blockIds (Edit) : SUCCESS"); + } + + if (ezlopi_core_scene_add_group_id_if_reqd(cj_updated_scene)) + { + TRACE_S("==> Added new_group_id (Edit) : SUCCESS"); + } + char* update_scene_str = cJSON_PrintBuffered(__FUNCTION__, cj_updated_scene, 4096, false); TRACE_D("length of 'update_scene_str': %d", strlen(update_scene_str)); @@ -41,7 +52,7 @@ int ezlopi_core_scene_edit_store_updated_to_nvs(cJSON* cj_updated_scene) int ezlopi_core_scene_edit_update_id(uint32_t scene_id, cJSON* cj_updated_scene) { int ret = 0; - CJSON_TRACE("cj_updated_scene", cj_updated_scene); + // CJSON_TRACE("cj_updated_scene", cj_updated_scene); if (scene_id && cj_updated_scene) { @@ -53,7 +64,7 @@ int ezlopi_core_scene_edit_update_id(uint32_t scene_id, cJSON* cj_updated_scene) ezlopi_meshobot_service_stop_scene(scene_node); _edit_scene(scene_node, cj_updated_scene); - TRACE_S("HERE : scene_node->enabled = [%s]", (scene_node->enabled) ? "true" : "false"); + // TRACE_S("HERE : scene_node->enabled = [%s]", (scene_node->enabled) ? "true" : "false"); if (scene_node->enabled == true) { ezlopi_meshbot_service_start_scene(scene_node); @@ -78,7 +89,15 @@ static void _edit_scene(l_scenes_list_v2_t* scene_node, cJSON* cj_scene) { CJSON_GET_VALUE_BOOL(cj_scene, ezlopi_enabled_str, scene_node->enabled); CJSON_GET_VALUE_BOOL(cj_scene, ezlopi_is_group_str, scene_node->is_group); - CJSON_GET_VALUE_STRING_BY_COPY(cj_scene, ezlopi_group_id_str, scene_node->group_id); + + { + CJSON_GET_VALUE_STRING_BY_COPY(cj_scene, ezlopi_group_id_str, scene_node->group_id); + if ((NULL != scene_node->group_id) && (0 < strlen(scene_node->group_id))) + { + TRACE_S("new_group_id (edit): %s", scene_node->group_id); + ezlopi_cloud_update_group_id((uint32_t)strtoul(scene_node->group_id, NULL, 16)); + } + } CJSON_GET_VALUE_STRING_BY_COPY(cj_scene, ezlopi_name_str, scene_node->name); CJSON_GET_VALUE_STRING_BY_COPY(cj_scene, ezlopi_parent_id_str, scene_node->parent_id); diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_expressions.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_expressions.c index 30e5cea2..f163608d 100644 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_expressions.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_expressions.c @@ -446,7 +446,7 @@ uint32_t ezlopi_scenes_expressions_add_to_head(uint32_t exp_id, cJSON* cj_expres current_exp->next = __expressions_create_node(exp_id, cj_expression); if (current_exp->next) { - ezlopi_scenes_expressions_print(current_exp->next); + // ezlopi_scenes_expressions_print(current_exp->next); new_exp_id = current_exp->next->exp_id; } } @@ -455,7 +455,7 @@ uint32_t ezlopi_scenes_expressions_add_to_head(uint32_t exp_id, cJSON* cj_expres l_expressions_head = __expressions_create_node(exp_id, cj_expression); if (l_expressions_head) { - ezlopi_scenes_expressions_print(l_expressions_head); + // ezlopi_scenes_expressions_print(l_expressions_head); new_exp_id = l_expressions_head->exp_id; } } @@ -1052,9 +1052,9 @@ static int __remove_exp_id_from_nvs_exp_list(uint32_t target_id) if (_id == target_id) { cJSON_DeleteItemFromArray(__FUNCTION__, cj_exp_ids, idx); - break; } + // iterate upto last elements (incase --> for doubles) idx++; } diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_operators.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_operators.c index 86228fe9..9dd73284 100755 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_operators.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_operators.c @@ -157,13 +157,13 @@ static int ____compare_exp_vs_other(s_ezlopi_expressions_t * curr_expr_left, l_f break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", ezlopi_scene_get_scene_value_type_name(curr_expr_left->value_type), ezlopi_scene_get_scene_value_type_name(value_field->value_type)); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", ezlopi_scene_get_scene_value_type_name(curr_expr_left->value_type), ezlopi_scene_get_scene_value_type_name(value_field->value_type)); } return ret; @@ -212,13 +212,13 @@ static int ____compare_exp_vs_exp(s_ezlopi_expressions_t * curr_expr_left, s_ezl break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", ezlopi_scene_get_scene_value_type_name(curr_expr_left->value_type), ezlopi_scene_get_scene_value_type_name(curr_expr_right->value_type)); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", ezlopi_scene_get_scene_value_type_name(curr_expr_left->value_type), ezlopi_scene_get_scene_value_type_name(curr_expr_right->value_type)); } return ret; @@ -276,7 +276,7 @@ static int ____compare_exp_vs_item(s_ezlopi_expressions_t * curr_expr_left, l_ez break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } @@ -285,7 +285,7 @@ static int ____compare_exp_vs_item(s_ezlopi_expressions_t * curr_expr_left, l_ez } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); } return ret; @@ -348,7 +348,7 @@ static int ____compare_item_vs_other(l_ezlopi_item_t * item_left, l_fields_v2_t break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } @@ -357,7 +357,7 @@ static int ____compare_item_vs_other(l_ezlopi_item_t * item_left, l_fields_v2_t } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); } return ret; @@ -417,7 +417,7 @@ static int ____compare_item_vs_exp(l_ezlopi_item_t * item_left, s_ezlopi_express break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } @@ -426,7 +426,7 @@ static int ____compare_item_vs_exp(l_ezlopi_item_t * item_left, s_ezlopi_express } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); } return ret; @@ -495,7 +495,7 @@ static int ____compare_item_vs_item(l_ezlopi_item_t * item_left, l_ezlopi_item_t break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } @@ -508,7 +508,7 @@ static int ____compare_item_vs_item(l_ezlopi_item_t * item_left, l_ezlopi_item_t } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); } return ret; @@ -687,13 +687,13 @@ static int ____compare_range_exp_vs_other(s_ezlopi_expressions_t * curr_expr_lef break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", ezlopi_scene_get_scene_value_type_name(start_value_field->value_type), ezlopi_scene_get_scene_value_type_name(end_value_field->value_type)); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", ezlopi_scene_get_scene_value_type_name(start_value_field->value_type), ezlopi_scene_get_scene_value_type_name(end_value_field->value_type)); } return ret; @@ -750,13 +750,13 @@ static int ____compare_range_exp_vs_exp(s_ezlopi_expressions_t * curr_expr_left, break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", ezlopi_scene_get_scene_value_type_name(curr_expr_right_start->value_type), ezlopi_scene_get_scene_value_type_name(curr_expr_right_end->value_type)); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", ezlopi_scene_get_scene_value_type_name(curr_expr_right_start->value_type), ezlopi_scene_get_scene_value_type_name(curr_expr_right_end->value_type)); } return ret; @@ -825,7 +825,7 @@ static int ____compare_range_item_vs_other(l_ezlopi_item_t * item, l_fields_v2_t break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } @@ -834,7 +834,7 @@ static int ____compare_range_item_vs_other(l_ezlopi_item_t * item, l_fields_v2_t } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); } return ret; } @@ -901,7 +901,7 @@ static int ____compare_range_item_vs_exp(l_ezlopi_item_t * item, s_ezlopi_expres break; } default: - TRACE_W("Comparison --->>> can compare only :- string / bool / number "); + TRACE_W("Error!! can compare only :- string / bool / number "); break; } } @@ -910,7 +910,7 @@ static int ____compare_range_item_vs_exp(l_ezlopi_item_t * item, s_ezlopi_expres } else { - TRACE_E("Comparison --->>> value_types of LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); + TRACE_E(" LHS != RHS [ '%s' vs '%s' ]", lhs_str, rhs_str); } return ret; diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_populate.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_populate.c index fb3bf7c0..bf5a9bee 100644 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_populate.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_populate.c @@ -5,6 +5,7 @@ #include "ezlopi_core_cjson_macros.h" #include "ezlopi_core_scenes_value.h" #include "ezlopi_core_scenes_populate.h" +#include "ezlopi_core_cloud.h" #include "ezlopi_cloud_constants.h" #include "EZLOPI_USER_CONFIG.h" @@ -20,7 +21,15 @@ void ezlopi_scenes_populate_scene(l_scenes_list_v2_t* new_scene, cJSON* cj_scene CJSON_GET_VALUE_BOOL(cj_scene, ezlopi_enabled_str, new_scene->enabled); CJSON_GET_VALUE_BOOL(cj_scene, ezlopi_is_group_str, new_scene->is_group); - CJSON_GET_VALUE_STRING_BY_COPY(cj_scene, ezlopi_group_id_str, new_scene->group_id); + { + CJSON_GET_VALUE_STRING_BY_COPY(cj_scene, ezlopi_group_id_str, new_scene->group_id); + if ((NULL != new_scene->group_id) && (0 < strlen(new_scene->group_id))) + { + TRACE_S("group_id: %s", new_scene->group_id); + ezlopi_cloud_update_group_id((uint32_t)strtoul(new_scene->group_id, NULL, 16)); + } + } + CJSON_GET_VALUE_STRING_BY_COPY(cj_scene, ezlopi_name_str, new_scene->name); CJSON_GET_VALUE_STRING_BY_COPY(cj_scene, ezlopi_parent_id_str, new_scene->parent_id); @@ -269,10 +278,24 @@ void ezlopi_scenes_populate_assign_when_block(l_when_block_v2_t* new_when_block, { if (new_when_block) { + cJSON * cj_blockEnable = cJSON_GetObjectItem(__FUNCTION__, cj_when_block, ezlopi_block_enable_str); + if ((cj_blockEnable) && cJSON_IsBool(cj_blockEnable)) + { + new_when_block->block_enable = (cJSON_True == cj_blockEnable->type) ? true : false; + TRACE_D("blockEnable (edit): %d", new_when_block->block_enable); + } + + CJSON_GET_VALUE_STRING_BY_COPY(cj_when_block, ezlopi_blockName_str, new_when_block->blockName); + if (NULL != new_when_block->blockName && (0 < strlen(new_when_block->blockName))) + { + TRACE_D("blockName (edit): %s ", new_when_block->blockName); + } + CJSON_GET_VALUE_STRING_BY_COPY(cj_when_block, ezlopi_blockId_str, new_when_block->blockId); - if (NULL != new_when_block->blockId) + if (NULL != new_when_block->blockId && (0 < strlen(new_when_block->blockName))) { - TRACE_D("when_blockId: %s", new_when_block->blockId); + TRACE_D("blockId (edit): %s", new_when_block->blockId); + ezlopi_cloud_update_when_blockId((uint32_t)strtoul(new_when_block->blockId, NULL, 16)); } cJSON* cj_block_options = cJSON_GetObjectItem(__FUNCTION__, cj_when_block, ezlopi_blockOptions_str); @@ -298,6 +321,15 @@ void ezlopi_scenes_populate_assign_block_options(s_block_options_v2_t* p_block_o { ezlopi_scenes_populate_assign_method(&p_block_options->method, cj_method); } + + if (0 == strncmp(ezlopi_function_str, p_block_options->method.name, 9)) + { + cJSON* cj_func = cJSON_GetObjectItem(__FUNCTION__, cj_block_options, ezlopi_function_str); + if (cj_func) + { + p_block_options->cj_function = cJSON_Duplicate(__FUNCTION__, cj_func, cJSON_True); + } + } } void ezlopi_scenes_populate_assign_method(s_method_v2_t* p_method, cJSON* cj_method) diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_v2.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_v2.c index 8c6c045b..26f36c54 100644 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_v2.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_v2.c @@ -53,17 +53,15 @@ static l_user_notification_v2_t* ___user_notifications_populate(cJSON* cj_user_n static l_scenes_list_v2_t* __new_scene_populate(cJSON* cj_scene, uint32_t scene_id); static l_scenes_list_v2_t* _scenes_populate(cJSON* cj_scene, uint32_t scene_id); -static int __new_scene_add_group_id_if_reqd(cJSON* cj_new_scene); -static int __new_scene_add_when_blockId_if_reqd(cJSON* cj_new_scene); //------------------------------------------------------------------------------------ int ezlopi_scene_edit_by_id(uint32_t scene_id, cJSON* cj_scene) { int ret = 0; - if (1 == ezlopi_core_scene_edit_update_id(scene_id, cj_scene)) + if (1 == ezlopi_core_scene_edit_store_updated_to_nvs(cj_scene)) // first store in nvs // add the new-block-id { - if (1 == ezlopi_core_scene_edit_store_updated_to_nvs(cj_scene)) + if (1 == ezlopi_core_scene_edit_update_id(scene_id, cj_scene)) // then populate to nvs { ret = 1; } @@ -98,16 +96,16 @@ uint32_t ezlopi_store_new_scene_v2(cJSON* cj_new_scene) if (cj_new_scene) { new_scene_id = ezlopi_cloud_generate_scene_id(); - char tmp_buffer[32]; - snprintf(tmp_buffer, sizeof(tmp_buffer), "%08x", new_scene_id); - cJSON_AddStringToObject(__FUNCTION__, cj_new_scene, ezlopi__id_str, tmp_buffer); + char new_scene_id_str[32]; + snprintf(new_scene_id_str, sizeof(new_scene_id_str), "%08x", new_scene_id); + cJSON_AddStringToObject(__FUNCTION__, cj_new_scene, ezlopi__id_str, new_scene_id_str); - if (__new_scene_add_when_blockId_if_reqd(cj_new_scene)) + if (ezlopi_core_scene_add_when_blockId_if_reqd(cj_new_scene)) { TRACE_S("==> Added new_blockIds : SUCCESS"); } - if (__new_scene_add_group_id_if_reqd(cj_new_scene)) + if (ezlopi_core_scene_add_group_id_if_reqd(cj_new_scene)) { TRACE_S("==> Added new_group_id : SUCCESS"); } @@ -117,7 +115,7 @@ uint32_t ezlopi_store_new_scene_v2(cJSON* cj_new_scene) if (new_scnee_str) { - if (ezlopi_nvs_write_str(new_scnee_str, strlen(new_scnee_str) + 1, tmp_buffer)) + if (ezlopi_nvs_write_str(new_scnee_str, strlen(new_scnee_str) + 1, new_scene_id_str)) { bool free_scene_list_str = 1; char* scenes_list_str = ezlopi_nvs_scene_get_v2(); @@ -211,7 +209,7 @@ uint32_t ezlopi_scenes_get_list_v2(cJSON* cj_scenes_array) { char scene_id_str[32]; snprintf(scene_id_str, sizeof(scene_id_str), "%08x", (uint32_t)cj_scene_id->valuedouble); - cJSON_AddStringToObject(__FUNCTION__, cj_scene, ezlopi__id_str, scene_id_str); + cJSON_AddStringToObject(__FUNCTION__, cj_scene, ezlopi__id_str, scene_id_str);// NVS already might have '_id' if (!cJSON_AddItemToArray(cj_scenes_array, cj_scene)) { cJSON_Delete(__FUNCTION__, cj_scene); @@ -324,14 +322,29 @@ int ezlopi_scenes_enable_disable_scene_by_id_v2(uint32_t _id, bool enabled_flag) CJSON_TRACE("cj_scene----> 2. updated", cj_scene); - if (1 == ezlopi_core_scene_edit_store_updated_to_nvs(cj_scene)) - { - ret = 1; - TRACE_W("nvs enabled successfull"); - } - else + /* DONOT use : 'ezlopi_core_scene_edit_store_updated_to_nvs' .. Here */ + char* update_scene_str = cJSON_PrintBuffered(__FUNCTION__, cj_scene, 4096, false); + TRACE_D("length of 'update_scene_str': %d", strlen(update_scene_str)); + + if (update_scene_str) { - TRACE_E("Error!! failed"); + cJSON* cj_scene_id = cJSON_GetObjectItem(__FUNCTION__, cj_scene, ezlopi__id_str); + if (cj_scene_id && cj_scene_id->valuestring) + { + ezlopi_nvs_delete_stored_data_by_name(cj_scene_id->valuestring); + ret = ezlopi_nvs_write_str(update_scene_str, strlen(update_scene_str), cj_scene_id->valuestring); + + if (ret) + { + TRACE_W("nvs updated successfull"); + } + else + { + TRACE_E("Error!! failed"); + } + } + + ezlopi_free(__FUNCTION__, update_scene_str); } } else @@ -409,6 +422,7 @@ void ezlopi_scenes_init_v2(void) if (scenes_id_list_str) { + TRACE_D("scenes_id_list_str : %s", scenes_id_list_str); cJSON* cj_scenes_ids = cJSON_Parse(__FUNCTION__, scenes_id_list_str); if (cj_scenes_ids) { @@ -493,7 +507,7 @@ static l_scenes_list_v2_t* __new_scene_populate(cJSON* cj_scene, uint32_t scene_ new_scene->_id = scene_id; new_scene->task_handle = NULL; - new_scene->status = EZLOPI_SCENE_STATUS_STOPPED; + new_scene->status = EZLOPI_SCENE_STATUS_STOPPED; // should be run?? CJSON_GET_VALUE_BOOL(cj_scene, ezlopi_enabled_str, new_scene->enabled); CJSON_GET_VALUE_BOOL(cj_scene, ezlopi_is_group_str, new_scene->is_group); @@ -749,7 +763,6 @@ static l_when_block_v2_t* ___when_blocks_populate(cJSON* cj_when_blocks) return tmp_when_block_head; } - static l_when_block_v2_t* ____new_when_block_populate(cJSON* cj_when_block) { l_when_block_v2_t* new_when_block = ezlopi_malloc(__FUNCTION__, sizeof(l_when_block_v2_t)); @@ -760,8 +773,8 @@ static l_when_block_v2_t* ____new_when_block_populate(cJSON* cj_when_block) cJSON * cj_blockEnable = cJSON_GetObjectItem(__FUNCTION__, cj_when_block, ezlopi_block_enable_str); if ((cj_blockEnable) && cJSON_IsBool(cj_blockEnable)) { - TRACE_D("blockEnable: %d", (cJSON_True == cj_blockEnable->type) ? 1 : 0); new_when_block->block_enable = (cJSON_True == cj_blockEnable->type) ? true : false; + TRACE_D("blockEnable: %d", new_when_block->block_enable); } CJSON_GET_VALUE_STRING_BY_COPY(cj_when_block, ezlopi_blockName_str, new_when_block->blockName); @@ -1021,7 +1034,7 @@ static l_fields_v2_t* ______new_field_populate(cJSON* cj_field) return field; } -//---------------------- For group-id ------------------------------------------------------------- +//---------------------- For group-id (only for complete_new setup)------------------------------------------------------------- static void ______add_groupID_and_flag(cJSON * cj_target) { /* 1. Adding is_group_flag */ @@ -1044,12 +1057,9 @@ static void ______add_groupID_and_flag(cJSON * cj_target) if (cj_group_id) { cJSON_DeleteItemFromObject(__FUNCTION__, cj_target, ezlopi_group_id_str); - cJSON_AddStringToObject(__FUNCTION__, cj_target, ezlopi_group_id_str, group_id_str); - } - else - { - cJSON_AddStringToObject(__FUNCTION__, cj_target, ezlopi_group_id_str, group_id_str); } + cJSON_AddStringToObject(__FUNCTION__, cj_target, ezlopi_group_id_str, group_id_str); + } static bool ____check_and_append_group_id(cJSON*cj_when_block) { @@ -1103,7 +1113,7 @@ static bool ____check_and_append_group_id(cJSON*cj_when_block) return add_groupId_flag; } -static int __new_scene_add_group_id_if_reqd(cJSON* cj_new_scene) +int ezlopi_core_scene_add_group_id_if_reqd(cJSON* cj_new_scene) { int ret = 0; /* [ In each-element form 'when-array' ] --> you can check for block_name and add group-id here*/ @@ -1129,7 +1139,7 @@ static int __new_scene_add_group_id_if_reqd(cJSON* cj_new_scene) return ret; } -//---------------------- For blockId --------------------------------------------------------------- +//---------------------- For blockId (only for complete_new setup)--------------------------------------------------------------- static int _____check_and_add_when_blockId(cJSON* cj_new_scene_when_block) { int ret = 0; @@ -1196,13 +1206,28 @@ static int _____check_and_add_when_blockId(cJSON* cj_new_scene_when_block) snprintf(_blockId_str, sizeof(_blockId_str), "%08x", _blockId); TRACE_S("---> new_when_blockId: %s", _blockId_str); - cJSON_AddBoolToObject(__FUNCTION__, cj_new_scene_when_block, ezlopi_block_enable_str, cJSON_True); + /* 1. Adding block_en flag */ + cJSON * cj_block_en = cJSON_GetObjectItem(__FUNCTION__, cj_new_scene_when_block, ezlopi_block_enable_str); + if (cj_block_en && (cJSON_False == cj_block_en->type)) + { + cj_block_en->type = cJSON_True; + } + else + { + cJSON_AddBoolToObject(__FUNCTION__, cj_new_scene_when_block, ezlopi_block_enable_str, cJSON_True); + } + + /* 2. Adding block_id */ + if (cJSON_GetObjectItem(__FUNCTION__, cj_new_scene_when_block, ezlopi_blockId_str)) + { + cJSON_DeleteItemFromObject(__FUNCTION__, cj_new_scene_when_block, ezlopi_blockId_str); + } cJSON_AddStringToObject(__FUNCTION__, cj_new_scene_when_block, ezlopi_blockId_str, _blockId_str); ret = 1; } return ret; } -static int __new_scene_add_when_blockId_if_reqd(cJSON* cj_new_scene) +int ezlopi_core_scene_add_when_blockId_if_reqd(cJSON* cj_new_scene) { int ret = 0; cJSON* cj_when_blocks = cJSON_GetObjectItem(__FUNCTION__, cj_new_scene, ezlopi_when_str); @@ -1217,6 +1242,8 @@ static int __new_scene_add_when_blockId_if_reqd(cJSON* cj_new_scene) } return ret; } + +//---------------------- For Function-block --------------------------------------------------------------- #if 0 /* ENABLE/DEIABLE Flag of FUNCTION -->> [for future use] */ //-------------------------------------------------------------------------------------------------- // Functions for : scene latch-Enable-flag change @@ -1341,11 +1368,11 @@ int ezlopi_core_scene_set_reset_latch_enable(const char* sceneId_str, const char { int ret = 0; uint32_t sceneId = strtoul(sceneId_str, NULL, 16); - l_scenes_list_v2_t* scene_to_reset_latch = ezlopi_scenes_get_by_id_v2(sceneId); - if (scene_to_reset_latch) + l_scenes_list_v2_t* curr_scene = ezlopi_scenes_get_by_id_v2(sceneId); + if (curr_scene) { /*first disable in scene-linked-list*/ - s_when_function_t* function_state = (s_when_function_t*)scene_to_reset_latch->when_block->fields->user_arg; + s_when_function_t* function_state = (s_when_function_t*)curr_scene->when_block->fields->user_arg; if (function_state) { function_state->transtion_instant = 0; @@ -1371,15 +1398,31 @@ int ezlopi_core_scene_set_reset_latch_enable(const char* sceneId_str, const char if (latch_cleared) { - if (1 == ezlopi_core_scene_edit_store_updated_to_nvs(cj_scene)) - { - ret = 1; - TRACE_W("nvs enabled successfull"); - } - else + /* DONOT use : 'ezlopi_core_scene_edit_store_updated_to_nvs' .. Here */ + char* update_scene_str = cJSON_PrintBuffered(__FUNCTION__, cj_scene, 4096, false); + TRACE_D("length of 'update_scene_str': %d", strlen(update_scene_str)); + + if (update_scene_str) { - TRACE_E("Error!! failed"); + cJSON* cj_scene_id = cJSON_GetObjectItem(__FUNCTION__, cj_scene, ezlopi__id_str); + if (cj_scene_id && cj_scene_id->valuestring) + { + ezlopi_nvs_delete_stored_data_by_name(cj_scene_id->valuestring); + ret = ezlopi_nvs_write_str(update_scene_str, strlen(update_scene_str), cj_scene_id->valuestring); + + if (ret) + { + TRACE_W("nvs updated successfull"); + } + else + { + TRACE_E("Error!! failed"); + } + } + + ezlopi_free(__FUNCTION__, update_scene_str); } + } cJSON_Delete(__FUNCTION__, cj_scene); } @@ -1392,20 +1435,20 @@ int ezlopi_core_scene_set_reset_latch_enable(const char* sceneId_str, const char #endif //-------------------------------------------------------------------------------------------------- -// Functions for : scene block-reset-when-condition --> ret_state only +// Functions for : Latch of when-block //-------------------------------------------------------------------------------------------------- int ezlopi_core_scene_reset_latch_state(const char* sceneId_str, const char* blockId_str) { int ret = 0; uint32_t sceneId = strtoul(sceneId_str, NULL, 16); - l_scenes_list_v2_t* scene_to_reset_latch = ezlopi_scenes_get_by_id_v2(sceneId); - if (scene_to_reset_latch) + l_scenes_list_v2_t* curr_scene = ezlopi_scenes_get_by_id_v2(sceneId); + if (curr_scene) { - l_when_block_v2_t * curr_when_block = scene_to_reset_latch->when_block; + l_when_block_v2_t * curr_when_block = curr_scene->when_block; while (curr_when_block) { - s_when_function_t* function_state = (s_when_function_t*)scene_to_reset_latch->when_block->fields->user_arg; + s_when_function_t* function_state = (s_when_function_t*)curr_scene->when_block->fields->user_arg; if (function_state) { ret = 1; @@ -1440,20 +1483,20 @@ int ezlopi_core_scene_reset_latch_state(const char* sceneId_str, const char* blo } //-------------------------------------------------------------------------------------------------- -// Functions for : when-block-output-reset only +// Functions for : when-block ( ALL when ; with/without latches) //-------------------------------------------------------------------------------------------------- -int ezlopi_core_scene_reset_block_status(const char* sceneId_str, const char* blockId_str) +int ezlopi_core_scene_reset_when_block(const char* sceneId_str, const char* blockId_str) { int ret = 0; /* 1. first turn-ON 'reset-flag' for sceneId */ uint32_t sceneId = strtoul(sceneId_str, NULL, 16); - l_scenes_list_v2_t* scene_to_reset_latch = ezlopi_scenes_get_by_id_v2(sceneId); - if (scene_to_reset_latch) + l_scenes_list_v2_t* curr_scene = ezlopi_scenes_get_by_id_v2(sceneId); + if (curr_scene) { ret = 1; - l_when_block_v2_t * curr_when_block = scene_to_reset_latch->when_block; + l_when_block_v2_t * curr_when_block = curr_scene->when_block; while (curr_when_block) { if (blockId_str) @@ -1486,11 +1529,11 @@ int ezlopi_core_scene_reset_block_status(const char* sceneId_str, const char* bl static bool _____change_block_en_status(cJSON* cj_when_block, bool enable_status) { bool ret = false; - cJSON* cj_block_en = cJSON_GetObjectItem(__FUNCTION__, cj_when_block, "block_enable"); if (cJSON_IsBool(cj_block_en) && cj_block_en) { ret = true; + // TRACE_S(" block_en => %d", enable_status); cj_block_en->type = (enable_status ? cJSON_True : cJSON_False); /* change latch-status in nvs*/ } @@ -1503,6 +1546,7 @@ static bool ___enable_disable_block_en_with_blockId(cJSON* cj_when_block, const int value_block_idx = 0; /* <1> single scene function */ + // CJSON_TRACE("cj_when_block : ", cj_when_block); cJSON * cj_blockId = cJSON_GetObjectItem(__FUNCTION__, cj_when_block, "blockId"); if ((cj_blockId && cj_blockId->valuestring) && (0 == strncmp(cj_blockId->valuestring, blockId_str, strlen(cj_blockId->valuestring) + 1))) { @@ -1546,15 +1590,14 @@ static bool ___enable_disable_block_en_with_blockId(cJSON* cj_when_block, const return block_en_changed; } - int ezlopi_core_scene_block_enable_set_reset(const char* sceneId_str, const char* blockId_str, bool enable_status) { int ret = 0; uint32_t sceneId = strtoul(sceneId_str, NULL, 16); - l_scenes_list_v2_t* scene_to_reset_latch = ezlopi_scenes_get_by_id_v2(sceneId); - if (scene_to_reset_latch) + l_scenes_list_v2_t* curr_scene = ezlopi_scenes_get_by_id_v2(sceneId); + if (curr_scene) { - /* secondly change the flag in nvs*/ + /* First change the flag in nvs*/ char* scene_str = ezlopi_nvs_read_str(sceneId_str); if (scene_str) { @@ -1573,25 +1616,47 @@ int ezlopi_core_scene_block_enable_set_reset(const char* sceneId_str, const char if (block_enabled_changed) { - if (1 == ezlopi_core_scene_edit_store_updated_to_nvs(cj_scene)) + /* DONOT use : 'ezlopi_core_scene_edit_store_updated_to_nvs' .. Here */ { - ret = 1; - TRACE_W("nvs updated successfull"); - } - else - { - TRACE_E("Error!! failed"); + char* update_scene_str = cJSON_PrintBuffered(__FUNCTION__, cj_scene, 4096, false); + TRACE_D("length of 'update_scene_str': %d", strlen(update_scene_str)); + + if (update_scene_str) + { + cJSON* cj_scene_id = cJSON_GetObjectItem(__FUNCTION__, cj_scene, ezlopi__id_str); + if (cj_scene_id && cj_scene_id->valuestring) + { + ezlopi_nvs_delete_stored_data_by_name(cj_scene_id->valuestring); + ret = ezlopi_nvs_write_str(update_scene_str, strlen(update_scene_str), cj_scene_id->valuestring); + + if (ret) + { + TRACE_W("nvs updated successfull"); + /*secondly Change in ll */ + ezlopi_core_scene_edit_update_id(sceneId, cj_scene); + } + else + { + TRACE_E("Error!! failed"); + } + } + + ezlopi_free(__FUNCTION__, update_scene_str); + } } } cJSON_Delete(__FUNCTION__, cj_scene); } ezlopi_free(__FUNCTION__, scene_str); } - } return ret; } +//-------------------------------------------------------------------------------------------------- +/* Add for Group-Id in future*/ +//-------------------------------------------------------------------------------------------------- + //----------------------------------------------------------------------------------------------------- #endif // CONFIG_EZPI_SERV_ENABLE_MESHBOTS \ No newline at end of file diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_v2.h b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_v2.h index 459c9815..1f05e41f 100644 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_v2.h +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_v2.h @@ -124,7 +124,7 @@ typedef struct l_when_block_v2 bool is_group; // may be used in future // currently not-populated from nvs char * group_id; // may be used in future // currently not-populated from nvs #endif - bool block_status_reset_once; // set this flag if you want to reset this 'when-block' once. + bool block_status_reset_once; // 'NOT-NVS parameter' [don't populate ; since not needed] // just a dummy flag to trigger function reset. e_scenes_block_type_v2_t block_type; s_block_options_v2_t block_options; l_fields_v2_t* fields; @@ -209,7 +209,7 @@ l_scenes_list_v2_t* ezlopi_scenes_pop_by_id_v2(uint32_t _id); void ezlopi_scenes_notifications_add(cJSON* cj_notifications); -#if 0 +#if 0 // for future usage //-------------------------------- Only for latch operations ---------------------------------------- /** * @brief This function checks for 'latch' struct within nvs_scenes. The scenes are filtered out using 'sceneId[necessary]' & 'blockId[optional]' @@ -223,11 +223,13 @@ int ezlopi_core_scene_set_reset_latch_enable(const char* sceneId_str, const char #endif int ezlopi_core_scene_block_enable_set_reset(const char* sceneId_str, const char* blockId_str, bool enable_status); - int ezlopi_core_scene_reset_latch_state(const char* sceneId_str, const char* blockId_str); +int ezlopi_core_scene_reset_when_block(const char* sceneId_str, const char* blockId_str); -int ezlopi_core_scene_reset_block_status(const char* sceneId_str, const char* blockId_str); - +// ----- # below function are called when 'creating' and 'editing' scene # --------- +int ezlopi_core_scene_add_group_id_if_reqd(cJSON* cj_new_scene); +int ezlopi_core_scene_add_when_blockId_if_reqd(cJSON* cj_new_scene); +// --------------------------------------------------------------------------------- #endif // CONFIG_EZPI_SERV_ENABLE_MESHBOTS #endif // _EZLOPI_CORE_SCENES_V2_H_ diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods.c index d65c3c6a..af66b007 100755 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods.c @@ -10,6 +10,7 @@ #include "ezlopi_core_ota.h" #include "ezlopi_core_http.h" #include "ezlopi_core_devices.h" +#include "ezlopi_core_device_group.h" #include "ezlopi_core_event_group.h" #include "ezlopi_core_scenes_operators.h" #include "ezlopi_core_scenes_expressions.h" @@ -26,7 +27,7 @@ int ezlopi_scene_when_is_item_state(l_scenes_list_v2_t* scene_node, void* arg) // TRACE_W(" is_item_state "); int ret = 0; l_when_block_v2_t* when_block = (l_when_block_v2_t*)arg; - if (when_block) + if (when_block && scene_node) { if (false == when_block->block_enable) { @@ -41,92 +42,44 @@ int ezlopi_scene_when_is_item_state(l_scenes_list_v2_t* scene_node, void* arg) } uint32_t item_id = 0; + uint32_t device_group_id = 0; + uint32_t item_group_id = 0; + l_fields_v2_t* value_field = NULL; #warning "Warning: armed check remains [Krishna]"; l_fields_v2_t* curr_field = when_block->fields; while (curr_field) { - if (EZPI_STRNCMP_IF_EQUAL(curr_field->name, "item", strlen(curr_field->name), 5)) + if (EZPI_STRNCMP_IF_EQUAL(curr_field->name, "item", strlen(curr_field->name), 5) && (NULL != curr_field->field_value.u_value.value_string)) { item_id = strtoul(curr_field->field_value.u_value.value_string, NULL, 16); } - else if (EZPI_STRNCMP_IF_EQUAL(curr_field->name, ezlopi_value_str, strlen(curr_field->name), 6)) + else if (EZPI_STRNCMP_IF_EQUAL(curr_field->name, ezlopi_value_str, strlen(curr_field->name), 6) && (NULL != curr_field->field_value.u_value.value_string)) { value_field = curr_field; } + else if (EZPI_STRNCMP_IF_EQUAL(curr_field->name, "deviceGroup", strlen(curr_field->name), 12) && (NULL != curr_field->field_value.u_value.value_string)) + { + device_group_id = strtoul(curr_field->field_value.u_value.value_string, NULL, 16); + } + else if (EZPI_STRNCMP_IF_EQUAL(curr_field->name, "itemGroup", strlen(curr_field->name), 10) && (NULL != curr_field->field_value.u_value.value_string)) + { + item_group_id = strtoul(curr_field->field_value.u_value.value_string, NULL, 16); + } + curr_field = curr_field->next; } if (item_id && value_field) { - l_ezlopi_device_t* curr_device = ezlopi_device_get_head(); - while (curr_device) - { - l_ezlopi_item_t* curr_item = curr_device->items; - while (curr_item) - { - if (item_id == curr_item->cloud_properties.item_id) - { - cJSON* cj_tmp_value = cJSON_CreateObject(__FUNCTION__); - if (cj_tmp_value) - { - curr_item->func(EZLOPI_ACTION_GET_EZLOPI_VALUE, curr_item, (void*)cj_tmp_value, NULL); - cJSON* cj_value = cJSON_GetObjectItem(__FUNCTION__, cj_tmp_value, ezlopi_value_str); - if (cj_value) - { - switch (cj_value->type) - { - case cJSON_True: - { - if (true == value_field->field_value.u_value.value_bool) - { - ret = 1; - } - break; - } - case cJSON_False: - { - if (false == value_field->field_value.u_value.value_bool) - { - ret = 1; - } - break; - } - case cJSON_Number: - { - if (cj_value->valuedouble == value_field->field_value.u_value.value_double) - { - ret = 1; - } - break; - } - case cJSON_String: - { - uint32_t cmp_size = (strlen(cj_value->valuestring) > strlen(value_field->field_value.u_value.value_string)) ? strlen(cj_value->valuestring) : strlen(value_field->field_value.u_value.value_string); - if (0 == strncmp(cj_value->valuestring, value_field->field_value.u_value.value_string, cmp_size)) - { - ret = 1; - } - break; - } - default: - { - TRACE_E("Value type mis-matched!"); - } - } - } - - cJSON_Delete(__FUNCTION__, cj_tmp_value); - } - break; - } - curr_item = curr_item->next; - } - - curr_device = curr_device->next; - } + ret = is_item_state_single_condition(item_id, value_field); } + else if (device_group_id && item_group_id && value_field) // since device_and_item group both need to exist + { + ret = is_item_state_with_grp_condition(device_group_id, item_group_id, value_field); + } + } return ret; @@ -631,7 +584,7 @@ int ezlopi_scene_when_is_House_Mode_Alarm_Phase_Range(l_scenes_list_v2_t* scene_ } curr_field = curr_field->next; } - } +} #endif return ret; } @@ -661,7 +614,7 @@ int ezlopi_scene_when_is_House_Mode_Switch_to_Range(l_scenes_list_v2_t* scene_no { TRACE_E(" Current HouseMode_phase does not have duration "); } - } +} #endif return ret; } diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods_helper_functions.c b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods_helper_functions.c index 2fe1eaba..d6134801 100644 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods_helper_functions.c +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods_helper_functions.c @@ -6,11 +6,141 @@ #include "ezlopi_util_trace.h" #include "ezlopi_core_nvs.h" #include "ezlopi_core_http.h" +#include "ezlopi_core_devices.h" +#include "ezlopi_core_device_group.h" #include "ezlopi_core_scenes_v2.h" #include "ezlopi_core_scenes_edit.h" #include "ezlopi_core_scenes_when_methods_helper_functions.h" + +#include "ezlopi_cloud_constants.h" #include "EZLOPI_USER_CONFIG.h" +//------------------------------- ezlopi_scene_when_is_itemState ------------------------------------------ +static int __compare_item_values(l_ezlopi_item_t* curr_item, l_fields_v2_t* value_field) +{ + int ret = 0; + cJSON* cj_tmp_value = cJSON_CreateObject(__FUNCTION__); + if (cj_tmp_value) + { + curr_item->func(EZLOPI_ACTION_GET_EZLOPI_VALUE, curr_item, (void*)cj_tmp_value, NULL); + cJSON* cj_value = cJSON_GetObjectItem(__FUNCTION__, cj_tmp_value, ezlopi_value_str); + if (cj_value) + { + switch (cj_value->type) + { + case cJSON_True: + { + if (true == value_field->field_value.u_value.value_bool) + { + ret = 1; + } + break; + } + case cJSON_False: + { + if (false == value_field->field_value.u_value.value_bool) + { + ret = 1; + } + break; + } + case cJSON_Number: + { + if (cj_value->valuedouble == value_field->field_value.u_value.value_double) + { + ret = 1; + } + break; + } + case cJSON_String: + { + if (EZPI_STRNCMP_IF_EQUAL(cj_value->valuestring, value_field->field_value.u_value.value_string, strlen(cj_value->valuestring), strlen(value_field->field_value.u_value.value_string))) + { + ret = 1; + } + break; + } + default: + { + TRACE_E("Value type mis-matched!"); + } + } + } + + cJSON_Delete(__FUNCTION__, cj_tmp_value); + } + + return ret; +} + +int is_item_state_single_condition(uint32_t item_id, l_fields_v2_t* value_field) +{ + int ret = 0; + l_ezlopi_device_t* curr_device = ezlopi_device_get_head(); + while (curr_device) + { + l_ezlopi_item_t* curr_item = curr_device->items; + while (curr_item) + { + if (item_id == curr_item->cloud_properties.item_id) + { + ret = __compare_item_values(curr_item, value_field); + break; + } + curr_item = curr_item->next; + } + curr_device = curr_device->next; + } + + return ret; +} + +int is_item_state_with_grp_condition(uint32_t device_group_id, uint32_t item_group_id, l_fields_v2_t* value_field) +{ + int ret = 0; + + l_ezlopi_device_grp_t * curr_devgrp = ezlopi_core_device_group_get_by_id(device_group_id); + if (curr_devgrp) + { + int idx = 0; + cJSON * cj_get_devarr = NULL; + while (NULL != (cj_get_devarr = cJSON_GetArrayItem(curr_devgrp->devices, idx))) // ["102ec000" , "102ec001" ,..] + { + uint32_t curr_devce_id = strtoul(cj_get_devarr->valuestring, NULL, 16); + l_ezlopi_device_t * curr_device = ezlopi_device_get_by_id(curr_devce_id); // immediately goto "102ec000" ... + if (curr_device) + { + l_ezlopi_item_t* curr_item_node = curr_device->items; // perform operation on items of above device --> "102ec000" + while (curr_item_node) + { + // compare with items_list stored in item_group_id + l_ezlopi_item_grp_t * curr_item_grp = ezlopi_core_item_group_get_by_id(item_group_id); // get "ll_itemgrp_node" + if (curr_item_grp) + { + int count = 0; + cJSON * cj_item_names = NULL; + while (NULL != (cj_item_names = cJSON_GetArrayItem(curr_item_grp->item_names, count))) // ["202ec000" , "202ec001" ,..] + { + uint32_t req_item_id_from_itemgrp = strtoul(cj_item_names->valuestring, NULL, 16); + // if the item_ids match ; Then compare the "item_values" with that of the "scene's" requirement + if (req_item_id_from_itemgrp == curr_item_node->cloud_properties.item_id) + { + // compare the values of "when-condition" & the "ll_item_node" + ret = __compare_item_values(curr_item_node, value_field); + break; + } + count++; + } + } + curr_item_node = curr_item_node->next; + } + } + idx++; + } + } + + return ret; +} //------------------------------- ezlopi_scene_when_is_date --------------------------------------------- diff --git a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods_helper_functions.h b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods_helper_functions.h index 7c320b5a..c1f63b08 100644 --- a/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods_helper_functions.h +++ b/ezlopi-core/ezlopi-core-scenes/ezlopi_core_scenes_when_methods_helper_functions.h @@ -56,6 +56,10 @@ typedef struct s_function_opr int(*opr_method)(l_scenes_list_v2_t* scene_node, l_when_block_v2_t* when_block, cJSON* cj_func_opr); } s_function_opr_t; +//------------------------------- ezlopi_scene_when_is_itemState ------------------------------------------ +int is_item_state_single_condition(uint32_t item_id, l_fields_v2_t* value_field); +int is_item_state_with_grp_condition(uint32_t device_group_id, uint32_t item_group_id, l_fields_v2_t* value_field); + //------------------------------- ezlopi_scene_when_is_date ----------------------------------------------- uint8_t isdate_type_check(e_isdate_modes_t* mode_type, struct tm* info, l_fields_v2_t* curr_field); uint8_t isdate_tm_check(e_isdate_modes_t* mode_type, struct tm* info, l_fields_v2_t* curr_field); diff --git a/ezlopi-services/ezlopi-service-meshbot/ezlopi_service_meshbot.c b/ezlopi-services/ezlopi-service-meshbot/ezlopi_service_meshbot.c index 2866193e..b609cb34 100644 --- a/ezlopi-services/ezlopi-service-meshbot/ezlopi_service_meshbot.c +++ b/ezlopi-services/ezlopi-service-meshbot/ezlopi_service_meshbot.c @@ -46,15 +46,16 @@ uint32_t ezlopi_meshbot_service_stop_for_scene_id(uint32_t _id) if (EZLOPI_SCENE_STATUS_RUNNING == scene_node->status) { scene_node->status = EZLOPI_SCENE_STATUS_STOP; - TRACE_D("stop scene_id : %#x [%d] ", scene_node->_id, scene_node->status); + TRACE_S("stop scene_id : %#x [%d] ", scene_node->_id, scene_node->status); } - // while (EZLOPI_SCENE_STATUS_STOPPED != scene_node->status) - // { - // vTaskDelay(10 / portTICK_RATE_MS); - // } + // #warning "Donot comment below : Remove this warning when merging into development"; + while (EZLOPI_SCENE_STATUS_STOPPED != scene_node->status) + { + vTaskDelay(10 / portTICK_RATE_MS); + } - // ezlopi_scenes_status_change_broadcast(scene_node, scene_status_stopped_str); + ezlopi_scenes_status_change_broadcast(scene_node, scene_status_stopped_str); ret = 1; } @@ -70,15 +71,16 @@ uint32_t ezlopi_meshobot_service_stop_scene(l_scenes_list_v2_t* scene_node) if (EZLOPI_SCENE_STATUS_RUNNING == scene_node->status) { scene_node->status = EZLOPI_SCENE_STATUS_STOP; - TRACE_D("stop scene_id : %#x [%d] ", scene_node->_id, scene_node->status); + TRACE_S("stop scene_id : %#x [%d] ", scene_node->_id, scene_node->status); } - // while (EZLOPI_SCENE_STATUS_STOPPED != scene_node->status) - // { - // vTaskDelay(10 / portTICK_RATE_MS); - // } + // #warning "Donot comment below : Remove this warning when merging into development"; + while (EZLOPI_SCENE_STATUS_STOPPED != scene_node->status) + { + vTaskDelay(10 / portTICK_RATE_MS); + } - // ezlopi_scenes_status_change_broadcast(scene_node, scene_status_stopped_str); + ezlopi_scenes_status_change_broadcast(scene_node, scene_status_stopped_str); ret = 1; } @@ -95,7 +97,8 @@ uint32_t ezlopi_meshbot_service_start_scene(l_scenes_list_v2_t* scene_node) { __execute_scene_start(scene_node); // xTaskCreate(__scenes_process, scene_node->name, 2 * 2048, scene_node, 2, NULL); - TRACE_D("start scene_id : %#x [%d] ", scene_node->_id, scene_node->status); + + TRACE_S("start scene_id : %#x [%d] ", scene_node->_id, scene_node->status); ret = 1; } } @@ -441,7 +444,7 @@ static int __execute_scene_stop(l_scenes_list_v2_t* scene_node) static int __execute_scene_start(l_scenes_list_v2_t* scene_node) { int ret = 0; - if (scene_node && (NULL == scene_node->thread_ctx)) + if (scene_node && (true == scene_node->enabled) && (NULL == scene_node->thread_ctx)) { scene_node->thread_ctx = (void*)ezlopi_malloc(__FUNCTION__, sizeof(s_thread_ctx_t)); if (scene_node->thread_ctx)