JN516X 如何遥控一盏灯

参考DEMO JN-AN-1218

Zigbee的网络通信功能如此强大,你按下遥控器,就可以改变一盏灯的状态。嗯,可以开关,可以改亮度,可以改颜色,可以定时。。。那么,这个过程是如何实现的呢?

简单说几个概念

PADID

网络ID,是一个16位数字(短地址)或64位数字(长地址),这个很像是路由器的地址或路由名字

NetAddr

网络地址同样分短地址(协调器分配的地址)和长地址(IEEE Addr),有点像互联网的IP地址

Device

设备,Doit

Endpoint

端口号,一个设备或一个节点可以有多个端口号,网络通信时不同设备之间可通过端口号访问,有点像互联网的端口号

Cluster

ON/OFF开关量是一个Cluster,温度是一个Cluster,OTA是一个Cluster。一个Cluster包含有属性和命令。

举个例子

例如,热水壶。
Profile = ZHA
Device = Thermostat_device
端口号=1,实际是APP指定的,与热水壶无直接关系
Cluster:TemperatureMeasurement,Time,Alarm,Poll,Scenes,Thermostat_UI,Basic,Identify,Power… 有很多,但并不是所有的Cluster都是必须的

遥控器如何工作

此处假定已完成组网、绑定,即遥控器按下时对应的灯会收到消息。

按键

按键按下,会触发一个按键事件,MCU会处理这个事件,参考JN-AN-1219,文件中的函数

PRIVATE void vSendDelayedCommands(te_TransitionCode eTransitionCode)
{
    DBG_vPrintf(TRACE_SWITCH_STATE,"\nIn vSendDelayedCommands with TransitionCode = %d -> ",eTransitionCode);
    switch(eTransitionCode)
    {
          case ON_PRESSED:
              DBG_vPrintf(TRACE_SWITCH_STATE," E_CLD_ONOFF_CMD_ON \n");
              vAppOnOff(E_CLD_ONOFF_CMD_ON);
              break;

          case OFF_PRESSED:
              DBG_vPrintf(TRACE_SWITCH_STATE," E_CLD_ONOFF_CMD_OFF \n");
              vAppOnOff(E_CLD_ONOFF_CMD_OFF);
              break;

		  //...

          default :
              break;
    }
    vDQButtonPress();
}

代码中可以看到捕捉到按键后调用了函数vAppOnOff,进而调用函数eCLD_OnOffCommandSend

PUBLIC void vAppOnOff(teCLD_OnOff_Command eCmd) {

    uint8 u8Seq;
    tsZCL_Address sAddress;

    vSetAddress(&sAddress, FALSE, GENERAL_CLUSTER_ID_ONOFF);

    if ((eCmd == E_CLD_ONOFF_CMD_ON) || (eCmd == E_CLD_ONOFF_CMD_OFF) || (eCmd
            == E_CLD_ONOFF_CMD_TOGGLE)) {
        eCLD_OnOffCommandSend(
                u8MyEndpoint,
                sDeviceInfo.sLightInfo[sDeviceInfo.u8Index].u8Ep,
                &sAddress, &u8Seq, eCmd);
    }
}

eCLD_OnOffCommandSend函数会把数据发送出去。
^_^, 按键的很简单吧。

灯泡

接收端整明白了也很简单,MCU底层会对接收到的数据进行处理,此处会修改灯泡上ON/OFF Cluster的状态和相应属性的值,并用事件的方式通知app。
还记得前面提到的Device和端口号的说明吧,其是通过注册函数的方式把不同Cluster的相关接口函数指针添加到协议栈[这里不确定描述是否正确]的,例如JN-AN-1218调用的是eApp_ZLO_RegisterEndpoint函数

eApp_ZLO_RegisterEndpoint(&APP_ZCL_cbEndpointCallback);

重要的是这里的APP_ZCL_cbEndpointCallback函数,底层发送事件后会在此函数中进行处理。

tsZLO_ColourTemperatureLightDevice sLight;
// 代码段 app_zcl_light_task.c line 518
PRIVATE void APP_ZCL_cbEndpointCallback(tsZCL_CallBackEvent *psEvent)
{
    bool_t bUpdateBulb = FALSE;

    switch (psEvent->eEventType)
    {
    // ...
        case E_ZCL_CBET_CLUSTER_CUSTOM:
        DBG_vPrintf(TRACE_ZCL, "\nEP EVT: Custom Cl %04x\n", psEvent->uMessage.sClusterCustomMessage.u16ClusterId);

        switch(psEvent->uMessage.sClusterCustomMessage.u16ClusterId)
        {
            case GENERAL_CLUSTER_ID_ONOFF:
            {

                tsCLD_OnOffCallBackMessage *psCallBackMessage = (tsCLD_OnOffCallBackMessage*)psEvent->uMessage.sClusterCustomMessage.pvCustomData;

                DBG_vPrintf(TRACE_ZCL, " CmdId=%d", psCallBackMessage->u8CommandId);

                switch(psCallBackMessage->u8CommandId)
                {

                    case E_CLD_ONOFF_CMD_OFF_EFFECT:
                        DBG_vPrintf(TRACE_ZCL, "\nOff with effect %d:%d", psCallBackMessage->uMessage.psOffWithEffectRequestPayload->u8EffectId,
                                                                      psCallBackMessage->uMessage.psOffWithEffectRequestPayload->u8EffectVariant);
                        break;

                }
                if (sLight.sIdentifyServerCluster.u16IdentifyTime == 0)
                {
                    /* only update bulb if not identifying */
                    bUpdateBulb = TRUE;
                }


            }
            break;
            // ...
    if (bUpdateBulb)
    {
        vUpdateBulbFromZCL(FALSE);
    }

请注意代码中的bUpdateBulb = TRUE;会触发函数vUpdateBulbFromZCL的执行。

PRIVATE void vUpdateBulbFromZCL(bool_t bResetInterpolation)
{
	vApp_eCLD_ColourControl_GetRGB(&u8Red, &u8Green, &u8Blue);
	。。。
    vRGBLight_SetLevels(sLight.sOnOffServerCluster.bOnOff,
                        sLight.sLevelControlServerCluster.u8CurrentLevel,
                        u8Red,
                        u8Green,
                        u8Blue);
#elif (defined MONO_ON_OFF)
    /*
     * mono on off bulb
     */
    DBG_vPrintf(TRACE_PATH, "\nJP on_off only bulb");
    vSetBulbState( sLight.sOnOffServerCluster.bOnOff);
#endif
    u8StateChangeTick = BULB_SAVE_DELAY_SEC;
}

函数中可以看到调用了vSetBulbState函数,这个函数最终完成灯泡的开关控制。

简单总结

ZCL会对接收的数据进行处理,并通过E_ZCL_CBET_CLUSTER_CUSTOM事件通知app,在回调函数APP_ZCL_cbEndpointCallback被执行的时候处理此时间,并根据ClusterID完成不同的事件处理。即Cluster的Handle函数只改变Cluster的属性值,有Callback函数再来根据Cluster的值来操作硬件。
灯泡与遥控配对过程的闪烁也是通过此方法实现的,区别是在不同的回调函数中调用vSetBulbState函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值