学习zigbee入门-4

【转】学习zigbee入门-4
Sample Application 分析(下)
      上节介绍了建立一个应用需要做的几个必须的事情,现在就来通过分析 SampleApplication 来具体看看需要做哪些事情,才能建立一个 ZIGBEE 应用功能。当然这里只是做点简单的必须的工作。 
The Sample Application (SampleApp) 
1、 介绍 
        主要是介绍一个应用建立的结构及需要进行的程序流程。 
1.1、程序流程 
1.1.1、初始化 
       首先需要调用初始化函数 SampleApp_Init()。 
SampleApp_TaskID = task_id; 
       初始化应用建立的任务 ID 号,这是工作的ID ,SampleApp必须使用自己设置一个定时器,来为自己制定了一个事件,或者发OS信息本身。上述行动的任何一个可能做是为了分裂一大块加工成较小的连续上执行“时段的,而不是采取单一的时间段太多时间OS”块了。 当一个任务划分成更小的是每次执行一个插槽大块大块的工作,任务是 以进行“合作”行为的OS任务设计的必要条件。
SampleApp_NwkState = DEV_INIT; 
        初始化应用设备的网络状态。怎么说呢,据说是设备类型的改变都要产生一个事件,叫ZDO_STATE_CHANGE,从字面理解为 ZDO 状态发生了改变。所以在设备初始化的时候一定要把它初始化为什么状态都没有。那么它就要去检测整个环境,看是否能重新建立或者加入存在的网络。但是有一种情况例外,就是当 NV_RESTORE 被设置的时候(NV_RESTORE 是把信息保存在非易失存储器中),那么当设备断电或者某种意外重启时,由于网络状态存储在非易失存储器中,那么此时就只需要恢复其网络状态,而不需要重新建立或者加入网络了。我也是从文档中这么理解的,至于为什么只有有待进一步考证。
SampleApp_DstAddr.addrMode = (afAddrMode_t)AddrNotPresent; 
SampleApp_DstAddr.endPoint = 0; 
SampleApp_DstAddr.addr.shortAddr = 0;
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;//--SampleApp EP描述符的EP号
SampleApp_epDesc.task_id = &SampleApp_TaskID;         //-- SampleApp EP描述符的任务ID
SampleApp_epDesc.simpleDesc =                                     //-- SampleApp EP简单描述符
SimpleDeionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs;
//在AF层中登记注册改应用EP
afRegister( &SampleApp_epDesc );
       这里其实是对SampleApp的EP描述符进行初始化.本人理解:要对改应用进行初始化并在AF进行登记,告诉应用层有这么一个EP已经可以使用,那么下层要是有关于改应用的信息或者应用要对下层做哪些操作,就自动得到下层的配合,至于这个配合是怎么回事,那么就需要好好研究下层的协议了。当然在这里肯定是没那时间精力和能力研究了! 其实在这个应用中,只是让AF配合SAMPLEAPP_PROFID / SAMPLEAPP_ENDPOINT这两个应用。那么通过什么呢,通过发送OSAL SYS_EVENT_MSG消息中的(AF_INCOMING_MSG_CMD)事件到SampleApp任务ID。
RegisterForKeys( SampleApp_TaskID );
        登记按键事件到SampleApp_TaskID,在前面已经说了按键这个是唯一的,也就是所有任务中有且只有各任务能登记键盘事件。前面还说了还有一个也是唯一,你猜是什么??
SampleApp_Group.ID = 0x0001;
osal_memcpy( SampleApp_Group.name, “Group1” );
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
        闪灯信息被发送到组1,同样也只有在组1的设备才能接收这个信息。设备启动时已经被设定为组1设备了,但是可以通过按SW1推出/加入组1。这里提到了组的概念,我反正暂时不是很清楚这个是什么东西,在程序中怎么实现也很模糊,但是应用中的好处还是不难想象的,不外呼是就是想控制谁可以事先规定好,还可以动态更改。
        玩过 OS 的人都知道,OS 中最重要的概念不外呼就是任务啦,消息啦,事件啦等。从我们自己平时的工作中也不难想象,如果老板安排了某项工作,那么我们就需要做的,这个工作可能是预先计划好的,也有可能是临时的,那么这些预先定好或者临时的工作可以称之为事件。而老板让您做的方式,比如通过文件下达,或者叫:某某你把 XXX 做下。那么让老板下达的文件内容或者说的内容我这里可以称之为消息。老板给了你不同的消息那么就需要干不同的事件,至于任务可以理解为公司的不同的员工,呵呵!我简直是理解的天才,这样举例居然也能忽悠通过!!!o(∩_∩)o…哈哈 言归正传   在 Z-Stack 中,每个应用任务都通过 SampleApp_ProcessEvent()函数来处理任务中的事件。一旦 SampleApp_TaskID 任务的某个 OSAL 事件发生,那么就可以通过调用 SampleApp_ProcessEvent()函数来处理。在 SampleApp_ProcessEvent()中有一个事件处理循环,循环检测是哪个事件发生。 
if ( events & SYS_EVENT_MSG ) 

