zigbee笔记:十三、议栈单播通信理论相关概念原理

news2024/12/22 17:01:16

一、端点(Endpoint)

        1、端点基础知识

        (1)、它是一个字节编号的(端点编号是0-255),数据接收和发送的基本单元,在模块通信的时候,发送模块必须指定收发双方模块的网络地址和端点。

        (2)、端点要使用必须要和模块里的某个任务挂钩定义。

        首先每一个端点可以看成是一个1给字节数字编号的开有一扇门的房间,数据的最终目标是进入到无线数据包指定的接收方的房间(端点);而获取无线数据的这个相关代码在任务事件处理函数中,而TI协议栈每一个层都有各自的一个任务事件处理函数,所以必须要指定在哪个任务事件处理函数来取这个无线数据包中有用的数据。

        (3)、一个端点只能挂钩在一个任务上,而一个任务可以挂钩多个端点,并且端点对所有的任务是公用的,定义一个少一个。

        理解:一个端点假如可以挂钩在多个任务上,那么接收模块接收到无线数据的时候,同一个端点有多个任务事件处理函数去处理,不合理;一个任务上挂钩多个端点(如6和7挂在应用层任务),发送给协调器模块的6、7端点的数据都会进入到应用层任务事件处理函数里来,仅仅做个判断到底是投递到6号房间还是7号房间就可以了。

        举例:假如我们接收模块定义两个两个端点6和7,并且都挂钩在应用层,那么端点6和7就不能再被其它层定义和挂钩。如果发送方发送一个无线数据到接收模块的6号端点或者7号端点,那么数据都会进入到应用层任务的任务事件处理函数里来,最后再判断是进入到6号端点房间还是7号端点房间。

        2、注册端点

        (1)、在目录APP下的smartHomeApp.c文件文件中,有一个smartHomeApp_Init( byte task_id )函数,定义端点和任务的挂钩的代码就在这里。

         代码的分析:

void smartHomeApp_Init( byte task_id ) //定义10号端点,并与这个模块的应用层任务挂钩
{
   ...
   ...
    // Fill out the endpoint description.
 //指定端点10
    smartHomeApp_epDesc.endPoint = 10;
 //smartHomeApp_TaskID是应用层任务ID,指定挂在哪个任务上
    smartHomeApp_epDesc.task_id = &smartHomeApp_TaskID;
//添加端点描述信息
    smartHomeApp_epDesc.simpleDesc
        = ( SimpleDescriptionFormat_t* )&smartHomeApp_SimpleDesc;
//添加端点描述信息
    smartHomeApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
//调用此函数完成最终的端点注册与挂载
    afRegister( &smartHomeApp_epDesc );
    ...
    ...
}

/*
smartHomeApp_epDesc是一个端点变量,是一个如下结构体类型

typedef struct
{
  byte endPoint;//端点编号
  byte *task_id;  //挂再的任务ID的地址 Pointer to location of the Application task ID.
  SimpleDescriptionFormat_t *simpleDesc;//更加详细的描述这个端点的一些情况
  afNetworkLatencyReq_t latencyReq;//更加详细的描述这个端点的一些情况
} endPointDesc_t;



*/

        (2) 如果同时有两个端点与应用层任务挂钩,那么一旦接收到数据,最后都会到smartHomeApp_MessageMSGCB 函数中(工程名被修改为smartHomeApp),因此我们可以针对不同端点进行区分,将外部来数据处理函数smartHome_MessageMSGCB修改如下:

static void StarryApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
    if(pkt->endPoint==10)//处理由目标端点10进入的数据
    {
      switch ( pkt->clusterId )//簇判断,具体由哪一个簇来接收数据
      {
        case StarryApp_CLUSTERID:
 
        ... ...
          break;
      }
    }
    if(应该接收的目标端点B)
    {
      switch ( pkt->clusterId )
      {
        case StarryApp_CLUSTERID:
 
        ... ...
          break;
      }
    }
    ... ...
}

 二、簇(clusterId)

        如果把端点可以看成是一个1给字节数字编号的开有一扇门的房间,那么簇就是相对于端点房间里的人,是数据的最终接收者,可以有很多个。它为2个字节编号。在射频发送的时候,必须要指定接收模块的簇,发送模块不需要指定。

        结合上一篇(zigbee笔记:十二)实验中的发送代码来看:

        (1)发送模块的代码和接收模块在定义注册的端点是一模一样的。

        (2) 在发送模块里,我们用的数据发送源端点编号也是10,所以我们定义这个端点10也和应用层任务挂钩。原则上,外部一旦给我们的此实验的发送模块(终端模块)的10号端点发来数据,也会进入应用层任务事件处理函数中。虽然我们这个端点仅仅作为发送模块,但是我们要使用10号端点就必须要挂钩定义。(这里定义的端点10既可以当本模块作为发送方时的源端点,也可以当本模块作为接收方时的目标端点。在本实验中作为发送源端点)

        在smartHomeApp_ProcessEvent的射频数据发送函数配置中

