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)


SRPC消息格式


CMD字节


命令长度(N


数据


1字节


1字节


n个字节

 

接下来顺藤摸瓜,我们看看这个函数,用户通过客户端发送命令想改变灯的状态,这个命令已经被网关接收到了,接下来网关就要通过主机接口[c3] 发送命令给CC2531来控制终端节点,CC2531是不能直接转发处理客户端发送给网关的命令的,因此网关需对命令解析,提取出需要通过串口传递给CC2531的参数,下面这个函数即实现了此功能。在此还是以设置灯的状态命令为例,RPCS_SET_DEV_STATE消息格式如表所示:


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)

{

 
uint8_t  endpoint, addrMode;

 
uint16_t  dstAddr;

  bool  state;

 

 
//increment past SRPC header

 
pBuf+=2;

//由 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]这部分吕慧珍他们正在做,应该问题不大。

来自为知笔记(Wiz)

附件列表

时间: 2024-11-01 21:14:05

ZLL本地局域网通信过程的相关文章

网络中两台主机的通信过程(TCP)

两台主机通信有两种情况:1.在同一网段中 2.不在同一网段中 (1.)在同一网段的通信过程 主机在应用层上的操作: TCP/IP协议上tcp的端口对应的各种应用程序,客户机要访问某个应用程序就会要求打开主机的这个固定的端口.而客户机自己会打开一个大于1024的随机端口用来跟对方的主机进行通信.用户使用应用程序编辑信息,一个单一的会话,实际上就是一个主机应用层之间的逻辑的软件连接. 主机在传输层的操作: 对数据分段(Segment),添加TCP报头(包含源端口,目的端口,顺序号等) 分段的原因:

局域网通信

标 题: 局域网通信作 者: itdef链 接: http://www.cnblogs.com/itdef/p/3989918.html 欢迎转帖 请保持文本完整并注明出处 最近没些什么 看了看JAVA 语言以及使用其语言的设计模式介绍  都是学习基本的东西  没什么好写的 还是写下最近写的C版本的小代码 模仿IPMSG 写了个简单版本的局域网通信程序 准备将来用于局域网客户端性能监控中 其实就是使用UDP 进行通讯 开启程序便UDP广播本机ID上线信息 关闭程序之前则广播本地下线 同时固定时间

Android BLE与终端通信(三)——client与服务端通信过程以及实现数据通信

Android BLE与终端通信(三)--client与服务端通信过程以及实现数据通信 前面的终究仅仅是小知识点.上不了台面,也仅仅能算是起到一个科普的作用.而同步到实际的开发上去,今天就来延续前两篇实现蓝牙主从关系的client和服务端了.本文相关链接须要去google的API上查看,须要FQ的 Bluetooth Low Energy:http://developer.android.com/guide/topics/connectivity/bluetooth-le.html 可是我们依旧

IOS-网络(GET请求和POST请求、HTTP通信过程、请求超时、URL转码)

1 // 2 // ViewController.m 3 // IOS_0129_HTTP请求 4 // 5 // Created by ma c on 16/1/29. 6 // Copyright © 2016年 博文科技. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import "MBProgressHUD+MJ.h" 11 12 @interface ViewController

android使用socket进行本地PC通信

一.编写思路 手机端为客户端,PC为服务端,手机访问PC通信,需建立一个虚拟的通信链路,客户端通过socket发送请求到服务端,服务端通过serversocket监听来自客户端的socket请求,并生成一个socket.这样就建立了一条虚拟通信网络,然后再通过相关方法进行通信.项目需在服务端建立一个java程序,客户端建立一个android程序. 二.代码编写 (一) PC端的代码编写--java程序 (1)相关方法 Socket accept() :如果接收到一个来自客户端的socket的连接

android的NDK和java进行本地socket通信

关于Android应用与Framework的socket通信,相信关心这个问题的朋友们已经看过<android使用socket使底层和framework通信>这篇文章,美中不足的是作者只贴出一些关键的代码片段而并没有放出源码.我这里还是以一个能实际运行的例子为基础来讲,这样也方便大家学习. 首先看一下效果,如下图.我填写姓名"Potter",选择性别"Mr"然后点击发送,底层socket收到消息后将消息直接返回给我,我将返回的结果(Mr.Potter)直

【转】WCF入门教程二[WCF应用的通信过程]

一.概述 WCF能够建立一个跨平台的安全.可信赖.事务性的解决方案,是一个WebService,.Net Remoting,Enterprise Service,WSE,MSMQ的并集,有一副很经典的对比图如下: WCF与其他分布式技术对比表 二.WCF中的 "A","B","C" 介绍 我们先看个生活中的例子,某一天,公司的领导让你去送一份合同文件,送文件的过程你可以选择的交通方式为"打车"."公交".&

二、WCF应用的通信过程

注:本文为学习摘抄,原文地址:http://www.cnblogs.com/iamlilinfeng/archive/2012/09/26/2703759.html 一.概述 WCF能够建立一个跨平台的安全.可信赖.事务性的解决方案,是一个WebService,.Net Remoting,Enterprise Service,WSE,MSMQ的并集,有一副很经典的对比图如下: WCF与其他分布式技术对比表 二.WCF中的 "A","B","C"

WCF入门教程二[WCF应用的通信过程]

一.概述 WCF能够建立一个跨平台的安全.可信赖.事务性的解决方案,是一个WebService,.Net Remoting,Enterprise Service,WSE,MSMQ的并集,有一副很经典的对比图如下: WCF与其他分布式技术对比表 二.WCF中的 "A","B","C" 介绍 我们先看个生活中的例子,某一天,公司的领导让你去送一份合同文件,送文件的过程你可以选择的交通方式为“打车”.“公交”.“地铁”,当然费用是根据发票来报销的,到了