CC2340R5: zigbee使用zcl多次发送固定数组数据后显示内存不足

Part Number: CC2340R5


如下方代码所示,先获取缓冲区,再使用zb_aps_send_user_payload()函数发送数据,发送完成或者失败后释放获得的缓冲区;
但是我使用定时每秒发送一次数据时,大约20分钟后程序就会卡死,显示内存错误,必须重新上电才能继续运行,且程序正常运行时间不确定。请问这是什么问题,这个代码是使用TI提供的例程中nortos->zigbee下面的onoff_light程序修改来的。望各位能够提供一点帮助,非常感谢。
 
 
zb_bufid_t param= zb_buf_get_out();
获取成功再执行下方函数,
zb_ret_t ret = zb_aps_send_user_payload(
//       param,
//       addr,                   /* dst_addr (协调器地址) */
//       0x0104,                 /* profile id (自定义应用配置文件) */
//       0xf00d,                 /* cluster id (自定义集群ID) */
//       ZB_OUTPUT_ENDPOINT,     /* destination endpoint (协调器的端点5) */
//       ZB_SWITCH_ENDPOINT,     /* source endpoint (终端设备的端点10) */
//       ZB_APS_ADDR_MODE_16_ENDP_PRESENT, /* address mode */
//       ZB_TRUE,                /* APS ACK enabled */
//       data_array,             /* payload pointer */
//       data_size);             /* size of payload */
   
//     if (ret != RET_OK) {
//         uartPrintf("Failed to send custom array, error code: %d\r\n", ret);
//         zb_buf_free(param);  /* 发送失败时释放缓冲区 */
//     } else {
//         // 发送成功,立即释放缓冲区
//         zb_buf_free(param);
//         uartPrintf("Custom array buffer freed after successful transmission\r\n");
//     }
//   }
  • 已经收到了您的案例,调查需要些时间,感谢您的耐心等待。

  • 在CCS中,能否使用内存分配和堆栈使用功能来检查是否有某种内存占用了过多空间?

  • 您这边可以进行代码运行吗?我这边初次接触ccs,对与里面的代码不熟悉,找不到对应函数,可以给您提供我这边的协调器以及终端代码

  • 没有找到相关检测函数
    和您描述一下我这边的现象吧:当不使用zb_aps_send_user_payload函数,只进行串口打印及其他功能时,程序不会卡死。
    但是一旦使用了zigbee数据发送函数,程序在运行一段时间后就会卡死,我设置的是每秒发送一条zigbee数据,自定义大小为34个字节。开始发送时协调器可以接收到数据,发送一段时间后,终端;可能会出现两种问题,一个是无法获取zigbee发送缓冲区,一个是打印内存不足错误;重新上电后,程序又可以运行一段时间。

    我不知道是不是因为zigbee数据发送太快导致的,但1s已经是我接受的底线了;想向您了解zb_aps_send_user_payload函数在数据发送后会不会自动释放空间,并且若是使用

    ZB_FALSE - 禁用APS确认,

    数据发送的速度是不是会大于1s,我不知道问题在哪。



    还有一个问题是我这边 IIC、ADC、UART都是在上电后就一直打开使用open函数,这会不会一直占用空间?
  • 能否提供给我一个CC2340R5芯片的zigbee数据收发例程,我这边其他外设都已经进行设置,应该没有什么问题,就是关于zigbee数据发送函数运用出现问题,使用一段时间程序就会卡死。

  • 目前我对自己的代码实在没有信心,贵公司关于CC2340R5芯片zigbee开发的例程以及相关技术资料实在太少了,我完全不知道该怎么使用才能完成正常的zigbee自定义数量数据收发功能。

  • 该参数类型为zb_uint8_t,仅在成功传输后才应从回调中释放。以下是其他资源:

     CC2340R5: The error "ZB_ZDO_DEVICE_UNAVAILABLE" occurred during the communication process. 
    ZBOSS User's Guide 
    Zigbee Fundamentals SLA 

  • 我这边的问题和您给的例子不一样,我的是终端可以一直发送数据,并不会显示无法连接;

    而是发送一段时间数据后终端uart打印显示


    这是在触发错误后打印的
    函数如下

    static zb_bool_t error_ind_handler(zb_uint8_t severity,
                                        zb_ret_t error_code,
                                        void *additional_info)
    {
      zb_bool_t ret = ZB_FALSE;
      ZVUNUSED(additional_info);
      /* Unused without trace. */
      ZVUNUSED(severity);

      // 使用串口打印详细的错误信息
      uartPrintf("=== ERROR HANDLER CALLED ===\r\n");
      uartPrintf("Error Severity: %d, Error Code: %d (0x%04X)\r\n", severity, error_code, error_code);
     
      // 解析错误类别
      zb_uint16_t error_category = (error_code >> 8) & 0xFF;
      zb_uint16_t error_subcode = error_code & 0xFF;
      uartPrintf("Error Category: 0x%02X, Subcode: 0x%02X\r\n", error_category, error_subcode);

      if (error_code == ERROR_CODE(ERROR_CATEGORY_MACSPLIT, ZB_ERROR_MACSPLIT_RADIO_HANG))
      {
        uartPrintf("!!! FATAL ERROR: MACSPLIT RADIO HANG !!!\r\n");
        uartPrintf("Cause: Radio module has stopped responding\r\n");
        uartPrintf("Action: Device will likely restart\r\n");

        ret = ZB_TRUE;
        /* return TRUE to prevent default error handling by the stack */
      }
      else if (error_code == ERROR_CODE(ERROR_CATEGORY_MACSPLIT, ZB_ERROR_MACSPLIT_RADIO_REBOOT))
      {
        uartPrintf("!!! RADIO REBOOT DETECTED !!!\r\n");
        uartPrintf("Cause: Radio module has been reset\r\n");
        uartPrintf("Action: Protocol stack recovery in progress\r\n");

        ret = ZB_TRUE;
      }
      else
      {
        // 其他错误类型的处理 - 允许默认处理
        uartPrintf("Unknown error type, allowing default handling\r\n");
        ret = ZB_FALSE;  // 确保返回FALSE,允许协议栈处理信号
      }
     
      uartPrintf("Error handler return value: %s\r\n", ret ? "TRUE (block default)" : "FALSE (allow default)");
      uartPrintf("=================================\r\n");
     
      return ret;
    }




    默认处理后终端重启,再次进行协调器连接并且发送数据,但是一段时间后会再次打印该错误并且重启
  • 我的问题和您给的案例不一样,我遇到的问题是终端在连接协调器后,在发送数据过程中大约10分钟左右,终端设备会发生重启现象,我查看了错误打印内容,发现问题提示为内存错误。

    而且该问题只有在设备使用zb_aps_send_user_payload函数时才会发生,若单纯的进行zigbee连接,并且申请、释放空间,程序是没有问题的,目前猜测导致内存不足的原因是zb_aps_send_user_payload函数使用后未及时释放空间,不知有没有其他问题?恳请解答。

  • 给您提供一下我的代码,当我使用数据发送函数zb_aps_send_user_payload时,不论发送是否成功都必须使用zb_buf_free(param);来释放空间,若是发送成功后不使用zb_buf_free(param);函数,则数据发送7次之后程序重启。。若数据发送成功后使用zb_buf_free(param);函数,则程序可以运行时间不定,约20分钟左右,会发生重启。


    /* 改进的ZCL标准格式数据发送函数
     * 参数: param - Zigbee缓冲区ID
     * 功能: 通过ZCL标准协议发送数据到父节点(协调器),包含错误处理和重试机制 */
    void send_zcl_payload(zb_uint8_t param)
    {
      zb_addr_u addr = { 0 };           /* Zigbee地址结构体 */
      zb_uint16_t parent = zb_nwk_get_parent();  /* 获取父节点(协调器)地址 */
     
      ZB_ASSERT(param);  /* 断言检查参数有效性 */
      uartPrintf("param2: %d\r\n", param);
      // Set target address to parent node (coordinator)
      if (parent != ZB_UNKNOWN_SHORT_ADDR) {
        addr.addr_short = parent;  /* Set target address to parent node short address */
      } else {
        uartPrintf("No parent node, cannot send data\r\n");
        zb_buf_free(param);  /* Release buffer */
        return;
      }

      {
        Log_printf(LogModule_Zigbee_App, Log_INFO, "send_zcl_data to parent: 0x%04x", parent);

        // Simplified log output to avoid overload
        uartPrintf("Sending ZCL frame to parent 0x%04X, size: %d bytes\r\n", parent, ZCL_FRAME_SIZE);

        /* Zigbee APS发送ZCL数据包
         * 参数说明:
         * param - 缓冲区ID
         * addr - 目标地址(父节点)
         * ZB_AF_HA_PROFILE_ID - 使用标准Home Automation配置文件ID (0x0104)
         * ZB_ZCL_CLUSTER_ID_BASIC - 使用标准基础集群ID (0x0000)
         * ZB_OUTPUT_ENDPOINT - 目标端点(协调器端点5)
         * ZB_SWITCH_ENDPOINT - 源端点(自定义端点10)
         * ZB_APS_ADDR_MODE_16_ENDP_PRESENT - 16位地址模式
         * ZB_FALSE - 禁用APS确认,避免ACK等待导致协调器积压
         * zclFrameData - ZCL帧数据指针
         * ZCL_FRAME_SIZE - ZCL帧大小 */
        zb_ret_t ret = zb_aps_send_user_payload(
          param,
          addr,                           /* dst_addr */
          ZB_AF_HA_PROFILE_ID,            /* profile id - 标准HA配置文件 */
          ZB_ZCL_CLUSTER_ID_BASIC,        /* cluster id - 基础集群 */
          ZB_OUTPUT_ENDPOINT,             /* destination endpoint (coordinator endpoint 5) */
          ZB_SWITCH_ENDPOINT,             /* source endpoint */
          ZB_APS_ADDR_MODE_16_ENDP_PRESENT, /* address mode */
          ZB_FALSE,                       /* APS ACK disabled - 避免ACK等待导致协调器积压 */
          zclFrameData,                   /* payload pointer */
          ZCL_FRAME_SIZE);                /* size of payload */
       
        if (ret != RET_OK) {
            uartPrintf("ZCL data send failed, error code: %d\r\n", ret);
           
            // Handle different error codes
            switch (ret) {
                case RET_INVALID_PARAMETER_1:
                    uartPrintf("Error: Invalid parameter\r\n");
                    break;
                case RET_NO_MEMORY:
                    uartPrintf("Error: Insufficient memory\r\n");
                    break;
                case RET_INVALID_STATE:
                    uartPrintf("Error: Invalid state\r\n");
                    break;
                default:
                    uartPrintf("Unknown error type\r\n");
                    break;
            }
           
            zb_buf_free(param);  /* 发送失败时释放缓冲区 */
        } else {
          uartPrintf("param3: %d\r\n", param);
            // 发送成功,立即释放缓冲区
            // if(param != ZB_BUF_INVALID){
                 zb_buf_free(param);    //发送成功后若不使用该函数则发送7次之后会重启。
            // }
           
        }
      }
    }
  • 以下是一个基于 on_off_switch.c 示例的代码,该示例在加入网络后每秒发送一个自定义数据包。它采用回调函数释放缓冲区,具体实现方式如我先前回复中发送的 SLA 所示。该代码经过超过一小时的测试,未出现任何缓冲区问题。

    /******************************************************************************
     Group: CMCU LPRF
     Target Device: cc23xx
    
     ******************************************************************************
     
     Copyright (c) 2024-2025, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form 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.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     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 OWNER 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.
    
     ******************************************************************************
     
     
     *****************************************************************************/
    
    /***** Trace related defines *****/
    #define ZB_TRACE_FILE_ID 40124
    
    /****** Application defines ******/
    #define ZB_SWITCH_ENDPOINT          10
    
    #include <ti/log/Log.h>
    
    #include "ti_zigbee_config.h"
    #include "zboss_api.h"
    #include "zb_led_button.h"
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(inc/hw_fcfg.h)
    #include DeviceFamily_constructPath(inc/hw_memmap.h)
    
    /* for button handling */
    #include <ti/drivers/GPIO.h>
    #include "ti_drivers_config.h"
    
    #ifdef ZB_CONFIGURABLE_MEM
    #include "zb_mem_config_lprf3.h"
    #endif
    
    #if !defined ZB_ED_FUNC
    #error define ZB_ED_ROLE to compile the tests
    #endif
    
    /****** Application variables declarations ******/
    /* IEEE address of the device */
    zb_bool_t cmd_in_progress = ZB_FALSE;
    zb_bool_t perform_factory_reset = ZB_FALSE;
    
    /****** Application function declarations ******/
    zb_uint8_t zcl_specific_cluster_cmd_handler(zb_uint8_t param);
    void on_off_read_attr_resp_handler(zb_bufid_t cmd_buf);
    void send_toggle_req(zb_uint8_t param);
    void button_press_handler(zb_uint8_t param);
    void send_aps_payload_cb(zb_uint8_t param);
    
    /****** Cluster declarations ******/
    /* Switch config cluster attributes */
    zb_uint8_t attr_switch_type =
        ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_TYPE_TOGGLE;
    zb_uint8_t attr_switch_actions =
        ZB_ZCL_ON_OFF_SWITCH_CONFIGURATION_SWITCH_ACTIONS_DEFAULT_VALUE;
    
    ZB_ZCL_DECLARE_ON_OFF_SWITCH_CONFIGURATION_ATTRIB_LIST(switch_cfg_attr_list,
                                                           &attr_switch_type,
                                                           &attr_switch_actions);
    /* Basic cluster attributes */
    zb_uint8_t attr_zcl_version  = ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE;
    zb_uint8_t attr_power_source = ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE;
    ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST(basic_attr_list, &attr_zcl_version, &attr_power_source);
    /* Identify cluster attributes */
    zb_uint16_t attr_identify_time = 0;
    ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(identify_attr_list, &attr_identify_time);
    /* Declare cluster list for the device */
    ZB_HA_DECLARE_ON_OFF_SWITCH_CLUSTER_LIST(on_off_switch_clusters,
                                             switch_cfg_attr_list,
                                             basic_attr_list,
                                             identify_attr_list);
    /* Declare endpoint */
    ZB_HA_DECLARE_ON_OFF_SWITCH_EP(on_off_switch_ep, ZB_SWITCH_ENDPOINT, on_off_switch_clusters);
    /* Declare application's device context for single-endpoint device */
    ZB_HA_DECLARE_ON_OFF_SWITCH_CTX(on_off_switch_ctx, on_off_switch_ep);
    
    void my_main_loop()
    {
      while (1)
      {
        /* ... User code ... */
        zboss_main_loop_iteration();
        /* ... User code ... */
      }
    }
    
    void off_network_attention(zb_uint8_t param)
    {
      ZVUNUSED(param);
      Log_printf(LogModule_Zigbee_App, Log_INFO, "off_network_attention");
      zb_osif_led_toggle(1);
    
      ZB_SCHEDULE_APP_ALARM(off_network_attention, 0, 1 * ZB_TIME_ONE_SECOND);
    }
    
    MAIN()
    {
      ARGV_UNUSED;
    
      /* Global ZBOSS initialization */
      ZB_INIT("on_off_switch");
    
      #ifdef ZB_LONG_ADDR
      // use the address that the customer set in the pre-defined symbols tab
      zb_ieee_addr_t g_long_addr = ZB_LONG_ADDR;
      zb_set_long_address(g_long_addr);
      #else
      /* Set the device's long address to the IEEE address pulling from the FCFG of the device */
      zb_ieee_addr_t ieee_mac_addr;
      ZB_MEMCPY(ieee_mac_addr, fcfg->deviceInfo.macAddr, 8);
      zb_set_long_address(ieee_mac_addr);
      #endif // ZB_LONG_ADDR
    
    #ifdef ZB_COORDINATOR_ROLE
      zb_set_network_coordinator_role(DEFAULT_CHANLIST);
    
      /* Set keepalive mode to mac data poll so sleepy zeds consume less power */
      zb_set_keepalive_mode(MAC_DATA_POLL_KEEPALIVE);
    #ifdef DEFAULT_NWK_KEY
      zb_uint8_t nwk_key[16] = DEFAULT_NWK_KEY;
      zb_secur_setup_nwk_key(nwk_key, 0);
    #endif //DEFAULT_NWK_KEY
    
    #ifdef ZBOSS_REV23
      zb_nwk_set_max_ed_capacity(MAX_ED_CAPACITY);
    #endif //ZBOSS_REV23
    
    #elif defined ZB_ROUTER_ROLE && !defined ZB_COORDINATOR_ROLE
      zb_set_network_router_role(DEFAULT_CHANLIST);
    
    #ifdef ZBOSS_REV23
      zb_nwk_set_max_ed_capacity(MAX_ED_CAPACITY);
    #endif //ZBOSS_REV23
    
      /* Set keepalive mode to mac data poll so sleepy zeds consume less power */
      zb_set_keepalive_mode(MAC_DATA_POLL_KEEPALIVE);
    
    #elif defined ZB_ED_ROLE
      zb_set_network_ed_role(DEFAULT_CHANLIST);
    
      /* Set end-device configuration parameters */
      zb_set_ed_timeout(ED_TIMEOUT_VALUE);
      zb_set_rx_on_when_idle(ED_RX_ALWAYS_ON);
    #if ( ED_RX_ALWAYS_ON == ZB_FALSE )
      zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(ED_POLL_RATE));
      zb_zdo_pim_set_long_poll_interval(ED_POLL_RATE);
    #ifdef DISABLE_TURBO_POLL
      // Disable turbo poll feature
      zb_zdo_pim_permit_turbo_poll(ZB_FALSE);
    #endif // DISABLE_TURBO_POLL
    #endif // ED_RX_ALWAYS_ON
    #endif //ZB_ED_ROLE
    
      zb_set_nvram_erase_at_start(ZB_FALSE);
    
      /* Register device ZCL context */
      ZB_AF_REGISTER_DEVICE_CTX(&on_off_switch_ctx);
      /* Register cluster commands handler for a specific endpoint */
      ZB_AF_SET_ENDPOINT_HANDLER(ZB_SWITCH_ENDPOINT, zcl_specific_cluster_cmd_handler);
    
      zb_aps_set_user_data_tx_cb(send_aps_payload_cb);
    
      /* Initiate the stack start without starting the commissioning */
      if (zboss_start_no_autostart() != RET_OK)
      {
        Log_printf(LogModule_Zigbee_App, Log_ERROR, "zboss_start failed");
      }
      else
      {
        GPIO_setConfig(CONFIG_GPIO_BTN1, GPIO_CFG_IN_PU);
        GPIO_setConfig(CONFIG_GPIO_BTN2, GPIO_CFG_IN_PU);
        // if either button 1 or button 2 gets pressed
        zb_bool_t sideButtonPressed = ((GPIO_read((zb_uint8_t)CONFIG_GPIO_BTN1) == 0U) || (GPIO_read((zb_uint8_t)CONFIG_GPIO_BTN2) == 0U));
        // then perform a factory reset
        if (sideButtonPressed)
        {
          perform_factory_reset = ZB_TRUE;
          Log_printf(LogModule_Zigbee_App, Log_INFO, "perform factory reset");
        }
    
        zb_osif_led_button_init();
    #ifndef ZB_COORDINATOR_ROLE
        ZB_SCHEDULE_APP_ALARM(off_network_attention, 0, 1 * ZB_TIME_ONE_SECOND);
    #endif /* ZB_COORDINATOR_ROLE */
    
        /* Call the application-specific main loop */
        my_main_loop();
      }
    
      MAIN_RETURN(0);
    }
    
    static zb_bool_t finding_binding_cb(zb_int16_t status,
                                        zb_ieee_addr_t addr,
                                        zb_uint8_t ep,
                                        zb_uint16_t cluster)
    {
      /* Unused without trace. */
      ZVUNUSED(status);
      ZVUNUSED(addr);
      ZVUNUSED(ep);
      ZVUNUSED(cluster);
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "finding_binding_cb status %d addr %x ep %d cluster %d",
                 status, ((zb_uint32_t *)addr)[0], ep, cluster);
      return ZB_TRUE;
    }
    
    zb_uint8_t zcl_specific_cluster_cmd_handler(zb_uint8_t param)
    {
      zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(param, zb_zcl_parsed_hdr_t);
      zb_bool_t unknown_cmd_received = ZB_TRUE;
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "> zcl_specific_cluster_cmd_handler %i", param);
      Log_printf(LogModule_Zigbee_App, Log_INFO, "payload size: %i", zb_buf_len(param));
    
      if (cmd_info->cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_CLI)
      {
        if (cmd_info->cmd_id == ZB_ZCL_CMD_DEFAULT_RESP)
        {
          unknown_cmd_received = ZB_FALSE;
    
          cmd_in_progress = ZB_FALSE;
    
          zb_buf_free(param);
        }
      }
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "< zcl_specific_cluster_cmd_handler %i", param);
      return ! unknown_cmd_received;
    }
    
    void send_aps_payload_cb(zb_uint8_t param)
    {
      zb_ret_t buf_status;
      zb_uint8_t i;
      zb_uint8_t aps_payload_size = 0U;
      zb_uint8_t *aps_payload_ptr;
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, ">> send_aps_payload_cb, param: %hd",
                 param);
    
      ZB_ASSERT(param != ZB_BUF_INVALID);
    
      buf_status = zb_buf_get_status(param);
      aps_payload_ptr = zb_aps_get_aps_payload(param, &aps_payload_size);
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "buf_status %d, buf_len: %hd, aps_payload_size: %hd",
                buf_status, zb_buf_len(param), aps_payload_size);
    
      switch ((zb_aps_user_payload_cb_status_t)buf_status)
      {
        case ZB_APS_USER_PAYLOAD_CB_STATUS_SUCCESS:
          Log_printf(LogModule_Zigbee_App, Log_INFO, "Transmission status: SUCCESS");
          break;
    
        case ZB_APS_USER_PAYLOAD_CB_STATUS_NO_APS_ACK:
          Log_printf(LogModule_Zigbee_App, Log_INFO, "Transmission status: NO_APS_ACK");
          break;
    
        default:
          Log_printf(LogModule_Zigbee_App, Log_INFO, "Transmission status: INVALID");
          break;
      }
    
      for (i = 0U; i < aps_payload_size; ++i)
      {
        Log_printf(LogModule_Zigbee_App, Log_INFO, "aps_payload[%hd] == 0x%hx",
                  aps_payload_ptr[i]);
      }
    
      zb_buf_free(param);
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "<< send_aps_payload_cb");
    }
    
    void send_aps_payload(zb_uint8_t param)
    {
      zb_addr_u addr = { 0 };
      uint8_t theMessageData[] = {"\0\0\30Hello World"};
    
      ZB_ASSERT(param);
    
      if (ZB_JOINED()  && !cmd_in_progress)
      {
        cmd_in_progress = ZB_TRUE;
        Log_printf(LogModule_Zigbee_App, Log_INFO, "send_af_data_req %d - send af data req", param);
    
        zb_aps_send_user_payload(
          param,
          addr,                   /* dst_addr */
          0x0104,                 /* profile id */
          0xf00d,                 /* cluster id */
          5,                      /* destination endpoint */
          ZB_SWITCH_ENDPOINT,     /* source endpoint */
          ZB_APS_ADDR_MODE_16_ENDP_PRESENT, /* address mode */
          ZB_TRUE,                /* APS ACK enabled */
          theMessageData,         /* payload pointer */
          sizeof(theMessageData)); /* size of payload */
      }
      else
      {
        Log_printf(LogModule_Zigbee_App, Log_INFO, "send_af_data_req %d - not joined", param);
        zb_buf_free(param);
      }
    }
    
    void send_toggle_req(zb_uint8_t param)
    {
      zb_uint16_t addr = 0;
    
      ZB_ASSERT(param);
    
      if (ZB_JOINED()  && !cmd_in_progress)
      {
        cmd_in_progress = ZB_TRUE;
        Log_printf(LogModule_Zigbee_App, Log_INFO, "send_toggle_req %d - send toggle", param);
    
        /* Destination address and endpoint are unknown; command will be sent via binding */
        ZB_ZCL_ON_OFF_SEND_TOGGLE_REQ(
          param,
          addr,
          ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT,
          0,
          ZB_SWITCH_ENDPOINT,
          ZB_AF_HA_PROFILE_ID,
          ZB_FALSE, NULL);
      }
      else
      {
        Log_printf(LogModule_Zigbee_App, Log_INFO, "send_toggle_req %d - not joined", param);
        zb_buf_free(param);
      }
    }
    
    void restart_commissioning(zb_uint8_t param)
    {
      ZVUNUSED(param);
      bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
    }
    
    void button_press_handler(zb_uint8_t param)
    {
      if (!param)
      {
        /* Button is pressed, gets buffer for outgoing command */
        zb_buf_get_out_delayed(button_press_handler);
      }
      else
      {
        Log_printf(LogModule_Zigbee_App, Log_INFO, "button_press_handler %d", param);
        send_aps_payload(param);
    //#ifndef ZB_USE_BUTTONS
        /* Do not have buttons in simulator - just start periodic on/off sending */
        ZB_SCHEDULE_APP_ALARM(button_press_handler, 0, 1 * ZB_TIME_ONE_SECOND);
    //#endif
      }
    }
    
    void permit_joining_cb(zb_uint8_t param)
    {
      Log_printf(LogModule_Zigbee_App, Log_INFO, "permit joining done");
      zb_buf_free(param);
    }
    
    void start_finding_binding(zb_uint8_t param)
    {
      ZVUNUSED(param);
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "Successful steering, start f&b initiator");
      zb_bdb_finding_binding_initiator(ZB_SWITCH_ENDPOINT, finding_binding_cb);
    }
    
    void set_tx_power(zb_int8_t power)
    {
      zb_uint32_t chanlist = DEFAULT_CHANLIST;
      for (zb_uint8_t i = 0; i < 32; i++) {
        if (chanlist & (1U << i)) {
          zb_bufid_t buf = zb_buf_get_out();
          if (!buf)
          {
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "no buffer available");
            return;
          }
    
          zb_tx_power_params_t *power_params = (zb_tx_power_params_t *)zb_buf_begin(buf);
          power_params->status = RET_OK;
          power_params->page = 0;
          power_params->channel = i;
          power_params->tx_power = power;
          power_params->cb = NULL;
    
          zb_set_tx_power_async(buf);
        }
      }
    }
    
    void zboss_signal_handler(zb_uint8_t param)
    {
      zb_zdo_app_signal_hdr_t *sg_p = NULL;
      zb_zdo_app_signal_type_t sig = zb_get_app_signal(param, &sg_p);
      zb_bufid_t buf;
      zb_bufid_t req_buf = 0;
      zb_zdo_mgmt_permit_joining_req_param_t *req_param;
    
      if (ZB_GET_APP_SIGNAL_STATUS(param) == 0)
      {
        switch(sig)
        {
          case ZB_ZDO_SIGNAL_SKIP_STARTUP:
    #ifndef ZB_MACSPLIT_HOST
            Log_printf(LogModule_Zigbee_App, Log_INFO, "ZB_ZDO_SIGNAL_SKIP_STARTUP: boot, not started yet");
            set_tx_power(DEFAULT_TX_PWR);
            zboss_start_continue();
    #endif /* ZB_MACSPLIT_HOST */
            break;
    
    #ifdef ZB_MACSPLIT_HOST
          case ZB_MACSPLIT_DEVICE_BOOT:
            Log_printf(LogModule_Zigbee_App, Log_INFO, "ZB_MACSPLIT_DEVICE_BOOT: boot, not started yet");
            set_tx_power(DEFAULT_TX_PWR);
            zboss_start_continue();
            break;
    #endif /* ZB_MACSPLIT_HOST */
          case ZB_BDB_SIGNAL_DEVICE_FIRST_START:
            Log_printf(LogModule_Zigbee_App, Log_INFO, "FIRST_START: start steering");
            if (perform_factory_reset)
            {
              // passing in 0 as the parameter means that a buffer will be allocated automatically for the reset
              zb_bdb_reset_via_local_action(0);
              perform_factory_reset = ZB_FALSE;
            }
            set_tx_power(DEFAULT_TX_PWR);
            bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
    
            buf = zb_buf_get_out();
            if (!buf)
            {
              Log_printf(LogModule_Zigbee_App, Log_WARNING, "no buffer available");
              break;
            }
    
            req_param = ZB_BUF_GET_PARAM(buf, zb_zdo_mgmt_permit_joining_req_param_t);
    
            req_param->dest_addr = 0xfffc;
            req_param->permit_duration = 0;
            req_param->tc_significance = 1;
    
            zb_zdo_mgmt_permit_joining_req(buf, permit_joining_cb);
    
    #ifdef ZB_USE_BUTTONS
    //        zb_button_register_handler(0, 0, button_press_handler);
    #endif /* ZB_USE_BUTTONS */
            break;
          case ZB_BDB_SIGNAL_DEVICE_REBOOT:
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Device RESTARTED OK");
            if (perform_factory_reset)
            {
              Log_printf(LogModule_Zigbee_App, Log_INFO, "Performing a factory reset.");
              zb_bdb_reset_via_local_action(0);
              perform_factory_reset = ZB_FALSE;
            }
            else
            {
              ZB_SCHEDULE_APP_ALARM_CANCEL(off_network_attention, ZB_ALARM_ANY_PARAM);
              zb_osif_led_off(1);
            }
    #ifdef ZB_USE_BUTTONS
    //        zb_button_register_handler(0, 0, button_press_handler);
    #endif /* ZB_USE_BUTTONS */
            break;
    #ifdef ZB_COORDINATOR_ROLE
          case ZB_ZDO_SIGNAL_DEVICE_ANNCE:
    #else
          case ZB_BDB_SIGNAL_TC_REJOIN_DONE:
            Log_printf(LogModule_Zigbee_App, Log_INFO, "TC rejoin is completed successfully");
          case ZB_BDB_SIGNAL_STEERING:
    #endif
          {
            zb_nwk_device_type_t device_type = ZB_NWK_DEVICE_TYPE_NONE;
            device_type = zb_get_device_type();
            ZVUNUSED(device_type);
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Device (%d) STARTED OK", device_type);
            ZB_SCHEDULE_APP_ALARM(start_finding_binding, 0, 3 * ZB_TIME_ONE_SECOND);
            ZB_SCHEDULE_APP_ALARM_CANCEL(off_network_attention, ZB_ALARM_ANY_PARAM);
    #ifdef ZB_USE_BUTTONS
    //        zb_button_register_handler(0, 0, button_press_handler);
    #endif /* ZB_USE_BUTTONS */
            zb_osif_led_off(1);
            break;
          }
    
          case ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED:
          {
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Finding&binding done");
    //#ifndef ZB_USE_BUTTONS
            /* Do not have buttons in simulator - just start periodic on/off sending */
            cmd_in_progress = ZB_FALSE;
            ZB_SCHEDULE_APP_ALARM_CANCEL(button_press_handler, ZB_ALARM_ANY_PARAM);
            ZB_SCHEDULE_APP_ALARM(button_press_handler, 0, 1 * ZB_TIME_ONE_SECOND);
    //#endif
          }
          break;
    
          case ZB_ZDO_SIGNAL_LEAVE:
          break;
          case ZB_COMMON_SIGNAL_CAN_SLEEP:
          {
    #ifdef ZB_USE_SLEEP
            zb_sleep_now();
    #endif
            break;
          }
          case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY:
          {
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Production config is ready");
            break;
          }
    
          default:
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "Unknown signal %d, do nothing", sig);
        }
      }
      else
      {
        switch (sig)
        {
          case ZB_BDB_SIGNAL_DEVICE_FIRST_START:
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "Device can not find any network on start, so try to perform network steering");
            ZB_SCHEDULE_APP_ALARM(restart_commissioning, 0, 10 * ZB_TIME_ONE_SECOND);
            break; /* ZB_BDB_SIGNAL_DEVICE_FIRST_START */
    
          case ZB_BDB_SIGNAL_DEVICE_REBOOT:
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "Device can not find any network on restart");
    
            if (zb_bdb_is_factory_new())
            {
              /* Device tried to perform TC rejoin after reboot and lost its authentication flag.
               * Do nothing here and wait for ZB_BDB_SIGNAL_TC_REJOIN_DONE to handle TC rejoin error */
              Log_printf(LogModule_Zigbee_App, Log_WARNING, "Device lost authentication flag");
            }
            else
            {
              /* Device tried to perform secure rejoin, but didn't found any networks or can't decrypt Rejoin Response
               * (it is possible when Trust Center changes network key when ZED is powered off) */
              Log_printf(LogModule_Zigbee_App, Log_WARNING, "Device is still authenticated, try to perform TC rejoin");
              ZB_SCHEDULE_APP_ALARM(zb_bdb_initiate_tc_rejoin, 0, ZB_TIME_ONE_SECOND);
            }
            break; /* ZB_BDB_SIGNAL_DEVICE_REBOOT */
    
          case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY:
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Production config is not present or invalid");
            break; /* ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY */
    
          case ZB_BDB_SIGNAL_TC_REJOIN_DONE:
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "TC rejoin failed, so try it again with interval");
    
            ZB_SCHEDULE_APP_ALARM(zb_bdb_initiate_tc_rejoin, 0, 3 * ZB_TIME_ONE_SECOND);
            break; /* ZB_BDB_SIGNAL_TC_REJOIN_DONE */
    
          case ZB_BDB_SIGNAL_STEERING:
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "Steering failed, retrying again in 10 seconds");
            ZB_SCHEDULE_APP_ALARM(restart_commissioning, 0, 10 * ZB_TIME_ONE_SECOND);
            break; /* ZB_BDB_SIGNAL_STEERING */
    
          default:
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "Unknown signal %hd with error status, do nothing", sig);
            break;
        }
      }
    
      if (param)
      {
        zb_buf_free(param);
      }
    }

  • 我使用了您给我提供的代码之后发现协调器只接收了一条on_off_switch原有数据,以及一条您自定义的Hello World数据,后续协调器不再接收终端数据,能否提供您测试使用的协调器代码,我这边查看哪里有不一样的地方;

    另外若是数据发送函数zb_aps_send_user_payload使用   0xf00d     以及    ZB_TRUE,我这边协调器程序需要哪些修改?

    以下是我的协调器代码,使用on_off_light实例修改而来

    /******************************************************************************
     Group: CMCU LPRF
     Target Device: cc23xx
    
     ******************************************************************************
     
     Copyright (c) 2024-2025, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form 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.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     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 OWNER 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.
    
     ******************************************************************************
     
     
     *****************************************************************************/
    
    /***** Trace related defines - 跟踪相关定义 *****/
    #define ZB_TRACE_FILE_ID 40123
    
    /****** Application defines - 应用程序定义 ******/
    #define ZB_OUTPUT_ENDPOINT          5     // 输出端点(用于控制输出)
    #define ZB_OUTPUT_MAX_CMD_PAYLOAD_SIZE 2  // 输出最大命令负载大小
    
    #include <ti/log/Log.h>  // TI日志模块
    
    #include "ti_zigbee_config.h"  // Zigbee配置文件
    #include "zboss_api.h"         // ZBOSS API
    #include "zb_led_button.h"     // LED和按钮处理
    #include "zboss_api_error.h"   // ZBOSS API错误定义
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(inc/hw_fcfg.h)     // Flash配置寄存器
    #include DeviceFamily_constructPath(inc/hw_memmap.h)   // 内存映射
    
    /* for button handling - 用于按钮处理 */
    #include <ti/drivers/GPIO.h>   // GPIO驱动
    #include "ti_drivers_config.h" // 驱动配置
    
    #ifdef ZB_CONFIGURABLE_MEM
    #include "zb_mem_config_lprf3.h"  // 低功耗RF内存配置
    #endif
    
    //JIAYU ADD BEGIN - Jiayu添加的代码开始
    #include "ti/drivers/GPIO.h"   // GPIO驱动(重复包含)
    #include "ti/drivers/UART2.h"  // UART2驱动
    
    #include "unistd.h"   // Unix标准函数
    #include "stdint.h"   // 标准整数类型
    #include "stddef.h"   // 标准定义
    
    #include "ti/display/Display.h"       // 显示接口
    #include "ti/display/DisplayUart2.h"  // UART2显示实现
    #include "stdio.h"     // 标准输入输出
    
    //JIAYU ADD END - Jiayu添加的代码结束
    
    /****** Application variables declarations - 应用程序变量声明 ******/
    zb_uint16_t g_dst_addr;    // 目标地址(存储发送方短地址)
    zb_uint8_t g_addr_mode;    // 地址模式
    zb_uint8_t g_endpoint;     // 端点号
    zb_bool_t perform_factory_reset = ZB_FALSE;  // 工厂复位标志
    
    // Jiayu add: 数据接收存储数组
    #define RX_DATA_BUFFER_SIZE 256
    zb_uint8_t rx_data_buffer[RX_DATA_BUFFER_SIZE];
    zb_uint16_t rx_data_length = 0;
    zb_bool_t rx_data_valid = ZB_FALSE;
    
    /* Jiayu add: 保持入网窗口开放的定时器 */
    #define PERMIT_JOIN_DURATION 60  // 每次开启60秒入网窗口
    void permit_join_refresh(zb_uint8_t param);
    
    /****** Application function declarations - 应用程序函数声明 ******/
    /* Handler for specific ZCL commands - ZCL命令处理器 */
    zb_uint8_t zcl_specific_cluster_cmd_handler(zb_uint8_t param);  // 处理特定端点的ZCL命令
    void test_device_interface_cb(zb_uint8_t param);                 // 设备接口回调函数
    void button_press_handler(zb_uint8_t param);                    // 按钮按下处理函数
    
    /* 集群(Cluster)声明 */
    /* On/Off 集群属性 - 控制设备开关状态 */
    zb_uint8_t g_attr_on_off = ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE;
    #ifdef ZB_ENABLE_ZLL
    /* On/Off 集群属性扩展 - 用于 ZLL(Zigbee Light Link)- 用于智能照明链接*/
    zb_bool_t g_attr_global_scene_ctrl  = ZB_TRUE;    // 全局场景控制标志
    zb_uint16_t g_attr_on_time  = 0;                // 开启时间(毫秒)
    zb_uint16_t g_attr_off_wait_time  = 0;           // 等待关闭时间(毫秒)
    
    /* 声明扩展的On/Off属性列表(包含ZLL扩展属性)*/
    ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST_EXT(on_off_attr_list, &g_attr_on_off,
        &g_attr_global_scene_ctrl, &g_attr_on_time, &g_attr_off_wait_time);
    #else
    /* 标准 On/Off 集群属性列表 - 仅包含基本开关属性 */
    ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST(on_off_attr_list, &g_attr_on_off);
    #endif
    
    /* Basic 集群属性 - 基本设备信息 - 所有Zigbee设备必须支持的基本集群 */
    zb_uint8_t g_attr_zcl_version  = ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE;  // ZCL协议版本
    zb_uint8_t g_attr_power_source = ZB_ZCL_BASIC_POWER_SOURCE_DEFAULT_VALUE; // 电源类型(如:电池、市电等)
    
    /* 声明Basic属性列表 */
    ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST(basic_attr_list, &g_attr_zcl_version, &g_attr_power_source);
    
    /* Identify 集群属性 - 设备识别功能 - 用于识别和定位设备 */
    zb_uint16_t g_attr_identify_time = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE;  // 识别时间(秒)
    
    /* 声明Identify属性列表 */
    ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(identify_attr_list, &g_attr_identify_time);
    
    /* Groups 集群属性 - 设备分组功能 - 允许设备分组以进行批量控制 */
    zb_uint8_t g_attr_name_support = 0;  // 名称支持标志(0:不支持组名)
    
    /* 声明Groups属性列表 */
    ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(groups_attr_list, &g_attr_name_support);
    
    #ifdef ZB_ZCL_SUPPORT_CLUSTER_SCENES
    /* Scenes 集群属性 - 场景功能 - 预设场景以快速恢复设备状态 */
    zb_uint8_t g_attr_scenes_scene_count = ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE;       // 场景数量(最大存储场景数)
    zb_uint8_t g_attr_scenes_current_scene = ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE; // 当前场景ID
    zb_uint16_t g_attr_scenes_current_group = ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE; // 当前组ID
    zb_uint8_t g_attr_scenes_scene_valid = ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE;    // 场景有效性标志
    zb_uint16_t g_attr_scenes_name_support = ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE; // 场景名称支持标志
    
    /* 声明Scenes属性列表 */
    ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST(scenes_attr_list, &g_attr_scenes_scene_count,
        &g_attr_scenes_current_scene, &g_attr_scenes_current_group,
        &g_attr_scenes_scene_valid, &g_attr_scenes_name_support);
    #else
    /* 空场景属性列表 - 不支持场景时使用 */
    zb_zcl_attr_t scenes_attr_list[] = { ZB_ZCL_NULL_ID, 0, 0, NULL };
    #endif
    
    /* 为设备声明集群列表(HA:Home Automation 家庭自动化) */
    ZB_HA_DECLARE_ON_OFF_OUTPUT_CLUSTER_LIST(on_off_output_clusters,
                                             on_off_attr_list,      // On/Off 集群(ID: 0x0006)
                                             basic_attr_list,       // Basic 集群(ID: 0x0000)
                                             identify_attr_list,    // Identify 集群(ID: 0x0003)
                                             groups_attr_list,      // Groups 集群(ID: 0x0004)
                                             scenes_attr_list);     // Scenes 集群(ID: 0x0005)
    
    /* 声明端点 - 定义端点5,使用上述集群列表 */
    ZB_HA_DECLARE_ON_OFF_OUTPUT_EP(on_off_output_ep, ZB_OUTPUT_ENDPOINT, on_off_output_clusters);
    
    /* 为单端点设备声明应用程序设备上下文 - 设备描述结构 */
    ZB_HA_DECLARE_ON_OFF_OUTPUT_CTX(on_off_output_ctx, on_off_output_ep);
    
    /* 错误指示处理函数声明 */
    static zb_bool_t error_ind_handler(zb_uint8_t severity,
                                       zb_ret_t error_code,
                                       void *additional_info);
    
    /* 离网警告函数 - LED闪烁提示设备未连接网络 */
    void off_network_attention(zb_uint8_t param)
    {
      ZVUNUSED(param);  // 未使用参数
      Log_printf(LogModule_Zigbee_App, Log_INFO, "off_network_attention");
      zb_osif_led_toggle(1);  // 切换LED1状态
    
      /* 每秒定时调用此函数 */
      ZB_SCHEDULE_APP_ALARM(off_network_attention, 0, 1 * ZB_TIME_ONE_SECOND);
    }
    /* ========== Jiayu添加:自定义功能开始 ========== */
    
    /* 初始化LED - 配置LED1和LED2为输出,默认高电平(灭) */
    void init_led()
    {
      GPIO_setConfig(LED1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH);
      GPIO_setConfig(LED2, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH);
    }
    /* 点亮LED1 - 写低电平 */
    void led1_on()
    {
      GPIO_write(LED1, 0);
    }
    
    /* 点亮LED2 - 写低电平 */
    void led2_on()
    {
     GPIO_write(LED2, 0);
    }
    
    /* 熄灭LED1 - 写高电平 */
    void led1_off()
    {
      GPIO_write(LED1, 1);
    }
    
    /* 熄灭LED2 - 写高电平 */
    void led2_off()
    {
     GPIO_write(LED2, 1);
    }
    
    /* UART2句柄和参数 */
    UART2_Handle uart;
    UART2_Params uartParams;
    
    /* UART格式化输出函数 - 类似printf,通过UART2输出 */
    void uartPrintf(const char *format, ...)
    {
        char buffer[256];   // 输出缓冲区
        va_list args;       // 可变参数列表
        int length;
    
        va_start(args, format);              // 开始可变参数处理
        length = vsnprintf(buffer, sizeof(buffer), format, args);  // 格式化字符串
        va_end(args);                     // 结束可变参数处理
    
        /* 如果格式化成功且UART已打开,则发送数据 */
        if (length > 0 && uart != NULL)
        {
            UART2_write(uart, buffer, length, NULL);
        }
    }
    /* 初始化UART2 - 配置为115200波特率 */
    void init_uart2()
    {
      char input;  // 未使用的输入缓冲区
      //UART2_Handle uart;
      //UART2_Params uartParams;
      size_t byteRead;          // 读取字节数
      size_t byteWritten = 0;    // 写入字节数
      uint32_t status = UART2_STATUS_SUCCESS;  // UART状态
    
      UART2_Params_init(&uartParams);  // 初始化参数为默认值
      uartParams.baudRate = 115200;     // 设置波特率为115200
    
      uart = UART2_open(CONFIG_UART2_0,&uartParams);  // 打开UART2_0
      if(uart == NULL)
      {
        //串口2打开失败 - 此处可添加错误处理
      }
    }
    
    /* 主循环函数 - LED闪烁 + Zigbee协议栈处理 */
    void my_main_loop()
    {
      uint32_t loop_counter = 0;
      static zb_bool_t led_state = ZB_FALSE;
    
      while(1)  // 无限循环
      {
        /* 每次循环调用多次协议栈迭代,确保及时处理Zigbee事件 */
        zboss_main_loop_iteration();
        zboss_main_loop_iteration();
        zboss_main_loop_iteration();
        zboss_main_loop_iteration();
        zboss_main_loop_iteration();
    
        /* 降低LED切换频率 - 每5000次循环切换一次LED(约5秒) */
        loop_counter++;
        if (loop_counter >= 5000)
        {
          led_state = !led_state;
          if (led_state)
          {
            led1_on();
          }
          else
          {
            led1_off();
          }
          loop_counter = 0;
        }
    
        /* 使用短延时,保持高频响应 */
        usleep(1000);  // 1ms延时
      }
    }
    /* ========== Jiayu添加:自定义功能结束 ========== */
    
    /* 主函数 - 程序入口点 */
    MAIN()
    {
      ARGV_UNUSED;  // 未使用的命令行参数
    
      init_uart2();      // 初始化UART2串口(用于调试输出)
      init_led();        // 初始化LED(LED1/LED2)
      uartPrintf("driver start...\r\n");
      uartPrintf("========================================\r\n");
      uartPrintf("CC2340 Zigbee start\r\n");
      //uartPrintf("编译时间: %s %s\r\n", __DATE__, __TIME__);
      uartPrintf("========================================\r\n");
    
      uartPrintf("ZBOSS start...\r\n");
    
      /* 全局ZBOSS初始化 */
    
      // 初始化Zigbee
    
      uartPrintf("[DEBUG] Before ZB_INIT...\r\n");
      ZB_INIT("on_off_light");  // 初始化ZBOSS协议栈,参数为设备名
      uartPrintf("[DEBUG] After ZB_INIT, OK\r\n");
    
      uartPrintf("[DEBUG] Checking ZB_LONG_ADDR...\r\n");
      #ifdef ZB_LONG_ADDR
      uartPrintf("[DEBUG] ZB_LONG_ADDR is defined\r\n");
      // 使用客户在预定义符号标签中设置的长地址
      zb_ieee_addr_t g_long_addr = ZB_LONG_ADDR;
      zb_set_long_address(g_long_addr);
      #else
      uartPrintf("[DEBUG] ZB_LONG_ADDR is NOT defined, using FCFG...\r\n");
      /* 从设备FCFG(Flash配置)中读取IEEE地址设置为设备长地址 - 这是设备的唯一64位地址 */
      zb_ieee_addr_t ieee_mac_addr;
      ZB_MEMCPY(ieee_mac_addr, fcfg->deviceInfo.macAddr, 8);  // 从FCFG读取MAC地址
      zb_set_long_address(ieee_mac_addr);  // 设置设备长地址
      uartPrintf("[DEBUG] Long address set OK\r\n");
      #endif // ZB_LONG_ADDR
    
      uartPrintf("[DEBUG] Checking device role...\r\n");
    #ifdef ZB_COORDINATOR_ROLE
      uartPrintf("[DEBUG] ZB_COORDINATOR_ROLE is defined\r\n");
      /* 设置协调器入网默认配置 - 协调器是网络的创建者和管理者 */
      uartPrintf("[DEBUG] Setting coordinator role...\r\n");
      zb_set_network_coordinator_role(DEFAULT_CHANLIST);  // 设置协调器角色并指定默认信道列表
      uartPrintf("[DEBUG] Coordinator role set OK\r\n");
    
      /* 设置MAC数据轮询保活模式,使睡眠终端消耗更少电力 */
      zb_set_keepalive_mode(MAC_DATA_POLL_KEEPALIVE);  // 使用数据轮询保活模式
      uartPrintf("[DEBUG] Keepalive mode set OK\r\n");
    
    #ifdef DEFAULT_NWK_KEY
      /* 设置网络密钥 - 用于网络加密 */
      zb_uint8_t nwk_key[16] = DEFAULT_NWK_KEY;
      zb_secur_setup_nwk_key(nwk_key, 0);  // 设置网络密钥
    #endif //DEFAULT_NWK_KEY
    
    #ifdef ZBOSS_REV23
      /* 设置最大终端设备容量 - 协调器可以支持的最大终端设备数量 */
      zb_nwk_set_max_ed_capacity(MAX_ED_CAPACITY);
    #endif //ZBOSS_REV23
    
    #elif defined ZB_ROUTER_ROLE && !defined ZB_COORDINATOR_ROLE
      uartPrintf("[DEBUG] ZB_ROUTER_ROLE is defined\r\n");
      /* 设置路由器角色 - 路由器可以转发数据并扩展网络范围 */
      zb_set_network_router_role(DEFAULT_CHANLIST);  // 设置路由器角色并指定默认信道列表
    
    #ifdef ZBOSS_REV23
      /* 设置最大终端设备容量 - 路由器可以支持的最大终端设备数量 */
      zb_nwk_set_max_ed_capacity(MAX_ED_CAPACITY);
    #endif //ZBOSS_REV23
    
      /* 设置MAC数据轮询保活模式 */
      zb_set_keepalive_mode(MAC_DATA_POLL_KEEPALIVE);  // 使用数据轮询保活模式
    
    #elif defined ZB_ED_ROLE
      uartPrintf("[DEBUG] ZB_ED_ROLE is defined\r\n");
      /* 设置终端设备角色 - 终端设备通常电池供电,功耗低 */
      zb_set_network_ed_role(DEFAULT_CHANLIST);  // 设置终端设备角色并指定默认信道列表
    
      /* 设置终%E7%AB%AF设备配置参数 */
      zb_set_ed_timeout(ED_TIMEOUT_VALUE);           // 设置父节点超时时间
      zb_set_rx_on_when_idle(ED_RX_ALWAYS_ON);      // 空闲时是否保持接收开启
    #if ( ED_RX_ALWAYS_ON == ZB_FALSE )
      /* 如果空闲时不保持接收开启,需要设置轮询参数 */
      zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(ED_POLL_RATE));  // 设置保活超时
      zb_zdo_pim_set_long_poll_interval(ED_POLL_RATE);  // 设置长轮询间隔
    #ifdef DISABLE_TURBO_POLL
      /* 禁用Turbo轮询功能 - Turbo轮询会快速轮询父节点 */
      zb_zdo_pim_permit_turbo_poll(ZB_FALSE);
    #endif // DISABLE_TURBO_POLL
    #endif //ED_RX_ALWAYS_ON
    #else
      uartPrintf("[DEBUG] ERROR: No device role defined!\r\n");
    #endif //ZB_ED_ROLE
    
      zb_set_nvram_erase_at_start(ZB_FALSE);  // 设置启动时不擦除NVRAM(保留配置)
      uartPrintf("[DEBUG] NVRAM erase set OK\r\n");
    
    #ifdef ZB_ENABLE_PTA
      zb_enable_pta(0);  // 启用PTA(Packet Traffic Arbitration,数据包流量仲裁)用于WiFi共存
      uartPrintf("[DEBUG] PTA enabled\r\n");
    #endif
    
      /* Register device ZCL context - 注册设备的ZCL上下文 */
      uartPrintf("[DEBUG] Registering device context...\r\n");
      ZB_AF_REGISTER_DEVICE_CTX(&on_off_output_ctx);
      uartPrintf("[DEBUG] Device context registered OK\r\n");
    
      /* Register cluster commands handler for a specific endpoint - 为端点注册ZCL命令处理器 */
      uartPrintf("[DEBUG] Registering endpoint handlers...\r\n");
      uartPrintf("[DEBUG] ZB_OUTPUT_ENDPOINT = %d\r\n", ZB_OUTPUT_ENDPOINT);
      uartPrintf("[DEBUG] About to call ZB_AF_SET_ENDPOINT_HANDLER for EP%d...\r\n", ZB_OUTPUT_ENDPOINT);
    
      ZB_AF_SET_ENDPOINT_HANDLER(ZB_OUTPUT_ENDPOINT, zcl_specific_cluster_cmd_handler);  // 为端点5注册
      uartPrintf("[DEBUG] EP%d handler registered OK\r\n", ZB_OUTPUT_ENDPOINT);
    
      /* Set Device user application callback - 设置设备用户应用回调 */
      uartPrintf("[DEBUG] Registering device callback...\r\n");
      ZB_ZCL_REGISTER_DEVICE_CB(test_device_interface_cb);
      uartPrintf("[DEBUG] Device callback registered OK\r\n");
    
      uartPrintf("[DEBUG] Registering error handler...\r\n");
      zb_error_register_app_handler(error_ind_handler);  // 注册错误处理函数
      uartPrintf("[DEBUG] Error handler registered OK\r\n");
    
      /* Initiate the stack start without starting the commissioning - 启动协议栈但不自动入网 */
      uartPrintf("[DEBUG] Calling zboss_start_no_autostart...\r\n");
      if (zboss_start_no_autostart() != RET_OK)
      {
        Log_printf(LogModule_Zigbee_App, Log_ERROR, "zboss_start failed");
        uartPrintf("zboss_start failed\r\n");
      }
      else  // 协议栈启动成功
      {
        //GPIO_setConfig(CONFIG_GPIO_BTN1, GPIO_CFG_IN_PU);  // 配置按钮1为上拉输入(已注释)
        //GPIO_setConfig(CONFIG_GPIO_BTN2, GPIO_CFG_IN_PU);  // 配置按钮2为上拉输入(已注释)
        // if either button 1 or button 2 gets pressed
        //zb_bool_t sideButtonPressed = ((GPIO_read((zb_uint8_t)CONFIG_GPIO_BTN1) == 0U) || (GPIO_read((zb_uint8_t)CONFIG_GPIO_BTN2) == 0U));  // 检测按钮是否按下(已注释)
        // then perform a factory reset
        //if (sideButtonPressed)  // 如果按钮按下则执行工厂复位(已注释)
        {
          //perform_factory_reset = ZB_TRUE;  // 设置工厂复位标志(已注释)
          Log_printf(LogModule_Zigbee_App, Log_INFO, "performing factory reset");
          uartPrintf("zboss_start success\r\n");
        }
    
        //zb_osif_led_button_init();  // 初始化LED和按钮(已注释)
    
    #ifndef ZB_COORDINATOR_ROLE
        /* 非协调器设备启动离网警告定时器 - LED闪烁提示未入网 */
        ZB_SCHEDULE_APP_ALARM(off_network_attention, 0, 1 * ZB_TIME_ONE_SECOND);
    #endif /* ZB_COORDINATOR_ROLE */
    
      //网络监控 - 打印网络状态信息
        uartPrintf( "=== Network Status ===\r\n");
        uartPrintf( "PAN ID: 0x%04X\r\n", zb_get_pan_id());  // 网络ID
        //uartPrintf("long_address: 0x%08X\r\n", longaddress);  // 长地址(已注释)
        uartPrintf("Short Addr: 0x%04X\r\n", zb_get_short_address());  // 短地址
        uartPrintf("Current channel: 0x%04X\r\n", zb_get_current_channel());  // 当前信道
        uartPrintf("zboss version: 0x%08X\r\n", zboss_version_get());  // ZBOSS版本
        uartPrintf("device_type: 0x%08X\r\n", zb_get_device_type());//返回值 0:协调器     1:路由器    2:终端设备    3:睡眠终端设备
    
        uartPrintf( "====================\r\n");
    
        /* Call the main loop - 调用主循环 */
        //zboss_main_loop();  // 标准主循环(已注释)
        //进入主函数S
        my_main_loop();  // 调用自定义主循环(带LED闪烁)
      }
    
      MAIN_RETURN(0);  // 主函数返回
    }
    
    
    /* 错误指示处理函数 - 处理ZBOSS协议栈错误 */
    static zb_bool_t error_ind_handler(zb_uint8_t severity,
                                        zb_ret_t error_code,
                                        void *additional_info)
    {
      zb_bool_t ret = ZB_FALSE;  // 返回值:TRUE表示已处理,FALSE表示使用默认处理
      ZVUNUSED(additional_info);  // 未使用的附加信息参数
      /* Unused without trace. */
      ZVUNUSED(severity);  // 未使用的严重性参数
    
      Log_printf(LogModule_Zigbee_App, Log_ERROR, "error_ind_handler severity %d error_code %d", severity, error_code);
    
      /* 处理MACSPLIT(MAC分离)射频挂起错误 - 致命错误 */
      if (error_code == ERROR_CODE(ERROR_CATEGORY_MACSPLIT, ZB_ERROR_MACSPLIT_RADIO_HANG))
      {
        Log_printf(LogModule_Zigbee_App, Log_ERROR, "Fatal macsplit error");
    
        ret = ZB_TRUE;
        /* return TRUE to prevent default error handling by the stack - 返回TRUE阻止协议栈的默认错误处理 */
      }
      /* 处理MACSPLIT射频重启错误 */
      if (error_code == ERROR_CODE(ERROR_CATEGORY_MACSPLIT, ZB_ERROR_MACSPLIT_RADIO_REBOOT))
      {
        Log_printf(LogModule_Zigbee_App, Log_ERROR, "macsplit radio reboot");
    
        ret = ZB_TRUE;
      }
      Log_printf(LogModule_Zigbee_App, Log_ERROR, "error_ind_handler ret %d", ret);
      return ret;
    }
    
    
    /* 设备接口回调函数 - 处理ZCL属性设置等设备操作 */
    void test_device_interface_cb(zb_uint8_t param)
    {
      /* 从缓冲区获取回调参数 */
      zb_zcl_device_callback_param_t *device_cb_param =
        ZB_BUF_GET_PARAM(param, zb_zcl_device_callback_param_t);
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "> test_device_interface_cb param %d id 0x%x",
                 param, device_cb_param->device_cb_id);
    
      device_cb_param->status = RET_OK;  // 默认返回成功
    
      switch (device_cb_param->device_cb_id)
      {
        /* 处理属性设置回调 */
        case ZB_ZCL_SET_ATTR_VALUE_CB_ID:
          /* 处理On/Off集群的开关属性 */
          if (device_cb_param->cb_param.set_attr_value_param.cluster_id == ZB_ZCL_CLUSTER_ID_ON_OFF &&
              device_cb_param->cb_param.set_attr_value_param.attr_id == ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID)
          {
            /* data8 == 1 表示开,0 表示关 */
            if (device_cb_param->cb_param.set_attr_value_param.values.data8)
            {
              Log_printf(LogModule_Zigbee_App, Log_INFO, "set ON");
    #ifdef ZB_USE_BUTTONS
              zb_osif_led_on(0);  // 点亮LED0
    #endif
            }
            else
            {
              Log_printf(LogModule_Zigbee_App, Log_INFO, "set OFF");
    #ifdef ZB_USE_BUTTONS
              zb_osif_led_off(0);  // 熄灭LED0
    #endif
            }
          }
          /* 处理Identify集群的识别时间属性 */
          else if (device_cb_param->cb_param.set_attr_value_param.cluster_id == ZB_ZCL_CLUSTER_ID_IDENTIFY &&
                   device_cb_param->cb_param.set_attr_value_param.attr_id == ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID)
          {
            Log_printf(LogModule_Zigbee_App, Log_INFO, "identify time changed to %d (0x%x)",
                       device_cb_param->cb_param.set_attr_value_param.values.data16, device_cb_param->cb_param.set_attr_value_param.values.data16);
          }
          else
          {
            /* MISRA rule 15.7 requires empty 'else' branch. - 其他属性不做处理 */
          }
          break;
    
        default:
          device_cb_param->status = RET_ERROR;  // 不支持的回调返回错误
          break;
      }
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "< test_device_interface_cb %d", device_cb_param->status);
    }
    
    /* 处理诊断数据响应 - 接收设备链路质量信息 */
    static void handle_diag_data_resp(zb_bufid_t buf)
    {
      zb_zdo_get_diag_data_resp_params_t *resp_params;
    
      /* 从缓冲区获取诊断数据响应参数 */
      resp_params = ZB_BUF_GET_PARAM(buf, zb_zdo_get_diag_data_resp_params_t);
    
      ZVUNUSED(resp_params);  // 参数未使用(实际已使用,但编译器提示警告)
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "handle_diag_data_resp, status: %d, addr: 0x%x, lqi: %d, rssi: %d",
                 resp_params->status, resp_params->short_address,
                 resp_params->lqi, resp_params->rssi);  // lqi: 链路质量指标,rssi: 接收信号强度
    
      zb_buf_free(buf);  // 释放缓冲区
    }
    
    /* 发送诊断数据请求 - 请求指定设备的链路质量信息 */
    static void send_diag_data_req(zb_uint16_t short_address)
    {
      zb_zdo_get_diag_data_req_params_t *req;  // 诊断数据请求参数
      zb_bufid_t buf;  // 缓冲区ID
    
      /* 获取输出缓冲区 */
      buf = zb_buf_get_out();
      if (buf != ZB_BUF_INVALID)  // 缓冲区有效
      {
        req = ZB_BUF_GET_PARAM(buf, zb_zdo_get_diag_data_req_params_t);
        ZB_BZERO(req, sizeof(*req));  // 清零请求参数
    
        req->short_address = short_address;  // 设置目标设备短地址
        zb_zdo_get_diag_data_async(buf, handle_diag_data_resp);  // 异步发送诊断数据请求
      }
      else
      {
        Log_printf(LogModule_Zigbee_App, Log_ERROR, "Failed to get a buffer");  // 缓冲区获取失败
      }
    }
    
    /* ZCL特定集群命令处理器 - 处理发送到指定端点的ZCL命令 */
    zb_uint8_t zcl_specific_cluster_cmd_handler(zb_uint8_t param)
    {
      zb_zcl_parsed_hdr_t cmd_info;  // ZCL命令头信息
      zb_uint16_t raw_data_len;      // 原始数据长度
      zb_uint8_t *raw_data_ptr;      // 原始数据指针
      zb_uint8_t *data_before_parse;  // 解析前的数据指针
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "> zcl_specific_cluster_cmd_handler");
    
      /* 保存解析前的数据指针(包含完整ZCL帧) */
      data_before_parse = (zb_uint8_t *)zb_buf_begin(param);
      raw_data_len = zb_buf_len(param);
    
      /* 复制并解析ZCL命令头 */
      ZB_ZCL_COPY_PARSED_HEADER(param, &cmd_info);
    
      /* 从命令头中提取源地址和源端点 */
      g_dst_addr = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).source.u.short_addr;  // 源设备短地址
      g_endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(&cmd_info).src_endpoint;          // 源端点
      g_addr_mode = ZB_APS_ADDR_MODE_16_ENDP_PRESENT;  // 地址模式:16位短地址+端点
    
      ZB_ZCL_DEBUG_DUMP_HEADER(&cmd_info);  // 打印ZCL命令头调试信息
    
      send_diag_data_req(g_dst_addr);  // 请求获取该设备的链路质量信息
    
      // Jiayu add: 数据接收并存储到数组,简化输出
      zb_uint16_t data_len = zb_buf_len(param);
      if (data_len > 0 && data_len <= RX_DATA_BUFFER_SIZE)
      {
        zb_uint8_t *data_ptr = (zb_uint8_t *)zb_buf_begin(param);
    
        // 复制数据到接收缓冲区
        ZB_MEMCPY(rx_data_buffer, data_ptr, data_len);
        rx_data_length = data_len;
        rx_data_valid = ZB_TRUE;
    
        // 简化输出,只打印关键信息
        uartPrintf("[RX] Addr:%04X EP:%d Len:%d\r\n", g_dst_addr, g_endpoint, data_len);
    
        // 如果数据较短,打印完整数据;否则只打印前16字节
        if (data_len <= 32)
        {
          uartPrintf("     ");
          for (zb_uint16_t i = 0; i < data_len; i++)
          {
            uartPrintf("%02X ", rx_data_buffer[i]);
          }
          uartPrintf("\r\n");
        }
      }
    
      /* 检查命令方向:如果是从服务器到客户端(当前设备是服务器)则报错 */
      if (cmd_info.cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_CLI)
      {
        Log_printf(LogModule_Zigbee_App, Log_ERROR, "Unsupported \"from server\" command direction");
      }
    
      Log_printf(LogModule_Zigbee_App, Log_INFO, "< zcl_specific_cluster_cmd_handler");
      return ZB_FALSE;  // 返回FALSE表示不处理该命令(让协议栈默认处理)
    }
    
    /* 重启入网过程 - 在入网失败后延迟重新入网 */
    void restart_commissioning(zb_uint8_t param)
    {
      ZVUNUSED(param);  // 参数未使用
      bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);  // 启动顶层入网(网络导入)
    }
    
    /* Jiayu add: 周期性开启Permit Join - 每60秒开启一次入网窗口 */
    void permit_join_refresh(zb_uint8_t param)
    {
      ZVUNUSED(param);  // 参数未使用
    
      /* 使用ZBOSS API直接设置Permit Join时长为254(永久开启) */
      zb_ret_t ret;
    
      ret = bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
    
      if (ret == RET_OK)
      {
        uartPrintf("[COORD] Permit join OPENED (permanent)\r\n");
      }
      else
      {
        Log_printf(LogModule_Zigbee_App, Log_ERROR, "Failed to start steering");
      }
    
      /* 每60秒刷新一次,确保入网窗口始终开放 */
      ZB_SCHEDULE_APP_ALARM(permit_join_refresh, 0, 60 * ZB_TIME_ONE_SECOND);
    }
    
    /* 按钮按下处理函数 - 当前不做任何操作 */
    void button_press_handler(zb_uint8_t param)
    {
      ZVUNUSED(param);  // 参数未使用
      Log_printf(LogModule_Zigbee_App, Log_INFO, "button is pressed, do nothing");
    }
    
    /* 设置发送功率 - 为所有启用的信道设置指定的发射功率 */
    void set_tx_power(zb_int8_t power)
    {
      zb_uint32_t chanlist = DEFAULT_CHANLIST;  // 获取默认信道列表
      for (zb_uint8_t i = 0; i < 32; i++) {    // 遍历所有信道
        if (chanlist & (1U << i)) {             // 如果该信道已启用
          zb_bufid_t buf = zb_buf_get_out();    // 获取输出缓冲区
          if (!buf)                             // 缓冲区无效
          {
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "no buffer available");
            return;
          }
    
          /* 设置发射功率参数 */
          zb_tx_power_params_t *power_params = (zb_tx_power_params_t *)zb_buf_begin(buf);
          power_params->status = RET_OK;       // 状态:成功
          power_params->page = 0;              // 页号(通常为0)
          power_params->channel = i;           // 信道号
          power_params->tx_power = power;      // 发射功率值(dBm)
          power_params->cb = NULL;             // 回调函数(NULL表示不使用回调)
    
          zb_set_tx_power_async(buf);  // 异步设置发射功率
        }
      }
    }
    
    /* ZBOSS信号处理器 - 处理ZBOSS协议栈的所有事件和信号 */
    void zboss_signal_handler(zb_uint8_t param)
    {
      zb_zdo_app_signal_type_t sig = zb_get_app_signal(param, NULL);  // 获取应用信号类型
    
      if (ZB_GET_APP_SIGNAL_STATUS(param) == 0)  // 信号状态为0表示成功
      {
        switch(sig)
        {
    #ifndef ZB_MACSPLIT_HOST
          /* 跳过启动信号 - ZBOSS协议栈已准备好继续 */
          case ZB_ZDO_SIGNAL_SKIP_STARTUP:
    #else
          /* MAC分离设备启动信号 - 当使用MAC分离模式时 */
          case ZB_MACSPLIT_DEVICE_BOOT:
    #endif /* ZB_MACSPLIT_HOST */
    
    #ifdef TEST_USE_INSTALLCODE
            /* 如果使用安装码,添加到安全模块 */
            zb_secur_ic_str_add(g_ed_addr, g_installcode, NULL);
    #endif
            set_tx_power(DEFAULT_TX_PWR);  // 设置默认发射功率
            zboss_start_continue();       // 继续启动协议栈
            break;
    
          /* 设备首次启动信号或设备重启信号 */
          case ZB_BDB_SIGNAL_DEVICE_FIRST_START:
          case ZB_BDB_SIGNAL_DEVICE_REBOOT:
          {
            zb_nwk_device_type_t device_type = ZB_NWK_DEVICE_TYPE_NONE;
            device_type = zb_get_device_type();  // 获取设备类型(协调器/路由器/终端)
            ZVUNUSED(device_type);  // 未使用(仅用于调试)
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Device (%d) STARTED OK", device_type);
            /* 如果需要执行工厂复位 */
            if (perform_factory_reset)
            {
              Log_printf(LogModule_Zigbee_App, Log_INFO, "Performing a factory reset.");
              zb_bdb_reset_via_local_action(0);  // 执行本地工厂复位
              perform_factory_reset = ZB_FALSE;
            }
            /* 如果是设备重启(非首次启动) */
            else if(ZB_BDB_SIGNAL_DEVICE_REBOOT == sig)
            {
              ZB_SCHEDULE_APP_ALARM_CANCEL(off_network_attention, ZB_ALARM_ANY_PARAM);  // 取消离网警告定时器
              zb_osif_led_off(1);  // 关闭LED1
            }
            set_tx_power(DEFAULT_TX_PWR);  // 设置默认发射功率
            bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);  // 启动顶层入网(网络导入)
    
            /* Jiayu add: 启动Permit Join定时器,每60秒刷新一次 */
            uartPrintf("[COORD] Starting permit join timer (60s interval)\r\n");
            ZB_SCHEDULE_APP_ALARM(permit_join_refresh, 0, 2 * ZB_TIME_ONE_SECOND);  // 2秒后首次开启
    
    #ifdef ZB_USE_BUTTONS
            zb_button_register_handler(0, 0, button_press_handler);  // 注册按钮处理函数
    #endif
            break;
          }
          /* 可以进入睡眠信号 - 低功耗应用使用 */
          case ZB_COMMON_SIGNAL_CAN_SLEEP:
          {
    #ifdef ZB_USE_SLEEP
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Sleeping now");
            zb_sleep_now();  // 进入睡眠模式
    #endif
            break;
          }
          /* 入网成功信号 */
          case ZB_BDB_SIGNAL_STEERING:
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Successful steering, start f&b target");
            zb_bdb_finding_binding_target(ZB_OUTPUT_ENDPOINT);  // 启动查找和绑定目标模式
            ZB_SCHEDULE_APP_ALARM_CANCEL(off_network_attention, ZB_ALARM_ANY_PARAM);  // 取消离网警告
            zb_osif_led_off(1);  // 关闭LED1
    
            // Jiayu add: 入网成功,Permit Join定时器已经在运行,无需额外操作
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Device joined successfully");
            uartPrintf("[COORD] Device joined, permit join timer is running\r\n");
            break;
    
          /* 设备公告信号 - 有新设备加入网络 */
          case ZB_ZDO_SIGNAL_DEVICE_ANNCE://是当有终端设备加入后的相关操作,在这里只输出终端的地址
          {
            zb_zdo_signal_device_annce_params_t *dev_annce_params;  // 设备公告参数
            dev_annce_params = ZB_BUF_GET_PARAM(param, zb_zdo_signal_device_annce_params_t);
            uartPrintf("connection with a new device\r\n");
            uartPrintf("Short Addr: %04X\r\n", dev_annce_params->device_short_addr);  // 设备短地址
            /* 打印设备IEEE地址(64位唯一地址) */
            uartPrintf("IEEE Addr: %02X%02X%02X%02X%02X%02X%02X%02X\r\n",
                       dev_annce_params->ieee_addr[7], dev_annce_params->ieee_addr[6],
                       dev_annce_params->ieee_addr[5], dev_annce_params->ieee_addr[4],
                       dev_annce_params->ieee_addr[3], dev_annce_params->ieee_addr[2],
                       dev_annce_params->ieee_addr[1], dev_annce_params->ieee_addr[0]);
            uartPrintf("Capability: %02X\r\n", dev_annce_params->capability);  // 设备能力(如是否支持睡眠等)
          }
          break;
    
          default:
            // 注释:0x0034 是 ZCL 数据包信号,会由 ZB_AF_SET_ENDPOINT_HANDLER 注册的 handler 处理
            // 0x003B 是常见的内部信号,不需要打印
            // 仅打印非 0x0034 和 0x003B 的未知信号,减少串口输出
            if (sig != 0x0034 && sig != 0x003B)
            {
              Log_printf(LogModule_Zigbee_App, Log_WARNING, "Unknown signal 0x%04X", (zb_uint16_t)sig);
            }
        }
      }
      else  /* 信号状态非0,表示错误 */
      {
        switch(sig)
        {
          /* 设备首次启动失败 - 找不到网络 */
          case ZB_BDB_SIGNAL_DEVICE_FIRST_START:
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "Device can not find any network on start, so try to perform network steering");
            ZB_SCHEDULE_APP_ALARM(restart_commissioning, 0, 10 * ZB_TIME_ONE_SECOND);  // 10秒后重试入网
            break; /* ZB_BDB_SIGNAL_DEVICE_FIRST_START */
    
          /* 生产配置准备信号 */
          case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY:
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Production config is not present or invalid");
            break;
    
          /* 入网失败信号 */
          case ZB_BDB_SIGNAL_STEERING:
            Log_printf(LogModule_Zigbee_App, Log_WARNING, "Steering failed, retrying again in 10 seconds");
            ZB_SCHEDULE_APP_ALARM(restart_commissioning, 0, 10 * ZB_TIME_ONE_SECOND);  // 10秒后重试入网
            break; /* ZB_BDB_SIGNAL_STEERING */
    
          default:
            Log_printf(LogModule_Zigbee_App, Log_INFO, "Device started FAILED status %d sig %d", ZB_GET_APP_SIGNAL_STATUS(param), sig);
        }
      }
    
      /* Free the buffer if it is not used - 释放缓冲区 */
      if (param)
      {
        zb_buf_free(param);
      }
    }
    


    非常抱歉第一次使用ZBOSS进行zigbee开发,给您添麻烦了,非常感谢您的帮助。