char theMessageData[] = "Hello World";

smartHomeApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
smartHomeApp_DstAddr.addr.shortAddr = 0x000;//接收模块的网络地址
smartHomeApp_DstAddr.endPoint = smartHomeApp_ENDPOINT;//接收模块的接收端点号

//smartHomeApp_epDesc  结构体  是一个端点结构体描述符,描述了发送源的端点的信息
AF_DataRequest( &smartHomeApp_DstAddr, &smartHomeApp_epDesc,
                       smartHomeApp_CLUSTERID,//指定接收模块的端点的簇;两个字节描述
                      (byte)osal_strlen( theMessageData ) + 1,  //表示发送字符串的长度
                     //   1, 
                       (byte *)&theMessageData,//发送的字符数组的首地址
                       &smartHomeApp_TransID,//记录我们应用层任务从开始到当前发送的数据包个数(也能表示当前数据包是发送的第几个)
                       AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );

三、抓包信息分析

        1、两个信号帧

        (1)数据信号帧

        (2)应答帧

        2、 信号帧各项标签含义

        (1)其中P.nbr.和Time(us)都是抓包工具自动生成的(和实际数据帧没有关系),P.nbr.表示从捕获开始空气中的第几个数据帧,Time(us)表示两帧之间的间隔时间以及从抓包开启到当前的时间长度

        (2)从Length开始才是数据包携带的信息。其中Length表示当前这个帧一共有多少个字节。

        (3)Dest Address为目标地址,Src Address为源地址(网络地址)。

        (4)Dest Endpoint为目标端点:10;

        (5)Src Endpoint为源端点:10;

        (6)帧末尾的LQI表示当前帧的信号强度是多少,最大为255;FCS表示硬件校验,校验成功为OK,失败为ERR。

        (7)APS Payload域里面的内容就是我们发送模块发送的有效信息,都为16进制表示。

        (8)Cluster Id是簇

        (9)APS Counter表示当前发送模块发送的第几个数据包(数据帧)

        (10)APS Profile Id在端点描述符里有提到。

四、手动实验验证理论

       1、 实验内容

        终端发送模块上使用端点11,挂载在应用层任务上。终端发送模块两个按钮KEY1和KEY2,实现以下功能:

        (1)终端发送模块按下KEY1给协调器接收模块发送字符 '1' ,目标端点为7,簇点0x0001,协调器的LED1灯状态翻转;再次按下KEY1给协调器接收模块发送字符 '2' ,目标端点为7,簇点0x0002,协调器的LED2灯状态翻转。

        (2)终端发送模块按下KEY2给协调器接收模块发送字符 '3' ,目标端点为8,簇点0x0001,协调器的LED3灯状态翻转;

        (3)终端发送模块按下KEY1和KEY1,自身的LED1状态翻转一次,以示指示。

        2 、终端发送模块配置

        (1)开发板原理图

        (2)定义11号端点并与应用层任务挂钩注册。

        在工程目录APP下的smartHome.c文件中的smartHomeApp_Init函数对应位置,修改端点注册的代码,如下图。

void smartHomeApp_Init( byte task_id )
{
    ...
    // Fill out the endpoint description.
    
    smartHomeApp_epDesc.endPoint = 11;//指定端点号
    smartHomeApp_epDesc.task_id = &smartHomeApp_TaskID;//指定绑定的应用层任务
    smartHomeApp_epDesc.simpleDesc
        = ( SimpleDescriptionFormat_t* )&smartHomeApp_SimpleDesc;//采用默认值
    smartHomeApp_epDesc.latencyReq = noLatencyReqs;//采用默认值
    // Register the endpoint description with the AF
    afRegister( &smartHomeApp_epDesc );
    ...
}

        (3)添加按键KEY1和KEY2 初始化函数和中断函数(编写自己的外部中断函数,注意统一要注释自带的中断函数定义声明)

