网关是一个特殊的设备,除具备一般设备功能之外,还具有子设备管理、子设备消息 转发的功能。SDK提供了AbstractGateway抽象类来简化网关的实现。该类提供了子设 备管理功能,需要从平台获取子设备信息并保存(需要子类提供子设备持久化接 口)、子设备下行消息转发功能(需要子类实现转发处理接口)、以及上报子设备列 表、上报子设备属性、上报子设备状态、上报子设备消息等接口。
● 使用AbstractGateway类
继承该类,在构造函数里提供子设备信息持久化接口,实现其下行消息转发的抽 象接口:
public abstract void onSubdevCommand(String requestId, Command command);
public abstract void onSubdevPropertiesSet(String requestId, PropsSet propsSet);
public abstract void onSubdevPropertiesGet(String requestId, PropsGet propsGet);
public abstract void onSubdevMessage(DeviceMessage message);
● iot-gateway-demo代码介绍
工程iot-gateway-demo基于AbstractGateway实现了一个简单的网关,它提供 tcp设备接入能力。关键类:
SimpleGateway:继承自AbstractGateway,实现子设备管理和下行消息转发 StringTcpServer:基于netty实现一个TCP server,本例中子设备采用TCP协议,
并且首条消息为鉴权消息
SubDevicesFilePersistence:子设备信息持久化,采用json文件来保存子设备信 息,并在内存中做了缓存
Session:设备会话类,保存了设备id和TCP的channel的对应关系
● SimpleGateway类 添加或删除子设备处理
添加子设备:AbstractGateway的onAddSubDevices接口已经完成了子设备信息 的保存。我们不需要再增加额外处理,因此SimpleGateway不需要重写
onAddSubDevices接口
删除子设备:我们不仅需要修改持久化信息,还需要断开当前子设备的连接。所 以我们重写了onDeleteSubDevices接口,增加了拆链处理,然后调用父类的 onDeleteSubDevices。
for (DeviceInfo subdevice : subDevicesInfo.getDevices()) {
Session session = nodeIdToSesseionMap.get(subdevice.getNodeId());
if (session != null) {
return super.onDeleteSubDevices(subDevicesInfo);
}
● 下行消息处理
网关收到平台下行消息时,需要转发给子设备。平台下行消息分为三种:设备消 息、属性读写、命令。
– 设备消息:这里我们需要根据deviceId获取nodeId,从而获取session,从 session里获取channel,就可以往channel发送消息。在转发消息时,可以根 据需要进行一定的转换处理。
@Override
public void onSubdevMessage(DeviceMessage message) {
//平台接口带的都是deviceId,deviceId是由nodeId和productId拼装生成的,即 //deviceId = productId_nodeId
String nodeId = IotUtil.getNodeIdFromDeviceId(message.getDeviceId());
if (nodeId == null) { return;
}
//通过nodeId获取session,进一步获取channel Session session = nodeIdToSesseionMap.get(nodeId);
if (session == null) {
session.getChannel().writeAndFlush(message.getContent());
log.info("writeAndFlush " + message);
}
– 属性读写:
属性读写包括属性设置和属性查询。
属性设置:
@Override
public void onSubdevPropertiesSet(String requestId, PropsSet propsSet) { if (propsSet.getDeviceId() == null) {
return;
}
String nodeId = IotUtil.getNodeIdFromDeviceId(propsSet.getDeviceId());
if (nodeId == null) { return;
}
Session session = nodeIdToSesseionMap.get(nodeId);
if (session == null) { return;
}
//这里我们直接把对象转成string发给子设备,实际场景中可能需要进行一定的编解码转换 session.getChannel().writeAndFlush(JsonUtil.convertObject2String(propsSet));
//为了简化处理,我们在这里直接回响应。更合理做法是在子设备处理完后再回响应 getClient().respondPropsSet(requestId, IotResult.SUCCESS);
log.info("writeAndFlush " + propsSet);
}
属性查询:
@Override
public void onSubdevPropertiesGet(String requestId, PropsGet propsGet) { //不建议平台直接读子设备的属性,这里直接返回失败
log.error("not supporte onSubdevPropertiesGet");
deviceClient.respondPropsSet(requestId, IotResult.FAIL);
}
– 命令:处理流程和消息类似,实际场景中可能需要不同的编解码转换。
@Override
public void onSubdevCommand(String requestId, Command command) { if (command.getDeviceId() == null) {
return;
}
String nodeId = IotUtil.getNodeIdFromDeviceId(command.getDeviceId());
if (nodeId == null) { return;
}
Session session = nodeIdToSesseionMap.get(nodeId);
if (session == null) { return;
}
//这里我们直接把command对象转成string发给子设备,实际场景中可能需要进行一定的编解 码转换 session.getChannel().writeAndFlush(JsonUtil.convertObject2String(command));
//为了简化处理,我们在这里直接回命令响应。更合理做法是在子设备处理完后再回响应 getClient().respondCommand(requestId, new CommandRsp(0));
log.info("writeAndFlush " + command);
@Override
protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception { Channel incoming = ctx.channel();
log.info("channelRead0" + incoming.remoteAddress() + " msg :" + s);
//如果是首条消息,创建session //如果是首条消息,创建session
Session session = simpleGateway.getSessionByChannel(incoming.id().asLongText());
if (session == null) { String nodeId = s;
session = simpleGateway.createSession(nodeId, incoming);
//创建会话失败,拒绝连接
} }
如果会话存在,则进行消息转发:
else {
//如果需要上报属性则调用reportSubDeviceProperties DeviceMessage deviceMessage = new DeviceMessage(s);
deviceMessage.setDeviceId(session.getDeviceId());
simpleGateway.reportSubDeviceMessage(deviceMessage, null);
}
到这里,网关的关键代码介绍完了,其他的部分看源代码。整个demo是开源的,
用户可以根据需要进行扩展。比如修改持久化方式、转发中增加消息格式的转 换、实现其他子设备接入协议。
● iot-gateway-demo的使用 a. 在平台上为网关注册开户。
b. 修改StringTcpServer的main函数,替换构造参数,然后运行该类。
simpleGateway = new SimpleGateway(new SubDevicesFilePersistence(), "ssl://iot-acc.cn-north-4.myhuaweicloud.com:8883",
"5e06bfee334dd4f33759f5b3_demo", "mysecret");
c. 在平台上看到该网关在线后,添加子设备。
此时网关上日志打印:
2020-02-11 09:42:17 INFO SubDevicesFilePersistence:75 - add subdev: ffff d. 运行TcpDevice类,建立连接后,输入子设备的nodeId。
e. 在平台上看到子设备上线。
f. 子设备上报消息
查看日志看到上报成功
g. 查看消息跟踪
在平台上找到网关,选择 设备详情-消息跟踪,打开消息跟踪。继续让子设备 发送数据,等待片刻后看到消息跟踪:
3.3 IoT Device SDK 使用指南(C)
IoT Device SDK(C)提供设备接入华为云IoT物联网平台的C版本的SDK,提供设备和 平台之间通讯能力,以及设备服务、网关服务、OTA等高级服务,并且针对各种场景 提供了丰富的demo代码。相关集成指导请参考IoT Device SDK(C)使用指南。
3.4 IoT Device SDK 使用指南(C#)
IoT Device SDK(C#)提供设备接入华为云IoT物联网平台的C#版本的SDK,提供设备 和平台之间通讯能力,以及设备服务、OTA等高级服务,并且针对各种场景提供了丰 富的demo代码。相关集成指导请参考IoT Device SDK(C#)使用指南。
3.5 IoT Device SDK 使用指南(Android)
IoT Device SDK(Android)提供设备接入华为云IoT物联网平台的Android版本的 SDK,提供设备和平台之间通讯能力,以及设备服务、OTA等高级服务,并且针对各种 场景提供了丰富的demo代码。相关集成指导请参考IoT Device SDK(Android)使用 指南。
3.6 IoT Device SDK 使用指南(Go 社区版)
Go语言版的SDK提供了跟平台基础的通信能力,由开源社区提供,如果使用有问题请 在github上提issue。
3.7 IoT Device SDK Tiny 使用指南(C)
物联网平台以及数据上报和命令接收等功能,相关集成指导请参见端云互通组件开发 指南。
说明
IoT Device SDK Tiny可以运行于无linux操作系统的设备,也可以被模组集成,但是不提供网关 服务。
4 历史 SDK
这里的历史SDK指的是SDK介绍章节所描述的所有SDK,新版SDK指的是SDK下载章节 所描述的设备侧SDK和应用侧SDK。为方便描述,后续统一将老版本称为v3版本,当前 版本称为v5版本。
4.1 SDK差异说明 4.2 SDK介绍
4.3 应用侧Python SDK API参考 4.4 应用侧JAVA SDK API参考 4.5 设备侧Agent Lite API参考(Java) 4.6 设备侧Agent Lite API参考(Android) 4.7 设备侧Agent Lite API参考(C)
4.1 SDK 差异说明
为提供更好的SDK性能、易用性、丰富性,我们全新开放了新版设备侧SDK。新版SDK 引入了物模型的概念,新增了消息、属性、设备影子,自定义Topic等功能,相关概念 解释请参考名词解释。
SDK差异参考下表:
使用 旧版SDK 新版SDK
支持版本
不同 ● 提供应用侧Java版、Python版 SDK。
● 提供设备侧C版、Java版、
Android版SDK(agentlite)。
● 提供应用侧Java版、C#版、
Python版SDK。
● 提供设备侧Java版、C版SDK
(iot-device-sdk)。
应用侧SDK 需用旧域名接入(内置了旧域名的 证书,旧域名及端口为:iot-api.cn-north-4.myhuaweicloud.com:
8743)
用新域名接入(内置了新域名的 证书,新域名为:iotda.cn-north-4.myhuaweicloud.com)
设备侧SDK 需用旧域名接入(内置了旧域名的 证书,旧域名为:iot-acc.cn-north-4.myhuaweicloud.com)
用新域名接入(内置了新域名的 证书,新域名为:iot-mqtts.cn-north-4.myhuaweicloud.com)
说明
历史SDK使用的是华为物联网平台提供的旧版本(V3)接口,当前console控制台界面呈现的地 址信息、资料中的证书和SDK等资源默认都是新版本(V5)接口。
平台仍然支持使用老(V3)接口,如果您想继续沿用历史SDK或API,务必配套对应域名和证 书,不能混淆使用。
设备侧SDK功能差异请参考下表:
功能 旧版SDK(agentlite) 新版SDK(iot-device-sdk)
开源 不开源 开源
协议 HTTPS+MQTTS MQTTS/MQTT
端口 8943+8883 8883/1883
设备登录 HTTPS协议登录绑定 MQTT协议鉴权
数据上报 一个接口 多样化接口数据上报,消息/属性/
平台下行命令的响应
命令下发 一个命令 多样化接口命令下发,分消息下
发/命令下发/属性设置/属性查询
子设备管理 网关管理 应用侧管理,通知网关
证书认证 - 新增,设备可以用证书方式接入
自定义topic - 新增,设备可以自定义Topic,发
布数据和订阅消息
设备影子 - 新增,设备可以查询设备影子的数
据
OTA升级 - 新增,设备可以通过OTA进行远程
升级