Java开发如何通过IoT边缘ModuleSDK进行协议转换?
摘要:使用ModuleSDK开发插件应用,接入其他协议设备(如HTTP请求数据),将其他协议的数据转化为MQTT协议JSON数据上报到IoTDA。
本文分享自华为云社区《【华为云IoTEdge开发实战】Java开发如何通过IoT边缘ModuleSDK进行协议转换》,作者: 华为IoT云服务 。
操作场景
使用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后,上报数据成功后,设备状态显示为未激活,如何上报子设备状态?


Java开发如何通过IoT边缘ModuleSDK进行协议转换?的更多相关文章
- 云中树莓派(5):利用 AWS IoT Greengrass 进行 IoT 边缘计算
云中树莓派(1):环境准备 云中树莓派(2):将传感器数据上传到AWS IoT 并利用Kibana进行展示 云中树莓派(3):通过 AWS IoT 控制树莓派上的Led 云中树莓派(4):利用声音传感 ...
- 万物智联,腾讯云 IoT 边缘计算揭秘——云+未来峰会开发者专场回顾
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 背景:现在是万物互联的时代,智能穿戴设备,智能家居,无人商业,改变了我们的生活方式.预计到2021年,全球物联网设数将达到150亿,超过手机 ...
- JAVA开发常用工具包
一个有经验的Java开发人员特征之一就是善于使用已有的轮子来造车.<Effective Java>的作者Joshua Bloch曾经说过:“建议使用现有的API来开发,而不是重复造轮子”. ...
- JAVA开发类似冒险岛的游戏Part1
JAVA开发类似冒险岛的游戏Part1 一.总结 二.JAVA开发类似冒险岛的游戏Part1 初学嘛) ,不过总的来说这个程序还是很有意思的.这里我重新再整理了一下,希望能帮助到其他想要开发类似程序的 ...
- Java开发笔记(一百四十五)FXML布局的伸展适配
前面介绍了FXML的基本格式及其控制器的用法,算是打通了FXML方式的编码流程.程序界面通常保持固定尺寸,不过有时也允许用户拖曳窗口大小,不拖不打紧,一拖就可能坏事.像之前的登录窗口,没拖的时候界面如 ...
- 2018-2019-2 20175323 实验一《Java开发环境的熟悉》实验报告
java开发环境的熟悉-1 java开发环境的熟悉-2 下载IDEA和破解的过程我参考了https://blog.csdn.net/shengshengshiwo/article/details/79 ...
- 一个老牌程序员说:做Java开发,怎么可以不会这 20 种类库和 API
- IoT边缘,你究竟是何方神圣?
摘要:IoT边缘扮演着纽带的作用,连接边缘和云,将边缘端的实时数据处理,云端的强大计算能力两者结合,创造无限的价值. 本文分享自华为云社区<IoT边缘如何实现海量IoT数据就地处理>,作者 ...
- 【搬砖】安卓入门(1)- Java开发入门
01.01_计算机基础知识(计算机概述)(了解) A:什么是计算机?计算机在生活中的应用举例 计算机(Computer)全称:电子计算机,俗称电脑.是一种能够按照程序运行,自动.高速处理海量数据的现代 ...
- 【java开发】ubuntu常用命令及环境搭建
学习第一天,今天内容相对简单,主要就是ubuntu一些常用命令及常规操作,后续涉及到环境的搭建,也会在本文再更. ubuntu环境搭建 第一种 也是最简单最方便的 通过vm虚拟机软件,下载iso镜像进 ...
随机推荐
- 10_SpringBoot更加详细
一. 原理初探 1.1 自动装配 1.1.1 pom.xml spring-boot-dependencies: 核心依赖在父工程中 我们在写入或者引入一些SpringBoot依赖的时候, 不需要指定 ...
- Node.js躬行记(23)——Worker threads
Node.js 官方提供了 Cluster 和 Child process 创建子进程,通过 Worker threads 模块创建子线程.但前者无法共享内存,通信必须使用 JSON 格式,有一定的局 ...
- Sqoop 之 安装
Sqoop 之 安装 前言 安装 Sqoop 的前提是已经具备 Java 和 Hadoop 的环境. 一.下载并解压 1) 下载地址:http://mirrors.hust.edu.cn/apache ...
- Kafka之配置信息
Kafka之配置信息 一.Broker配置信息 属性 默认值 描述 broker.id 必填参数,broker的唯一标识 log.dirs /tmp/kafka-logs Kafka数据存放的目录 ...
- window安装MySQL 5.5教程
window安装MySQL 5.5教程 1.官网下载MySQL 5.5 下载地址:https://dev.mysql.com/downloads/mysql/5.5.html#downloads 2. ...
- XSS-Game
很简单的弹窗 http://192.168.31.177/xssgame/level1.php?name=<script>alert(1)</script> 过滤了>.& ...
- Xray
Xray基础操作 代理设置 运行xray.exe xray.exe genca 运行后会生成ca.crt和cr.key 浏览器导入证书 设置代理7777端口 第一次启动 xray 之后,当前目录会生成 ...
- 从0搭建vue3组件库:Shake抖动组件
先看下效果 其实就是个抖动效果组件,实现起来也非常简单.之所以做这样一个组件是为了后面写Form表单的时候会用到它做一个规则校验,比如下面一个简单的登录页面,当点击登录会提示用户哪个信息没输入,当然这 ...
- How to get the return value of the setTimeout inner function in js All In One
How to get the return value of the setTimeout inner function in js All In One 在 js 中如何获取 setTimeout ...
- 【算法】浅学 LCA
参考资料 浅析最近公共祖先(LCA) 最近公共祖先 - OI Wiki [白话系列]倍增算法 一.概念 最近公共祖先称为 LCA (Lowest Common Ancestor) 它指的是在一颗树中, ...