MeshTalos-Client/managed_components/espressif__esp-zboss-lib/include/zcl/zb_zcl_identify.h
2025-12-03 14:20:11 +08:00

464 lines
22 KiB
C

/*
* Copyright (c) 2012-2022 DSR Corporation, Denver CO, USA
* Copyright (c) 2021-2022 Espressif Systems (Shanghai) PTE LTD
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Espressif Systems
* integrated circuit in a product or a software update for such product,
* must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* 4. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* PURPOSE: ZCL "Identify cluster" definitions
*/
#ifndef ZB_ZCL_IDENTIFY_H
#define ZB_ZCL_IDENTIFY_H 1
#if defined(ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY) || defined(DOXYGEN)
#include "zcl/zb_zcl_common.h"
#include "zcl/zb_zcl_commands.h"
/** @cond DOXYGEN_ZCL_SECTION */
/** @addtogroup ZB_ZCL_IDENTIFY
* @{
* @details
* Identify cluster implementation supports Identify command and Identify Query request-response
* command pair. All these commands have simple payload. Both Identify and Identify Query
* request are being processed, and Identify Query response is being generated in ZCL internals.
*
* @par Example
* Identify sending:
* @snippet HA_samples/door_lock/sample_zed.c send_identify_req
*
* Identify Query request sending:
* @snippet HA_samples/on_off_switch/sample_zed.c identify_send_identify_query_req
*/
/** @name Identify cluster attributes
* @{
*/
/** @brief Identify cluster attribute identifier
@see ZCL8 spec, subclause 3.5.2.2
*/
enum zb_zcl_identify_attr_e
{
/*! Identify time attribute */
ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID = 0x0000
};
/** @brief Default value for Identify cluster revision global attribute */
#define ZB_ZCL_IDENTIFY_CLUSTER_REVISION_DEFAULT ((zb_uint16_t)0x0002u)
/** @brief Default value for Identify attribute */
#define ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE 0x0000
/** @} */ /* Identify cluster attributes */
/*! @name Identify cluster command structures and definitions
@{
*/
/** @brief Command identifiers for "Identify" cluster
@see ZCL8 spec, subclauses 3.5.2.3, 3.5.2.4
*/
enum zb_zcl_identify_cmd_e
{
ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID = 0x00, /**< Identify command */
ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_ID = 0x01, /**< Identify query command */
ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID = 0x40, /**< "Trigger effect" command identifier. */
ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_RSP_ID = 0x00 /**< Identify query response */
};
/** @cond internals_doc */
/* Identify cluster commands lists : only for information - do not modify */
#define ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_RECEIVED_CMD_LIST \
ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID, \
ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_ID, \
ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID,
#define ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_RECEIVED_CMD_LIST \
ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_RSP_ID,
#define ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_GENERATED_CMD_LIST ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_RECEIVED_CMD_LIST
#define ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_GENERATED_CMD_LIST ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_RECEIVED_CMD_LIST
/*! @}
* @endcond */ /* internals_doc */
/** Effect identifier enum
* @see ZCL8 spec 3.5.2.3.3.1 */
enum zb_zcl_identify_trigger_effect_e
{
/**< Effect identifier field value: Light is turned on/off once */
ZB_ZCL_IDENTIFY_EFFECT_ID_BLINK = 0x00,
/**< Effect identifier field value: Light turned on/off over 1 second and
* repeated 15 times */
ZB_ZCL_IDENTIFY_EFFECT_ID_BREATHE = 0x01,
/**< Effect identifier field value: Colored light turns green for 1 second;
* non-colored light flashes twice */
ZB_ZCL_IDENTIFY_EFFECT_ID_OKAY = 0x02,
/**< Effect identifier field value: Colored light turns orange for 8 seconds; non-colored
* light switches to maximum brightness for 0.5s and then minimum brightness for 7.5s */
ZB_ZCL_IDENTIFY_EFFECT_ID_CHANNEL_CHANGE = 0x0b,
/**< Effect identifier field value: Complete the current effect sequence before terminating.
* E.g., if in the middle of a breathe effect (as above), first complete the current 1s
* breathe effect and then terminate the effect*/
ZB_ZCL_IDENTIFY_EFFECT_ID_FINISH_EFFECT = 0xfe,
/**< Effect identifier field value: Terminate the effect as soon as possible */
ZB_ZCL_IDENTIFY_EFFECT_ID_STOP = 0xff,
};
/** Effect variant enum
* @see ZCL8 spec 3.5.2.3.3.2 */
enum zb_zcl_identify_trigger_variant_e
{
/**< Effect variant field value: Default */
ZB_ZCL_IDENTIFY_EFFECT_ID_VARIANT_DEFAULT = 0x00,
};
/*! @brief Structured representation of Trigger effect command payload */
typedef ZB_PACKED_PRE struct zb_zcl_identify_effect_req_s
{
zb_uint8_t effect_id; /*!< Effect identify, see @ref zb_zcl_identify_trigger_effect_e */
zb_uint8_t effect_variant; /*!< Effect variant, see @ref zb_zcl_identify_trigger_variant_e */
} ZB_PACKED_STRUCT zb_zcl_identify_effect_req_t;
/*! @brief Send Trigger effect command
@param buffer to put packet to
@param addr - address to send packet to
@param dst_addr_mode - addressing mode
@param dst_ep - destination endpoint
@param ep - sending endpoint
@param prof_id - profile identifier
@param def_resp - flag "Default response required"
@param cb - callback for getting command send status
@param effect_id - effect identify, see @ref zb_zcl_identify_trigger_effect_e
@param effect_var - effect variant, see @ref zb_zcl_identify_trigger_variant_e
*/
#define ZB_ZCL_IDENTIFY_SEND_TRIGGER_VARIANT_REQ( \
buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, def_resp, cb, effect_id, effect_var) \
{ \
zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \
ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \
ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_IDENTIFY_TRIGGER_EFFECT_ID); \
ZB_ZCL_PACKET_PUT_DATA8(ptr, (effect_id)); \
ZB_ZCL_PACKET_PUT_DATA8(ptr, (effect_var)); \
ZB_ZCL_FINISH_PACKET(buffer, ptr) \
ZB_ZCL_SEND_COMMAND_SHORT( \
buffer, addr, dst_addr_mode, dst_ep, ep, prof_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, cb); \
}
/** @brief Parses Trigger effect command
* @attention Assumes that ZCL header already cut.
* @param data_ptr - pointer to a variable of type @ref
* zb_zcl_identify_effect_req_s.
* @param buffer containing the packet (by pointer).
* @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t).
*/
#define ZB_ZCL_IDENTIFY_GET_TRIGGER_VARIANT_REQ(data_ptr, buffer, status) \
{ \
if (zb_buf_len((buffer)) < sizeof(zb_zcl_identify_effect_req_t)) \
{ \
(status) = ZB_ZCL_PARSE_STATUS_FAILURE; \
} \
else \
{ \
zb_zcl_identify_effect_req_t *src_ptr = \
(zb_zcl_identify_effect_req_t*)zb_buf_begin((buffer)); \
(status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \
ZB_MEMCPY((data_ptr), src_ptr, sizeof(zb_zcl_identify_effect_req_t)); \
} \
}
/**
* @name Inform User App about ZCL Identify cluster command and change attributes.
* Internal structures and define-procedure for inform User App about ZCL Identify
* cluster command and change attributes.
* @internal
* @{
*/
/** @brief Declare change Identify attribute for User Application
*/
typedef struct zb_zcl_identify_effect_value_param_s
{
zb_uint8_t effect_id; /*!< Effect identify */
zb_uint8_t effect_variant; /*!< Effect variant */
} zb_zcl_identify_effect_value_param_t;
/*! Struct for invoke User App & continue after */
typedef struct zb_zcl_identify_effect_user_app_schedule_e
{
zb_zcl_parsed_hdr_t cmd_info; /**< Parameters for continue command,
see @ref zb_zcl_parsed_hdr_s */
zb_zcl_identify_effect_value_param_t param; /**< User App command parameters,
see @ref zb_zcl_identify_effect_value_param_s */
} zb_zcl_identify_effect_user_app_schedule_t;
#define ZB_ZCL_IDENTIFY_EFFECT_SCHEDULE_USER_APP(buffer, pcmd_info, effectId, effectVar) \
{ \
zb_zcl_identify_effect_user_app_schedule_t* data = \
ZB_BUF_GET_PARAM((buffer), zb_zcl_identify_effect_user_app_schedule_t); \
ZB_MEMMOVE(&(data->cmd_info), (pcmd_info), sizeof(zb_zcl_parsed_hdr_t)); \
data->param.effect_id = (effectId); \
data->param.effect_variant = (effectVar); \
ZB_SCHEDULE_CALLBACK(zb_zcl_identify_effect_invoke_user_app, (buffer)); \
}
/*! @} */ /* internal */
/*! @brief Send Identify command
@param buffer to put packet to
@param time the device will be identifying
@param addr - address to send packet to
@param dst_addr_mode - addressing mode
@param dst_ep - destination endpoint
@param ep - sending endpoint
@param prfl_id - profile identifier
@param def_resp - flag "Default response required"
@param cb - callback for getting command send status
*/
#define ZB_ZCL_IDENTIFY_SEND_IDENTIFY_REQ( \
buffer, time, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \
{ \
zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \
ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \
ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ(ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_IDENTIFY_IDENTIFY_ID); \
ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, time); \
ZB_ZCL_FINISH_PACKET(buffer, ptr) \
ZB_ZCL_SEND_COMMAND_SHORT( \
buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, cb); \
}
/*! @brief Send Identify Query command
@param buffer to put packet to
@param addr - address to send packet to
@param dst_addr_mode - addressing mode
@param dst_ep - destination endpoint
@param ep - sending endpoint
@param prfl_id - profile identifier
@param def_resp - flag "Default response required"
@param cb - callback for getting command send status
@snippet on_off_switch/sample_zed.c identify_send_identify_query_req
*/
#define ZB_ZCL_IDENTIFY_SEND_IDENTIFY_QUERY_REQ( \
buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, def_resp, cb) \
{ \
zb_uint8_t* ptr = ZB_ZCL_START_PACKET_REQ(buffer) \
ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_REQ_FRAME_CONTROL(ptr, def_resp) \
ZB_ZCL_CONSTRUCT_COMMAND_HEADER_REQ( \
ptr, ZB_ZCL_GET_SEQ_NUM(), ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_ID); \
ZB_ZCL_FINISH_PACKET(buffer, ptr) \
ZB_ZCL_SEND_COMMAND_SHORT( \
buffer, addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, cb); \
}
/*! @brief Send Identify Query Response command
@param buffer to put packet to
@param time the device will be identifying
@param addr - address to send packet to
@param dst_addr_mode - addressing mode
@param dst_ep - destination endpoint
@param ep - sending endpoint
@param prfl_id - profile identifier
@param seq_num - sequence number
@param aps_secured - APS security mode
*/
#define ZB_ZCL_IDENTIFY_SEND_IDENTIFY_QUERY_RES( \
buffer, time, addr, dst_addr_mode, dst_ep, ep, prfl_id, seq_num, aps_secured) \
{ \
zb_uint8_t* ptr = ZB_ZCL_START_PACKET(buffer); \
ZB_ZCL_CONSTRUCT_SPECIFIC_COMMAND_RES_FRAME_CONTROL(ptr); \
ZB_ZCL_CONSTRUCT_COMMAND_HEADER(ptr, seq_num, ZB_ZCL_CMD_IDENTIFY_IDENTIFY_QUERY_RSP_ID); \
ZB_ZCL_PACKET_PUT_DATA16_VAL(ptr, time); \
ZB_ZCL_FINISH_N_SEND_PACKET_NEW(buffer, ptr, \
addr, dst_addr_mode, dst_ep, ep, prfl_id, ZB_ZCL_CLUSTER_ID_IDENTIFY, NULL, aps_secured, \
ZB_FALSE, 0); \
}
/**
* @brief Start identify process on given endpoint
*
* @param endpoint - endpoint to start identifying on
* @param timeout - time (in seconds) after which identifying will stop
*/
zb_uint8_t zb_zcl_start_identifying(zb_uint8_t endpoint, zb_uint16_t timeout);
/**
* @brief Stop identify process on given endpoint
* Complimentary function to @ref zb_zcl_start_identifying.
* Used to force identify termination before timeout provided to
* @ref zb_zcl_start_identifying is elapsed
*
* @param endpoint Endpoint
*/
void zb_zcl_stop_identifying(zb_uint8_t endpoint);
/**
* @brief Indicates that endpoint supports Identify cluster and is identifying
* @param endpoint number to analyze
* @return ZB_TRUE if endpoint is in the "identifying" state, ZB_FALSE otherwise.
*/
zb_uint8_t zb_zcl_is_identifying(zb_uint8_t endpoint);
/*! @brief Structured representation of Identify command payload */
typedef ZB_PACKED_PRE struct zb_zcl_identify_req_s
{
zb_uint16_t timeout; /*!< Time to identify */
} ZB_PACKED_STRUCT zb_zcl_identify_req_t;
/*! @brief Structured representation of Identify Query Response command payload */
typedef ZB_PACKED_PRE struct zb_zcl_identify_query_res_s
{
zb_uint16_t timeout; /*!< Reported time to identify */
} ZB_PACKED_STRUCT zb_zcl_identify_query_res_t;
/*! @brief Identify cluster Identify command payload structured read
* @param data_ptr - pointer to a variable of type @ref zb_zcl_identify_req_t
* @param buffer containing the packet (by pointer).
* @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t).
*/
#define ZB_ZCL_IDENTIFY_GET_IDENTIFY_REQ(data_ptr, buffer, status) \
{ \
if (zb_buf_len((buffer)) < sizeof(zb_zcl_identify_req_t)) \
{ \
(status) = ZB_ZCL_PARSE_STATUS_FAILURE; \
} \
else \
{ \
zb_zcl_identify_req_t *src_ptr = \
(zb_zcl_identify_req_t*)zb_buf_begin((buffer)); \
(status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \
ZB_HTOLE16(&((data_ptr)->timeout), &(src_ptr->timeout)); \
} \
}
/*! @brief Identify cluster Identify Query Response command payload structured
read
* @param data_ptr - pointer to a variable of type @ref zb_zcl_identify_query_res_t
* @param buffer containing the packet (by pointer).
* @param status - variable to put parse status to (see @ref zb_zcl_parse_status_t).
*/
#define ZB_ZCL_IDENTIFY_GET_IDENTIFY_QUERY_RES(data_ptr, buffer, status) \
{ \
if (zb_buf_len((buffer)) < sizeof(zb_zcl_identify_query_res_t)) \
{ \
(status) = ZB_ZCL_PARSE_STATUS_FAILURE; \
} \
else \
{ \
zb_zcl_identify_query_res_t *src_ptr = \
(zb_zcl_identify_query_res_t*)zb_buf_begin((buffer)); \
(status) = ZB_ZCL_PARSE_STATUS_SUCCESS; \
ZB_HTOLE16(&((data_ptr)->timeout), &(src_ptr->timeout)); \
} \
}
/*! @} */ /* Identify cluster command structures and definitions */
/** @cond internals_doc */
/*!
@name Identify cluster internals
@internal
Internal structures for attribute representation in cluster definitions.
@{
*/
#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID(data_ptr) \
{ \
ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID, \
ZB_ZCL_ATTR_TYPE_U16, \
ZB_ZCL_ATTR_ACCESS_READ_WRITE, \
(ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \
(void*) data_ptr \
}
#if defined ZB_ZCL_SUPPORT_CLUSTER_SCENES
/*! Scenes fieldset length for Identify cluster */
#define ZB_ZCL_CLUSTER_ID_IDENTIFY_SCENE_FIELD_SETS_LENGTH 0
#endif /* defined ZB_ZCL_SUPPORT_CLUSTER_SCENES */
/*! @} */ /* Identify cluster internals */
/*! @}
* @endcond */ /* internals_doc */
/** @brief Declare attribute list for Identify cluster
@param attr_list - attribute list name
@param identify_time - pointer to variable to store identify time attribute value
*/
#define ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(attr_list, identify_time) \
ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_IDENTIFY) \
ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID, (identify_time)) \
ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST
/**
* @brief Identify cluster attributes
*/
typedef struct zb_zcl_identify_attrs_s
{
/** @copydoc ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID
* @see ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID
*/
zb_uint16_t identify_time;
} zb_zcl_identify_attrs_t;
/** @brief Declare attribute list for Identify cluster cluster
* @param[in] attr_list - attribute list variable name
* @param[in] attrs - variable of zb_zcl_identify_attrs_t type (containing Identify cluster attributes)
*/
#define ZB_ZCL_DECLARE_IDENTIFY_ATTR_LIST(attr_list, attrs) \
ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(attr_list, &attrs.identify_time)
#if defined ZB_ENABLE_HA
zb_uint8_t zb_zcl_get_cmd_list_identify(zb_bool_t is_client_generated, zb_uint8_t **cmd_list);
#endif /* defined ZB_ENABLE_HA */
/** @endcond */ /* DOXYGEN_ZCL_SECTION */
void zb_zcl_identify_init_server(void);
void zb_zcl_identify_init_client(void);
#define ZB_ZCL_CLUSTER_ID_IDENTIFY_SERVER_ROLE_INIT zb_zcl_identify_init_server
#define ZB_ZCL_CLUSTER_ID_IDENTIFY_CLIENT_ROLE_INIT zb_zcl_identify_init_client
#endif /* defined(ZB_ZCL_SUPPORT_CLUSTER_IDENTIFY) */
#endif /* ZB_ZCL_IDENTIFY_H */