#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR( void )
{
 
    if( P0IFG & 0x02 )           //按键中断
    {
        osal_start_timerEx( smartHomeApp_TaskID, smartHomeApp_ZFM_EVT, 20 );
        //smartHomeApp_ZFM_EVT  为自行定义的一个应用任务的事件
    
    }
    P0IFG = 0;   //清除中断标志
    P0IF = 0;     //清除中断标志
}

#pragma vector = P2INT_VECTOR
__interrupt void P2_ISR( void )
{
 
    if( P2IFG & 0x01 )           //按键中断
    {
        osal_start_timerEx( smartHomeApp_TaskID, smartHomeApp_ZFM_EVT, 20 );
        
    
    }
    P2IFG = 0;   //清除中断标志
    P2IF = 0;     //清除中断标志
}

         (3)在应用层处理函数中的自定义事件添加处理内容(发送内容)

...
if( events & smartHomeApp_ZFM_EVT )
    {
        static unsigned char isTwice = 1;
        if( Btn1 == 0 )
        {
            if( isTwice )
            {
                char theMessageData[] = {'1'};
                smartHomeApp_DstAddr.addrMode = ( afAddrMode_t )Addr16Bit;
                smartHomeApp_DstAddr.addr.shortAddr = 0x000;
                smartHomeApp_DstAddr.endPoint = 7;
                AF_DataRequest( &smartHomeApp_DstAddr, &smartHomeApp_epDesc,
                                0x0001,
                                // (byte)osal_strlen( theMessageData ) + 1,  //表示发送字节个数
                                1,
                                ( byte* )&theMessageData, //发送的数组的首地址
                                &smartHomeApp_TransID,
                                AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
                LED1 = ~LED1;
            }
            else
            {
                char theMessageData[] = {'2'};
                smartHomeApp_DstAddr.addrMode = ( afAddrMode_t )Addr16Bit;
                smartHomeApp_DstAddr.addr.shortAddr = 0x000;
                smartHomeApp_DstAddr.endPoint = 7;
                AF_DataRequest( &smartHomeApp_DstAddr, &smartHomeApp_epDesc,
                                0x0002,
                                // (byte)osal_strlen( theMessageData ) + 1,  //表示发送字节个数
                                1,
                                ( byte* )&theMessageData, //发送的数组的首地址
                                &smartHomeApp_TransID,
                                AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
                LED1 = ~LED1;
            }
            if( isTwice == 1 )
            {
                isTwice = 0;
            }
            else
            {
                isTwice = 1;
            }
        }
        if( Btn2 == 0 )
        {
            char theMessageData[] = {'3'};
            smartHomeApp_DstAddr.addrMode = ( afAddrMode_t )Addr16Bit;
            smartHomeApp_DstAddr.addr.shortAddr = 0x000;
            smartHomeApp_DstAddr.endPoint = 8;
            AF_DataRequest( &smartHomeApp_DstAddr, &smartHomeApp_epDesc,
                            0x0001,
                            // (byte)osal_strlen( theMessageData ) + 1,  //表示发送字节个数
                            1,
                            ( byte* )&theMessageData, //发送的数组的首地址
                            &smartHomeApp_TransID,
                            AF_DISCV_ROUTE, AF_DEFAULT_RADIUS );
            LED1 = ~LED1;
        }
        return ( events ^ smartHomeApp_ZFM_EVT );
    }
...

        3 、协调器接收模块配置

        (1)定义7、8号端点并与应用层任务挂钩注册。

        在工程目录APP下的smartHome.c文件中的smartHomeApp_Init函数对应位置,修改端点注册的代码,如下图。

        (2)添加LED1~3初始化函数、串口0 初始化函数

        LED1~3初始化函数  

        串口0 初始化函数

        在 ZMain目录下的ZMain.c文件中的main函数中,对应位置添加初始化函数

 

        (3)在工程目录APP下的smartHome.c文件中的smartHomeApp_MessageMSGCB函数中,修改添加数据接收函数。

void smartHomeApp_MessageMSGCB( afIncomingMSGPacket_t* pkt )
{
  //外来数据包投入到7号端点
  if(pkt->endPoint==7){
    //判断接收簇
    switch( pkt->clusterId ){
      
    case  0x0001:
      InformationSend(pkt->cmd.Data,pkt->cmd.DataLength);
      LED1=~LED1;
      break;
      case  0x0002:
        InformationSend(pkt->cmd.Data,pkt->cmd.DataLength);//串口0发送函数,自行编写
        LED2=~LED2;
      break;
      
    default:
      break;
    
    }
    
  }
     //外来数据包投入到8号端点
  if(pkt->endPoint==8){
     //判断接收簇
    switch( pkt->clusterId ){
      
    case  0x0001:
      InformationSend(pkt->cmd.Data,pkt->cmd.DataLength);//串口0发送函数,自行编写
      LED3=~LED3;
      break;
      
      
    default:
      break;
    
    }
    
  }
  
  
//    switch( pkt->clusterId )
//    {
//        case smartHomeApp_CLUSTERID:
//            // "the" message
//#if defined( LCD_SUPPORTED )
//            HalLcdWriteScreen( ( char* )pkt->cmd.Data, "rcvd" );
//#elif defined( WIN32 )
//            WPRINTSTR( pkt->cmd.Data );
// #endif           
//            InformationSend(pkt->cmd.Data,pkt->cmd.DataLength);
//            LED2 = ~LED2;
//            break;
//    }
}

        参考链接

        (1)lesson 8下 Zigbee单播通信理论相关概念原理(端点、簇)_zigbee 簇-CSDN博客

        (2)胜达zigbee lesson8中协议栈单播通信理论相关概念原理_哔哩哔哩_bilibili

        (3)lesson8下自动动手全面实验验证理论_转_哔哩哔哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2044247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GNOME 如何关闭显示输出 ? (wayland / mutter / KMS / DRI) (源代码阅读)

GNOME 设置里面有这样一个功能: 鼠标/键盘无操作几分钟之后, 自动关闭显示输出, 具体表现为显示器黑屏, 进入休眠模式. 按一下鼠标/键盘, 恢复显示. 这是一个很常见的功能, 但是需要等待一段时间. 于是窝就想, 可不可以用一种简单的方式, 比如 执行一条命令, 随时随地直接进入这…

routine.hpp路由匹配模块

一.路由匹配模块介绍 路由匹配模块可以验证路由键(routing key)和绑定键(binding key)的合法性,并根据不同的交换机类型(如Direct、Fanout和Topic)进行消息的路由匹配。 二.Routine类的实现 设…

从〇 搭建PO模式的Web UI自动化测试框架

Page Object模式简介 核心思想 将页面元素和操作行为封装在独立的类中,形成页面对象(Page Object)。每个页面对象代表应用程序中的一个特定页面或组件。 优点: 代码复用性高 页面对象可以在多个测试用例中复用。 易于维护 …

10 个最佳 Java NLP 库和工具

发现用于高级自然语言处理的最佳 Java NLP 库。通过文本分析、情感分析等增强您的应用程序。 Java 已成为一种功能强大且用途广泛的编程语言,广泛用于开发跨领域的各种应用程序。其丰富的库和工具生态系统使其成为各种任务的理想选择,包括自然语言处理 (…

NVDLA专题1:NVDLA框架介绍

NVDLA概述 深度学习的计算部分主要可以分为4部分:卷积、激活单元(神经元)、池化和归一化。由于每个运算模块都有比较独特的共享特征,因此非常适合给每个模块设计一个对应的特殊硬件实现:内存访问模式容易预测并且很容…

超高速NVME FPGA存储卡记录

板卡概述 XNM-KU-M4 是一款基于KU115 的高速存储模块。 该模块基于NVME固态硬盘,主要用于高速实时数据流的存储和回放,主要用于雷达、通信、电子、卫星等领域,包括高速ADC数据采样实时记录、DAC数据回放、基于光纤或者Rapid IO的高速数据记录…

SOLIDWORKS 2024:开启创新设计新篇章

随着2024年的到来,SOLIDWORKS也迎来了全新的篇章——SOLIDWORKS 2024。这款由Dassault Systmes开发的三维CAD软件,一直以其强大的功能和易用性引领着工程设计领域的潮流。作为SOLIDWORKS在中国的官方授权代理商,亿达四方致力于为企业提供最新…

一个人活成一个团队:python的django项目devops实战

文章目录 一、需求规划二、代码管理三、创建流水线1、配置流水线源 四、自动测试五、自动构建六、自动部署七、总结 对于开发团队来说提高软件交付的速度和质量是一个永恒的话题,对于个人开发者来说同样如此。作为一个码农,一定会有几个自己私有的小项目…

漏洞扫描的重要性,如何做好漏洞扫描服务

随着互联网技术的飞速发展,网络安全问题已成为不容忽视的重大挑战。其中,系统漏洞威胁作为最常见且严重的安全危险之一,对组织和个人的信息资产构成了巨大威胁。下面我们就来了解下漏洞扫描的好处、漏洞扫描的操作方法以及如何做好网络安全。…

【学习笔记】A2X通信的协议(九)- 广播远程ID(BRID)

3GPP TS 24.577 V18.1.0的技术规范,主要定义了5G系统中A2X通信的协议方面,特别是在PC5接口和Uu接口上的A2X服务。以下是文件的核心内容分析: 7. 广播远程ID(BRID) 7.1 概述 本条款描述了以下程序: 在用…

复现、并改进open-mmlab的mmpose详细细节

复现open-mmlab的mmpose详细细节 1.配置环境2.数据处理3.训练4.改进mmpose4.1 快速调试技巧4.2 快速定位4.3 改进backbone4.3.1 使用说明4.3.2 改进案例4.3.2.1 复现mmpose原配置文件4.3.2.2 复现开源项目4.3.2.3 修改配置文件4.3.2.4 修改新模型 4.4 添加auxiliary_head4.4.1 …

Python OpenCV 影像处理:读取、显示、储存影片

► 前言 本篇将介绍使用OpenCV Python撷取网路摄影机(webcam)的即时画面影像处理与显示,以及透过读取、显示和储存硬盘中的影片档案来实现影片操作。这将帮助大家了解如何使用OpenCV在影片上进行各种操作。 ► OpenCV Python撷取网路摄影机 OpenCV首先建立了一个…

【计算机网络】TCP实战

其实有了UDP的基础,TCP不管怎么说学习起来都还是比较舒服的,至少是比直接就学习TCP的感觉好。 这篇文章最多就是介绍一下起手式,如果想带业务的话和UDP那篇是完全一样的,就不进行演示了。 总的来说还是很简单的。 目录 Echo服务端…

魔方远程时时获取短信内容APP 前端Vue 后端Ruoyi框架(含搭建教程)

前端Vue 后端Ruoyi框架 APP原生JAVA 全兼容至Android14(鸿蒙 澎湃等等) 前后端功能: ①后端可查看用户在线状态(归属地IP) ②发送短信(自定义输入收信号码以及短信内容,带发送记录) ③短信内容分类清晰(接收时间、上传时间等等) ④前后端分离以及A…

Doris与StarRocks

目录 Doris Doris 架构 存储引擎 查询引擎 索引结构 存储模型 物化视图 使用场景 StarRocks 架构设计 架构选择 存算一体 节点 FE BE 存算分离 节点 存储 缓存 适用场景 OLAP 多维分析 实时数据仓库 高并发查询 统一分析 Doris和StarRocks对比 大规模…

Vue3中组件的多种写法

SFC单文件组件,一个vue写一个组件 使用 defineComponent h函数 去进行组件编写 使用 defineComponent JSX/TSX 去进行组件编写 需要安装插件pnpm i vitejs/plugin-vue-jsx -D 引入 配置 使用组件

Android的OkHttp使用和原理

前言 OkHttp的出现代替了HttpUrlConnection,被谷歌官方收纳为底层的网络框架。特点如下: 支持HTTP/2框架下的socket复用通过连接池减少连接的延时使用GZIP进行数据压缩使用缓存技术避免重复请求 当网络出现问题时,OkHttp会静默重新恢复连接…

uniapp组件使用

uni-popup 默认z-index是99 https://uniapp.dcloud.net.cn/component/uniui/uni-popup.html#uni-popup-%E5%BC%B9%E5%87%BA%E5%B1%82 uni-icons uniapp自带图标&#xff1a;https://hellouniapp.dcloud.net.cn/pages/extUI/icons/icons <uni-icons type"left"…

基于JAVA的在线教育系统设计与实现,源码、部署+讲解

摘 要 随着信息化的日益发展&#xff0c;互联网信息技术的发展日新月异。互联网在线教育模式也在不断的被革新。从传统的线下辅导授课&#xff0c;转变成现在的线上教育遍地开花。线上教育已经犹如雨后春笋一般冒芽而出&#xff0c;这为我们的生活带来了许多变动。 基于网络…

江协科技STM32学习笔记(第12章 PWR电源控制)

第12章 PWR电源控制 12.1 PWR电源控制 12.1.1 PWR简介 芯片在3种低功耗模式下&#xff0c;是没法直接再下载程序的。这是因为芯片在睡眠&#xff0c;不会关注调试端口了。解决办法就是&#xff1a;1.按住复位键不动&#xff1b;2.点下载按钮&#xff1b;3.及时从开复位键。这…