【华为云IoTEdge开发实战】Java开发如何通过集成IoT边缘ModuleSDK进行工业子系统接入

举报
华为IoT云服务 发表于 2022/12/07 12:45:02 2022/12/07
【摘要】 如何通过技术实现在更靠近制造设备端部署边缘节点进行本地化的感知、决策、控制、分析一体化,降低网络需求的同时提高响应实时性?下面为大家讲解Java是如何通过集成IoT边缘ModuleSDK完成工业子系统接入,进而实现有效提高现有工业互联网平台处理能力。

一家智能工厂一天就可以产生1PB的数据。如果这些海量的“边缘数据”全部传输到网络上,对于任何企业的计算系统都会产生巨大压力。如何通过技术实现在更靠近制造设备端部署边缘节点进行本地化的感知、决策、控制、分析一体化,降低网络需求的同时提高响应实时性?下面为大家讲解Java是如何通过集成IoT边缘ModuleSDK完成工业子系统接入,进而实现有效提高现有工业互联网平台处理能力。

1    操作场景

开发应用集成ModuleSDK进行工业子系统接入。

用户在个节点下部署了多个子系统(如erp),北向应用NA需要调用某个子系统的接口,该子系统需要将order数据上传到用户的北向应用NA上。

2    代码解析

项目结构如下

image001.png


  • ApiController:提供被北向应用NA调用的接口。
  • Application:主启动类
  • AuthFilter:鉴权过滤器。
  • ConfigController:被云端调用进行配置处理。
  • ConfigService:配置管理服务 
  • ItIntegrationService:向北向应用NA发送数据。

代码解释使用ModuleSDK开发it子系统集成服务时使用的主要ItClient类。

ItClient类有以下几个关键方法(具体参考JavaDoc)。

  • createFromEnv(): ItClient创建时由此方法自动获取环境变量。
  • syncConfigs()IT应用启动时由此方法实现从北向应用NA同步配置。
  • confirmConfigs():向北向应用NA确认已经同步的配置。
  • sign():对于发送到APIGW的请求,需要使用此方法进行签名。
  • verify():对于来自APIGW的请求,由此方法进行鉴权。
  • **Json():根据需求选择不同的方法向NA发送请求。

片段一

ItIntegrationService 

    @Scheduled(cron = "0 0/5 * * * ?")

    public void collectData() throws HttpException, CryptException {

        //TODO 采集订单数据

        String body = "{\"orders\":\"data of orders\"}";

        itClient.postJson("/nas/erp/orders", body);

    }

对于来自子系统erp的数据orders(此处未真正接入erp系统),采用定时任务进行发送。

注意请求的地址(demo"/nas/erp/orders",erpNAid(创建路由管理时定义)

最终请求地址http://sys-edge-apigw:8900/nas/erp/orders

http://sys-edge-apigw:8900Api GW接受请求的地址,Api GW接收到此请求会查询本地存储的NA信息中的API网关地址向网关发送请求,如API网关分组下的子域名为

068b72f3b75444dda67cc6e********.apic.cn-south-1.huaweicloudapis.com

Api GW转发地址为https://068b72f3b75444dda67cc6e********.apic.cn-south-1.huaweicloudapis.com/oreders

API网关再将请求转发到定义的NA地址。如如API定义的后端NA:

请求方式:http

host地址:110.*.*.*

端口号:8080

API网关会将请求转发至http://110.*.*.*:8080/orders

注意:

Api GW保存NAIA信息的位置为:/var/IoTEdge/db/sys_edge_apigw/db

Api GW无法转发请求请查看该sqlite数据库是否正确保存了NAIA的信息。

片段二

AuthFilter 

@Order(1)

@WebFilter(filterName = "authFilter", urlPatterns = "/*")

    @Override

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)

        throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;

        try {

            itClient.verify(request.getHeader("Authorization"));

            filterChain.doFilter(servletRequest, servletResponse);

        } catch (AuthException e) {

            HttpServletResponse response = (HttpServletResponse) servletResponse;

            response.sendError(HttpStatus.SC_FORBIDDEN);

        }

    }

对于来自Api GW的请求,此过滤器会进行拦截,并由itClient.verify()方法进行鉴权。

鉴权的方式为在请求头中增加Authorization字段,值的示例如下所示:

Algorithm=HMAC_SHA_256;AK=ia_1;SignedTime=1600763045361;Signature=0A1B0C3D

其中:

Algorithm:表示签名使用的算法名称。

AK:表示客户端身份。

SignedTime:表示签名时间戳。

Signature:为使用由Algorithm指定的签名算法对以上相应字段进行签名的结果。

