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

Posted 华为云开发者联盟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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进行协议转换?的主要内容,如果未能解决你的问题,请参考以下文章

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

关于华为 IOT平台的框架理解

万物智联,腾讯云 IoT 边缘计算揭秘——云+未来峰会开发者专场回顾

腾讯云 IoT 边缘计算是什么?这篇文章告诉你

百万奖池角逐,华为云IoT边缘带你看懂“边缘计算开发者大赛”

阿里云iot平台缺陷