目录

理清思路

基本理清了所有流程,文杰观察的直接现象是多功能传感器(ZigBee End-Device,以下简称ZED)通过小米86盒开关 路由设备(ZigBee Router,以下简称ZR)关联加入网络很容易脱离网络。

首先,需要理清的ZR在IEEE-802.15.4 规定为RFD (精简功能设备),精剪功能主要在不能中继数据,作为树状网络拓扑的终端存在,同时受限于功耗,通常会选择大部分时间休眠以节约功耗。为了保证设备休眠能够正常接收数据,所以接收数据的时候选择间接交易,也就是父节点不直接向终端设备发送数据,是唤醒后的终端设备主动去轮询父节点字节是否有数据需要接收。所以其必须依赖父节点完成正常的通信业务,

通常地,如果ZED多次才能够父亲轮询数据失败,机会考虑其成为孤儿并且考虑重新加入网络,基于此特性在TI 协议栈被 描述为可移动设备(Portable Devices)。

不允许加入

下面是同父节点失去联系的ZED重新重新加入网络的流程,不幸的是,没有成功加入网络,还直接被踢出了网络。

  1. 我成为孤儿了;
  2. 小米插座:让我作为你的父亲吧,给你取个新的名字;
  3. 我有新名字了;
  4. 小米插座:这事我还得通信下信任中心(Trust Center)登记下,让他给你一个通信密钥;
  5. 信任中心:这事我不同意,现阶段我们不允许任何人加入,@小米插座 剔除了他;
  6. 好的,离开网络;

设备离线,发起了rejoin,通过关联小米路由加入网络,小米路由发起请求密钥(update device)并且通过如下的Status 标记为Unsecured Rejoin

成功收到如上update device 命令后,ZStack根据实际的Status 选择不同的处理,如果是Secure join ,理论上不会任何操作。

//ZDSecmgr.c  Function.ZDSecMgrUpdateDeviceInd  Line.1754
void ZDSecMgrUpdateDeviceInd( ZDO_UpdateDeviceInd_t* ind  {
  ZDSecMgrDevice_t device;
  // Trust Center should identify the type of JOIN/REJOIN and
  // Transport the NWK key accordingly, it will only be transported for:
  //              APSME_UD_STANDARD_UNSECURED_JOIN
  //   OR         APSME_UD_STANDARD_TRUST_CENTER_REJOIN
  if ( ind->status != APSME_UD_DEVICE_LEFT )  {
    if ( ind->status == APSME_UD_STANDARD_SECURED_REJOIN) {
      device.secure = TRUE;
    }
    ZDSecMgrDeviceJoin( &device );
  }
}

但是状态如果是Unsecure join 这里会直接交由信任中心(Trust Center) 处理。信任中心会根据ZDSecMgrDeviceValidate 的结果来决定添加设备(ZDSecMgrAddrStore)并且交换传输密钥 (ZDSecMgrSendNwkKey)还是直接踢出设备(ZDSecMgrDeviceRemove)。

//ZDSecmgr.c  Function.ZDSecMgrDeviceJoin  Line.1112
ZStatus_t ZDSecMgrDeviceJoin( ZDSecMgrDevice_t* device ) {
  ZStatus_t status = ZSuccess;
  uint16    ami;

  // attempt to validate device that joined/rejoined without security
  if ( device->secure == FALSE )  {
    status = ZDSecMgrDeviceValidate( device );
  }

  if ( status == ZSuccess ) {
    // Add the device to the address manager
    ZDSecMgrAddrStore( device->nwkAddr, device->extAddr, &ami );
    //send the nwk key data to the joining device
    status = ZDSecMgrSendNwkKey( device );
    }
  }
  if ( status != ZSuccess ) {
    // not allowed or transport key failed, remove the device
    ZDSecMgrDeviceRemove( device );
  }

ZDSecMgrDeviceValidate 是通过ZDSecMgrPermitJoiningEnabledzgSecurePermitJoin,使能位决定的。

//ZDSecMgr.c Function.ZDSecMgrDeviceValidate Line.1087
ZStatus_t ZDSecMgrDeviceValidate( ZDSecMgrDevice_t* device ) {
  ZStatus_t status;

  if ( ZDSecMgrPermitJoiningEnabled == TRUE ) {
      // For test purpose, turning off the zgSecurePermitJoin flag will force
      // the trust center to reject any newly joining devices by sending
      // Remove-device to the parents.
      if ( zgSecurePermitJoin == FALSE )  {
        status = ZNwkUnknownDevice;
      }
  } else {
    status = ZNwkUnknownDevice;
  }
  return status;
}

而控制如上ZDSecMgrPermitJoiningEnabledzgSecurePermitJoin 正是我们的Web界面控制的允许入网。

//zcl_samplesw Function.PermitJoin  Line885  
NLME_PermitJoiningRequest(60);
ZDP_MgmtPermitJoinReq( &MXJ_GbAddr, 60, TRUE, TRUE);

PermitJoin是如何控制TC的工作状态

//zcl_samplesw Function.PermitJoin  Line885  
NLME_PermitJoiningRequest(60);
ZDP_MgmtPermitJoinReq( &MXJ_GbAddr, 60, TRUE, TRUE);

先说结论,如上的Web页面控制的允许入网 功能对应的代码其实是控制了三个功能;

对于第三点,是如何影响到信任中心(Trust Center)功能使能的。需要继续review代码。

//ZDSecMgr.c Function.ZDSecMgrDeviceValidate Line.1803
void ZDO_ProcessMgmtPermitJoinReq( zdoIncomingMsg_t *inMsg ) {
  if ( tcsig == TRUE ) {
      ZDSecMgrPermitJoining( duration );
  }

上面代码显示在收到PermitJoin 后的信任中心选择通过tcsig标志位来处理是否禁止/使能 信任中心的功能。

也就是ZDP_MgmtPermitJoinReq 第三个形参,我们设置为FALSE 即表示通过permit join 命令不控制TC功能。

ZDP_MgmtPermitJoinReq( &MXJ_GbAddr, 60, FALSE, TRUE);

允许加入

如下是为设置信任中心允许设备加入后的抓包,ZR成功加入到网络。

  1. 我成为孤儿了;
  2. 小米插座:让我作为你的父亲吧,给你取个新的名字;
  3. 我有新名字了;
  4. 小米插座:这事我还得通信下信任中心(Trust Center)让他给你一个通信密钥;
  5. 信任中心:允许加入,给你密钥;
  6. 正常通信了;