zoukankan      html  css  js  c++  java
  • 实验九 ZStack 广播通信实验

    实验 ZStack 广播通信实验
    【实验目的】
    1. 了解 ZigBee 广播通信的原理
    2. 掌握在 ZigBee 网络中进行广播通信的方法
    【实验设备】
    1. 装有 IAR 开发工具的 PC 机一台
    2. 实验箱一台
    3. CCDebugger(以及 USB A-B 延长线)一个
    4. USB Mini 延长线一根
    【实验要求】
    1. 编程要求:使用协议栈提供的 API 函数编写应用程序。
    2. 实现功能:送节点向加入到同一 PANID 的 ZigBee 网络的所有节点以广播形式发送消息。
    3. 实验现象:带有广播信息接收功能的节点收到广播信息后连续、快速闪烁节点上的通信指示灯
    LED_D8(并通过串口输出接收到的信息——字符串“Broadcast Message”)。
    【实验原理】
     ZigBee 网络中设置一个广播信息发送节点,若干个广播信息接收节点,发送节点周期性的向所有
    节点广播消息,广播发送节点发送广播消息后通信指示灯会连续闪烁 3 次,允许接收广播消息的节点接收
    到广播信息后,控制节点的通信指示灯 LED_D8 连续闪烁四次。通过观察各个节点的通信指示灯就可以判断是否接收到广播信息。

    实验流程图


    实验步骤

    .打开Tools中的f8wConfig.cfg,将里面DZAPP_CONFIG_PAN_ID=0xFFFF

    的0xFFFF改成其他值;

    PAN_ID改成0x0020

    2. 在工程目录结构树上方的下拉列表中,选择“CoordinatorEB” ,将实验箱的一个节点指定为协调器,编译调试,将代码烧进节点里;

    3. “SAPP_Device.h”文件中,取消“HAS_BROADCASTSEND”的注释,

    4.在工程目录结构树上方的下拉列表中,选择“EndDeviceEB”, 转换实验箱节点,将此节点指定为发送节点,编译调试,将代码烧进节点里;

    5. “SAPP_Device.h”文件中,取消“HAS_BROADCASTSEND”的注释,

    转换实验箱节点,将此节点指定为接收节点,编译调试,将代码烧进节点里,重复几次第5步骤,可多设置接收节点;

    实验现象:可以看到协调器节点和发送端的节点的通信灯同时闪烁,接收器节点的D8连续闪烁4次,表示接收到信息。

    实验感想:

    通过此次实验了解了 ZigBee 广播通信的原理,掌握在 ZigBee 网络中进行广播通信的方法,通过课上教授的知识,学以致用。

    实验完整代码:

    节点定义广播发送和接收

    APP_Base.c
    #include "APP_Base.h"

    #if defined(SAPP_ZSTACK_DEMO)

    #include "hal_led.h"

    // 任务建立实验范例代码

    // 任务处理函数

    uint16 Hello_ProcessEvent(uint8 task_id, uint16 events);

    uint16 Hello_ProcessEvent(uint8 task_id, uint16 events)

    {

        if(events & 0x0001)

        {

            // 控制LED闪烁

            HalLedBlink(HAL_LED_1, 1, 50, 250);

            // 启动定时器, 设置1秒钟后再次触发该任务

            osal_start_timerEx(task_id, 0x0001, 1000);

        }

        // 清除定时器事件标志

        return (events ^ 0x0001);

    }

    #endif

    // 任务列表

    const pTaskEventHandlerFn tasksArr[] = {

        macEventLoop,

        nwk_event_loop,

        Hal_ProcessEvent,

    #if defined( MT_TASK )

        MT_ProcessEvent,

    #endif

        APS_event_loop,

    #if defined ( ZIGBEE_FRAGMENTATION )

        APSF_ProcessEvent,

    #endif

        ZDApp_event_loop,

    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )

        ZDNwkMgr_event_loop,

    #endif

    #if defined(SAPP_ZSTACK)

        sapp_controlEpProcess,

        sapp_functionEpProcess,

    #endif

    #if defined(SAPP_ZSTACK_DEMO)

        // 任务建立实验范例代码

        // 任务列表

        Hello_ProcessEvent,

    #endif

    };

    const uint8 tasksCnt = sizeof(tasksArr)/sizeof(tasksArr[0]);

    // 初始化任务

    void osalInitTasks( void )

    {

        uint8 taskID = 0;

        macTaskInit( taskID++ );

        nwk_init( taskID++ );

        Hal_Init( taskID++ );

    #if defined( MT_TASK )

        MT_TaskInit( taskID++ );

    #endif

        APS_Init( taskID++ );

    #if defined ( ZIGBEE_FRAGMENTATION )

        APSF_Init( taskID++ );

    #endif

        ZDApp_Init( taskID++ );

    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )

        ZDNwkMgr_Init( taskID++ );

    #endif

    #if defined(SAPP_ZSTACK)

        sapp_taskInitProcess();

    #endif

    #if defined(SAPP_ZSTACK_DEMO)

        // 任务建立实验范例代码

        // 启动定时器

        osal_start_timerEx(taskID, 0x0001, 1000);

    #endif

    }

    APP_Base.h

    #ifndef _APP_BASE_H_

    #define _APP_BASE_H_

    #include "ZComDef.h"

    #include "hal_drivers.h"

    #include "OSAL.h"

    #include "ZGlobals.h"

    #include "AF.h"

    #include "aps_groups.h"

    #include "nwk.h"

    #include "APS.h"

    #if defined ( ZIGBEE_FRAGMENTATION )

      #include "aps_frag.h"

    #endif

    #include "MT.h"

    #include "MT_UART.h"

    #if defined( MT_TASK )

    #include "MT_TASK.h"

    #endif

    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )

      #include "ZDNwkMgr.h"

    #endif

    #include "ZDApp.h"

    #include "ZComDef.h"

    #include "OSAL_Tasks.h"

    #include "aps_groups.h"

    #include "OnBoard.h"

    #if defined(SAPP_ZSTACK)

    #include "SAPP_FrameWork.h"

    #endif

    #endif//_APP_BASE_H_

    SAPP_Device.c

    #if defined(SAPP_ZSTACK)

    #include "SAPP_Device.h"

    #include "hal_io.h"

    #include <string.h>

    /**************************************************************/

    /* 传感器列表                                                 */

    /**************************************************************/

    /********************************/

    /* 燃气传感器                   */

    /********************************/

    #if defined(HAS_GAS)

    #define GAS_IO_GROUP        0

    #define GAS_IO_BIT          0

    void sensorGasResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensorGasResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            HalIOSetInput(GAS_IO_GROUP, GAS_IO_BIT, Pull_Down);

            HalIOIntSet(ep->ep, GAS_IO_GROUP, GAS_IO_BIT, IOInt_Rising, 0);

        }

        //IO端口中断触发,中断源检测

        if(type == ResIOInt)

        {

            uint8 GasValue = 1;

            SendData(ep->ep, &GasValue, 0x0000, TRANSFER_ENDPOINT, sizeof(GasValue));

        }

    }

    void sensorGasTimeout(struct ep_info_t *ep);

    void sensorGasTimeout(struct ep_info_t *ep)

    {

        uint8 value = HalIOGetLevel(GAS_IO_GROUP, GAS_IO_BIT);

        SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, sizeof(value));

    }

    #endif

    /********************************/

    /* 温度传感器                   */

    /********************************/

    #if defined(HAS_TEMP) || defined(HAS_HUMM)

    #include "sht10.h"

    static uint16 TempValue = 0;

    #endif

    #if defined(HAS_TEMP)

    void sensorTempResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensorTempResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            SHT10_init(0x01);

        }

    }

    void sensorTempTimeout(struct ep_info_t *ep);

    void sensorTempTimeout(struct ep_info_t *ep)

    {

        unsigned int value = 0;

        unsigned char checksum = 0;

        SHT10_Measure(&value,&checksum, TEMPERATURE);

        TempValue = (value << 2) - 3960;

        SendData(ep->ep, &TempValue, 0x0000, TRANSFER_ENDPOINT, sizeof(TempValue));

    }

    #endif

    /********************************/

    /* 湿度传感器                   */

    /********************************/

    #if defined(HAS_HUMM)

    void sensorHummResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensorHummResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            SHT10_init(0x01);

        }

    }

    void sensorHummTimeout(struct ep_info_t *ep);

    void sensorHummTimeout(struct ep_info_t *ep)

    {

        const float C1 = -4.0f;              // for 8 Bit

        const float C2 = +0.648f;            // for 8 Bit

        const float C3 = -0.0000072f;        // for 8 Bit

        const float T1 = 0.01f;              // for 8 bit

        const float T2 = 0.00128f;           // for 8 bit

        float rh_lin    =   0.0f;                     // rh_lin: Humidity linear

        float rh_true   =   0.0f;                    // rh_true: Temperature compensated humidity

        float t_C   = 0.0f;                        // t_C   : Temperature []

        unsigned int HumiValue = 0;

        unsigned char checksum = 0;

        SHT10_Measure(&HumiValue,&checksum, HUMIDITY);

        rh_lin=C3*HumiValue*HumiValue + C2*HumiValue + C1;     //calc. humidity from ticks to [%RH]

        rh_true=(t_C-25)*(T1+T2*HumiValue)+rh_lin;   //calc. temperature compensated humidity [%RH]

        if(rh_true>100)

            rh_true=100;       //cut if the value is outside of

        if(rh_true<0.1)

            rh_true=0.1f;       //the physical possible range

        HumiValue = (unsigned int)(rh_true * 100);

        SendData(ep->ep, &HumiValue, 0x0000, TRANSFER_ENDPOINT, sizeof(HumiValue));

    }

    #endif

    /********************************/

    /* 雨滴传感器                   */

    /********************************/

    #if defined(HAS_RAIN)

    #define RAIN_IO_GROUP       0

    #define RAIN_IO_BIT         0

    void sensorRainResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensorRainResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            HalIOSetInput(RAIN_IO_GROUP, RAIN_IO_BIT, Pull_None);

            HalIOIntSet(ep->ep, RAIN_IO_GROUP, RAIN_IO_BIT, IOInt_Rising, 0);

        }

        //IO端口中断触发,中断源检测

        if(type == ResIOInt)

        {

            uint8 RainValue = 1;

            SendData(ep->ep, &RainValue, 0x0000, TRANSFER_ENDPOINT, sizeof(RainValue));

        }

    }

    void sensorRainTimeout(struct ep_info_t *ep);

    void sensorRainTimeout(struct ep_info_t *ep)

    {

        uint8 value = HalIOGetLevel(RAIN_IO_GROUP, RAIN_IO_BIT);

        SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, sizeof(value));

    }

    #endif

    /********************************/

    /* 火焰传感器                   */

    /********************************/

    #if defined(HAS_FIRE)

    #define FIRE_IO_GROUP       0

    #define FIRE_IO_BIT         0

    void sensorFireResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensorFireResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            HalIOSetInput(FIRE_IO_GROUP, FIRE_IO_BIT, Pull_Down);

            HalIOIntSet(ep->ep, FIRE_IO_GROUP, FIRE_IO_BIT, IOInt_Rising, 0);

        }

        //IO端口中断触发,中断源检测

        if(type == ResIOInt)

        {

            uint8 FireValue = 1;

            SendData(ep->ep, &FireValue, 0x0000, TRANSFER_ENDPOINT, sizeof(FireValue));

        }

    }

    void sensorFireTimeout(struct ep_info_t *ep);

    void sensorFireTimeout(struct ep_info_t *ep)

    {

        uint8 value = HalIOGetLevel(FIRE_IO_GROUP, FIRE_IO_BIT);

        SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, sizeof(value));

    }

    #endif

    /********************************/

    /* 烟雾传感器                   */

    /********************************/

    #if defined(HAS_SMOKE)

    #define SMOKE_IO_GROUP      0

    #define SMOKE_IO_BIT        0

    void sensorSmokeResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensorSmokeResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            HalIOSetInput(SMOKE_IO_GROUP, SMOKE_IO_BIT, Pull_Down);

            HalIOIntSet(ep->ep, SMOKE_IO_GROUP, SMOKE_IO_BIT, IOInt_Rising, 0);

        }

        //IO端口中断触发,中断源检测

        if(type == ResIOInt)

        {

            uint8 SmokeValue = 1;

            SendData(ep->ep, &SmokeValue, 0x0000, TRANSFER_ENDPOINT, sizeof(SmokeValue));

        }

    }

    void sensorSmokeTimeout(struct ep_info_t *ep);

    void sensorSmokeTimeout(struct ep_info_t *ep)

    {

        uint8 value = HalIOGetLevel(SMOKE_IO_GROUP, SMOKE_IO_BIT);

        SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, sizeof(value));

    }

    #endif

    /********************************/

    /* 光照度传感器                 */

    /********************************/

    #if defined(HAS_ILLUM)

    #include "hal_adc.h"

    void sensorILLumTimeout(struct ep_info_t *ep);

    void sensorILLumTimeout(struct ep_info_t *ep)

    {

        uint16 LightValue = 256 - (HalAdcRead(0, HAL_ADC_RESOLUTION_14) >> 3);

        // 将AD值变换为光照度的100倍

        LightValue = LightValue * 39;// * 10000 / 256;

        SendData(ep->ep, &LightValue, 0x0000, TRANSFER_ENDPOINT, sizeof(LightValue));

    }

    #endif

    /********************************/

    /* 安防传感器                   */

    /********************************/

    #if defined(HAS_IRPERS)

    #define SAFTY_IO_GROUP      1

    #define SAFTY_IO_BIT        0

    void sensorIRPersResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensorIRPersResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            HalIOSetInput(SAFTY_IO_GROUP, SAFTY_IO_BIT, Pull_Down);

            HalIOIntSet(ep->ep, SAFTY_IO_GROUP, SAFTY_IO_BIT, IOInt_Rising, 0);

        }

        //IO端口中断触发,中断源检测

        if(type == ResIOInt)

        {

            uint8 IRPersValue = 1;

            SendData(ep->ep, &IRPersValue, 0x0000, TRANSFER_ENDPOINT, sizeof(IRPersValue));

        }

    }

    void sensorIRPersTimeout(struct ep_info_t *ep);

    void sensorIRPersTimeout(struct ep_info_t *ep)

    {

        uint8 value = HalIOGetLevel(SAFTY_IO_GROUP, SAFTY_IO_BIT);

        SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, sizeof(value));

    }

    #endif

    /********************************/

    /* 红外测距传感器               */

    /********************************/

    #if defined(HAS_IRDIST)

    #include "hal_adc.h"

    extern uint16 irDistTab[256];

    void sensorIRDistTimeout(struct ep_info_t *ep);

    void sensorIRDistTimeout(struct ep_info_t *ep)

    {

        uint8 value = HalAdcRead(0, HAL_ADC_RESOLUTION_14) >> 3;

        // 计算距离值value的单位为mm

        uint16 IRDistValue = irDistTab[value];

        SendData(ep->ep, &IRDistValue, 0x0000, TRANSFER_ENDPOINT, sizeof(IRDistValue));

    }

    #endif

    /********************************/

    /* 语音传感器                   */

    /********************************/

    #if defined(HAS_VOICE)

    #include "hal_uart.h"

    static struct ep_info_t *voiceEndPoint = NULL;

    static uint8 LastVoiceData = 0;

    static void sensorVoiceUartProcess( uint8 port, uint8 event );

    static void sensorVoiceUartProcess( uint8 port, uint8 event )

    {

        (void)event;  // Intentionally unreferenced parameter

        while (Hal_UART_RxBufLen(port))

        {

            HalUARTRead(port, &LastVoiceData, 1);

            if(LastVoiceData == 0xAA)

                LastVoiceData = 1;

            else if(LastVoiceData == 0x55)

                LastVoiceData = 0;

            else

                LastVoiceData = -1;

            if(voiceEndPoint != NULL)

                SendData(voiceEndPoint->ep, &LastVoiceData, 0x0000, TRANSFER_ENDPOINT, 1);

        }

    }

    void sensorVoiceNwkStateChange(struct ep_info_t *ep);

    void sensorVoiceNwkStateChange(struct ep_info_t *ep)

    {

        voiceEndPoint = ep;

    }

    void sensorVoiceResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensorVoiceResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            halUARTCfg_t uartConfig;

            voiceEndPoint = ep;

            /* UART Configuration */

            uartConfig.configured           = TRUE;

            uartConfig.baudRate             = HAL_UART_BR_9600;

            uartConfig.flowControl          = FALSE;

            uartConfig.flowControlThreshold = MT_UART_DEFAULT_THRESHOLD;

            uartConfig.rx.maxBufSize        = MT_UART_DEFAULT_MAX_RX_BUFF;

            uartConfig.tx.maxBufSize        = MT_UART_DEFAULT_MAX_TX_BUFF;

            uartConfig.idleTimeout          = MT_UART_DEFAULT_IDLE_TIMEOUT;

            uartConfig.intEnable            = TRUE;

            uartConfig.callBackFunc         = sensorVoiceUartProcess;

            HalUARTOpen(HAL_UART_PORT_1, &uartConfig);

        }

    }

    void sensorVoiceTimeout(struct ep_info_t *ep);

    void sensorVoiceTimeout(struct ep_info_t *ep)

    {

        uint8 nulData = 0;

        SendData(ep->ep, &nulData, 0x0000, TRANSFER_ENDPOINT, 1);

    }

    #endif

    /********************************/

    /* 二进制执行器传感器           */

    /********************************/

    #if defined(HAS_EXECUTEB)

    #define ControlInit()   do { HalIOSetOutput(1,4);HalIOSetOutput(1,5);HalIOSetOutput(1,6);HalIOSetOutput(1,7);Control(0); } while(0)

    #define Control(mask)   do { HalIOSetLevel(1,4,mask&0x01);HalIOSetLevel(1,5,mask&0x02);HalIOSetLevel(1,6,mask&0x04);HalIOSetLevel(1,7,mask&0x08); } while(0)

    void OutputExecuteBResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void OutputExecuteBResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

            ControlInit();

    }

    void outputExecuteB(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg);

    void outputExecuteB(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg)

    {

        //msg->Data[], msg->DataLength, msg->TransSeqNumber

        Control(msg->Data[0]);

        SendData(ep->ep, &msg->Data[0], 0x0000, TRANSFER_ENDPOINT, 1);

    }

    void outputExecuteBTimeout(struct ep_info_t *ep);

    void outputExecuteBTimeout(struct ep_info_t *ep)

    {

        uint8 value = P1 >> 4;

        SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, sizeof(value));

    }

    #endif

    /********************************/

    /* 模拟执行器传感器             */

    /********************************/

    #if defined(HAS_EXECUTEA)

    void outputExecuteA(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg);

    void outputExecuteA(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg)

    {

    }

    #endif

    /********************************/

    /* 遥控器传感器                 */

    /********************************/

    #if defined(HAS_REMOTER)

    #include "IR.h"

    static uint8 lastCode[32];

    static uint8 lastCodeLen = 0;

    void IRSendResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void IRSendResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

            IRSendInit();   // 需要初始化

    }

    void outputRemoter(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg);

    void outputRemoter(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg)

    {

       lastCodeLen = msg->Data[0];

       memcpy(lastCode, &msg->Data[1], lastCodeLen);

       GenIR(&msg->Data[1], IRGuideLen_9ms, (uint8)lastCodeLen);

       SendData(ep->ep, lastCode, 0x0000, TRANSFER_ENDPOINT, lastCodeLen>>3);

    }

    void outputRemoterTimeout(struct ep_info_t *ep);

    void outputRemoterTimeout(struct ep_info_t *ep)

    {

        if(lastCodeLen <= 0)

        {

            uint8 value = 0;

            SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, 1);

        }

        else

            SendData(ep->ep, lastCode, 0x0000, TRANSFER_ENDPOINT, lastCodeLen>>3);

    }

    #endif

    /********************************/

    /* 虚拟功能                     */

    /********************************/

    #if defined(HAS_TESTFUNCTION)

    #define TEST_STRING     "Z-Stack for SAPP"

    static uint8 lastData[119] = TEST_STRING;

    static uint8 lastLen = 0;

    void testFunc_RecvData(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg);

    void testFunc_RecvData(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg)

    {

        lastLen = msg->DataLength;

        memcpy(&lastData[sizeof(TEST_STRING) - 1], msg->Data, lastLen);

        SendData(ep->ep, lastData, 0x0000, TRANSFER_ENDPOINT,

                         lastLen + sizeof(TEST_STRING) - 1);

    }

    void testFunc_TimeOut(struct ep_info_t *ep);

    void testFunc_TimeOut(struct ep_info_t *ep)

    {

        SendData(ep->ep, lastData, 0x0000, TRANSFER_ENDPOINT,

                         lastLen + sizeof(TEST_STRING) - 1);

    }

    #endif

    /********************************/

    /* 广播发送功能                 */

    /********************************/

    #if defined(HAS_BROADCASTSEND)

    #define BROADCAST_STRING     " Broadcast Message "

    void BroadcastSend_TimeOut(struct ep_info_t *ep);

    void BroadcastSend_TimeOut(struct ep_info_t *ep)

    {

        SendData(ep->ep, BROADCAST_STRING, 0XFFFF, TRANSFER_ENDPOINT,

                         sizeof(BROADCAST_STRING) - 1);

        //广播后指示灯 LED_D9 闪烁2次

        HalLedBlink( HAL_LED_2, 2, 50, 100 );

    }

    #endif

    /********************************/

    /* 广播接收功能                 */

    /********************************/

    #if defined(HAS_BROADCASTRECEIVE)

    void BroadcastReceiveData(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg);

    void BroadcastReceiveData(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg)

    {

        //收到广播数据后 LED_D8 连续闪烁4次!

        HalLedBlink( HAL_LED_1, 4, 50, 120 );

        HalUARTWrite(HAL_UART_PORT_0, msg->Data, msg->DataLength);

    }

    #define BROADCAST_STRING     "Broadcast Message"

    void BroadcastSend_TimeOut(struct ep_info_t *ep);

    void BroadcastSend_TimeOut(struct ep_info_t *ep)

    {

        SendData(ep->ep, BROADCAST_STRING, 0X0000, TRANSFER_ENDPOINT,

                         sizeof(BROADCAST_STRING) - 1);

    }

    #endif

    /********************************/

    /* IC卡读卡器                   */

    /********************************/

    #if defined(HAS_125KREADER)

    #include "hal_uart.h"

    #define CARDID_SIZE     5                   // 卡号长度

    static uint8 lastCardId[CARDID_SIZE];       // 用来保存接收到的卡号

    static uint8 cardRecvIdx;                   // 上一次接收到的长度

    static uint32 lastTick;                     // 上一次接收数据的系统时间

    static struct ep_info_t *cardEndPoint;

    static void sensor125kReaderUartProcess( uint8 port, uint8 event );

    static void sensor125kReaderUartProcess( uint8 port, uint8 event )

    {

        (void)event;  // Intentionally unreferenced parameter

        if((lastTick + 100) <= osal_GetSystemClock())

        {                                       // 如果本次接收到的时间距离上次超过了0.1秒

            cardRecvIdx = 0;                    // 则清空计数器,重新接收卡号

        }

        lastTick = osal_GetSystemClock();       // 记录下当前的时间

        while (Hal_UART_RxBufLen(port))

        {

            uint16 restLen = Hal_UART_RxBufLen(port);

            if(restLen > (CARDID_SIZE - cardRecvIdx))

                restLen = CARDID_SIZE - cardRecvIdx;

            HalUARTRead(port, &lastCardId[cardRecvIdx], restLen);

            cardRecvIdx += restLen;

            if(cardRecvIdx >= CARDID_SIZE)      // 如果已经接收完成一个完整的卡号

            {                                   // 则发送给协调器

                SendData(cardEndPoint->ep, lastCardId, 0x0000, TRANSFER_ENDPOINT, CARDID_SIZE);

            }

        }

    }

    void sensor125kReaderResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void sensor125kReaderResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            halUARTCfg_t uartConfig;

            memset(lastCardId, 0, sizeof(lastCardId));

            cardRecvIdx = 0;

            cardEndPoint = ep;

            /* UART Configuration */

            uartConfig.configured           = TRUE;

            uartConfig.baudRate             = HAL_UART_BR_19200;

            uartConfig.flowControl          = FALSE;

            uartConfig.flowControlThreshold = MT_UART_DEFAULT_THRESHOLD;

            uartConfig.rx.maxBufSize        = MT_UART_DEFAULT_MAX_RX_BUFF;

            uartConfig.tx.maxBufSize        = MT_UART_DEFAULT_MAX_TX_BUFF;

            uartConfig.idleTimeout          = MT_UART_DEFAULT_IDLE_TIMEOUT;

            uartConfig.intEnable            = TRUE;

            uartConfig.callBackFunc         = sensor125kReaderUartProcess;

            HalUARTOpen(HAL_UART_PORT_0, &uartConfig);

        }

    }

    void sensor125kReaderTimeout(struct ep_info_t *ep);

    void sensor125kReaderTimeout(struct ep_info_t *ep)

    {

        uint8 nullId[CARDID_SIZE] = { 0x00 };

        SendData(cardEndPoint->ep, nullId, 0x0000, TRANSFER_ENDPOINT, CARDID_SIZE);

    }

    #endif

    /********************************/

    /* 语音播放节点                 */

    /********************************/

    #if defined(HAS_SPEAKER)

    void OutputSpeakerResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void OutputSpeakerResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

            HalUART1HwInit();

    }

    void outputSpeaker(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg);

    void outputSpeaker(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg)

    {

        //msg->Data[], msg->DataLength, msg->TransSeqNumber

        HalUART1HwTxByte(msg->Data[0]);

    //    SendData(ep->ep, &msg->Data[0], 0x0000, TRANSFER_ENDPOINT, 1);

    }

    void outputSpeakerTimeout(struct ep_info_t *ep);

    void outputSpeakerTimeout(struct ep_info_t *ep)

    {

        uint8 value = 0;

        SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, sizeof(value));

    }

    #endif

    /********************************/

    /* 红外接收解码                 */

    /********************************/

    #if defined(HAS_IRDecode)

    #include <hal_irdec.h>

    void IRDecodeResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res);

    void IRDecodeResAvailable(struct ep_info_t *ep, RES_TYPE type, void *res)

    {

        if(type == ResInit)

        {

            IRDecodeT1Init(ep->task_id, ep->ep);

        }

        //定时器1通道0一次红外解码结束,向上传送解码结果

        if(type == ResTimerInt)

        {

            OSALIRDecData_t *irData = (OSALIRDecData_t *)res;

            SendData(ep->ep, irData->irCode, 0x0000, TRANSFER_ENDPOINT, irData->irLen);

        }

    }

    void IRDecodeTimeout(struct ep_info_t *ep);

    void IRDecodeTimeout(struct ep_info_t *ep)

    {

        uint8 value = 0;

        SendData(ep->ep, &value, 0x0000, TRANSFER_ENDPOINT, sizeof(value));

    }

    #endif

    /***************************************************/

    /* 节点功能列表                                    */

    /***************************************************/

    struct ep_info_t funcList[] = {

    #if defined(HAS_GAS)

        {

            // 加入网络,收到数据,超时处理,资源变化

            NULL, NULL, sensorGasTimeout, sensorGasResAvailable,

            { DevGas, 0, 5 },                   // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_TEMP)

        {

            NULL, NULL, sensorTempTimeout, sensorTempResAvailable,

            { DevTemp, 1, 5 },                 // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_HUMM)

        {

            NULL, NULL, sensorHummTimeout, sensorHummResAvailable,

            { DevHumm, 0, 5 },                 // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_ILLUM)

        {

            NULL, NULL, sensorILLumTimeout, NULL,

            { DevILLum, 0, 3 },                // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_RAIN)

        {

            NULL, NULL, sensorRainTimeout, sensorRainResAvailable,

            { DevRain, 0, 5 },                 // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_IRDIST)

        {

            NULL, NULL, sensorIRDistTimeout, NULL,

            { DevIRDist, 0, 3 },               // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_SMOKE)

        {

            NULL, NULL, sensorSmokeTimeout, sensorSmokeResAvailable,

            { DevSmoke, 0, 5 },                 // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_FIRE)

        {

            NULL, NULL, sensorFireTimeout, sensorFireResAvailable,

            { DevFire, 0, 3 },                  // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_IRPERS)

        {

            NULL, NULL, sensorIRPersTimeout, sensorIRPersResAvailable,

            { DevIRPers, 0, 2 },                // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_VOICE)

        {

            sensorVoiceNwkStateChange, NULL, sensorVoiceTimeout, sensorVoiceResAvailable,

            { DevVoice, 0, 5 },                // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_EXECUTEB)

        {

            NULL, outputExecuteB, outputExecuteBTimeout, OutputExecuteBResAvailable,

            { DevExecuteB, 3, 10 },              // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_EXECUTEA)

        {

            NULL, outputExecuteA, NULL, NULL,

            { DevExecuteA, 0, 3 },              // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_REMOTER)

        {

            NULL, outputRemoter, outputRemoterTimeout, IRSendResAvailable,

            { DevRemoter, 0, 3 },              // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_TESTFUNCTION)

        {

            NULL,

            testFunc_RecvData,

            testFunc_TimeOut,

            NULL,

            { DevTest, 0, 3 },

        },

    #endif

    #if defined(HAS_BROADCASTSEND)

        {

            NULL,

            NULL,

            BroadcastSend_TimeOut,

            NULL,

            { DevBroadcastSend, 0, 3 },

        },

    #endif

    #if defined(HAS_BROADCASTRECEIVE)

        {

            NULL,

            BroadcastReceiveData,

            BroadcastSend_TimeOut,

            NULL,

            { DevBroadcastReceive, 0, 30 },

        },

    #endif

    #if defined(HAS_125KREADER)

        {

            NULL, NULL, sensor125kReaderTimeout, sensor125kReaderResAvailable,

            { Dev125kReader, 0, 10 },

        },

    #endif

    #if defined(HAS_SPEAKER)

        {

            NULL, outputSpeaker, outputSpeakerTimeout, OutputSpeakerResAvailable,

            { DevSpeaker, 0, 9 },              // type, id, refresh cycle

        },

    #endif

    #if defined(HAS_IRDecode)

        {

            NULL, NULL, IRDecodeTimeout, IRDecodeResAvailable,

            { DevIRDecode, 0, 5 },              // type, id, refresh cycle

        },

    #endif

    #if defined(ZDO_COORDINATOR)

        {   // 协调器

            CoordinatorNwkStateChangeRoutine,

            CoordinatorIncomingRoutine,

            CoordinatorTimeoutRoutine,

            CoordinatorResAvailableRoutine,

            { DevCoordinator, 0, 0 },

        },

    #elif defined(RTR_NWK)

        {   // 路由器

            RouterNwkStateChangeRoutine,

            RouterIncomingRoutine,

            RouterTimeoutRoutine,

            RouterResAvailableRoutine,

            { DevRouter, 0, 30 },

        },

    #endif

    };

    // 不能修改下面的内容!!!

    const uint8 funcCount = sizeof(funcList) / sizeof(funcList[0]);

    #endif

    SAPP_Device.h

    #ifndef _SAPP_DEVICE_H_

    #define _SAPP_DEVICE_H_

    #include "SAPP_FrameWork.h"

    #ifdef __cplusplus

    extern "C"

    {

    #endif

    // 功能类型值定义

    enum {

        DevTemp = 1,                    // 空气温度

        DevHumm,                        // 空气湿度

        DevILLum,                       // 光照度

        DevRain,                        // 雨滴

        DevIRDist,                      // 红外测距

        DevGas,                         // 燃气

        DevSmoke,                       // 烟雾

        DevFire,                        // 火焰

        DevIRPers,                      // 人体红外

        DevVoice,                       // 语音识别

        DevExecuteB,                    // 开关量输出执行器

        DevExecuteA,                    // 模拟量输出执行器

        DevRemoter,                     // 红外遥控

        Dev125kReader,                  // 125kHz读卡器

        DevSpeaker,                     // 语音报警

        DevTest,                        // 功能测试

        DevBroadcastSend,               // 广播发送

        DevBroadcastReceive,            // 广播接收

        DevIRDecode,                    // 红外遥控解码

        DevMaxNum,

    };

    #if !defined( ZDO_COORDINATOR ) && !defined( RTR_NWK )

    // 节点功能定义

    //#define HAS_GAS                   // 瓦斯传感器

    //#define HAS_TEMP                  // 温度传感器

    //#define HAS_HUMM                  // 湿度传感器

    //#define HAS_RAIN                  // 雨滴传感器

    //#define HAS_FIRE                  // 火焰传感器

    //#define HAS_SMOKE                 // 烟雾传感器

    //#define HAS_ILLUM                 // 光照度传感器

    //#define HAS_IRPERS                // 人体红外传感器

    //#define HAS_IRDIST                // 红外测距传感器

    //#define HAS_VOICE                 // 语音传感器, 修改 HAL_UART_DMA 的定义为2

    //#define HAS_EXECUTEB              // 执行器

    //#define HAS_EXECUTEA              // 模拟执行器(预留扩展)

    //#define HAS_REMOTER               // 红外遥控(预留扩展)

    //#define HAS_TESTFUNCTION          // 虚拟功能

    //#define HAS_BROADCASTSEND         // 广播发送

    //#define HAS_BROADCASTRECEIVE      // 广播接收

    //#define HAS_125KREADER            // 125K电子标签阅读器

    //#define HAS_SPEAKER               // 语音报警器

    //#define HAS_IRDecode              // 红外解码

    #endif

    #ifdef __cplusplus

    }

    #endif

    #endif//_SAPP_DEVICE_H_

    SAPP_FrameWork.h

    #if defined(SAPP_ZSTACK)

    #include "SAPP_FrameWork.h"

    #include <string.h>

    /*********************************************************************

     * FUNCTIONS

     *********************************************************************/

    static void createEndPoint(struct ep_info_t *epInfo, uint8 *task_id, uint8 ep);

    #if defined(ZDO_COORDINATOR)

    static uint8 uartMsgProcesser(uint8 *msg);

    #endif

    /*********************************************************************

     * Local Variables

     *********************************************************************/

    //uint8 ctrlBuffer[sizeof(TOPOINFO) + sizeof(FUNCTABLE) + FUNC_NUM * sizeof(FUNCINFO)];

    static TOPOINFO topoBuffer = { 0x02 };

    FUNCTABLE *funcTableBuffer;// = (FUNCTABLE *)(&ctrlBuffer[sizeof(TOPOINFO)]);

    static devStates_t curNwkState;

    static uint8 controlTaskId;

    static uint8 functionTaskId;

    static struct ep_info_t controlEndPointInfo;

    static uint8 isUserTimerRunning = 0;

    void sapp_taskInitProcess(void)

    {

     #if defined ( BUILD_ALL_DEVICES )

        // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START

        // We are looking at a jumper (defined in SampleAppHw.c) to be jumpered

        // together - if they are - we will start up a coordinator. Otherwise,

        // the device will start as a router.

        if ( readCoordinatorJumper() )

            zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;

        else

            zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;

    #endif // BUILD_ALL_DEVICES

    #if defined ( HOLD_AUTO_START )

        // HOLD_AUTO_START is a compile option that will surpress ZDApp

        //  from starting the device and wait for the application to

        //  start the device.

        ZDOInitDevice(0);

    #endif

        // 构造功能列表

        funcTableBuffer = createFuncTable(funcCount);

        funcTableBuffer->ft_type = 0x01;

        funcTableBuffer->ft_count = funcCount;

        int i;

        for(i = 0; i < funcCount; i++)

        {

            funcTableBuffer->ft_list[i].type = funcList[i].function.type;

            funcTableBuffer->ft_list[i].id = funcList[i].function.id;

            funcTableBuffer->ft_list[i].cycle = funcList[i].function.cycle;

        }

        controlTaskId = tasksCnt - 2;

        functionTaskId = tasksCnt - 1;

        HalIOInit(functionTaskId);

        createEndPoint(&controlEndPointInfo, &controlTaskId, CONTROL_ENDPOINT);

        for(i = 0; i < funcCount; i++)

        {

            struct ep_info_t *ep = &funcList[i];

            createEndPoint(ep, &functionTaskId, i + 1);

            if(ep->res_available)

              (*ep->res_available)(ep, ResInit, NULL);

        }

    #if defined(ZDO_COORDINATOR)// || defined(RTR_NWK)

    //    RegisterForKeys( SampleApp_TaskID );

        MT_UartRegisterTaskID(controlTaskId);

    #endif

    }

    /*********************************************************************

     * LOCAL FUNCTIONS

     */

    static void createEndPoint(struct ep_info_t *epInfo, uint8 *task_id, uint8 ep)

    {

        static cId_t commonClusterId = SAPP_PERIODIC_CLUSTERID;

        // Fill out the endpoint description.

        epInfo->task_id = *task_id;

        epInfo->ep = ep;

        epInfo->timerTick = epInfo->function.cycle;

        epInfo->userTimer = 0;

        epInfo->simpleDesc.EndPoint = ep;

        epInfo->simpleDesc.AppProfId = SAPP_PROFID;

        epInfo->simpleDesc.AppDeviceId = SAPP_DEVICEID;

        epInfo->simpleDesc.AppDevVer = SAPP_DEVICE_VERSION;

        epInfo->simpleDesc.Reserved = 0;

        epInfo->simpleDesc.AppNumInClusters = 1;

        epInfo->simpleDesc.pAppInClusterList = &commonClusterId;

        epInfo->simpleDesc.AppNumOutClusters = 1;

        epInfo->simpleDesc.pAppOutClusterList = &commonClusterId;

        epInfo->SampleApp_epDesc.endPoint = ep;

        epInfo->SampleApp_epDesc.task_id = task_id;

        epInfo->SampleApp_epDesc.simpleDesc = &epInfo->simpleDesc;

        epInfo->SampleApp_epDesc.latencyReq = noLatencyReqs;

        // Register the endpoint description with the AF

        afRegister(&epInfo->SampleApp_epDesc);

    }

    uint16 sapp_controlEpProcess(uint8 task_id, uint16 events)

    {

        afIncomingMSGPacket_t *MSGpkt;

        if ( events & SYS_EVENT_MSG )

        {

            MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(task_id);

            while ( MSGpkt )

            {

                switch ( MSGpkt->hdr.event )

                {

    #if defined(ZDO_COORDINATOR)

                case CMD_SERIAL_MSG:

    //                SampleApp_UartMessage((uint8 *)MSGpkt);

                    uartMsgProcesser((uint8 *)MSGpkt);

                    HalLedBlink( HAL_LED_1, 2, 50, 90 );

                    break;

    #endif

                    // Received when a messages is received (OTA) for this endpoint

                case AF_INCOMING_MSG_CMD:

                {

                    // TODO: QueryProfile or QueryTopo

                    switch(MSGpkt->clusterId)

                    {

                    case SAPP_PERIODIC_CLUSTERID:

                        switch(MSGpkt->cmd.Data[0])

                        {

                        case 0x01:

                            // CtrlQueryProfile

                            // 获取到数据包的来源地址来当做发送数据的目标

                            SendData(CONTROL_ENDPOINT, funcTableBuffer->ft_data, MSGpkt->srcAddr.addr.shortAddr, MSGpkt->srcAddr.endPoint, sizeof(FUNCTABLE) + funcCount * sizeof(FUNCINFO));

                            break;

                        case 0x02:

                            // CtrlQueryTopo

                            // 获取到数据包的来源地址来当做发送数据的目标

                            SendData(CONTROL_ENDPOINT, (unsigned char *)&topoBuffer, MSGpkt->srcAddr.addr.shortAddr, MSGpkt->srcAddr.endPoint, sizeof(TOPOINFO));

                            break;

                        case 0x03:

                            // CtrlQuerySpecialFunction

                            // cmd.Data[0] = 3, cmd.Data[1] = funcCode, cmd.Data[2] = funcID

                            {

                                uint8 i;

                                for(i = 0; i < funcTableBuffer->ft_count; i++)

                                {

                                    if((funcTableBuffer->ft_list[i].type == MSGpkt->cmd.Data[1])

                                       && (funcTableBuffer->ft_list[i].id == MSGpkt->cmd.Data[2]))

                                    {

                                        // 0x03, EndPoint, rCycle

                                        uint8 specialFunc[3] = { 0x03, i + 1, funcTableBuffer->ft_list[i].cycle };

                                        SendData(CONTROL_ENDPOINT, specialFunc, MSGpkt->srcAddr.addr.shortAddr, MSGpkt->srcAddr.endPoint, sizeof(specialFunc));

                                        break;

                                    }

                                }

                            }

                            break;

                        default:

                            {

                                int i;

                                for(i = 0; i < funcCount; i++)

                                {

                                    struct ep_info_t *ep = &funcList[i];

                                    if(ep->res_available)   (*ep->res_available)(ep, ResControlPkg, MSGpkt);

                                }

                            }

                            break;

                        }

                        HalLedBlink( HAL_LED_2, 1, 50, 250 );

                        break;

                    }

                    break;

                }

                // Received whenever the device changes state in the network

                case ZDO_STATE_CHANGE:

                {

                    devStates_t st = (devStates_t)(MSGpkt->hdr.status);

                    if ( (st == DEV_ZB_COORD)

                            || (st == DEV_ROUTER)

                            || (st == DEV_END_DEVICE) )

                    {

    //                    topoBuffer->type = 0x02;

                        memcpy(topoBuffer.IEEE, NLME_GetExtAddr(), 8);

    #if !defined(ZDO_COORDINATOR)

                        topoBuffer.PAddr = NLME_GetCoordShortAddr();

    #else

                        topoBuffer.PAddr = 0xFFFF;

    #endif

                        osal_memcpy(&topoBuffer.panid, &_NIB.nwkPanId, sizeof(uint16));

                        osal_memcpy(&topoBuffer.channel, &_NIB.nwkLogicalChannel, sizeof(uint8));

                        //向协调器发送拓扑信息

                        SendData(CONTROL_ENDPOINT, (unsigned char *)&topoBuffer, 0x0000, TRANSFER_ENDPOINT, sizeof(TOPOINFO));

                        HalLedBlink( HAL_LED_2, 4, 50, 250 );

                    }

                }

                break;

                default:

                    break;

                }

                // Release the memory

                osal_msg_deallocate( (uint8 *)MSGpkt );

                // Next - if one is available

                MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( task_id );

            }

            // return unprocessed events

            return (events ^ SYS_EVENT_MSG);

        }

        // 定时器时间到, 遍历所有端点看是否有userTimer

        if(events & SAPP_SEND_PERIODIC_MSG_EVT)

        {

            int i;

            uint8 hasUserTimer = 0;

            for(i = 0; i < funcCount; i++)

            {

                struct ep_info_t *ep = &funcList[i];

                if(ep->userTimer && ep->res_available)

                {

                    hasUserTimer = 1;

                    ep->userTimer = ep->userTimer - 1;

                    if(ep->userTimer <= 1)

                    {

                        ep->userTimer = 0;

                        (*ep->res_available)(ep, ResUserTimer, NULL);

                    }

                }

            }

            if(hasUserTimer)

            {

                // 重新启动定时器

                osal_start_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT, 1000);

            }

            else

            {

                isUserTimerRunning = 0;

                osal_stop_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT);

            }

            // return unprocessed events

            return (events ^ SAPP_SEND_PERIODIC_MSG_EVT);

        }

        // Discard unknown events

        return 0;

    }

    uint16 sapp_functionEpProcess(uint8 task_id, uint16 events)

    {

        afIncomingMSGPacket_t *MSGpkt;

        if(events & SYS_EVENT_MSG)

        {

            MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( task_id );

            while ( MSGpkt )

            {

                switch ( MSGpkt->hdr.event )

                {

                // 接收到数据包

                case AF_INCOMING_MSG_CMD:

                    {

                        switch ( MSGpkt->clusterId )

                        {

                        case SAPP_PERIODIC_CLUSTERID:

                            if(MSGpkt->endPoint <= funcCount)

                            {

                                struct ep_info_t *ep = &funcList[MSGpkt->endPoint - 1];

                                if(ep->incoming_data)

                                    (*ep->incoming_data)(ep, MSGpkt->srcAddr.addr.shortAddr, MSGpkt->srcAddr.endPoint, &MSGpkt->cmd);

                            }

                            HalLedBlink( HAL_LED_2, 1, 50, 250 );

                            break;

                        }

                    }

                    break;

                case ZDO_STATE_CHANGE:

                    {

                        curNwkState = (devStates_t)(MSGpkt->hdr.status);

                        if ( (curNwkState == DEV_ZB_COORD)

                                || (curNwkState == DEV_ROUTER)

                                || (curNwkState == DEV_END_DEVICE) )

                        {

                            int i;

                            int hasTimeOut = 0;

                            for(i = 0; i < funcCount; i++)

                            {

                                struct ep_info_t *ep = &funcList[i];

                                if(ep->nwk_stat_change)

                                    (*ep->nwk_stat_change)(ep);

                                // 重置端点计数器

                                if(ep->time_out && ep->function.cycle)

                                {

                                    ep->timerTick = ep->function.cycle;

                                    hasTimeOut = 1;

                                }

                            }

                            if(hasTimeOut)

                            {

                                // 加入网络成功,启动定时器,为各个端点提供定时

                                osal_start_timerEx(task_id,

                                                   SAPP_SEND_PERIODIC_MSG_EVT,

                                                   1000);

                            }

                        }

                        else

                            osal_stop_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT);

                    }

                    break;

                case IOPORT_INT_EVENT:

                  {

                    OSALIOIntData_t* IOIntData;

                    IOIntData =(OSALIOIntData_t*)MSGpkt;

                    if(IOIntData->endPoint <= funcCount)

                    {

                        struct ep_info_t *ep = &funcList[IOIntData->endPoint - 1];

                        if(ep->res_available)

                            (*ep->res_available)(ep, ResIOInt, IOIntData->arg);

                    }

                  }

                  break;

    #if defined(HAL_IRDEC) && (HAL_IRDEC == TRUE)

                case IRDEC_INT_EVENT:   //

                  {

                    OSALIRDecIntData_t* TimerIntData = (OSALIRDecIntData_t*)MSGpkt;

                    if(TimerIntData->endPoint <= funcCount)

                    {

                        struct ep_info_t *ep = &funcList[TimerIntData->endPoint - 1];

                        if(ep->res_available)

                            (*ep->res_available)(ep, ResTimerInt, TimerIntData->data);

                    }

                  }

                  break;

    #endif

                default:

                    break;

                }

                // Release the memory

                osal_msg_deallocate( (uint8 *)MSGpkt );

                // Next - if one is available

                MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( task_id );

            }

            // return unprocessed events

            return (events ^ SYS_EVENT_MSG);

        }

        // 定时器时间到, 遍历所有端点看是否有需要调用time_out

        if(events & SAPP_SEND_PERIODIC_MSG_EVT)

        {

            int i;

            for(i = 0; i < funcCount; i++)

            {

                struct ep_info_t *ep = &funcList[i];

                if(ep->time_out && ep->function.cycle)

                {

                    // 端点需要周期执行

                    ep->timerTick = ep->timerTick - 1;

                    if(ep->timerTick == 0)

                    {

                      // 定时时间到,执行time_out函数

                      (*ep->time_out)(ep);

                      ep->timerTick = ep->function.cycle;

                    }

                }

    #if 0

                if(ep->userTimer && ep->res_available)

                {

                    ep->userTimer = ep->userTimer - 1;

                    if(ep->userTimer <= 1)

                    {

                        (*ep->res_available)(ep, ResUserTimer, NULL);

                        ep->userTimer = 0;

                    }

                }

    #endif

            }

            // 重新启动定时器

            osal_start_timerEx(task_id, SAPP_SEND_PERIODIC_MSG_EVT, 1000);

            // return unprocessed events

            return (events ^ SAPP_SEND_PERIODIC_MSG_EVT);

        }

        // Discard unknown events

        return 0;

    }

    #if defined(ZDO_COORDINATOR)

    static uint8 uartMsgProcesser(uint8 *msg)

    {

        mtOSALSerialData_t *pMsg = (mtOSALSerialData_t *)msg;

        mtUserSerialMsg_t *pMsgBody = (mtUserSerialMsg_t *)pMsg->msg;

        if ( (curNwkState != DEV_ZB_COORD)

                && (curNwkState != DEV_ROUTER)

                && (curNwkState != DEV_END_DEVICE) )

            return 1;

        switch(pMsgBody->cmd)

        {

        case 0x0018:

            {

                switch(pMsgBody->cmdEndPoint)

                {

                case 0xF1:

                    {

                        // 转发数据

                        SendData(TRANSFER_ENDPOINT, pMsgBody->data,

                                 pMsgBody->addr, pMsgBody->endPoint,

                                 pMsgBody->len - 6);

                    }

                    break;

                }

            }

            break;

        }

        return 1;

    }

    #endif

    uint8 SendData(uint8 srcEP, const void *buf, uint16 addr, uint8 dstEP, uint8 Len)

    {

        static uint8 transID = 0;

        afAddrType_t SendDataAddr;

        struct ep_info_t *epInfo;

        if(srcEP <= funcCount)

            epInfo = &funcList[srcEP - 1];

        else

            epInfo = &controlEndPointInfo;

        SendDataAddr.addrMode = (afAddrMode_t)Addr16Bit;         //短地址发送

        SendDataAddr.endPoint = dstEP;

        SendDataAddr.addr.shortAddr = addr;

        if ( AF_DataRequest( &SendDataAddr, //发送的地址和模式

                             // TODO:

                             &epInfo->SampleApp_epDesc,   //终端(比如操作系统中任务ID等)

                             SAPP_PERIODIC_CLUSTERID,//发送串ID

                             Len,

                             (uint8*)buf,

                             &transID,  //信息ID(操作系统参数)

                             AF_DISCV_ROUTE,

                             AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )

        {

            HalLedBlink( HAL_LED_1, 1, 50, 250 );

            return 1;

        }

        else

        {

            return 0;

        }

    }

    void CreateUserTimer(struct ep_info_t *ep, uint8 seconds)

    {

        if(ep == NULL)

            return;

        if(ep->res_available == NULL)

            return;

        ep->userTimer = seconds;

        if(isUserTimerRunning == 0)

        {

            osal_start_timerEx(controlTaskId,

                               SAPP_SEND_PERIODIC_MSG_EVT,

                               1000);

            isUserTimerRunning = 1;

        }

    }

    void DeleteUserTimer(struct ep_info_t *ep)

    {

        if(ep == NULL)

            return;

        ep->userTimer = 0;

    }

    void ModifyRefreshCycle(struct ep_info_t *ep, uint8 seconds)

    {

        if(ep == NULL)

            return;

        if(ep->time_out == NULL)

            return;

        ep->function.cycle = seconds;

        if(ep->timerTick > seconds)

            ep->timerTick = seconds;

    }

    #if ! defined(ZDO_COORDINATOR) && defined(RTR_NWK)

    void RouterTimeoutRoutine(struct ep_info_t *ep)

    {

        SendData(ep->ep, (unsigned char *)&topoBuffer, 0x0000, TRANSFER_ENDPOINT, sizeof(TOPOINFO)); //节点向协调器发送采集数据

    }

    #endif

    #if defined(ZDO_COORDINATOR)

    void CoordinatorIncomingRoutine(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg)

    {

        //msg->Data[], msg->DataLength, msg->TransSeqNumber

        // 转发数据到串口

        if(msg->DataLength > 0)

        {

            mtUserSerialMsg_t *pMsg = osal_mem_alloc(sizeof(mtUserSerialMsg_t) + msg->DataLength - 1);

            pMsg->sop = MT_UART_SOF;

            pMsg->len = msg->DataLength + 6;

            pMsg->cmd = 0x0018;

            pMsg->cmdEndPoint = 0xF1;

            pMsg->addr = addr;

            pMsg->endPoint = endPoint;

            memcpy(pMsg->data, msg->Data, msg->DataLength);

            pMsg->fsc = MT_UartCalcFCS(0, &pMsg->len, 1);

            pMsg->fsc = MT_UartCalcFCS(pMsg->fsc, pMsg->dataBody, pMsg->len);

            HalUARTWrite(HAL_UART_PORT_0, &pMsg->sop, sizeof(mtUserSerialMsg_t) - 2 + msg->DataLength);

            HalUARTWrite(HAL_UART_PORT_0, &pMsg->fsc, 1);

            osal_mem_free(pMsg);

        }

    }

    #endif

    #endif//SAPP_ZSTACK

    SAPP_FrameWork.h

    #ifndef _SAPP_FRAMEWORK_H_

    #define _SAPP_FRAMEWORK_H_

    #include <hal_board.h>

    #include "ZComDef.h"

    #include "hal_drivers.h"

    #include "OSAL.h"

    #include "ZGlobals.h"

    #include "AF.h"

    #include "aps_groups.h"

    #include "nwk.h"

    #include "APS.h"

    #if defined ( ZIGBEE_FRAGMENTATION )

      #include "aps_frag.h"

    #endif

    #include "MT.h"

    #include "MT_UART.h"

    #if defined( MT_TASK )

    #include "MT_TASK.h"

    #endif

    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )

      #include "ZDNwkMgr.h"

    #endif

    #include "ZDApp.h"

    #include "ZComDef.h"

    #include "OSAL_Tasks.h"

    #include "aps_groups.h"

    #include "OnBoard.h"

    /* HAL */

    #include "hal_led.h"

    #include "hal_io.h"

    #include "hal_irdec.h"

    // These constants are only for example and should be changed to the

    // device's needs

    #define CONTROL_ENDPOINT             0xF0

    #define TRANSFER_ENDPOINT            1

    #define SAPP_PROFID                  0x0F08

    #define SAPP_DEVICEID                0x0001

    #define SAPP_DEVICE_VERSION          0

    #define SAPP_PERIODIC_CLUSTERID      1

    // Application Events (OSAL) - These are bit weighted definitions.

    #define SAPP_SEND_PERIODIC_MSG_EVT   0x0001

    enum {

        DevRouter = 240,

        DevCoordinator

    };

    typedef struct topo_info_t {

        uint8 type;

        uint8 IEEE[8];

        uint16 PAddr;

        uint16 panid;

        uint8 channel;

    } TOPOINFO;

    typedef struct func_info_t {

        uint8 type;

        uint8 id;

        uint8 cycle;

    } FUNCINFO;

    typedef union {

        uint8 ft_data[2];

        struct {

            uint8 ft_type;

            uint8 ft_count;

            FUNCINFO ft_list[0];

        } ft_field;

    } FUNCTABLE;

    #define ft_type ft_field.ft_type

    #define ft_count ft_field.ft_count

    #define ft_list ft_field.ft_list

    #define createFuncTable(count)  (FUNCTABLE *)osal_mem_alloc(sizeof(FUNCTABLE) + count * sizeof(FUNCINFO))

    #define destroyFuncTable(ft)    osal_mem_free(ft)

    typedef enum {

        ResMinType = 0,

        ResInit,            // 表示模块初始化

        ResSerial,

        ResUserTimer,

        ResControlPkg,

        ResIOInt,

        ResTimerInt,

        ResMaxType,

    } RES_TYPE;

    struct ep_info_t {

        // 网络状态发生变化时会调用该函数

        void (*nwk_stat_change)(struct ep_info_t *ep);

        // 接收到数据时会调用该函数

        void (*incoming_data)(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg);

        // 周期性调用的函数

        void (*time_out)(struct ep_info_t *ep);

        // 系统资源可用时调用该函数,系统资源指的是:串口接收到数据/中断等等

        void (*res_available)(struct ep_info_t *ep, RES_TYPE type, void *res);

        // NOTE: cycle成员会被用来计数,并周期性调用time_out函数

        struct func_info_t function;

        // 当前端点号

        uint8 ep;

        // 与此端点绑定的任务ID

        uint8 task_id;

        // 递减计数,为0时调用time_out函数,并重载初值=cycle

        uint8 timerTick;

        uint8 userTimer;

        endPointDesc_t SampleApp_epDesc;

        SimpleDescriptionFormat_t simpleDesc;

    };

    extern struct ep_info_t funcList[];

    extern const uint8 funcCount;

    extern void sapp_taskInitProcess(void);

    extern uint16 sapp_controlEpProcess(uint8 task_id, uint16 events);

    extern UINT16 sapp_functionEpProcess( uint8 task_id, uint16 events );

    extern uint8 SendData(uint8 srcEP, const void *buf, uint16 addr, uint8 dstEP, uint8 Len);

    extern void CreateUserTimer(struct ep_info_t *ep, uint8 seconds);

    extern void DeleteUserTimer(struct ep_info_t *ep);

    extern void ModifyRefreshCycle(struct ep_info_t *ep, uint8 seconds);

    #if defined(ZDO_COORDINATOR)

    #define CoordinatorNwkStateChangeRoutine    NULL

    void CoordinatorIncomingRoutine(struct ep_info_t *ep, uint16 addr, uint8 endPoint, afMSGCommandFormat_t *msg);

    #define CoordinatorTimeoutRoutine           NULL

    #define CoordinatorResAvailableRoutine      NULL

    #elif defined(RTR_NWK)

    #define RouterNwkStateChangeRoutine         NULL

    #define  RouterIncomingRoutine              NULL

    void RouterTimeoutRoutine(struct ep_info_t *ep);

    #define RouterResAvailableRoutine           NULL

    #endif

    #endif//_SAPP_FRAMEWORK_H_

  • 相关阅读:
    如何打开指定文件所在的文件夹并选中文件
    不阻止多线程中控件跨线程访问
    .NET使用并行计算 提高执行效率
    关于线程安全中Lock的一些说明
    多线程中调用多参数的方法
    C#把汉字转换成拼音
    跨窗体Invoke时使用匿名方法或者带参方法
    给MP3音乐文件写ID3信息和专辑封面
    用Python作GIS:菜谱篇
    python中对象self的由来
  • 原文地址:https://www.cnblogs.com/LeonNchu/p/10695806.html
Copyright © 2011-2022 走看看