Java开发如何通过IoT边缘ModuleSDK进行协议转换?

java,开发,如何,通过,iot,边缘,modulesdk,进行,协议,转换 · 浏览次数 : 163

小编点评

**设备建模** 1.进入边缘节点概览页,在左侧导航中选择“边缘设备”,单击“添加边缘设备”。所属产品:选择设备建模中创建的产品设备标识码:与代码示例保持一致设备名称:与代码示例保持一致模块ID: 与部署应用的模块id保持一致 2.单击“确认”,添加设备完成。启动HTTP服务端,进入设备详情页可看到上报的数据。设备状态显示未激活。如需更改可参照集成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进行协议转换?相似的内容:

Java开发如何通过IoT边缘ModuleSDK进行协议转换?

摘要:使用ModuleSDK开发插件应用,接入其他协议设备(如HTTP请求数据),将其他协议的数据转化为MQTT协议JSON数据上报到IoTDA。 本文分享自华为云社区《【华为云IoTEdge开发实战】Java开发如何通过IoT边缘ModuleSDK进行协议转换》,作者: 华为IoT云服务 。 操作

Java开发如何通过IoT边缘ModuleSDK进行进程应用的开发?

摘要:为解决用户自定义处理设备数据以及自定义协议设备快速接入IOT平台的诉求,华为IoT边缘提供ModuleSDK,用户可通过集成SDK让设备以及设备数据快速上云。 本文分享自华为云社区《【华为云IoTEdge开发实战】Java开发如何通过IoT边缘ModuleSDK进行进程应用的开发》,作者: 华

[转帖]如何通过JMeter测试金仓数据库KingbaseES并搭建环境

1.安装JMeter Apache JMeter是Apache组织开发的基于Java的压力测试工具,主要用于对软件的压力测试,它最初被设计用于Web应用测试,但后来扩展到其它测试领域。它可测试静态、动态资源,如静态文件、Java小服务程序、CGI脚本、Java对象、数据库等等。JMeter可以用于对

如何使用Java创建数据透视表并导出为PDF

摘要:本文由葡萄城技术团队原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 前言 数据透视分析是一种强大的工具,可以帮助我们从大量数据中提取有用信息并进行深入分析。而在Java开发中,可以借助PivotTable,通过数据透视分析揭示数据中的隐藏

使用shell脚本在Linux中管理Java应用程序

目录前言一、目录结构二、脚本实现1. 脚本内容2. 使用说明2.1 配置脚本2.2 脚本部署2.3 操作你的Java应用总结 前言 在日常开发和运维工作中,管理基于Java的应用程序是一项基础且频繁的任务。本文将通过一个示例脚本,展示如何利用Shell脚本简化这一流程,实现Java应用的一键式启动、

支持JDK19虚拟线程的web框架,之一:体验

随着JDK19的发布,虚拟线程也逐渐被大家了解和使用,然而,主流java框架是否支持虚拟线程这一特性呢?咱们应用开发者如何通过框架使用虚拟线程特性?经过精心准备,欣宸原创在第一时间为您带来详细的实战系列,与您共同学习,窥探虚拟线程技术的未来

支持JDK19虚拟线程的web框架,之一:体验

随着JDK19的发布,虚拟线程也逐渐被大家了解和使用,然而,主流java框架是否支持虚拟线程这一特性呢?咱们应用开发者如何通过框架使用虚拟线程特性?经过精心准备,欣宸原创在第一时间为您带来详细的实战系列,与您共同学习

如何通过jstat命令进行查看堆内存使用情况?

摘要:jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。 本文分享自华为云社区《JVM之通过jstat命令进行查看堆内存使用情况》,作者:共饮一杯无 。 基本概念 jstat是JDK自带的一个轻量级小工具。它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性

Mybatis中的设计模式

最近在看《通用源码阅读指导书:Mybatis源码详解》,这本书一一介绍了Mybatis中的各个包的功能,同时也涉及讲了一些阅读源码的技巧,还讲了一些源码中涉及的设计模式,这是本篇文章介绍的内容 在多说一点这本书,Mybatis是大部分Java开发者都熟悉的一个框架,通过这本书去学习如何阅读源码非常合

如何让Java编译器帮你写代码

本文结合京东监控埋点场景,对解决样板代码的技术选型方案进行分析,给出最终解决方案后,结合理论和实践进一步展开。通过关注文中的技术分析过程和技术场景,读者可收获一种样板代码思想过程和解决思路,并对Java编译器底层有初步了解。