Java 开发如何通过 IoT 边缘 ModuleSDK 进行协议转换
操作场景
使用 ModuleSDK 开发插件应用,接入其他协议设备(如 HTTP 请求数据),将其他协议的数据转化为 MQTT 协议 JSON 数据上报到 IoTDA。
代码解析
项目结构如下
ModbusDriver 代码解析
片段一
通过 DriverClient.createFromEnv 初始化客户端,调用 driverClient 来完成数据的发送。
public ModbusDriver() throws GeneraException {
driverClient = DriverClient.createFromEnv();
}
public void start() throws Exception {
//设置回调,打开客户端
driverClient.setGatewayCallback(this);
driverClient.open();
loadConfig();
startCollection();
}
复制代码
片段二
此为模拟 http 请求的代码,随机数模拟设备数采。
private void startCollection() {
scheduler.scheduleAtFixedRate(() -> {
String s = null;
//todo 采集点位数据,保存到points
try {
//1、主动发HTTP请求采集子设备数据
// s = HttpUtils.doGet("http://127.0.0.1:8080/module/sdk", null);
// System.out.println(s);
// Module module = JSON.parseObject(s, Module.class);
//2、模拟设备数采数据
//构造上报参数 设备id.服务id.属性
Module module = new Module();
module.setStatus(String.valueOf(Math.random()));
module.setTemp(String.valueOf(Math.random()));
points.put("bf40f0c4-4022-41c6-a201-c5133122054a.BasicData.status", module.getStatus());
points.put("bf40f0c4-4022-41c6-a201-c5133122054a.BasicData.temp", module.getTemp());
} catch (Exception exception) {
System.out.println("http请求异常");
}
//上报数据
List<DeviceService> devices = new LinkedList<>();
for (Device device : modbusCfg.getDevices()) {
List<ServiceData> services = new LinkedList<>();
for (Service service : device.getServices()) {
Map<String, Object> properties = new HashMap<>();
for (Property property : service.getProperties()) {
String key = device.getId() + "." + service.getServiceId() + "." + property.getPropertyName();
properties.put(property.getPropertyName(), points.get(key));
}
services.add(new ServiceData(service.getServiceId(), properties, ZonedDateTime.now()));
}
String deviceId = deviceIds.get(device.getId());
if (deviceId != null) {
devices.add(new DeviceService(deviceId, services));
}
}
try {
driverClient.reportSubDevicesProperties(new SubDevicesPropsReport(devices));
} catch (Exception e) {
System.out.println("上报数据异常" + e.getMessage());
}
}, 0, modbusCfg.getPeriod(), TimeUnit.SECONDS);
}
复制代码
片段三
查看“modbus.json”文件,点位上报数据关系对应:设备 id.模型 id.服务 id.属性名;设备 id 需要与添加边缘设备时设置的“设备标识码”一致。
{
"period": 10,
"server": "10.69.33.154:502",
"devices": [{
"id": "bf40f0c4-4022-41c6-a201-c5133122054a",
"product_id": "6247f7e36fe7862a3aa0d803",
"name": "TEST1",
"slave_id": 1,
"services": [{
"service_id": "BasicData",
"properties": [{
"property_name": "status",
"register_address": 0,
"data_type": "string"
},{
"property_name": "temp",
"register_address": 1,
"data_type": "string"
}]
}]
}]
}
复制代码
片段四
查看“device_ids.json”文件,设备 id 需要与添加边缘设备时设置的“设备标识码”一致。
{
"bf40f0c4-4022-41c6-a201-c5133122054a": "bf40f0c4-4022-41c6-a201-c5133122054a"
}
复制代码
片段五
平台对部署此应用模块下的设备下发命令后,回调此函数。
@Override
public CommandRsp onDeviceCommandCalled(String requestId, Command command) {
// command json体
//{
// "object_device_id": "bf40f0c4-4022-41c6-a201-c5133122054a", 设备id
// "service_id": "BasicData", 模型service_id
// "command_name": "Control", 命令下发名称
// "paras": { 命令下发参数
// "State": "1"
//}
//}
// 响应示例
return new CommandRsp(200, "supported ok", null);
}
复制代码
片段六
平台对部署此应用模块下的设备的影子属性配置后,回调此函数。
@Override
public IotResult onDevicePropertiesSet(String requestId, PropsSet propsSet) {
//propsSet的json结构体
// {
// "object_device_id": "bf40f0c4-4022-41c6-a201-c5133122054a", 设备id
// "services": [
// {
// "service_id": "$config", 模型service_id
// "properties": {
// "password": "" 模型属性
// }
// },
// {
// "service_id": "BasicData", 模型service_id
// "properties": { 模型属性
// "status": "123",
// "temp": "123"
// }
// }
//]
// }
// 响应
return new IotResult(200, "supported");
}
复制代码
片段七
子设备收到属性获取的请求后,调用此函数。
设备接入后,可通过 IOTDA 提供的接口触发此函数,请参考IOTDA接口指引。
@Override
public PropsGetRsp onDevicePropertiesGet(String requestId, PropsGet propsGet) {
//propsGet的json结构体
//{
// "objectDeviceId": "bf40f0c4-4022-41c6-a201-c5133122054a",
// "serviceId": "BasicData"
//}
return new PropsGetRsp();
}
复制代码
片段八
边缘设备的影子属性配置后,回调此函数。
@Override
public void onDeviceShadowReceived(String requestId, ShadowGetRsp shadowGetRsp) {
// {
// "objectDeviceId": "bf40f0c4-4022-41c6-a201-c5133122054a", 设备id
// "shadow": [
// {
// "desired": {
// "eventTime": "2022-05-07T07:44:53Z[UTC]",
// "properties": {
// "status": "22222222222", 设备影子期望属性
// "temp": "11111111111111" 设备影子期望属性
// }
// },
// "reported": {
// "eventTime": "2022-05-07T07:34:15Z[UTC]",
// "properties": {
// "status": "1595803812", 设备上报属性
// "temp": "-947623559" 设备上报属性
// }
// },
// "serviceId": "BasicData", 模型服务id
// "version": 19
// }
//]
// }
}
复制代码
片段九
平台对部署此应用模块下的节点的添加边缘设备后,回调此函数。
注意:
部署边缘设备的模块 id 是集成了 ModuleSDK 应用的模块 ID。
@Override
public void onSubDevicesAdded(String eventId, AddSubDevicesEvent addSubDevicesEvent) {
// addSubDevicesEvent的json结构体
// {
// "devices": [
// {
// "description": "", 描述
// "deviceId": "bf40f0c4-4022-41c6-a201-c5133122054a", 设备id
// "extensionInfo": {
// "module_id": "user_ot_test" 模块id
// },
// "fwVersion": "",
// "name": "TEST1",
// "nodeId": "bf40f0c4-4022-41c6-a201-c5133122054a", 设备id
// "parentDeviceId": "720259701929160704", 父设备id
// "productId": "6247f7e36fe7862a3aa0d803", 模型id
// "status": "INACTIVE", 状态
// "swVersion": ""
// }
//],
// "version": 13
// }
//保存本地设备Id与云端设备Id映射关系
}
复制代码
片段十
平台对部署此应用模块下的节点的删除边缘设备后,回调此函数。
注意:
部署边缘设备的模块 id 是集成了 ModuleSDK 应用的模块 ID。
@Override
public void onSubDevicesDeleted(String eventId, DeleteSubDevicesEvent deleteSubDevicesEvent) {
// deleteSubDevicesEvent的json结构体
// {
// "devices": [
// {
// "description": "",
// "deviceId": "bf40f0c4-4022-41c6-a201-c5133122054a",
// "fwVersion": "",
// "name": "",
// "nodeId": "bf40f0c4-4022-41c6-a201-c5133122054a",
// "parentDeviceId": "720259701929160704",
// "productId": "",
// "status": "",
// "swVersion": ""
// }
//],
// "version": 14
// }
}
复制代码
片段十一
收到获取模型的请求,调用此函数。
@Override
public void onGetProductsResponse(String eventId, GetProductsRspEvent response) {
//使用 driverClient.getProducts()可获得模型数据
//try {
// GetProductsEvent event = new GetProductsEvent();
//event.setProductIds(Collections.singletonList("6247f7e36fe7862a3aa0d803"));
// driverClient.getProducts("12345", event);
//} catch (JsonException e) {
// log.error("getProducts exception:" + e);
//}
// response的json结构体
// {
// "products": [
// {
// "dataFormat": "json",
// "description": "",
// "deviceType": "moduleSDK测试", 模型名字
// "industry": "",
// "name": "moduleSDK测试",
// "productId": "6247f7e36fe7862a3aa0d803", 模型id
// "protocolType": "MQTT",
// "serviceCapabilities": [
// {
// "commands": [
// {
// "commandName": "Control", 命令名称
// "paras": [ 命令配置
// {
// "dataType": "string",
// "max": "2147483647",
// "maxLength": 200,
// "min": "1",
// "paraName": "State",
// "required": true,
// "step": 0.0,
// "unit": ""
// }
// ]
// }
// ],
// "description": "",
// "option": "Optional",
// "properties": [ 属性配置
// {
// "dataType": "string",
// "maxLength": 50,
// "method": "R",
// "propertyName": "temp",
// "required": false,
// "step": 0.0
// },
// {
// "dataType": "string",
// "maxLength": 50,
// "method": "RW",
// "propertyName": "status",
// "required": false,
// "step": 0.0
// }
// ],
// "serviceId": "BasicData",
// "serviceType": "BasicData"
// },
// {
// "description": "mqtt_config",
// "option": "Optional",
// "properties": [
// {
// "dataType": "string",
// "description": "mqtt设备接入平台密码",
// "max": "32",
// "maxLength": 10240,
// "method": "RW",
// "min": "8",
// "propertyName": "password",
// "required": false,
// "step": 0.0
// }
// ],
// "serviceId": "$config",
// "serviceType": "$config"
// }
// ]
// }
//]
// }
}
复制代码
注册节点
注册节点,请参照注册边缘节点。
设备建模
1.访问IoT边缘,单击“立即使用”进入 IoT 边缘控制台。
2.在左侧导航中选择“设备建模”,单击页面右上角“创建产品”。
3.填写参数信息,如图所示,单击“立即创建”。
4.进入产品详情页,单击“自定义模型”,添加“BasicData”服务 ID,并“确认”。
5.展开服务列表,依次添加“temp”、“status”两个属性。
6.单击添加命令,添加 Control 命令名称。
7.单击新增下发参数,填写对应参数。
说明:
产品 ID、服务 ID、属性名称需要与代码中示例保持一致。
项目打包
打包参考项目打包
将 modbusdriver 进行打包得到 modbusdriver.jar。
制作镜像包
将 jar 文件打包成镜像文件上,请参照制作镜像包或插件包。
dockerfile 内容参照如下(具体可参考编写高效的Dockerfile )。
FROM registry-cbu.huawei.com/csopenjdk/openjdk
RUN mkdir -p /opt/iot/edge/monitor / && chmod -R 777 /opt/
COPY monitor /opt/iot/edge/monitor
USER root
EXPOSE 8080
CMD ["java", "-jar", "/opt/iot/edge/monitor/monitor-app.jar", "run"]
#构造镜像
#docker build -t edge_monitor:1.0.0 /home --no-cache
#打标签
#docker tag edge_monitor:1.0.0 swr.cn-north-4.myhuaweicloud.com/iot_edge_test/ot_test:v1
#推送
#docker push swr.cn-north-4.myhuaweicloud.com/iot_edge_test/ot_test:v1
#打成镜像包
#docker save swr.cn-north-4.myhuaweicloud.com/iot_edge_test/ot_test:v1 > ot_test.tar
添加应用
以容器镜像方式为例,镜像包上传到容器镜像服务 SWR 后,创建应用。
1.在 IoT 边缘单击创建应用,进入软件部署配置、运行配置,并确认发布。
2.在左侧导航栏,单击“应用管理”,选择“应用名称”进入页面,查看应用为“已发布”状态。
部署应用
部署应用,具体请参考部署应用,进入我们的节点详情页安装应用。
添加边缘设备
1.进入边缘节点概览页,在左侧导航中选择“边缘设备”,单击“添加边缘设备”。
-
所属产品:选择设备建模中创建的产品
-
设备标识码:与代码示例保持一致
-
设备名称:与代码示例保持一致
-
模块 ID: 与部署应用的模块 id 保持一致
2.单击“确认”,添加设备完成。
启动 HTTP 服务端,进入设备详情页可看到上报的数据。设备状态显示未激活。如需更改可参照集成ModuleSDK后,上报数据成功后,设备状态显示为未激活,如何上报子设备状态?