须知:

对于发送到Api GW的请求,ItClient中提供的**Json()方法已做鉴权相关处理。

片段三

ConfigService 

    //创建时运行一次

    @PostConstruct

    public void syncConfigs() {

        //TODO 先从本地加载配置项

        //从云端同步配置

        try {

            List<Config> configs = itClient.syncConfigs();

            configs.forEach(config -> configMap.put(config.getId(), config));

            //TODO 持久化保存配置

            //确认已同步的配置

            itClient.confirmConfigs(configs);

        } catch (GeneraException e) {

            System.out.println(e.getMessage());

        }

    }

创建时ItClient从云端ITIntegration获取配置并确认(IA>Api GW>云端ITIntegration)。

片段四

/**

 * 该类实现供北向应用调用的接口

 */

@RestController

@RequestMapping(value = "/api")

public class ApiController {

 private final String moduleId;

 

    @Autowired

    public ApiController(ItClient itClient) {

        this.moduleId = itClient.getConfig().getModuleId();

    }

 

    @GetMapping("/get")

    public AppResponse GetTest() {

        return AppResponse.success("GetTest Success", new ReturnDto(moduleId));

    }

 

    @PostMapping("/post")

    public AppResponse PostTest(@RequestBody Map<String, Object> inputArgs) {

        return AppResponse.success("PostTest Success", new ReturnDto(moduleId, inputArgs));

    }

}

APIGW能将来自北向NA的响应(如配置)自ITIntegration请求转发送到iT应用(NA>ITIntegration>Api GW>IA)IT应用可以由此实现对本地子系统的控制。

EdgeApiGW收到南向3rdIA的应答后,需要将应答信息构造成用于进行websocket传输的ResponseDto,并调用sendResponse接口,发送该数据到云端。