MSGpkt = (afIncomingMSGPacket_t*)osal_msg_receive( SampleApp_TaskID ); 
while ( MSGpkt ) 
{ ………………………………….. 
可以看到是通过检测 SYS_EVENT_MSG 是否有事件信息发生。 
   switch ( MSGpkt->hdr.event ) 
这里是判断 SYS_EVENT_MSG 事件类型,不同的 SYS_EVENT_MSG 类型需要不同的处理。 
case KEY_CHANGE: 
SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, 
((keyChange_t *)MSGpkt)->keys ); 
break; 
比如这里判断是否是键盘事件,如果键盘事件就调用键盘处理函数。如果一个 OSAL 任务已经被登记组侧,那么任何键盘事件都将接受一个 KEY_CHANGE 事件信息。可能有如下几种方式得到键盘事件信息 
1)、HAL 检测到键盘按下(中断或者查询检测) 
2)、HAL 的 OSAL 任务检测到一个键盘状态改变调用回叫函数产生 
3)、OSAL 键盘改变回叫函数发送一个 OSAL 系统事件信息(KEY_CHANGE)。 
case AF_DATA_CONFIRM_CMD: 
// The status is of ZStatus_t type [defined in ZComDef.h] 
// The message fields are defined in AF.h 
afDataConfirm = (afDataConfirm_t *)MSGpkt; 
sentEP = afDataConfirm->endpoint; 
sentStatus = afDataConfirm->hdr.status; 
sentTransID = afDataConfirm->transID; 
任何 AF_DataRequest()数据请求函数调用后,都通过 AF_DATA_CONFIRM_CMD 系统事件信息回叫返回成功 Zsuccess。 
case ZDO_STATE_CHANGE: 
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status); 
if ( (SampleApp_NwkState == DEV_ZB_COORD) 
||(SampleApp_NwkState == DEV_ROUTER) 
||(SampleApp_NwkState == DEV_END_DEVICE) ) 

// Update the LCD’s network indicator 
// Start sending "the" message in a regular interval. 
osal_start_timer( SAMPLEAPP_SEND_PERIODIC_MSG_EVT, 
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT ); 

break; 
       这里就是前面介绍的设备状态改变事件处理了。 只要网络状态发生改变,那么通过 ZDO_STATE_CHANGE 事件通知所有的任务。注意:在这个例子中,一旦设备成功加入网络,是通过定时运行的方式运行的。一旦网络状态为加入”JOINED”,那么它可能不需要任何的认为操作就能绑定其他设备,因为设置为自动发现并绑定的。 
// Release the memory 
osal_msg_deallocate( (uint8 *)MSGpkt ); 
释放存储空间。 
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ) 

// Send "the" message 
SampleApp_SendPeriodicMessage(); 
// Setup to send message again 
osal_start_timer( SAMPLEAPP_SEND_PERIODIC_MSG_EVT, 
SAMPLEAPP_SEND_MSG_TIMEOUT ); 
// return unprocessed events 
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT); 

这里检测事件是否为周期发送信息事件。 
在 SampleApp.h 中定义了: 
#define SAMPLEAPP_SEND_PERIODIC_MSG_EVT 0x0001 
在这个应用中,调用了 osal_start_timer()函数来定时产生发送周期信息事件。而定时器的运行是设备一旦加入网络就不停的在运行。从上面可以看到,用函数SampleApp_SendPeriodicMessage()发送周期信息,而用函数 osal_start_timer( SAMPLEAPP_SEND_PERIODIC_MSG_EVT,SAMPLEAPP_SEND_MSG_TIMEOUT )来继续运行定时器定时发送这个周期信息。关于这个 osal_start_timer 可以多了解下,第一个参数 SAMPLEAPP_SEND_PERIODIC_MSG_EVT 是信息时间,也就是事件到了产生一个什么事件。第二各参数 SAMPLEAPP_SEND_MSG_TIMEOUT 是需要定时的时间,这里就是发送周期信息的时间周期。 
1.3、消息流程 
        通过 OSAL 定时器,这个应用定时发送一个周期信息: 
void SampleApp_SendPeriodicMessage( void ) 

afAddrType_t dstAddr; 
dstAddr. addrMode = afAddrBroadcast; 
dstAddr.addr.shortAddr = 0xFFFF; // --广播发送 
dstAddr. endpoint = SAMPLEAPP_ENDPOINT; 
if ( AF_DataRequest( & dstAddr, 
     &SampleApp_epDesc, 
     SAMPLEAPP_PERIODIC_CLUSTERID, 
     (uint8)sampleAppPeriodicCounter++, 
     (uint8 *)&sampleAppPeriodCounter, 
      &SampleApp_TransID, 
      AF_DISCV_ROUTE, 
      AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ) 

// Successfully requested to be sent.----发送成功处理 

else 

// Error occurred in request to send.---发送失败处理 


       在这里调用了 AF_DataRequest()函数用来发送数据。关于发送数据的具体过程这里就不做深入研究,不外乎就是把数据从应用层传到网络层,在传到 MAC,在传到无力层,最后通过 OTA 发送出去。接收数据就是相反的过程了,那么接收之后,在应用层有什么反应呢,最直观的反应就是会发送一个 AF_INCOMING_MSG_CMD 消息事件。 
case AF_INCOMING_MSG_CMD: 
SampleApp_MessageMSGCB( MSGpkt ); 
break; 
这里表示收到某个信息,然后在里面调用了收到信息的信息处理函数 SampleApp_MessageMSGCB( MSGpkt )。 
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) 

switch ( pkt->clusterId ) 

case SAMPLEAPP_PERIODIC_CLUSTERID: 
// Display and increment a counter on the LCD in the periodic space 
break; 
case SAMPLEAPP_FLASH_CLUSTERID: 
flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] ); 
HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); 
break; 


      这里判断了两种信息: 周期信息    闪灯信息 不同的信息就相当于收到了不同的命令,然后根据不同的命令做出了不同的处理。是个会写程序都明白!到这里,我就基本上把这个应用文档看完了,至于理解了多少我迷糊,理解正确了多少我更加迷糊,反正我按照我自己的方式理解了!

       看见这几句话从字面理解为:初始化目标设备地址模式及目标设备EP号和网络地址。从代码可以看出,这些地址或EP均为0。也就是说目标设备为协调者的ZDO,这个意义就很明显了,就是设备建立后可以直接与协调器的ZDO交互信息。

1.2、事件处理 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值