diff --git a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts index 8f5c651371..87e2e8f45b 100644 --- a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts +++ b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts @@ -7274,6 +7274,13 @@ export let ClusterTypeAttrs: any = { isArray: false, } ] + }, + { + id: 128, + name: "GetAllPINCodes", + required: false, + fields: [ + ] } ] } diff --git a/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_cmdmapper_gen_cmd_publish.cpp b/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_cmdmapper_gen_cmd_publish.cpp index 541f7289af..87eb68fbd1 100644 --- a/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_cmdmapper_gen_cmd_publish.cpp +++ b/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_cmdmapper_gen_cmd_publish.cpp @@ -316,14 +316,14 @@ static void zigpc_command_mapper_publish_door_lock_getpin_code_response( ) { std::string unid(zigpc_ucl::mqtt::build_unid(zigbee_eui64_to_uint(eui64))); - uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t fields = { + uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t fields = { (uint16_t) data->door_lock_getpin_code_response.userid, (DrlkUserStatus) data->door_lock_getpin_code_response.user_status, (DrlkUserType) data->door_lock_getpin_code_response.user_type, (const char*) data->door_lock_getpin_code_response.code }; - uic_mqtt_dotdot_door_lock_publish_generated_getpin_code_response_command( + uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( unid.c_str(), endpoint_id, &fields diff --git a/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_command_mapper_bygroup_handlers.cpp b/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_command_mapper_bygroup_handlers.cpp index 7e36d563f4..93598aed17 100644 --- a/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_command_mapper_bygroup_handlers.cpp +++ b/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_command_mapper_bygroup_handlers.cpp @@ -2269,6 +2269,54 @@ void zigpc_command_mapper_bygroup_door_lock_clear_allrfid_codes_handler( 0, nullptr ); +/** + * @brief DotDot MQTT by-group handler for DoorLock/GetAllPINCodes command. + * + * @param group_id UCL group identifier. + + */ +void zigpc_command_mapper_bygroup_door_lock_get_all_pin_codes_handler( + const dotdot_group_id_t group_id +) { + + + + + zigpc_command_mapper_send_multicast( + group_id, + ZIGPC_ZCL_FRAME_TYPE_CMD_TO_SERVER, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK_COMMAND_GET_ALL_PIN_CODES, + 0, + nullptr + ); + +} + + +} + +/** + * @brief DotDot MQTT by-group handler for DoorLock/GetAllPINCodes command. + * + * @param group_id UCL group identifier. + + */ +void zigpc_command_mapper_bygroup_door_lock_get_allpin_codes_handler( + const dotdot_group_id_t group_id +) { + + + + + zigpc_command_mapper_send_multicast( + group_id, + ZIGPC_ZCL_FRAME_TYPE_CMD_TO_SERVER, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK_COMMAND_GET_ALLPIN_CODES, + 0, + nullptr + ); } @@ -4051,6 +4099,8 @@ sl_status_t zigpc_command_mapper_mqtt_bygroup_handlers_init(void) uic_mqtt_dotdot_by_group_door_lock_getrfid_code_callback_set(zigpc_command_mapper_bygroup_door_lock_getrfid_code_handler); uic_mqtt_dotdot_by_group_door_lock_clearrfid_code_callback_set(zigpc_command_mapper_bygroup_door_lock_clearrfid_code_handler); uic_mqtt_dotdot_by_group_door_lock_clear_allrfid_codes_callback_set(zigpc_command_mapper_bygroup_door_lock_clear_allrfid_codes_handler); + uic_mqtt_dotdot_by_group_door_lock_get_allpin_codes_callback_set(zigpc_command_mapper_bygroup_door_lock_get_allpin_codes_handler); + uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback_set(zigpc_command_mapper_bygroup_door_lock_get_all_pin_codes_handler); uic_mqtt_dotdot_by_group_thermostat_write_attributes_callback_set(zigpc_command_mapper_bygroup_thermostat_write_attributes_handler); uic_mqtt_dotdot_by_group_thermostat_setpoint_raise_or_lower_callback_set(zigpc_command_mapper_bygroup_thermostat_setpoint_raise_or_lower_handler); uic_mqtt_dotdot_by_group_thermostat_set_weekly_schedule_callback_set(zigpc_command_mapper_bygroup_thermostat_set_weekly_schedule_handler); diff --git a/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_command_mapper_handlers.cpp b/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_command_mapper_handlers.cpp index aa5a30d40c..50ee069afc 100644 --- a/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_command_mapper_handlers.cpp +++ b/applications/zigpc/components/command_mapper/zap-generated/src/zigpc_command_mapper_handlers.cpp @@ -4231,6 +4231,50 @@ sl_status_t zigpc_command_mapper_door_lock_clear_allrfid_codes_handler( status = SL_STATUS_NOT_AVAILABLE; } return status; + * @brief DotDot MQTT translator handler for DoorLock/GetAllPINCodes command. + * + * @param unid Unify device identifier string + * @param endpoint Unify device endpoint identifier + * @param callback_type Callback type + * @return SL_STATUS_OK if callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL and call is successful + * @return SL_STATUS_OK if callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK and command is supported by the unid/endpoint + * @return SL_STATUS_NOT_AVAILABLE if callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK and command is not supported by the unid/endpoint + */ +sl_status_t zigpc_command_mapper_door_lock_get_all_pin_codes_handler( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type +) { + sl_status_t status = SL_STATUS_NOT_AVAILABLE; + + if (callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) { + status = zigpc_command_mapper_cluster_support_check(unid, endpoint, ZIGPC_ZCL_CLUSTER_DOOR_LOCK); + if (status != SL_STATUS_OK) { + status = SL_STATUS_NOT_AVAILABLE; + } + return status; + } + + + + + if (status == SL_STATUS_OK) { + zigpc_command_mapper_send_unicast( + unid, + endpoint, + ZIGPC_ZCL_FRAME_TYPE_CMD_TO_SERVER, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK_COMMAND_get_all_pin_CODES, + 0, + nullptr + ); + } + + // Always return SL_STATUS_OK if being called normally. + return status; +} + +/** } @@ -4252,6 +4296,50 @@ sl_status_t zigpc_command_mapper_door_lock_clear_allrfid_codes_handler( return SL_STATUS_OK; } +/** + * @brief DotDot MQTT translator handler for DoorLock/GetAllPINCodes command. + * + * @param unid Unify device identifier string + * @param endpoint Unify device endpoint identifier + * @param callback_type Callback type + * @return SL_STATUS_OK if callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL and call is successful + * @return SL_STATUS_OK if callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK and command is supported by the unid/endpoint + * @return SL_STATUS_NOT_AVAILABLE if callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK and command is not supported by the unid/endpoint + */ +sl_status_t zigpc_command_mapper_door_lock_get_allpin_codes_handler( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type +) { + sl_status_t status = SL_STATUS_OK; + + if (callback_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) { + status = zigpc_command_mapper_cluster_support_check(unid, endpoint, ZIGPC_ZCL_CLUSTER_DOOR_LOCK); + if (status != SL_STATUS_OK) { + status = SL_STATUS_NOT_AVAILABLE; + } + return status; + } + + + + + if (status == SL_STATUS_OK) { + zigpc_command_mapper_send_unicast( + unid, + endpoint, + ZIGPC_ZCL_FRAME_TYPE_CMD_TO_SERVER, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK_COMMAND_GET_ALLPIN_CODES, + 0, + nullptr + ); + } + + // Always return SL_STATUS_OK if being called normally. + return SL_STATUS_OK; +} + /****************** * DotDot MQTT Command Handlers for Thermostat cluster ******************/ @@ -8054,6 +8142,12 @@ sl_status_t zigpc_command_mapper_register_dotdot_mqtt_handlers(void) uic_mqtt_dotdot_door_lock_clear_allrfid_codes_callback_set( zigpc_command_mapper_door_lock_clear_allrfid_codes_handler ); + uic_mqtt_dotdot_door_lock_get_allpin_codes_callback_set( + zigpc_command_mapper_door_lock_get_allpin_codes_handler + ); + ); + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_set( + zigpc_command_mapper_door_lock_get_all_pin_codes_handler uic_mqtt_dotdot_set_thermostat_write_attributes_callback( zigpc_command_mapper_thermostat_write_attributes_handler ); diff --git a/applications/zigpc/components/zcl_util/zap-generated/include/zcl_definitions.h b/applications/zigpc/components/zcl_util/zap-generated/include/zcl_definitions.h index 753da5c2bb..ebb064c1b1 100644 --- a/applications/zigpc/components/zcl_util/zap-generated/include/zcl_definitions.h +++ b/applications/zigpc/components/zcl_util/zap-generated/include/zcl_definitions.h @@ -479,6 +479,7 @@ typedef enum { ZIGPC_ZCL_CLUSTER_DOOR_LOCK_COMMAND_CLEAR_ALLRFID_CODES_RESPONSE = 0x19, ZIGPC_ZCL_CLUSTER_DOOR_LOCK_COMMAND_OPERATING_EVENT_NOTIFICATION = 0x20, ZIGPC_ZCL_CLUSTER_DOOR_LOCK_COMMAND_PROGRAMMING_EVENT_NOTIFICATION = 0x21, + ZIGPC_ZCL_CLUSTER_DOOR_LOCK_COMMAND_GET_ALL_PIN_CODES = 0x80, } zigpc_zcl_door_lock_command_type_t; /***************************************************************** diff --git a/applications/zpc/components/dotdot_mapper/rules/DoorLock_to_DoorLockCC.uam b/applications/zpc/components/dotdot_mapper/rules/DoorLock_to_DoorLockCC.uam index 3b311f7da2..d161969a00 100644 --- a/applications/zpc/components/dotdot_mapper/rules/DoorLock_to_DoorLockCC.uam +++ b/applications/zpc/components/dotdot_mapper/rules/DoorLock_to_DoorLockCC.uam @@ -4,10 +4,34 @@ def zwDOOR_LOCK_OPERATION_DOOR_LOCK_MODE 0x6207 def zwDOOR_LOCK_CAPABILITIES_SUPPORTED_DOOR_COMPONENTS 0x6217 +def zwDOOR_LOCK_CONFIGURATION_OPERATION_TYPE 0x6202 +def zwDOOR_LOCK_CONFIGURATION_INSIDE_DOOR_HANDLES_STATE 0x6203 +def zwDOOR_LOCK_CONFIGURATION_OUTSIDE_DOOR_HANDLES_STATE 0x6204 +def zwDOOR_LOCK_CONFIGURATION_LOCK_TIMEOUT_MINUTES 0x6205 +def zwDOOR_LOCK_CONFIGURATION_LOCK_TIMEOUT_SECONDS 0x6206 + +def zwDOOR_LOCK_OPERATION_INSIDE_DOOR_HANDLES_MODE 0x6208 +def zwDOOR_LOCK_OPERATION_OUTSIDE_DOOR_HANDLES_MODE 0x6209 +def zwDOOR_LOCK_OPERATION_DOOR_CONDITION 0x620A +def zwDOOR_LOCK_OPERATION_LOCK_TIMEOUT_MINUTES 0x620B +def zwDOOR_LOCK_OPERATION_LOCK_TIMEOUT_SECONDS 0x620C + +// UserCode Zwave attributes +def zwUSER_CODE_DATA 0x6302 +def zwUSER_CODE_NUMBER_OF_USERS 0x6303 +def zwUSER_CODE_CAPABILITIES 0x6309 +def zwUSER_CODE_SUPPORTED_FLAGS 0x630A +def zwUSER_CODE_SUPPORTED_USER_ID_STATUS_BITMASK 0x630B +def zwUSER_CODE_SUPPORTED_KEYPAD_MODES_BITMASK 0x630C +def zwUSER_CODE_SUPPORTED_KEYS_BITMASK 0x630D + +def zwUSER_CODE_KEYPAD_MODE 0x630F + // ZigBee DoorLock attributes def zbDOOR_LOCK_CLUSTER_LOCK_STATE 0x01010000 def zbDOOR_LOCK_CLUSTER_LOCK_TYPE 0x01010001 def zbDOOR_LOCK_ACTUATOR_ENABLED 0x01010002 +def zbDOOR_LOCK_NUMBER_OF_PIN_USERS 0x01010012 // -------- // Zwave lock types @@ -35,6 +59,8 @@ def zbDOOR_UNDEFINED 0xFF scope 0 { + r'zbDOOR_LOCK_NUMBER_OF_PIN_USERS = r'zwUSER_CODE_DATA.zwUSER_CODE_NUMBER_OF_USERS + // Linking Zigbee Lock State to mapped ZWave Lock State r'zbDOOR_LOCK_CLUSTER_LOCK_STATE = if ( r'zwDOOR_LOCK_OPERATION_DOOR_LOCK_MODE == zwDOOR_UNSECURE_FOR_OUTSIDE ) zbDOOR_NOT_FULLY_LOCKED diff --git a/applications/zpc/components/dotdot_mapper/rules/Notification_to_DoorLock.uam b/applications/zpc/components/dotdot_mapper/rules/Notification_to_DoorLock.uam new file mode 100644 index 0000000000..d14f8e2aca --- /dev/null +++ b/applications/zpc/components/dotdot_mapper/rules/Notification_to_DoorLock.uam @@ -0,0 +1,38 @@ +// Custom Notification to DoorLock mappings +def zwNOTIFICATION_TYPE 0x7103 +def zwNOTIFICATION_ACCESS_CONTROL_STATE 0x7105 +def zwVALUE 0x7106 + +def zbDOOR_LOCK_CLUSTER_LOCK_STATE 0x01010000 +def zbDOOR_LOCKED 0x01 +def zbDOOR_UNLOCKED 0x02 + +def ACCESS_CONTROL 0x06 +def ACCESS_CONTROL_TYPE 0xFF + +def MANUAL_LOCK_OPERATION 0x01 +def MANUAL_UNLOCK_OPERATION 0x02 +def RF_LOCK_OPERATION 0x03 +def RF_UNLOCK_OPERATION 0x04 +def KEYPAD_LOCK_OPERATOIN 0x05 +def KEYPAD_UNLOCK_OPERATOIN 0x06 +def AUTO_LOCK_LOCKED_OPERATION 0x09 +def UNLOCK_BY_RF_WITH_INVALID_USER_CODE 0x14 +def LOCKED_BY_RF_WITH_INVALID_USER_CODE 0x15 + + +scope 0 { + +r'zbDOOR_LOCK_CLUSTER_LOCK_STATE = + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == MANUAL_LOCK_OPERATION ) zbDOOR_LOCKED + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == MANUAL_UNLOCK_OPERATION ) zbDOOR_UNLOCKED + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == RF_LOCK_OPERATION ) zbDOOR_LOCKED + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == RF_UNLOCK_OPERATION ) zbDOOR_UNLOCKED + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == KEYPAD_LOCK_OPERATOIN ) zbDOOR_LOCKED + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == KEYPAD_UNLOCK_OPERATOIN ) zbDOOR_UNLOCKED + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == AUTO_LOCK_LOCKED_OPERATION ) zbDOOR_LOCKED + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == UNLOCK_BY_RF_WITH_INVALID_USER_CODE ) zbDOOR_UNLOCKED + if ( r'zwNOTIFICATION_TYPE[ACCESS_CONTROL].zwNOTIFICATION_ACCESS_CONTROL_STATE[ACCESS_CONTROL_TYPE].zwVALUE == LOCKED_BY_RF_WITH_INVALID_USER_CODE ) zbDOOR_LOCKED + undefined + +} \ No newline at end of file diff --git a/applications/zpc/components/zcl_cluster_servers/src/user_code_cluster_server.cpp b/applications/zpc/components/zcl_cluster_servers/src/user_code_cluster_server.cpp index c56e8222c0..632f568339 100644 --- a/applications/zpc/components/zcl_cluster_servers/src/user_code_cluster_server.cpp +++ b/applications/zpc/components/zcl_cluster_servers/src/user_code_cluster_server.cpp @@ -195,6 +195,22 @@ static sl_status_t (uint8_t *)&user_id, sizeof(uint16_t), 0); + uint16_t number_of_users = 0; + attribute_store_get_child_reported(user_code_data, + ATTRIBUTE(NUMBER_OF_USERS), + &number_of_users, + sizeof(number_of_users)); + + if ((user_id > 0) && (user_id <= number_of_users)) { + if (user_id_node == ATTRIBUTE_STORE_INVALID_NODE) { + user_id_node = attribute_store_emplace(user_code_data, + ATTRIBUTE(USER_ID), + &user_id, + sizeof(user_id)); + } + } else { + return SL_STATUS_FAIL; + } attribute_store_node_t user_code_node = attribute_store_get_first_child_by_type(user_id_node, ATTRIBUTE(CODE)); @@ -205,6 +221,82 @@ static sl_status_t : SL_STATUS_FAIL; } +/** + * @brief Checks if the User ID node matches what we expect and undefines + * the User Code data underneath. + * + * @param user_id_node Attribute Store node for the User ID. + */ +static void undefine_user_code(attribute_store_node_t user_id_node) +{ + if (attribute_store_get_node_type(user_id_node) != ATTRIBUTE(USER_ID)) { + return; + } + + // Set the user code to nothing: + attribute_store_node_t user_code_node + = attribute_store_get_first_child_by_type(user_id_node, ATTRIBUTE(CODE)); + + attribute_store_undefine_desired(user_code_node); + attribute_store_undefine_reported(user_code_node); + + attribute_store_node_t user_id_status_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(USER_ID_STATUS)); + + attribute_store_undefine_desired(user_id_status_node); + attribute_store_undefine_reported(user_id_status_node); +} + +/** + * @brief Navigates under the endpoint node and undefines all the + * known user code data. + * + * @param node Attribute Store node for the Endpoint. + */ +static void undefine_all_user_codes(attribute_store_node_t endpoint_node) +{ + attribute_store_node_t data_node + = attribute_store_get_first_child_by_type(endpoint_node, ATTRIBUTE(DATA)); + + attribute_store_walk_tree(data_node, &undefine_user_code); +} + +sl_status_t get_all_pin_codes_command(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type) +{ + attribute_store_node_t user_code_data + = get_user_code_data_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return attribute_store_node_exists(user_code_data) ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + attribute_store_node_t data_node + = attribute_store_get_first_child_by_type(endpoint_node, ATTRIBUTE(DATA)); + + uint16_t number_of_users = 0; + attribute_store_get_child_reported(user_code_data, + ATTRIBUTE(NUMBER_OF_USERS), + &number_of_users, + sizeof(number_of_users)); + + for (uint16_t i = 1; (i <= number_of_users) && (i != 0); i++) { + attribute_store_emplace(data_node, ATTRIBUTE(USER_ID), &i, sizeof(i)); + } + + undefine_all_user_codes(endpoint_node); + + return SL_STATUS_OK; +} + static sl_status_t set_user_status_command(dotdot_unid_t unid, dotdot_endpoint_id_t endpoint, @@ -291,6 +383,7 @@ sl_status_t user_code_cluster_server_init() // Register the callback for handling commands from IoT service uic_mqtt_dotdot_door_lock_setpin_code_callback_set(&set_pin_code_command); uic_mqtt_dotdot_door_lock_getpin_code_callback_set(&get_pin_code_command); + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_set(&get_all_pin_codes_command); uic_mqtt_dotdot_door_lock_clearpin_code_callback_set(&clear_pin_code_command); uic_mqtt_dotdot_door_lock_clear_allpin_codes_callback_set( &clear_all_pin_codes_command); diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_code.c b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_code.c index 17df70b566..d757abc506 100644 --- a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_code.c +++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_code.c @@ -24,8 +24,11 @@ #include "zwave_controller_utils.h" #include "zpc_attribute_store_network_helper.h" #include "zpc_attribute_resolver.h" +#include "zwave_command_class_user_code_types.h" // Includes from Unify Components +#include "dotdot_mqtt.h" +#include "dotdot_mqtt_generated_commands.h" #include "attribute_store.h" #include "attribute_store_helper.h" #include "attribute_resolver.h" @@ -323,13 +326,38 @@ static bool is_mucr_supported(attribute_store_node_t endpoint_node) static sl_status_t zwave_command_class_user_code_number_get( attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) { - (void)node; // unused. + attribute_store_node_t endpoint_node + = attribute_store_get_first_parent_with_type(node, ATTRIBUTE_ENDPOINT_ID); + attribute_store_node_t version_node + = attribute_store_get_first_child_by_type(endpoint_node, + ATTRIBUTE(VERSION)); + // We need to check the version of the supporting node: + zwave_cc_version_t supporting_node_version = 0; + attribute_store_get_reported(version_node, + &supporting_node_version, + sizeof(supporting_node_version)); + + if (supporting_node_version == 0) { + // Wait to know the supporting node version + *frame_length = 0; + return SL_STATUS_IS_WAITING; + } + + if (supporting_node_version == 1) { + ZW_USERS_NUMBER_GET_FRAME *get_frame + = (ZW_USERS_NUMBER_GET_FRAME *)frame; + get_frame->cmdClass = COMMAND_CLASS_USER_CODE; + get_frame->cmd = USERS_NUMBER_GET; + *frame_length = sizeof(ZW_USERS_NUMBER_GET_FRAME); + } + else { // This is a static payload. ZW_USERS_NUMBER_GET_V2_FRAME *get_frame = (ZW_USERS_NUMBER_GET_V2_FRAME *)frame; get_frame->cmdClass = COMMAND_CLASS_USER_CODE_V2; get_frame->cmd = USERS_NUMBER_GET_V2; *frame_length = sizeof(ZW_USERS_NUMBER_GET_V2_FRAME); + } return SL_STATUS_OK; } @@ -375,8 +403,8 @@ static sl_status_t zwave_command_class_user_code_get( *frame_length = 0; return SL_STATUS_ALREADY_EXISTS; } - frame[0] = COMMAND_CLASS_USER_CODE_V2; - frame[1] = USER_CODE_GET_V2; + frame[0] = COMMAND_CLASS_USER_CODE; + frame[1] = USER_CODE_GET; frame[2] = (uint8_t)user_id; *frame_length = 3; return SL_STATUS_OK; @@ -537,7 +565,30 @@ static sl_status_t zwave_command_class_user_code_admin_code_get( static sl_status_t zwave_command_class_user_code_keypad_mode_get( attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) { - (void)node; // unused. + attribute_store_node_t endpoint_node + = attribute_store_get_first_parent_with_type(node, ATTRIBUTE_ENDPOINT_ID); + attribute_store_node_t version_node + = attribute_store_get_first_child_by_type(endpoint_node, + ATTRIBUTE(VERSION)); + // We need to check the version of the supporting node: + zwave_cc_version_t supporting_node_version = 0; + attribute_store_get_reported(version_node, + &supporting_node_version, + sizeof(supporting_node_version)); + + if (supporting_node_version == 0) { + // Wait to know the supporting node version + *frame_length = 0; + return SL_STATUS_IS_WAITING; + } + + if (supporting_node_version == 1) { + sl_log_warning(LOG_TAG, "Keypad Mode attribute found for v1 node. Deleting"); + attribute_store_delete_node(node); + *frame_length = 0; + return SL_STATUS_ALREADY_EXISTS; + } + zwave_minimum_frame_t *get_frame = (zwave_minimum_frame_t *)frame; get_frame->command_class = COMMAND_CLASS_USER_CODE_V2; get_frame->command = USER_CODE_KEYPAD_MODE_GET_V2; @@ -557,6 +608,30 @@ static sl_status_t zwave_command_class_user_code_keypad_mode_get( static sl_status_t zwave_command_class_user_code_keypad_mode_set( attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) { + attribute_store_node_t endpoint_node + = attribute_store_get_first_parent_with_type(node, ATTRIBUTE_ENDPOINT_ID); + attribute_store_node_t version_node + = attribute_store_get_first_child_by_type(endpoint_node, + ATTRIBUTE(VERSION)); + // We need to check the version of the supporting node: + zwave_cc_version_t supporting_node_version = 0; + attribute_store_get_reported(version_node, + &supporting_node_version, + sizeof(supporting_node_version)); + + if (supporting_node_version == 0) { + // Wait to know the supporting node version + *frame_length = 0; + return SL_STATUS_IS_WAITING; + } + + if (supporting_node_version == 1) { + sl_log_warning(LOG_TAG, "Keypad mode attribute found for v1 node. Deleting"); + attribute_store_delete_node(node); + *frame_length = 0; + return SL_STATUS_ALREADY_EXISTS; + } + ZW_USER_CODE_KEYPAD_MODE_SET_V2_FRAME *set_frame = (ZW_USER_CODE_KEYPAD_MODE_SET_V2_FRAME *)frame; set_frame->cmdClass = COMMAND_CLASS_USER_CODE_V2; @@ -650,8 +725,8 @@ static sl_status_t zwave_command_class_user_code_set( &user_id_status, sizeof(user_id_status)); - frame[0] = COMMAND_CLASS_USER_CODE_V2; - frame[1] = USER_CODE_SET_V2; + frame[0] = COMMAND_CLASS_USER_CODE; + frame[1] = USER_CODE_SET; frame[2] = (uint8_t)user_id; frame[3] = user_id_status; if (user_id_status == 0) { @@ -667,6 +742,8 @@ static sl_status_t zwave_command_class_user_code_set( } *frame_length = 4 + user_code_size; + attribute_store_undefine_desired(user_code_node); + attribute_store_undefine_reported(user_code_node); return SL_STATUS_OK; } @@ -783,8 +860,8 @@ static sl_status_t zwave_command_class_user_code_delete_all( if (supporting_node_version == 1) { ZW_USER_CODE_SET_4BYTE_FRAME *set_frame = (ZW_USER_CODE_SET_4BYTE_FRAME *)frame; - set_frame->cmdClass = COMMAND_CLASS_USER_CODE_V2; - set_frame->cmd = USER_CODE_SET_V2; + set_frame->cmdClass = COMMAND_CLASS_USER_CODE; + set_frame->cmd = USER_CODE_SET; set_frame->userIdentifier = 0; set_frame->userIdStatus = 0; set_frame->userCode1 = 0; @@ -875,6 +952,19 @@ static void zwave_command_class_user_code_on_number_of_users_update( attribute_store_node_t endpoint_node = attribute_store_get_first_parent_with_type(updated_node, ATTRIBUTE_ENDPOINT_ID); + attribute_store_node_t version_node + = attribute_store_get_first_child_by_type(endpoint_node, + ATTRIBUTE(VERSION)); + // We need to check the version of the supporting node: + zwave_cc_version_t supporting_node_version = 0; + attribute_store_get_reported(version_node, + &supporting_node_version, + sizeof(supporting_node_version)); + if (supporting_node_version == 1) { + sl_log_debug(LOG_TAG, "Skip creating User ID nodes for CC UserCode V1."); + return; + } + attribute_store_node_t data_node = attribute_store_get_first_child_by_type(endpoint_node, ATTRIBUTE(DATA)); @@ -905,6 +995,78 @@ static void zwave_command_class_user_code_on_capabilities_created( COUNT_OF(capabilities_attributes)); } +static void zwave_command_class_user_code_on_code_update( + attribute_store_node_t updated_node, attribute_store_change_t change) +{ + if (change != ATTRIBUTE_UPDATED) { + return; + } + + // Get pin code value + char pin_code [ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH] = {0}; + attribute_store_get_reported_string(updated_node, + pin_code, + ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH); + attribute_store_node_t user_id_node + = attribute_store_get_first_parent_with_type(updated_node, + ATTRIBUTE(USER_ID)); + // get user id value + uint16_t user_id = 0; + attribute_store_get_reported(user_id_node, &user_id, sizeof(user_id)); + + attribute_store_node_t endpoint_id_node + = attribute_store_get_first_parent_with_type(user_id_node, + ATTRIBUTE_ENDPOINT_ID); + zwave_endpoint_id_t endpoint_id = 0; + attribute_store_get_reported(endpoint_id_node, &endpoint_id, sizeof(endpoint_id)); + + attribute_store_node_t node_id_node + = attribute_store_get_first_parent_with_type(endpoint_id_node, + ATTRIBUTE_NODE_ID); + zwave_node_id_t node_id = 0; + attribute_store_get_reported(node_id_node, &node_id, sizeof(node_id)); + + unid_t node_unid; + zwave_unid_from_node_id(node_id, node_unid); + + attribute_store_node_t status_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(USER_ID_STATUS)); + uint8_t ustatus = 0; + attribute_store_get_reported(status_node, &ustatus, sizeof(ustatus)); + DrlkUserStatus user_status = 0; + switch (ustatus) { + case USER_STATUS_AVAILABLE: + user_status = ZCL_DRLK_USER_STATUS_AVAILABLE; + break; + case USER_STATUS_ENABLED: + user_status = ZCL_DRLK_USER_STATUS_OCCUPIED_ENABLED; + break; + case USER_STATUS_DISABLED: + user_status = ZCL_DRLK_USER_STATUS_OCCUPIED_DISABLED; + break; + case USER_STATUS_MESSAGING: + user_status = ZCL_DRLK_USER_STATUS_OCCUPIED_ENABLED; + break; + case USER_STATUS_PASSAGE_MODE: + user_status = ZCL_DRLK_USER_STATUS_OCCUPIED_DISABLED; + break; + } + + if (attribute_store_is_desired_defined(updated_node) == false) { + uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t fields = + { + .userid = (DrlkPINUserID) user_id, + .user_status = (DrlkUserStatus) user_status, + .user_type = (DrlkUserType) ZCL_DRLK_USER_TYPE_UNRESTRICTED_USER, + .code = pin_code + }; + + uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( + node_unid, endpoint_id, &fields); + } +} + /////////////////////////////////////////////////////////////////////////////// // Attribute Resolver callback functions /////////////////////////////////////////////////////////////////////////////// @@ -1067,6 +1229,10 @@ static sl_status_t memcpy(user_code, &frame[4], user_code_length); user_code[user_code_length] = '\0'; attribute_store_set_reported_string(user_code_node, user_code); + if (user_code_node != ATTRIBUTE_STORE_INVALID_NODE) { + zwave_command_class_user_code_on_code_update(user_code_node, + ATTRIBUTE_UPDATED); + } attribute_store_undefine_desired(user_code_node); return SL_STATUS_OK; @@ -1167,6 +1333,10 @@ static sl_status_t handle_extended_user_code_report( } attribute_store_set_reported_string(user_code_node, user_code); + if (user_code_node != ATTRIBUTE_STORE_INVALID_NODE) { + zwave_command_class_user_code_on_code_update(user_code_node, + ATTRIBUTE_UPDATED); + } attribute_store_undefine_desired(user_code_node); j += 4 + user_code_length; diff --git a/components/uic_dotdot/dotdot-xml/DoorLock.xml b/components/uic_dotdot/dotdot-xml/DoorLock.xml index b56da971c8..d68173bece 100644 --- a/components/uic_dotdot/dotdot-xml/DoorLock.xml +++ b/components/uic_dotdot/dotdot-xml/DoorLock.xml @@ -1,9 +1,9 @@  - + + diff --git a/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h index 1237008bc0..d3846ccba2 100644 --- a/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h +++ b/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h @@ -189,6 +189,7 @@ #define DOTDOT_DOOR_LOCK_CLEAR_ALLRFID_CODES_RESPONSE_COMMAND_ID (0x19) #define DOTDOT_DOOR_LOCK_OPERATING_EVENT_NOTIFICATION_COMMAND_ID (0x20) #define DOTDOT_DOOR_LOCK_PROGRAMMING_EVENT_NOTIFICATION_COMMAND_ID (0x21) +#define DOTDOT_DOOR_LOCK_GET_ALL_PIN_CODES_COMMAND_ID (0x80) // Commands for cluster: WindowCovering #define DOTDOT_WINDOW_COVERING_UP_OR_OPEN_COMMAND_ID (0x0) diff --git a/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md b/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md index 2df0310f75..67daa63d64 100644 --- a/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md +++ b/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md @@ -14083,6 +14083,7 @@ ucl/by-unid///DoorLock/Attributes/ClusterRevision/Reported { "value": "ClearAllRFIDCodesResponse", "OperatingEventNotification", "ProgrammingEventNotification", + "GetAllPINCodes", "WriteAttributes", "ForceReadAttributes" ] @@ -14103,7 +14104,7 @@ To see supported commands for DoorLock cluster under the by-unid topic space: ```console mosquitto_sub -t 'ucl/by-unid///DoorLock/SupportedCommands' # Example output -ucl/by-unid///DoorLock/SupportedCommands { "value": ["LockDoor","UnlockDoor","Toggle","UnlockWithTimeout","GetLogRecord","SetPINCode","GetPINCode","ClearPINCode","ClearAllPINCodes","SetUserStatus","GetUserStatus","SetWeekdaySchedule","GetWeekdaySchedule","ClearWeekdaySchedule","SetYearDaySchedule","GetYearDaySchedule","ClearYearDaySchedule","SetHolidaySchedule","GetHolidaySchedule","ClearHolidaySchedule","SetUserType","GetUserType","SetRFIDCode","GetRFIDCode","ClearRFIDCode","ClearAllRFIDCodes",] } +ucl/by-unid///DoorLock/SupportedCommands { "value": ["LockDoor","UnlockDoor","Toggle","UnlockWithTimeout","GetLogRecord","SetPINCode","GetPINCode","ClearPINCode","ClearAllPINCodes","SetUserStatus","GetUserStatus","SetWeekdaySchedule","GetWeekdaySchedule","ClearWeekdaySchedule","SetYearDaySchedule","GetYearDaySchedule","ClearYearDaySchedule","SetHolidaySchedule","GetHolidaySchedule","ClearHolidaySchedule","SetUserType","GetUserType","SetRFIDCode","GetRFIDCode","ClearRFIDCode","ClearAllRFIDCodes","GetAllPINCodes","WriteAttributes", "ForceReadAttributes"] } ``` To see supported generated commands for DoorLock cluster under the by-unid topic space: @@ -14111,7 +14112,7 @@ To see supported generated commands for DoorLock cluster under the by-unid topic ```console mosquitto_sub -t 'ucl/by-unid///DoorLock/SupportedGeneratedCommands' # Example output -ucl/by-unid///DoorLock/SupportedGeneratedCommands { "value": ["LockDoorResponse","UnlockDoorResponse","ToggleResponse","UnlockWithTimeoutResponse","GetLogRecordResponse","SetPINCodeResponse","GetPINCodeResponse","ClearPINCodeResponse","ClearAllPINCodesResponse","SetUserStatusResponse","GetUserStatusResponse","SetWeekdayScheduleResponse","GetWeekdayScheduleResponse","ClearWeekdayScheduleResponse","SetYearDayScheduleResponse","GetYearDayScheduleResponse","ClearYearDayScheduleResponse","SetHolidayScheduleResponse","GetHolidayScheduleResponse","ClearHolidayScheduleResponse","SetUserTypeResponse","GetUserTypeResponse","SetRFIDCodeResponse","GetRFIDCodeResponse","ClearRFIDCodeResponse","ClearAllRFIDCodesResponse","OperatingEventNotification","ProgrammingEventNotification"] } +ucl/by-unid///DoorLock/SupportedGeneratedCommands { "value": ["LockDoorResponse","UnlockDoorResponse","ToggleResponse","UnlockWithTimeoutResponse","GetLogRecordResponse","SetPINCodeResponse","GetPINCodeResponse","ClearPINCodeResponse","ClearAllPINCodesResponse","SetUserStatusResponse","GetUserStatusResponse","SetWeekdayScheduleResponse","GetWeekdayScheduleResponse","ClearWeekdayScheduleResponse","SetYearDayScheduleResponse","GetYearDayScheduleResponse","ClearYearDayScheduleResponse","SetHolidayScheduleResponse","GetHolidayScheduleResponse","ClearHolidayScheduleResponse","SetUserTypeResponse","GetUserTypeResponse","SetRFIDCodeResponse","GetRFIDCodeResponse","ClearRFIDCodeResponse","ClearAllRFIDCodesResponse","OperatingEventNotification","ProgrammingEventNotification",] } ``` @@ -16705,6 +16706,45 @@ mosquitto_sub -t 'ucl/by-unid///DoorLock/GeneratedCommands/Programming

+\subsection door_lock_get_all_pin_codes_cmd DoorLock/GetAllPINCodes Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/DoorLock/Commands/GetAllPINCodes +[PREFIX]/DoorLock/GeneratedCommands/GetAllPINCodes +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "DoorLock Cluster GetAllPINCodes Command Properties", + "type": "object", + "properties": { + }, + "required": [ + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a DoorLock/GetAllPINCodes command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///DoorLock/Commands/GetAllPINCodes' -m '{ }' +``` + +To receive a DoorLock/GetAllPINCodes generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///DoorLock/GeneratedCommands/GetAllPINCodes' +``` + +

+ \subsection door_lock_write_attr_cmd DoorLock/WriteAttributes Command **MQTT Topic Pattern:** diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h index 78d1266968..df32419436 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h @@ -9931,6 +9931,11 @@ typedef sl_status_t (*uic_mqtt_dotdot_door_lock_programming_event_notification_c const char* data ); +typedef sl_status_t (*uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type +); typedef struct { uint8_t lock_state; @@ -10162,7 +10167,7 @@ typedef struct { DrlkUserType user_type; const char* code; -} uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t; +} uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t; /** * @brief Command fields for DoorLock/ClearPINCode @@ -12697,6 +12702,46 @@ void uic_mqtt_dotdot_door_lock_generated_programming_event_notification_callback * +/DoorLock/GeneratedCommands/programming_event_notification is received. */ void uic_mqtt_dotdot_door_lock_generated_programming_event_notification_callback_clear(); +/** + * @brief Setup callback to be called when a + * DoorLock/Commands/get_all_pin_codes is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_set(const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback); +/** + * @brief Unsets callback to be called when a + * DoorLock/Commands/get_all_pin_codes is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_unset(const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * DoorLock/Commands/get_all_pin_codes is received. + */ +void uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/DoorLock/GeneratedCommands/get_all_pin_codes is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback_set(const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/DoorLock/GeneratedCommands/get_all_pin_codes is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback_unset(const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/DoorLock/GeneratedCommands/get_all_pin_codes is received. + */ +void uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback_clear(); /** * @brief Setup a callback for WriteAttribute to be called when a diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h index 0a53501954..6987fd2d42 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h @@ -1804,10 +1804,10 @@ void uic_mqtt_dotdot_door_lock_publish_generated_getpin_code_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_getpin_code_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ); /** @@ -2642,6 +2642,23 @@ void uic_mqtt_dotdot_door_lock_publish_generated_programming_event_notification_ const uic_mqtt_dotdot_door_lock_command_programming_event_notification_fields_t *fields ); +/** + * @brief Publishes an incoming/generated GetAllPINCodes command for + * the DoorLock cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetAllPINCodes + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_door_lock_publish_generated_get_all_pin_codes_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +); /** * @brief Publishes an incoming/generated WriteAttributes command for diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h index aa21153465..8bb8a00e6b 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h @@ -1405,7 +1405,7 @@ void uic_mqtt_dotdot_by_group_door_lock_getpin_code_callback_set(const uic_mqtt_ */ typedef void (*uic_mqtt_dotdot_by_group_door_lock_getpin_code_response_callback_t)( const dotdot_group_id_t group_id, - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ); /** @@ -2054,6 +2054,21 @@ typedef void (*uic_mqtt_dotdot_by_group_door_lock_programming_event_notification */ void uic_mqtt_dotdot_by_group_door_lock_programming_event_notification_callback_set(const uic_mqtt_dotdot_by_group_door_lock_programming_event_notification_callback_t callback); +/** + * @brief Callback signature for by-group DoorLock::GetAllPINCodes command. + */ +typedef void (*uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback_t)( + const dotdot_group_id_t group_id +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/DoorLock/get_all_pin_codes is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback_set(const uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback_t callback); + typedef void (*uic_mqtt_dotdot_by_group_door_lock_write_attributes_callback_t)( const dotdot_group_id_t group_id, uic_mqtt_dotdot_door_lock_state_t, diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h index 4e394039f2..a6cf984dde 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h @@ -2805,7 +2805,7 @@ void uic_mqtt_dotdot_door_lock_publish_getpin_code_command_to_group( void uic_mqtt_dotdot_door_lock_publish_getpin_code_response_command( const dotdot_unid_t destination_unid, const dotdot_endpoint_id_t destination_endpoint, - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ); @@ -2823,7 +2823,7 @@ void uic_mqtt_dotdot_door_lock_publish_getpin_code_response_command( */ void uic_mqtt_dotdot_door_lock_publish_getpin_code_response_command_to_group( uint16_t destination_group_id, - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ); /** @@ -4370,6 +4370,37 @@ void uic_mqtt_dotdot_door_lock_publish_programming_event_notification_command_to const uic_mqtt_dotdot_door_lock_command_programming_event_notification_fields_t *fields ); +/** + * @brief Sends/Publishes a GetAllPINCodes command for + * the DoorLock cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/DoorLock/Commands/GetAllPINCodes + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_door_lock_publish_get_all_pin_codes_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +); + +/** + * @brief Sends/Publishes a GetAllPINCodes command for + * the DoorLock cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/DoorLock/Commands/GetAllPINCodes + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_door_lock_publish_get_all_pin_codes_command_to_group( + uint16_t destination_group_id +); /** * @brief Sends/Publishes a UpOrOpen command for * the WindowCovering cluster to a destination. diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h index b9a453d4c1..95cc4009fe 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h @@ -488,6 +488,7 @@ typedef struct _uic_mqtt_dotdot_door_lock_supported_commands_ { bool clear_allrfid_codes_response; bool operating_event_notification; bool programming_event_notification; + bool get_all_pin_codes; bool write_attributes; } uic_mqtt_dotdot_door_lock_supported_commands_t; diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp index 44440b4d95..e29e7892be 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp @@ -22681,6 +22681,8 @@ static std::set uic_mqtt_dotdot_door_lock_generated_operating_event_notification_callback; static std::set uic_mqtt_dotdot_door_lock_programming_event_notification_callback; static std::set uic_mqtt_dotdot_door_lock_generated_programming_event_notification_callback; +static std::set uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback; +static std::set uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback; static std::set uic_mqtt_dotdot_door_lock_write_attributes_callback; static std::set uic_mqtt_dotdot_door_lock_force_read_attributes_callback; @@ -24467,6 +24469,39 @@ void uic_mqtt_dotdot_door_lock_generated_programming_event_notification_callback { uic_mqtt_dotdot_door_lock_generated_programming_event_notification_callback.clear(); } +void uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_set(const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback.insert(callback); + } +} +void uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_unset(const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback) +{ + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback.erase(callback); +} +void uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_clear() +{ + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback() +{ + return uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback; +} + +void uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback_set(const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback.insert(callback); + } +} +void uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback_unset(const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback) +{ + uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback.erase(callback); +} +void uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback_clear() +{ + uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback.clear(); +} void uic_mqtt_dotdot_set_door_lock_write_attributes_callback( const uic_mqtt_dotdot_door_lock_write_attributes_callback_t callback) @@ -31561,6 +31596,109 @@ static void uic_mqtt_dotdot_on_generated_door_lock_programming_event_notificatio } +// Callback function for incoming publications on ucl/by-unid/+/+/DoorLock/Commands/GetAllPINCodes +void uic_mqtt_dotdot_on_door_lock_get_all_pin_codes( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback.empty())) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "DoorLock", "GetAllPINCodes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "DoorLock", "GetAllPINCodes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "DoorLock", "GetAllPINCodes", ""); + return; + } + + + + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); + } + +} + +// Callback function for incoming publications on ucl/by-unid/+/+/DoorLock/GeneratedCommands/GetAllPINCodes +static void uic_mqtt_dotdot_on_generated_door_lock_get_all_pin_codes( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback.empty())) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "DoorLock", "GetAllPINCodes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "DoorLock", "GetAllPINCodes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "DoorLock", "GetAllPINCodes", ""); + return; + } + + + + + for (const auto& callback: uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); + } +} + + // Callback function for incoming publications on ucl/by-unid/+/+/DoorLock/Commands/WriteAttributes void uic_mqtt_dotdot_on_door_lock_WriteAttributes( const char *topic, @@ -35224,6 +35362,14 @@ sl_status_t uic_mqtt_dotdot_door_lock_init() subscription_topic = base_topic + "DoorLock/GeneratedCommands/ProgrammingEventNotification"; uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_door_lock_programming_event_notification); } + if (!uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback.empty()) { + subscription_topic = base_topic + "DoorLock/Commands/GetAllPINCodes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_door_lock_get_all_pin_codes); + } + if (!uic_mqtt_dotdot_door_lock_generated_get_all_pin_codes_callback.empty()) { + subscription_topic = base_topic + "DoorLock/GeneratedCommands/GetAllPINCodes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_door_lock_get_all_pin_codes); + } // Init the attributes for that cluster uic_mqtt_dotdot_door_lock_attributes_init(); @@ -97568,6 +97714,20 @@ static inline bool uic_mqtt_dotdot_door_lock_programming_event_notification_is_s return false; } +static inline bool uic_mqtt_dotdot_door_lock_get_all_pin_codes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} static inline bool uic_mqtt_dotdot_door_lock_write_attributes_is_supported( const dotdot_unid_t unid, @@ -97996,6 +98156,13 @@ void uic_mqtt_dotdot_door_lock_publish_supported_commands( first_command = false; ss << R"("ProgrammingEventNotification")"; } + if (uic_mqtt_dotdot_door_lock_get_all_pin_codes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetAllPINCodes")"; + } // Check for a WriteAttributes Callback if(uic_mqtt_dotdot_door_lock_write_attributes_is_supported(unid, endpoint_id)) { @@ -108391,10 +108558,10 @@ void uic_mqtt_dotdot_door_lock_publish_generated_getpin_code_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_getpin_code_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ) { // Create the topic @@ -109844,6 +110011,38 @@ void uic_mqtt_dotdot_door_lock_publish_generated_programming_event_notification_ payload.size(), false); } +/** + * @brief Publishes an incoming/generated GetAllPINCodes command for + * the DoorLock cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetAllPINCodes + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_door_lock_publish_generated_get_all_pin_codes_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "DoorLock/GeneratedCommands/GetAllPINCodes"; + + std::string payload = + get_json_payload_for_door_lock_get_all_pin_codes_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} /** * @brief Publishes an incoming/generated UpOrOpen command for * the WindowCovering cluster. diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp index bbde38863d..269a125ca8 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp @@ -2782,6 +2782,25 @@ void uic_mqtt_dotdot_on_door_lock_programming_event_notification( const size_t message_length); // clang-format on +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid DoorLock/Commands/GetAllPINCodes messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/DoorLock/Commands/GetAllPINCodes + */ +// clang-format off +void uic_mqtt_dotdot_on_door_lock_get_all_pin_codes( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + /** * @brief Retrieves the container with callback pointers for by-unid * /Commands/WriteAttributes messages diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp index 6b9b26e104..3496e7bd36 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp @@ -5106,7 +5106,7 @@ void uic_mqtt_dotdot_parse_door_lock_getpin_code( std::string get_json_payload_for_door_lock_getpin_code_response_command( - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ){ bool command_with_no_fields = true; @@ -7842,6 +7842,25 @@ void uic_mqtt_dotdot_parse_door_lock_programming_event_notification( } +std::string get_json_payload_for_door_lock_get_all_pin_codes_command( + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + + + /** * @brief JSON parser for ::WriteAttributes command arguments. * diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp index be59b23a45..c27ba5fc34 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp @@ -2233,7 +2233,7 @@ void uic_mqtt_dotdot_parse_door_lock_getpin_code( */ std::string get_json_payload_for_door_lock_getpin_code_response_command( - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ); @@ -3453,6 +3453,19 @@ void uic_mqtt_dotdot_parse_door_lock_programming_event_notification( +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a DoorLock GetAllPINCodes command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_door_lock_get_all_pin_codes_command( + +); + + + + /** * @brief JSON parser for DoorLock WriteAttributes command arguments. * diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp index b690c468ed..1299d4273d 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp @@ -3922,10 +3922,10 @@ void uic_mqtt_dotdot_door_lock_publish_generated_getpin_code_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_getpin_code_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ) { // Create the topic @@ -5375,6 +5375,38 @@ void uic_mqtt_dotdot_door_lock_publish_generated_programming_event_notification_ payload.size(), false); } +/** + * @brief Publishes an incoming/generated GetAllPINCodes command for + * the DoorLock cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetAllPINCodes + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_door_lock_publish_generated_get_all_pin_codes_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "DoorLock/GeneratedCommands/GetAllPINCodes"; + + std::string payload = + get_json_payload_for_door_lock_get_all_pin_codes_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} /** diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp index 29ef1f4752..a3b1af3e40 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp @@ -194,6 +194,7 @@ static uic_mqtt_dotdot_by_group_door_lock_clear_allrfid_codes_callback_t uic_mqt static uic_mqtt_dotdot_by_group_door_lock_clear_allrfid_codes_response_callback_t uic_mqtt_dotdot_by_group_door_lock_clear_allrfid_codes_response_callback = nullptr; static uic_mqtt_dotdot_by_group_door_lock_operating_event_notification_callback_t uic_mqtt_dotdot_by_group_door_lock_operating_event_notification_callback = nullptr; static uic_mqtt_dotdot_by_group_door_lock_programming_event_notification_callback_t uic_mqtt_dotdot_by_group_door_lock_programming_event_notification_callback = nullptr; +static uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback_t uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback = nullptr; static uic_mqtt_dotdot_by_group_door_lock_write_attributes_callback_t uic_mqtt_dotdot_by_group_door_lock_write_attributes_callback = nullptr; @@ -1147,6 +1148,12 @@ void uic_mqtt_dotdot_by_group_door_lock_programming_event_notification_callback_ uic_mqtt_dotdot_by_group_door_lock_programming_event_notification_callback = callback; } + +void uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback_set(const uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback_t callback) +{ + uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback = callback; +} + void uic_mqtt_dotdot_by_group_door_lock_write_attributes_callback_set( const uic_mqtt_dotdot_by_group_door_lock_write_attributes_callback_t callback) { @@ -9760,7 +9767,7 @@ static void uic_mqtt_dotdot_on_by_group_door_lock_getpin_code_response( if (uic_mqtt_dotdot_by_group_door_lock_getpin_code_response_callback != nullptr) { - uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t fields; + uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t fields; std::string code; @@ -13547,6 +13554,80 @@ static void uic_mqtt_dotdot_on_by_group_door_lock_programming_event_notification } +// Callback function for incoming publications on ucl/by-group/+/DoorLock/Commands/GetAllPINCodes +static void uic_mqtt_dotdot_on_by_group_door_lock_get_all_pin_codes( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback != nullptr) { + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "DoorLock", "GetAllPINCodes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "DoorLock", "GetAllPINCodes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "DoorLock", "GetAllPINCodes", ""); + return; + } + + uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback( + group_id + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + + group_dispatch_callback( + group_id, + "DoorLock", + "GetAllPINCodes", + message, + message_length, + uic_mqtt_dotdot_on_door_lock_get_all_pin_codes); + + } catch (...) { + sl_log_debug(LOG_TAG, "GetAllPINCodes: Unable to parse JSON payload.\n"); + return; + } + } + +} + static void uic_mqtt_dotdot_on_by_group_door_lock_WriteAttributes( const char *topic, const char *message, @@ -13841,6 +13922,10 @@ sl_status_t uic_mqtt_dotdot_by_group_door_lock_init() subscription_topic = topic_bygroup + "DoorLock/Commands/ProgrammingEventNotification"; uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_door_lock_programming_event_notification); } + if (uic_mqtt_dotdot_by_group_door_lock_get_all_pin_codes_callback) { + subscription_topic = topic_bygroup + "DoorLock/Commands/GetAllPINCodes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_door_lock_get_all_pin_codes); + } return SL_STATUS_OK; } @@ -22541,6 +22626,7 @@ void uic_mqtt_dotdot_set_group_dispatch_callback(group_dispatch_t callback) uic_mqtt_subscribe("ucl/by-group/+/DoorLock/Commands/ClearAllRFIDCodesResponse", uic_mqtt_dotdot_on_by_group_door_lock_clear_allrfid_codes_response); uic_mqtt_subscribe("ucl/by-group/+/DoorLock/Commands/OperatingEventNotification", uic_mqtt_dotdot_on_by_group_door_lock_operating_event_notification); uic_mqtt_subscribe("ucl/by-group/+/DoorLock/Commands/ProgrammingEventNotification", uic_mqtt_dotdot_on_by_group_door_lock_programming_event_notification); + uic_mqtt_subscribe("ucl/by-group/+/DoorLock/Commands/GetAllPINCodes", uic_mqtt_dotdot_on_by_group_door_lock_get_all_pin_codes); uic_mqtt_subscribe("ucl/by-group/+/WindowCovering/Commands/WriteAttributes", uic_mqtt_dotdot_on_by_group_window_covering_WriteAttributes); uic_mqtt_subscribe("ucl/by-group/+/WindowCovering/Commands/UpOrOpen", uic_mqtt_dotdot_on_by_group_window_covering_up_or_open); diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp index f44611a5a6..6a7f56976f 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp @@ -5354,7 +5354,7 @@ void uic_mqtt_dotdot_door_lock_publish_getpin_code_command_to_group( void uic_mqtt_dotdot_door_lock_publish_getpin_code_response_command( const dotdot_unid_t destination_unid, const dotdot_endpoint_id_t destination_endpoint, - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ) { // Create the topic @@ -5390,7 +5390,7 @@ void uic_mqtt_dotdot_door_lock_publish_getpin_code_response_command( */ void uic_mqtt_dotdot_door_lock_publish_getpin_code_response_command_to_group( uint16_t destination_group_id, - const uic_mqtt_dotdot_door_lock_command_getpin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields ){ // Create the topic @@ -8354,6 +8354,72 @@ void uic_mqtt_dotdot_door_lock_publish_programming_event_notification_command_to false); } +/** + * @brief Sends/Publishes a GetAllPINCodes command for + * the DoorLock cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/DoorLock/Commands/GetAllPINCodes + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_door_lock_publish_get_all_pin_codes_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "DoorLock/Commands/GetAllPINCodes"; + + + std::string payload = + get_json_payload_for_door_lock_get_all_pin_codes_command( + ); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a GetAllPINCodes command for + * the DoorLock cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/DoorLock/Commands/GetAllPINCodes + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_door_lock_publish_get_all_pin_codes_command_to_group( + uint16_t destination_group_id +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/DoorLock/Commands/GetAllPINCodes"; + + std::string payload = + get_json_payload_for_door_lock_get_all_pin_codes_command( + ); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + /** * @brief Sends/Publishes a UpOrOpen command for * the WindowCovering cluster to a destination. diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp index 4a3ce0d72e..c3aeb569b6 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp @@ -908,6 +908,9 @@ void uic_mqtt_dotdot_door_lock_publish_supported_generated_commands( if (command_list->programming_event_notification == true) { command_vector.emplace_back("ProgrammingEventNotification"); } + if (command_list->get_all_pin_codes == true) { + command_vector.emplace_back("GetAllPINCodes"); + } if (command_list->write_attributes == true) { command_vector.emplace_back("WriteAttributes"); } diff --git a/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include b/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include index 7a5d843550..54a3956c40 100644 --- a/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include +++ b/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include @@ -1770,6 +1770,17 @@ static sl_status_t uic_mqtt_dotdot_door_lock_programming_event_notification_call return SL_STATUS_OK; } +static unsigned int uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_count; +static sl_status_t uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type +) { + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + static unsigned int uic_mqtt_dotdot_window_covering_up_or_open_callback_count; static sl_status_t uic_mqtt_dotdot_window_covering_up_or_open_callback_func( dotdot_unid_t unid, @@ -3106,6 +3117,8 @@ static unsigned int set_all_callbacks() num_callbacks++; uic_mqtt_dotdot_door_lock_programming_event_notification_callback_set(&uic_mqtt_dotdot_door_lock_programming_event_notification_callback_func); num_callbacks++; + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_set(&uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_func); + num_callbacks++; uic_mqtt_dotdot_window_covering_up_or_open_callback_set(&uic_mqtt_dotdot_window_covering_up_or_open_callback_func); num_callbacks++; uic_mqtt_dotdot_window_covering_down_or_close_callback_set(&uic_mqtt_dotdot_window_covering_down_or_close_callback_func); @@ -3368,6 +3381,7 @@ static void unset_all_callbacks() uic_mqtt_dotdot_door_lock_clear_allrfid_codes_response_callback_clear(); uic_mqtt_dotdot_door_lock_operating_event_notification_callback_clear(); uic_mqtt_dotdot_door_lock_programming_event_notification_callback_clear(); + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_clear(); uic_mqtt_dotdot_clear_door_lock_write_attributes_callbacks(); uic_mqtt_dotdot_window_covering_up_or_open_callback_clear(); uic_mqtt_dotdot_window_covering_down_or_close_callback_clear(); @@ -3591,6 +3605,7 @@ static void reset_callback_counters() uic_mqtt_dotdot_door_lock_clear_allrfid_codes_response_callback_count = 0; uic_mqtt_dotdot_door_lock_operating_event_notification_callback_count = 0; uic_mqtt_dotdot_door_lock_programming_event_notification_callback_count = 0; + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_count = 0; uic_mqtt_dotdot_window_covering_up_or_open_callback_count = 0; uic_mqtt_dotdot_window_covering_down_or_close_callback_count = 0; uic_mqtt_dotdot_window_covering_stop_callback_count = 0; diff --git a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c index c883ae57b8..be5636f5f5 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c +++ b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c @@ -622,6 +622,10 @@ static uic_mqtt_dotdot_door_lock_programming_event_notification_callback_t test_ uic_mqtt_dotdot_door_lock_programming_event_notification_callback_t get_uic_mqtt_dotdot_door_lock_programming_event_notification_callback(){ return test_uic_mqtt_dotdot_door_lock_programming_event_notification_callback; } +static uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t test_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback = NULL; +uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t get_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback(){ + return test_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback; +} static uic_mqtt_dotdot_window_covering_force_read_attributes_callback_t test_uic_mqtt_dotdot_window_covering_force_read_attributes_callback = NULL; static uic_mqtt_dotdot_window_covering_write_attributes_callback_t test_uic_mqtt_dotdot_window_covering_write_attributes_callback = NULL; @@ -2063,6 +2067,11 @@ void uic_mqtt_dotdot_door_lock_programming_event_notification_callback_set_stub( { test_uic_mqtt_dotdot_door_lock_programming_event_notification_callback = callback; } +void uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_set_stub( + const uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback = callback; +} void set_uic_mqtt_dotdot_window_covering_force_read_attributes_callback_stub( const uic_mqtt_dotdot_window_covering_force_read_attributes_callback_t callback, int cmock_num_calls) { @@ -3229,6 +3238,9 @@ void setUp() test_uic_mqtt_dotdot_door_lock_programming_event_notification_callback = NULL; uic_mqtt_dotdot_door_lock_programming_event_notification_callback_set_Stub( &uic_mqtt_dotdot_door_lock_programming_event_notification_callback_set_stub); + test_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback = NULL; + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_set_Stub( + &uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_set_stub); test_uic_mqtt_dotdot_window_covering_force_read_attributes_callback = NULL; uic_mqtt_dotdot_set_window_covering_force_read_attributes_callback_Stub( &set_uic_mqtt_dotdot_window_covering_force_read_attributes_callback_stub); @@ -6196,6 +6208,13 @@ void test_automatic_deduction_of_supported_commands() )); } + if (NULL != test_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } if (NULL != test_uic_mqtt_dotdot_window_covering_up_or_open_callback) { // Dummy command parameters // Invoke with support check @@ -9181,6 +9200,13 @@ void test_automatic_deduction_of_supported_commands() )); } + if (NULL != test_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } if (NULL != test_uic_mqtt_dotdot_window_covering_up_or_open_callback) { // Dummy command parameters // Invoke with support check diff --git a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h index 8a73e5cb1e..09e6896326 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h +++ b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h @@ -413,6 +413,9 @@ uic_mqtt_dotdot_door_lock_programming_event_notification_callback_t get_uic_mqtt_dotdot_door_lock_programming_event_notification_callback(); + uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback_t get_uic_mqtt_dotdot_door_lock_get_all_pin_codes_callback(); + + uic_mqtt_dotdot_window_covering_force_read_attributes_callback_t get_uic_mqtt_dotdot_window_covering_force_read_attributes_callback(); uic_mqtt_dotdot_window_covering_write_attributes_callback_t get_uic_mqtt_dotdot_window_covering_write_attributes_callback();