實驗九 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 連續閃爍四次。通過觀察各個節點的通信指示燈就可以判斷是否接收到廣播信息。
實驗流程圖
實驗步驟
1.打開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 "\r\nBroadcast Message\r\n"
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_