/api/** 注:支持GET/POST/PUT/DELETE/PATCH五种方式。

3    项目打包

image003.png


打包方式idea右上方>Maven>选择ero-integration模块>选择package>点击上方绿色三角按钮。完成打包。

4    制作镜像包

jar打包成镜像文件上传,请参照制作镜像包或插件包

5    添加应用

添加边缘应用具体请参考添加应用

1.应用配置:功能用途请选择本地子系统集成

image005.png

2.软件和运行配置需要在高级设置中的数据存储添加挂载点。

image007.png


o    本地卷名称:config

o    类型:CONFIG

o    主机目录:config

o    容器目录:config

o    权限:读写

3.端点和部署配置

image009.png

不添加端点,网络类型选择端口映射。

添加端口映射是自定义的,如

容器端口:8080

主机端口:8080

6    注册节点

创建边缘节点请参照注册边缘节点

注意对于需要部署IT应用的节点,节点需要绑定工业资源包。

如没有工业网关资源包选项,请先购买。工业网关资源包计费及使用请参考工业资源包

绑定方法如下。

1.资源包类型选择工业网关资源包

image011.png

2.绑定工业资源包选择工业子系统采集服务。

image013.png

7    创建API

1.创建API分组。

API网关>开放API>右上方创建分组。

image015.png

编辑分组

image017.png

填写分组名称(自定义),带年纪确定完成创建。

2.创建API

进入API分组,创建APIAPI提供erp数据上传的请求转发功能。

image019.png

创建过程说明:

  1. 基本信息。

image021.png

API名称:自定义。

所属分组:默认。

网关响应:默认。

类型:公开。

安全认证:App认证。

其他根据需要填写,没有则默认。

2.定义API请求。

image023.png

域名:默认。

请求协议:根据需要选择。

请求path:

IT应用发送数据的请求地址:/orders

匹配模式:绝对匹配。

MethodPOST(根据请求方式选择)。

入参定义:

对于带有参数的请求需要声明入参定义,如请求path"/configs/{ia_id}",则入参定义为:

参数名:ia_id

参数位置:path

3.定义后端请求。

image025.png

后端服务类型提供了三种方式。

后端服务类型选择HTTP/HTTPS时的配置:

image027.png

协议:根据北向应用NA使用的协议填写。

请求方式:根据北向应用NA定义的请求方式填写。

vpc通道:根据需求选择。

Virtual Private Network,虚拟专用网络。在公用网络上建立专用网络,进行加密通讯。在企业网络中有广泛应用。VPN网关通过对数据包的加密和数据包目标地址的转换实现远程访问。VPN可通过服务器、硬件、软件等多种方式实现。

后端服务地址:北向应用NA接受请求的ip或域名。

后端请求Path:北向应用NA接受请求的地址。

后端超时:自定义。

注意:

后端服务地址和后端请求Path很重要,这两项决定NA的请求地址。

后端服务类型选择Mock时的配置:

定义后端请求即定义API网关接受的请求将转发的位置,可通过Mock模拟后端响应。

Mock返回结果:此处定义的内容会被返回到请求端。(非必填)

返回示例:

{

  "configs": [

    {

      "id": "config1203",

      "name": "config1202",

      "value": "config1202",

      "description": "config1202",

      "version": "1606878222614",

      "state": "SUCCESS",

      "create_time": "2020-12-02T03:02:42Z",

      "update_time": "2020-12-16T08:44:33Z"

    }

  ]

}

须知:

使用mock不能显示请求携带的数据,只能接收到请求后返回定义的结果。

4.定义返回结果

image029.png

成功响应示例:自定义。

失败响应示例:自定义。

5.发布API

将创建的API发布到release环境。

API网关>API分组>选择创建的API分组>API管理>勾选创建API>点击发布。

image031.png


8    网关应用创建及绑定

1.创建网关应用

API网关>调用API>应用管理。

image033.png

2.绑定API

image035.png

勾选前面创建的API,点击绑定。

image037.png

9    添加数据端点

IoT边缘>路由管理>添加数据接收端点。

image039.png


端点名称:自定义。

端点IDerp (端点id即为NAid,代码中IA请求NA地址需要与此对应,如"/nas/erp/orders")

数据接收地址:

API分组绑定的子域名。创建API时会自动分配一个访问量和性能都极低的子域名用于开发测试(API分组>选择创建的API>概览),用于生产环境请绑定子域名!

image041.png

接入方式:选择ROMA

集成应用keysecret选择API应用分配的keyAppSecret(API网关>调用API>应用管理)

image043.png


绑定节点:勾选为部署IT应用注册的节点。

10        部署应用

IoTEdge 边缘>节点边缘>选择创建的节点>模块管理。

1.部署$edge_apigw

image045.png

2.部署It应用

image047.png

3.最终节点部署了四个应用

image049.png

11        使用

  1. 验证北向应用NA通过云端ITIntegration调用IT应用(IA

验证方法可选择华为API ExplorerPostman等接口测试工具、实际构建南向应用NA三种方式来验证。

如果使用Postman等接口调试工具或者实际构建南向应用NA来测试请参考API参考

API Explorer界面如下:

image051.png

如果调用开发的IT应用erp-integrationApiController下的GetTest()方法,

即对应工程代码中的请求路径/api/get

image053.png

API Explorer设置如下:

在模块调试区域选择IoT>边缘>北向http请求代理>InvokeGetProxy

Region:选择所在区域

Headers:选择AK/SK认证,即使用Authorization

Params

project_id:选择Region后自动填充(如没有自动填充请开通统一身份认证服务,开通参照统一身份认证服务IAM文档,项目id获取参照 获取项目ID)。

image055.png

node_id:节点id,获取方式:IoT边缘>边缘节点>点击节点列表中节点名称>基本信息。

image057.png


ia_idIA应用id,获取方式:IoT边缘>边缘节点>点击节点列表中节点名称>模块管理。

ia_uriIA应用的接口地址,/api/get

填写完成后点击调试

image059.png

右侧的返回结果即是IT应用(IA)响应的结果。

  1. 验证IT应用(IA)通过API网关调用北向应用NA

以下代码是模拟NA接受来自API网关的转发请求。

@Controller

@Slf4j

public class ReceiveDataController {

    @RequestMapping(value = "/orders", method = RequestMethod.POST)

    @ResponseBody

    public void receive(HttpServletRequest request) {

        InputStream inputStream = null;

        ByteArrayOutputStream outputStream = null;

        try {

            inputStream = request.getInputStream();

            outputStream = new ByteArrayOutputStream();

            byte[] b = new byte[1024];

            int len;

            while ((len = inputStream.read(b)) != -1) {

                outputStream.write(b, 0, len);

            }

            log.info(new String("receive data:----------->" + new String(outputStream.toByteArray())));

        } catch (Exception e) {

            log.error("get InputStream from request failed");

        } finally {

            if (inputStream != null) {

                try {

                    inputStream.close();

                } catch (IOException e) {

                    log.error("close inputStream failed");

                }

            }

            if (outputStream != null) {

                try {

                    outputStream.close();

                } catch (IOException e) {

                    log.error("close outputStream failed");

                }

            }

        }

    }

}

将以上工程打包,部署到创建API时定义的后端服务器上运行(创建API网关时定义的host主机)。可以看到IA定时发送的数据。

image061.png

至此,运用IoT边缘,Java开发工业子系统接入完成。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。