打印

(转)ZCL调用机制

[复制链接]
1022|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
heimaojingzhang|  楼主 | 2018-7-24 09:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ST, ge, Gen, TE, se
1.如果有一个ZCL命令发出,如zclGeneral_SendOnOff_CmdToggle(AT_ZCL_ENDPOINT,&dstAddr,0,1),此函数实际上是zcl_SendCommand函数的宏定义,此函数调用AF_DataRequest函数将信息通过无线发出去。2.在接收端,必须先要对端点描述符和回调函数进行注册,在这里讲一下在初始化函数里调用的一个函数zclGeneral_RegisterCmdCallbacks( AT_ZCL_ENDPOINT, &AT_ZCL_GEN_CmdCallbacks ),即回调注册函数,进入这个函数,有如下代码:
if ( zclGenPluginRegisted == FALSE )
  {
    zcl_registerPlugin( ZCL_CLUSTER_ID_GEN_BASIC,
                        ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC,
                        zclGeneral_HdlIncoming );
......
就是如果没有注册回调函数,则对其进行注册。只要是相应簇注册了回调函数,接收到相关命令就会处理。
3.当AF层收到数据包时,会进入zcl_event_loop处理函数,注意里面这段代码:
if ( *msgPtr == AF_INCOMING_MSG_CMD )
      {
        rawAFMsg = (afIncomingMSGPacket_t *)msgPtr;
        zclProcessMessageMSG( rawAFMsg );
        rawAFMsg = NULL;
      }

如果收到AF层的消息,则调用zclProcessMessageMSG( rawAFMsg ),那这个函数又干了什么呢?不妨先看看函数体,
epDesc = afFindEndPointDesc( pkt->endPoint );首先是获取相应端点信息,
......
  pInPlugin = zclFindPlugin( pkt->clusterId, epDesc->simpleDesc->AppProfId );接着根据簇寻找簇范围内的对应回调函数,

......
else  // Not a foundation type message, so it must be specific to the cluster ID.
  {
    if ( pInPlugin && pInPlugin->pfnIncomingHdlr )
    {
      // The return value of the plugin function will be
      //  ZSuccess - Supported and need default response
      //  ZFailure - Unsupported
      //  ZCL_STATUS_CMD_HAS_RSP - Supported and do not need default rsp
      //  ZCL_STATUS_INVALID_FIELD - Supported, but the incoming msg is wrong formatted
      //  ZCL_STATUS_INVALID_VALUE - Supported, but the request not achievable by the h/w
      //  ZCL_STATUS_SOFTWARE_FAILURE - Supported but ZStack memory allocation fails
      status = pInPlugin->pfnIncomingHdlr( &inMsg );
      if ( status == ZCL_STATUS_CMD_HAS_RSP || ( interPanMsg && status == ZSuccess ) )
      {
        return; // We're done
      }
    }

这里就是调用函数zclGeneral_HdlIncoming,进入
if ( zcl_ClusterCmd( pInMsg->hdr.fc.type ) )
  {
    // Is this a manufacturer specific command?
    if ( pInMsg->hdr.fc.manuSpecific == 0 )
    {
      stat = zclGeneral_HdlInSpecificCommands( pInMsg );
    }
    else
    {
      // We don't support any manufacturer specific command.
      stat = ZFailure;
    }
  }
这里调用到了zclGeneral_HdlInSpecificCommands( pInMsg ),进入
static ZStatus_t zclGeneral_HdlInSpecificCommands( zclIncoming_t *pInMsg )
{
  ZStatus_t stat;
  zclGeneral_AppCallbacks_t *pCBs;

  // make sure endpoint exists
  pCBs = zclGeneral_FindCallbacks( pInMsg->msg->endPoint );
  if ( pCBs == NULL )
    return ( ZFailure );

  switch ( pInMsg->msg->clusterId )
  {
#ifdef ZCL_BASIC
    case ZCL_CLUSTER_ID_GEN_BASIC:
      stat = zclGeneral_ProcessInBasic( pInMsg, pCBs );
      break;
#endif // ZCL_BASIC

#ifdef ZCL_IDENTIFY
    case ZCL_CLUSTER_ID_GEN_IDENTIFY:
      stat = zclGeneral_ProcessInIdentity( pInMsg, pCBs );
      break;
#endif // ZCL_IDENTIFY

#ifdef ZCL_GROUPS
    case ZCL_CLUSTER_ID_GEN_GROUPS:
      if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
        stat = zclGeneral_ProcessInGroupsServer( pInMsg );
      else
        stat = zclGeneral_ProcessInGroupsClient( pInMsg, pCBs );
      break;
#endif // ZCL_GROUPS

#ifdef ZCL_SCENES
    case ZCL_CLUSTER_ID_GEN_SCENES:
      if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
        stat = zclGeneral_ProcessInScenesServer( pInMsg, pCBs );
      else
        stat = zclGeneral_ProcessInScenesClient( pInMsg, pCBs );
      break;
#endif // ZCL_SCENES

#ifdef ZCL_ON_OFF
    case ZCL_CLUSTER_ID_GEN_ON_OFF:
      stat = zclGeneral_ProcessInOnOff( pInMsg, pCBs );
      break;
#endif // ZCL_ON_OFF

#ifdef ZCL_LEVEL_CTRL
    case ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL:
      stat = zclGeneral_ProcessInLevelControl( pInMsg, pCBs );
      break;
#endif // ZCL_LEVEL_CTRL

#ifdef ZCL_ALARMS
    case ZCL_CLUSTER_ID_GEN_ALARMS:
      if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
        stat = zclGeneral_ProcessInAlarmsServer( pInMsg, pCBs );
      else
        stat = zclGeneral_ProcessInAlarmsClient( pInMsg, pCBs );
      break;
#endif // ZCL_ALARMS

#ifdef ZCL_LOCATION
    case ZCL_CLUSTER_ID_GEN_LOCATION:
      if ( zcl_ServerCmd( pInMsg->hdr.fc.direction ) )
        stat = zclGeneral_ProcessInLocationServer( pInMsg, pCBs );
      else
        stat = zclGeneral_ProcessInLocationClient( pInMsg, pCBs );
      break;
#endif // ZCL_LOCATION

    case ZCL_CLUSTER_ID_GEN_POWER_CFG:
    case ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG:
    case ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG:
    case ZCL_CLUSTER_ID_GEN_TIME:
    default:
      stat = ZFailure;
      break;
  }

  return ( stat );
}

到这里,是不是都全明白了,原来所有的簇处理函数都可以在这里完成。


相关帖子

沙发
keaibukelian| | 2018-7-24 10:01 | 只看该作者
我看了你的好几个帖子 也没看明白到底应该怎么添加代码 以什么样的顺序添加

使用特权

评论回复
板凳
dirtwillfly| | 2018-7-24 20:27 | 只看该作者
keaibukelian 发表于 2018-7-24 10:01
我看了你的好几个帖子 也没看明白到底应该怎么添加代码 以什么样的顺序添加 ...

你用的哪个型号?一般在官网提供的协议栈里有例程和使用说明

使用特权

评论回复
地板
keaibukelian| | 2018-7-25 08:12 | 只看该作者
dirtwillfly 发表于 2018-7-24 20:27
你用的哪个型号?一般在官网提供的协议栈里有例程和使用说明

好的 我去看看 非常感谢

使用特权

评论回复
5
renzheshengui| | 2018-7-27 09:36 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

74

主题

3882

帖子

4

粉丝