理解HA规范主要从ZStack中以下的两个函数进入分析: zcl_event_loop(); zclSampleLight_Init(); 主要理解:程序的执行过程,相关概念术语在协议栈里的表现和实现,各种数据类型、数据集合的定义。 另外需要理解ZCL API的调用,需要明白对API的参数怎么配置。许多命令都是通过调用API来实现对对方节点的控制的。 一、Light节点 1、 首先需要理解协议栈的任务、事件、消息的概念(关系:任务→ 事件 → 消息) 2、 在ZStack协议栈里用户可以在 osalInitTasks() 中添加自己的应用任务,同时需要在tasksArr[]中添加任务事件进入的函数(如:zclSampleLight_event_loop)。 3、 每个任务都有一个任务ID。在用户自定义的应用任务的上一层是ZCL应用支持子层zcl_event_loop。 进入ZCL应用支持子层(ZCL任务),当中有系统事件if ( events & SYS_EVENT_MSG ),在其中的AF收入消息 if( *msgPtr == AF_INCOMING_MSG_CMD ) 里,提取来自AF层的无线接收的原生数据rawAFMsg,并进入消息处理函数 zcl_ProcessMessageMSG( rawAFMsg ); 中进行处理。 rawAFMsg的数据类型为afIncomingMSGPacket_t,进入可以查看其所包含的数据有哪些。 在消息处理函数zcl_ProcessMessageMSG(rawAFMsg );中的 epDesc =afFindEndPointDesc( pkt->endPoint ); 提取设备描述epDesc(若设备描述(端口)不存在或设备不能回应,则return; // Error, ignore the message)。 (接着的 #if defined (INTE_PAN) 是判断网络是否设置成了网络之间的互通,一般很少用到。 ) 获取安全选项options = zclGetClusterOption(pkt->endPoint, pkt->clusterId ); 接下来是根据设备描述和簇ID来发现想要的插件pInPlugin = zclFindPlugin( pkt->clusterId,epDesc->simpleDesc->AppProfId ); (插件pInPlugin的类型为:zclLibPlugin_t;查看可以知道其实就是寻找簇范围内的对应回调函数) 接着的if ( (pInPlugin != NULL ) && !zcl_DefaultRspCmd( inMsg.hdr ) )是对安全选项进行匹配。 之后判断是否为基础类型信息: // Is this a foundation type message if ( !interPanMsg && zcl_ProfileCmd( inMsg.hdr.fc.type ) ) 结果进入的是: else // Not a foundation type message, so it must be specific to the clusterID. 当中的:status =pInPlugin->pfnIncomingHdlr( &inMsg ); 是调用回调函数(例如灯切换的回调函数是:zclSampleLight_OnOffCB();)
二、 switch节点 Switch节点的按键处理函数如下: static void zclSampleSw_HandleKeys( byteshift, byte keys ) { zAddrType_t dstAddr; (void)shift; // Intentionally unreferenced parameter if ( keys & HAL_KEY_SW_1 ) { //Using this as the "Light Switch" #ifdefZCL_ON_OFF zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT,&zclSampleSw_DstAddr, false, 0 ); #endif } ... … } 程序中红色字体的函数为ZCL API,直接调用此API可以实现向灯节点发送开关切换命令。
|
感谢分享