Leshan 源码分析
简介
Leshan是iot.eclipse.org推出的辅助实现LwM2M的开源工具库集合。以Java实现,使用EDL1.0(BSD)和EPL1.0的License。目前(2018/11)Leshan的实现是基于LwM2M 1.0.2的。
介绍:https://www.eclipse.org/leshan/
源码:https://github.com/eclipse/leshan
iot.eclipse.org下其他相关项目:
- Californium(Cf),Leshan底层实现CoAP的框架。
- Wakaama,LwM2M客户端工具库,C语言实现。
编译与运行
下载源码:
#using ssh
git clone [email protected]:eclipse/leshan.git
or
#using https
git clone https://github.com/eclipse/leshan.git
编译(需安装maven,使用Ubuntu 18.04和OpenJDK 10):
#install maven
sudo apt install maven
#compile
mvn clean install
注:使用openjdk-8-jdk编译时如遇到surefire报错,可以参考stackoverflow,要解决此问题,可以拷贝此settings.xml到**~/.m2/**。如该目录下已有settings.xml文件,则需要自行合并文件内容。
运行Server:
java -jar leshan-server-demo/target/leshan-server-demo-*-SNAPSHOT-jar-with-dependencies.jar
此时可以通过http://localhost:8080访问Server控制界面。
运行Bootstrap Server:
java -jar leshan-bsserver-demo/target/leshan-bsserver-demo-*-SNAPSHOT-jar-with-dependencies.jar
本机运行Client:
java -jar leshan-client-demo/target/leshan-client-demo-*-SNAPSHOT-jar-with-dependencies.jar
在网络中其他机器上运行Client:
java -jar leshan-client-demo-*-SNAPSHOT-jar-with-dependencies.jar -u xxx.xxx.xxx.xxx:5683
在网络中其他机器上运行Client时需要注意:
- jar路径和名称需正确
- xxx.xxx.xxx.xxx需替换成正确ip
- 5683是服务端默认端口,需保持正确
源码树分析
- leshan-all:目录下所有工程的编译 / 打包配置,依赖于 leshan-client-cf 和 leshan-server-cf
- leshan-bsserver-demo:bootstrap server demo,不可直接用于生产环境,仅供参考
- leshan-client-cf:客户端cf接口,依赖 leshan-core-cf / leshan-client-core 以及 californium 相关
- leshan-client-core:leshan client对象,依赖于 leshan-core
- leshan-client-demo:client demo,不可直接用于生产环境,仅供参考
- leshan-core:leshan基本数据结构及接口
- leshan-core-cf:leshan中针对californium的抽象,依赖于 leshan-core 及 californium 相关
- leshan-integration-tests:集成测试
- leshan-server-cf:服务端cf接口,依赖 leshan-core-cf / leshan-server-core 以及 californium 相关
- leshan-server-cluster:集群实现
- leshan-server-core:leshan server对象,依赖于 leshan-core
- leshan-server-demo:server demo,不可直接用于生产环境,仅供参考
从依赖关系分析,可参考下图:
leshan-client-demo 和 leshan-server-demo 属于demo性质,可以参考,但不能直接使用于生产环境。
californium 是CoAP底层框架,也无需深入研究,只需要了解其接口。
要实现自己的server / client,需要基于 leshan-server-cf 和 leshan-client-cf 实现。
初步的说明在Getting-started。Client另一种实现方式是基于Wakaama。
注:cf 即是californium framework的简写。
源码初步分析
leshan-core
leshan-core是leshan的基础核心,包括:
- src/main/resources/models:LwM2M协议定义的各种profile
- org.eclipse.leshan,leshan基础类,可以认为是一些POJO和常量定义
- org.eclipse.leshan.core,核心数据结构,包括各种基础工具类
- org.eclipse.leshan.json,Json相关数据结构及工具类
- org.eclipse.leshan.tlv,TLV指的是Type-Length-Value,这是TLV容器定义及编解码库
- org.eclipse.leshan.util,各种基础工具类库,包含:
- Base64
- Hex
- ThreadFactory
- RandomString + String
- Security / Credential
- Validate简化验证判断写法
leshan-core-cf
org.eclipse.leshan.core.californium,实现了leshan在CoAP之上的抽象定义。
leshan-server-core
org.eclipse.leshan.server,实现了leshan的Server对象。
LwM2MServer提供了以下接口:
- start / stop / destroy
- send接口是泛型接口,有 同步 / 同步+timeout / 异步 / 异步+timeout 共4种形态
- get "Registration / Observation / Presence" Service
- getSecurityStore
- getModelProvider
leshan-server-cf
org.eclipse.leshan.server.californium,包含接口类及实现类。
LeshanServerBuilder和LeshanBootstrapServerBuilder协助创建Server。
ObserveUtil协助处理Observation相关。
leshan-server-demo
该工程是作为server实现的范例,是前后端分离的模式,包含:
- Server后端,放在src/main/java/org/eclipse/leshan/server/demo
这是一个java应用,从LeshanServerDemo的main函数启动。 - credentials资源,放在src/main/resources/credentials
- models资源,放在src/main/resources/models,是LwM2M定义的模型profile
- web app前端,放在src/main/resources/webapp
这是一个独立的SPA,基于angular 1.2.17实现。
该web app通过http请求发送到Server获取响应。
工程整体打包成jar运行。内置jetty作为web app的服务。后端跟前端通过REST接口传递消息。
后端对外提供的几个REST接口 / servlet(随时可能改变):
- /event/*
- /api/clients/*
- /api/security/*
- /api/objectspecs/*
leshan-client-core(略)
leshan-client-cf(略)
leshan-client-demo(略)
部分接口使用方法
从LeshanServer里面可以看出,主要提供了以下几个公开接口:
- start() / stop() / destroy() - 启动停止相关
- getRegistrationService() - 设备注册相关,可通过RegistrationService监听/查询设备注册/更新/下线情况
- RegistrationListener
- getObservationService() - 设备Observation相关
- getPresenceService() - 设备Presence(在线情况?)
- getSecurityStore() - Server安全设置?
- getModelProvider() - Server支持的Model配置
- send() - 通过此接口给设备发送Create/Read/Write/Delete/Execute/Discover/Observe+Request
- getUnsecuredAddress() / getSecuredAddress() 获取Server访问地址
- coap().getServer() 获取底层CoapServer实例
以下对于必要的接口进一步分析。
ModelProvider
LwM2M中把设备的所有可读/写/执行的属性视为Resource(资源)。将Resource根据其类型,组织在不同的Object(对象)中。OMA维护了一个Resource Registry(资源注册表)。可以通过已经定义的Object查看/下载其对应的Resource描述xml文件。从Resource Registry中可以看出Object ID的范围如下:
- 0-1023,OMA定义的Objects
- 1024-2047,OMA保留的Objects
- 2048-10240,第三方标准组织或联盟定义的Objects
- 10241-26240 / 26241-32768 / 32769-42768,公司/个人/供应商提供的Objects
说明:关于这部分内容我并不是非常理解,感觉似乎是第4部分可以自由定义,但要想不冲突,需要向OMA提交注册并得到认可,成为第3部分。
Resource ID也有范围,如下:
- 0-2047,一般资源,每个Object中的Resource ID必须不同,但在不同Objects中可以重用
- 2048-26240,公司/标准组织或联盟定义的资源
- 26241-32768,私有资源,无需注册
举例来说,Device在LWM2M_Device-v1_0_3.xml中定义,其定义是It provides a range of device related information which can be queried by the LWM2M Server, and a device reboot and factory reset function。Device的Object ID是3,其中Model Number的Resource ID是1,Model Number的定义是A model identifier (manufacturer specified string)。对于LwM2M/Leshan来说,使用“/3/0/1”就可以唯一标识这个Resource(中间的0是Instance ID)。
从代码的角度来看,LeshanServer通过ModelProvider可以获得一个LwM2mModel。
在LwM2mModel中,包含Server所支持的所有ObjectModel的定义。
一个ObjectModel里面含有多个ResourceModel。
一个Client设备可能包含一个或多个ObjectModel。设备中的ObjectModel并不一定包含所有ResourceModel的值。
LeshanServer可以通过send()接口向Client设备发送各种请求,以创建/读取/写入/执行资源节点。