ZLL本地局域网通信过程
Interface_srpcserver
-----以灯的状态操作位例
网关与客户端通过Socket API通信,Socket API在socket_server.c中实现,socket_server.c中不只实现了网关与客户端的通信,还对客户端进行了简单的管理,如建立客户端列表[c1] ,因为可能有多个客户端连接到同时连接到同一个网关。Socket API是在LwIP的基础上实现的,这一底层通信过程,我们不需要知道它具体怎么实现(但是在具体开发环节中还是需要大量修改和添加功能),只需要知道怎么用Socket API通信。下面就假设网关已经接收到了来自客户端clientFd的命令信息存在*pBuf指向的内存,后面我将介绍网关如何处理这个命令消息。首先调用下面的函数
void RPSC_ProcessIncoming(uint8_t *pBuf, uint32_t clientFd)
功能:处理客户端发送到网关的命令信息
参数:pBuf –网关收到的命令信息
{
rpcsProcessMsg_t func;
func = rpcsProcessIncoming[(pBuf[SRPC_FUNC_ID] & ~(0x80))];
if (func)
{
(*func)(pBuf, clientFd);
}
else
{
printf("Error: no processing function for CMD 0x%x\n", pBuf[SRPC_FUNC_ID]);
}
}
解释:在interface_srpcserver.c的宏定义中定义了这样一个指针函数类型:
typedef uint8_t (*rpcsProcessMsg_t)(uint8_t *pBuf, uint32_t clientFd);
上述定义如果难懂可参考http://zhidao.baidu.com/question/170422609.html[c2]
第一行定义了一个这样的函数指针
第二行pBuf[SRPC_FUNC_ID] & ~(0x80)。这里的SRPC_FUNC_ID是在interface_srpcserver.h中定义的一个宏定义常数0,pBuf[SRPC_FUNC_ID]就是pBuf的第一个字节的值,由SRPC消息格式可知,第一个字节表示CMD ID,即标识网关收到的是哪个命令,如收到的命令为设置灯的状态,则CMD ID为:RPCS_SET_DEV_STATE 0x82(在nterface_srpcserver.h中已定义),0x82& ~(0x80)得到的结果为2,因此func = rpcsProcessIncoming[2],由字符串数组rpcsProcessIncoming[](在interface_srpcserver.c的开始已定义)可知rpcsProcessIncoming[2]即为RPCS_ZLL_setDeviceState,自此我们完成了命令的解析,也就是说我们知道了客户端要求网关来干什么,接下来的if语句 执行 (*func)(pBuf, clientFd);即为上述定义的指针函数,还是以设置灯的状态的命令为例,前面我们已经得到func即为RPCS_ZLL_setDeviceState,因此这里实际上调用的函数为:
static uint8_t RPCS_ZLL_setDeviceState(uint8_t *pBuf, uint32_t clientFd)
CMD字节 |
命令长度(N) |
数据 |
1字节 |
1字节 |
n个字节 |
RPCS_SET_DEV_STATE消息格式 |
||
字节 |
描述 |
值 |
1 |
命令ID Command ID |
0X82 |
1 |
长度 Length |
13 |
1 |
地址模式 Address Mode |
1 = 组播或2 =单播 1=groupcast OR 2=unicast |
2 |
网络地址 Network Address |
NwkAddr或组ID NwkAddr OR Group ID |
6 |
保留的 Reserved |
0 |
1 |
端点 Endpoint |
设备端点或为0xFF Devices Endpoint OR 0xFF |
2 |
保留的 Reserved |
0 |
1 |
状态 State |
0或1(开启或关闭) 0 or 1 (on or off) |
static uint8_t RPCS_ZLL_setDeviceState(uint8_t *pBuf, uint32_t clientFd)
功能:This function exposes an interface to set a devices on/off attribute.
参数:pBuf - incomin messages 网关接收到的命令消息
static uint8_t RPCS_ZLL_setDeviceState(uint8_t *pBuf, uint32_t clientFd)
//由 SRPC消息格式可知命令的前两个字节标识命令的ID及命令的长度,这两个字节是告诉网关该如何处理这个命令,并不需要转发给主机接口,因此指针+2跳过
addrMode = (afAddrMode_t)*pBuf++;
// 由RPCS_SET_DEV_STATE消息格式可知第三个字节标识 地址模式 Address Mode
dstAddr = BUILD_UINT16(pBuf[0], pBuf[1]);
//网络地址由两个字节构成,BUILD_UINT16是在hal_defs.h中定义的一个函数方法,将两个字节组合成一个16位无符号整数
pBuf += Z_EXTADDR_LEN;//指针跳过保留字节,Z_EXTADDR_LEN即为保留字节的个数
endpoint = *pBuf++; //从命令中提取端点ID
// index past panId
pBuf += 2;// 指针跳过两个保留字节
state = (bool)*pBuf; //从命令中提取 状态
// Set light state on/off
参数已经全部从命令中提取出来了,下面就要通过串口发送参数到CC2531,这是通过下面的函数完成的
zllSocSetState(state, dstAddr, endpoint, addrMode);
return 0;
}
zllSocSetState(state, dstAddr, endpoint, addrMode)在
这个函数实现了通过串口发送数据到CC2531的功能,具体实现在zllSocCmd.c中,这个主机[z4] 接口的问题在此不再叙述
以上网关完成了一个完整的命令处理过程,主要由三个函数完成:
void RPSC_ProcessIncoming(uint8_t *pBuf, uint32_t clientFd) 解析命令
static uint8_t RPCS_ZLL_setDeviceState(uint8_t *pBuf, uint32_t clientFd) 提取参数
zllSocSetState(state, dstAddr, endpoint, addrMode); 主机接口发送命令
上面我是以“设置灯的状态”命令为例的,这个功能不需要网关返回数据给客户端,如果客户端发送的命令为“获取灯的状态”,则网关还需将灯的状态信息返回给客户端。前面的过程与上例相同,
void RPSC_ProcessIncoming(uint8_t *pBuf, uint32_t clientFd) 解析命令
static uint8_t RPCS_ZLL_getDeviceState(uint8_t *pBuf, uint32_t clientFd) 提取参数
zllSocGetState(dstAddr, endpoint, addrMode); 主机接口发送命令
假设通过主机接口获得了“灯的状态”存放在变量state中,接下来我们就要将这个状态数据返回给客户端。这是就需要调用函数:
void RPCS_ZLL_CallBack_getStateRsp(uint8_t state, uint16_t srcAddr, uint8_t endpoint, uint32_t clientFd)
{
uint8_t *pSrpcMessage, *pBuf;
//RpcMessage contains function ID param Data Len and param data
pSrpcMessage = malloc(2+ 4);
pBuf = pSrpcMessage; //使两个指针指向同一内存
//Set func ID in RPCS buffer
*pBuf++ = RPCS_GET_DEV_STATE_RSP;
//param size
*pBuf++ = 4;
*pBuf++ = srcAddr & 0xFF;
*pBuf++ = (srcAddr & 0xFF00) >> 8;
*pBuf++ = endpoint;
*pBuf++ = state & 0xFF;
//Store the device that sent the request, for now send to all clients
srpcSendAll(pSrpcMessage);
//printf("RPCS_ZLL_CallBack_addSceneRsp--\n");
return;
}
上面的函数是按照下面的命令格式来装载数据的,最后调用srpcSendAll(pSrpcMessage); 函数将封装好的信息发送给所有客户端
RPCS_GET_DEV_STATE_RSP消息格式 |
||
字节 |
描述 |
值 |
1 |
命令ID Command ID |
0X07 |
1 |
长度 Length |
0x4 |
2 |
网络地址 Network Address |
0x1234 |
1 |
端点 End Point |
0X56 |
1 |
状态 state |
0X0 |
srpcSendAll(pSrpcMessage);是通过调用socket_server.c中的
int32 socketSeverSendAllclients(uint8* buf, uint32 len)来实现的
参考Linux gateway远程过程调用设计方法,下面面对的问题主要就是:
一. 在LwIP的基础上能不能实现类似Linux gateway的socket_server;
二. Interface_srpcserver能不能准确移植到STM32中
三. 主机接口能不能准确移植到STM32中[c5]
四. 主机接口与interface_srpcserver如何实现数据交互
[c1]如何做的?不同的客户端如何区分的?
[c2]这个附注加得好,别人就可以更好的学习相关的内容了,以便共同提高。
[c3]也就是吕慧珍和谢红涛正在做移植的部分。
[z4]红色字体表示的为Interface_srpcserver与主机接口交互部分
[c5]这部分吕慧珍他们正在做,应该问题不大。
附件列表
转载于:https://www.cnblogs.com/star91/p/4888968.html
ZLL本地局域网通信过程相关推荐
- Linux_网络_数据链路层协议 MAC帧/ARP协议 (以太网通信原理,MAC地址与IP地址的区分,MTU对IP/TCP/IP的影响,ARP协议及其通信过程)
文章目录 1. 以太网(基于碰撞区与碰撞检测的局域网通信标准) 2. 以太网的帧格式(MAC帧) MAC地址,IP地址的区分 MTU MTU对IP协议的影响 MTU对TCP/UDP协议的影响 3.AR ...
- Socket编程(C语言实现)—— AF_INET(典型的TCP/IP四层模型的通信过程),AF_UNIX(本地进程间通信)
1.AF_INET域与Socket通信 其是典型的TCP/IP四层模型的通信过程. (1)接收方与发送方依赖IP和port来标识,即,将本地socket绑定到对应的IP端口上: (2)发送数据时指定对 ...
- 【计算机网络】网络层 : 移动 IP 技术 ( 移动节点 | 本地代理 | 外部代理 | 永久地址 | 转交地址 | 移动 IP 通信过程 )
文章目录 一.移动 IP 技术 简介 二.移动 IP 通信 一.移动 IP 技术 简介 移动 IP 技术 简介 : ① "移动 IP 技术" 概念 : 移动节点 以 固定的网络 I ...
- 局域网同一个网段通信过程
局域网内同网段通信的过程 这个时候就需要用到ENSP模拟器了,之前已经安装好了,我们通过ENSP来搭建实验环境,这样可以看到实验的效果以及通过抓包来分享整个过程,先看同网段内的通信过程. 1.准备工作 ...
- 【网络通信与信息安全】之深入解析两台主机之间的通信过程和原理
一.前言 本文通过在 Docker 容器中执行命令,来深入了解两台主机之间的通信过程.阅读完本文,您将熟悉以下内容: Docker 的基本操作: 创建 socket 并发送 HTTP 请求: 路由表. ...
- 网络基础2(分层模型,通信过程,以太网,ARP协议格式和具体功能详解)
分层模型 OSI七层模型 OSI模型 1 物理层:主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达 ...
- 如何在 Windows 主机上访问本地局域网中的 Linux 主机
如何在 Windows 主机上访问本地局域网中的 Linux 主机 使用 Xshell 建立远程连接 在 Windows 主机上是可以访问本地局域网中的 Linux 主机的.这样做之所以可行,是因 ...
- linux网络编程之网络应用设计模式、分层模型、通信过程
(1)网络协议 可以理解为规则,其中包含着数据传输和数据的解释. 典型的协议:传输层:tcp/udp协议,应用层:http/ftp协议,网络层:ip协议,网路接口:arp协议 (2)网络应用设计模式 ...
- 一文入门网络编程:常见协议、通信过程、Socket、CS/BS、TCP/UDP
网络编程三要素:ip地址.端口.协议,在网络通信协议下,不同计算机上运行的程序,可以进行数据传输 常见协议: 传输层 常见协议有TCP/UDP协议. 应用层 常见的协议有HTTP协议,FTP协议. 网 ...
最新文章
- CSS里常见的块级元素和行内元素
- CrowdRec:众包环境中,基于信任感知的工人推荐
- Linux tcpdump命令用法详解
- linux性能监控sar命令详解
- 手机厂商们,不鸡贼能死?
- 修改GDAL库支持RPC像方改正模型
- jquery 图像滑块_jQuery CSS图像滑块–自行编写代码
- 三维重建笔记_相机标定_求本质矩阵E
- 钉钉微应用怎么进入_海目星激光张荣:激光焊接在锂电池生产应用中越来越多...
- 第六章 jQuery选择器
- java怎么开发app_如何开发一款APP
- html元素 按键精灵鼠标移动,按键精灵后台鼠标移动和点击脚本怎么制作。
- 获取当前屏幕高度方法总结
- 稳定性及性能调优<二十四>-------性能优化3【页面加载耗时优化实战、页面滑动流畅度FPS优化实战】
- tplink软件升级有用吗_tplink路由器固件更新的方法
- Java for循环和foreach循环区别
- 易语言新手入门教程第十四课 - QQ自动登录器第二部分
- ybc_art打印艺术字
- C++中cout后面输出时加endl和不加endl的区别
- 学习teardrop攻击并伪造一个ip包