0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

尝试轻量系统上的软总线应用

OpenAtom OpenHarmony 来源:OpenAtom OpenHarmony 作者:张宇航 2022-07-08 09:54 次阅读

项目概述

可能有些同学已经接触过了标准系统上的软总线应用开发,但是你玩过轻量系统上的软总线应用吗?现在它来了。我们利用OpenAtom OpenHarmony 3.1 Release(以下简称“OpenHarmony”)版本的轻量系统软总线能力,将智能燃气检测设备和智能窗户通风设备组成一个轻量级分布式网络,实现设备之间的相互控制。 原理图如下:

8f4aefb2-fdf6-11ec-ba43-dac502259ad0.jpg

以下是实际操作效果: 当家中的燃气告警时,无需任何操作,直接控制窗户通风系统中的电机工作。

开发说明

从上面的视频中可以看到,相关案例设备的应用界面都可以分成外设交互页面和软总线操作页面两大块。在下面的系统框图中可以看到相关页面和其依赖的相关轻量系统能力。例如外设交互界面通过自定义JSI接口与设备硬件打交道,软总线操作界面则通过轻量系统的设备管理能力、软总线能力来实现设备间的发现、认证、传输等软总线操作。

在下面的内容中我们将以智能燃气告警器设备为例,将相关开发过程分成JS应用端开发、自定义JSI实现、开发板端代码三部分来说明:

8f5e4bf2-fdf6-11ec-ba43-dac502259ad0.png

JS应用开发

燃气告警器JS应用是基于3.1 release版本,并结合方舟开发框架(ArkUI)、分布式组网等特性,使用JS语言开发的一款分布式安全厨房应用。为了体现了 OpenHarmony轻量级分布式特性,不仅需要考虑页面该如何设计、应用怎样同外设交互,还需要考虑两个轻量级设备间如何进行设备认证,设备间如何进行通讯等问题。

所以在相关应用中设计了操作页面,报警页面以及设备认证页面。其中首页是设置燃气浓度阈值,以及显示当前燃气浓度;报警页面是当首页检测到当前燃气浓度达到或高于我们设置的阈值时,会从首页跳转到报警界面;设备认证页面则是对两台设备进行分布式组网。

代码结构如下图:

8f71cd80-fdf6-11ec-ba43-dac502259ad0.png

外设交互页面开发

8f80db86-fdf6-11ec-ba43-dac502259ad0.png

相关界面如上图所示,我们将首页页面分成三个部分:顶部标签、燃气浓度显示、设置告警阈值。接下来是具体的解析内容:

1)顶部标签解析

顶部标签中除了相关文本界面,主要是顶部两个按钮,分别用来显示当前Wi-Fi连接状态以及跳转到设备认证页面。

GetKey() { com.get({ // 获取wifi状态 key: 'storage_key', success: (data)=> { let res = JSON.parse(data) if (res.wifi) { if(res.wifi == 'connected') { this.isWifi = true; } else { this.isWifi = false; } } ..... }, }); }, changePage(operation) { router.replace({ uri:"pages/dm/dm" // 跳转到设备认证页面 });}

2)燃气浓度显示

主要是获取当前燃气浓度,并实时刷新到相关界面上。

onInit() { setTimeout(()=>{ setInterval(()=>this.GetKey(),500) // 每500ms 获取一次 },3000); }, GetKey() { com.get({ key: 'storage_key', success: (data)=> { let res = JSON.parse(data) if (res.CurrentGasCONC) { this.currentValue = res.CurrentGasCONC; this.progressPercent = ((this.currentValue ) /300) * 100 if(this.currentValue >this.PresetValue && !this.isChange){ this.isChange = true; router.replace({ uri:"pages/warn/warn" // 燃气数值超标后自动跳转告警页面 }); } } }, ...... });},

3)设置报警阈值

首页界面中对于报警阈值的处理,主要包含减小预设阈值和增大预设阈值,都是通过调用相关SetKey操作完成的。

reduceProgress(){ //减小预设阈值 if (this.PresetValue <= 0) { this.PresetValue = 0 }else{ this.PresetValue = parseInt(this.PresetValue) - 20 } this.isChange = false; this.setProgress = ((this.PresetValue ) /300) * 100 this.SetKey( 'GasThreshold', this.PresetValue ); }, addProgress(){ //增大预设阈值 if (this.PresetValue >= 300) { this.PresetValue = 300 }else{ this.PresetValue = parseInt(this.PresetValue) + 20 } this.isChange = false; this.setProgress = ((this.PresetValue ) /300) * 100 this.SetKey( 'GasThreshold', this.PresetValue ); }, SetKey(key1, value1) { com.set({ key: key1 + '', value: value1 + '', // success or failed 状态打印 });},设备认证页面开发

8f9eb606-fdf6-11ec-ba43-dac502259ad0.png

相关界面如上图所示,我们将设备认证步骤分成四个步骤:发现设备、发起认证、允许认证、输入PIN码。接下来是具体的解析内容:

1)发现设备解析

设备认证因设备状态不同显示对应的UI,上图显示的UI对应设备状态”status = start“。

startDevice(){ this.subscribeId = Math.floor(Math.random() * 10000 + 1000) var info = { "subscribeId": this.subscribeId, // 特定随机的 "mode": 0xAA, // 设置主动发现模式,除此之外还有被动模式DISCOVER_MODE_PASSIVE "medium": 0, // 自动选择发现介质,目前用的是coap "freq": 2, // 发送发现消息的频率,目前用的是HIGH 还有LOW/MID/SUPER_HIGH "isSameAccount": false, // 取消同一账号下才能发现的限制 "isWakeRemote": false, // 目前轻量系统没有睡眠模式,所以不用睡眠唤醒功能 "capability": 0 // 目前使用DDMP devicemanager.startDeviceDiscovery(info); // 开始设备发现},2)发起认证解析

AuthenticateDevice(){ // 发起认证 let extraInfo = { targetPkgName: 'test', appName: "Newname", appDescription: "testAPP", business: '0', displayOwner: 0 }; let AuthParam = { authType: 1, // 以PIN 码方式进行认证校验 appIcon:null, appThumbnail:null, extraInfo: extraInfo }; let _this = this; devicemanager.authenticateDevice(this.statusInfo, AuthParam, { // 省略了相关success 和fail 回调处理,完整代码见参考链接},

3)允许认证解析

当设备状态”status = join-pin“,允许相关认证动作并且显示相关PIN码。

joinAuthOk() { this.joinPin() //切换显示PIN码界面 this.initStatue() //获取PIN码并显示 devicemanager.setUserOperation(0) }, initStatue() { this.log('initStatue') const data = devicemanager.getAuthenticationParam() // 参数值转换为 JSON 字符串写入data this.log('getAuthenticationParam:' + JSON.stringify(data)) // Authentication type, 1 for pin code. // ode ==1,pin码 if (data && data.authType == 1) { // 完整代码见参考链接 }},

4)输入PIN码解析

当设备状态"status = main-pin",进到相关PIN码输入、校验界面。

mainInputPin(s) { // 输入六位数字 if (this.pinNumb == 6) return if (this.pinNumb < 6) { this.pin[this.pinNumb] = s ++this.pinNumb } if (this.pinNumb == 6) { console.log("verifyAuthInfo ok") this.verifyAuthInfo(this.pin.join('')) // PIN码校验 }    }, 

自定义JSI原理和实现

JSI是OpenHarmony轻量和小型系统的一种JS API实现机制,适合封装IO、CPU密集型、OS底层等能力给到JS应用调用,通过JSI可以实现JS与C/C++代码互相访问。与OpenHarmony 轻量级系统中涉及到的 audio、device、sensor 等需要与硬件打交道的JSI 模块类似,CommunicationKit 和DeviceManager模块同样首先要加入到相关的配置文件中。ace_lite_engine 通过JSI::SetModuleAPI将JS应用中使用的关键字映射成C++函数。具体操作如下:

foundation/ace/ace_engine_lite/frameworks/module_manager/ohos_module_config.h中的OHOS_MODULES新增如下字段:

{"CommunicationKit", InitNativeApiCommunicationKit},{"devicemanager",InitDeviceManagerModule},

加载自定义模块

如上所示,在JS应用外设控制界面中数据读取和命令下发时,引入了CommunicationKit模块,现在我们就看一下相关具体内容:

InitNativeApiCommunicationKit函数相关内容如下:

vendor/team_x/common/communicationkit/native_utils/src/nativeapi_communication_kit.cppvoid InitNativeApiCommunicationKit(JSIValue exports) { JSI::SetModuleAPI(exports, "get", NativeapiCommunicationKit::Get); // 与JS应用中的关键字一致 JSI::SetModuleAPI(exports, "set", NativeapiCommunicationKit::Set);} 相关C++实现NativeapiCommunicationKit::Get 和Set 的方式类似,我们参考轻量系统源码中其他模块的实现,使用ExecuteAsyncWork函数。根据给定的参数创建一个异步工作,并将其分派给主应用程序任务处理程序。其获取燃气浓度逻辑在ExecuteGet实现,设置轻量系统燃气告警阈值由ExecuteSet实现。函数args参数用来接收JS端传过来的参数(JSIValue数组),argsNum表示该数组长度。

ExecuteAsyncWork(thisVal, args, argsNum, ExecuteGet, false);ExecuteAsyncWork(thisVal,args,argsNum,ExecuteSet,false);

加载设备管理模块

与自定义模块类似,JS应用使用软总线接口时,需要在应用执行前加载设备管理模块。设备管理模块也是OpenHarmony系统中的重要组成部分,我们在标准系统中是通过NAPI的方式来加载相关模块,而在我们轻量系统中,设备管理模块是通过JSI的方式来加载的。首先看到InitDeviceManagerModule函数相关内容如下:

foundation/distributedhardware/devicemanager/interfaces/kits/js_mini/src/native_devicemanager_js.cppvoid InitDeviceManagerModule(JSIValue exports) { JSI::SetModuleAPI(exports, "createDeviceManager", DeviceManagerModule::CreateDeviceManager); ...... JSI::SetModuleAPI(exports, "startDeviceDiscovery", DeviceManagerModule::StartDeviceDiscoverSync); JSI::SetModuleAPI(exports, "stopDeviceDiscovery", DeviceManagerModule::StopDeviceDiscoverSync); JSI::SetModuleAPI(exports, "authenticateDevice", DeviceManagerModule::AuthenticateDevice); JSI::SetModuleAPI(exports, "verifyAuthInfo", DeviceManagerModule::VerifyAuthInfo); JSI::SetModuleAPI(exports, "setUserOperation", DeviceManagerModule::SetUserOperationSync); JSI::SetModuleAPI(exports, "getAuthenticationParam", DeviceManagerModule::GetAuthenticationParamSync); ......}

开发板端代码开发说明

如下图所示,我们从轻量系统软总线设备的系统启动流程出发,来分析软总线应用执行的相关要点。第一步:首先初始化软总线server;第二步:注册与软总线相关的服务,例如PRC、设备管理DeviceManager服务;第三步:JS engine加载DeviceManager接口声明;第四步:具体的RPC通信操作流程。

8fb5ff28-fdf6-11ec-ba43-dac502259ad0.png

初始化软总线服务

轻量系统设备启动的启动过程中,会注册相关初始化软总线服务线程。该线程中的主要内容就是调用InitSoftBusServer函数。该函数会初始化与软总线相关的配置、发现、认证等相关操作。

8fc2dbb2-fdf6-11ec-ba43-dac502259ad0.jpg

软总线相关服务注册

服务是OpenHarmony系统中的一个重要概念,不同的功能模块,不同线程/进程之间的调用接口,都统一抽象成了服务。利用服务机制,操作系统、驱动框架等提供的能力都能被包装成服务提供给到应用调用。下面给大家具体介绍软总线相关的服务注册细节和要点。

8fd74bec-fdf6-11ec-ba43-dac502259ad0.png

SAMGR:作为中介者,管理Provider提供的能力,同时帮助Consumer发现Provider的能力。

Provider:服务的提供者,为系统提供能力(对外接口)。

PRC服务注册

RPC:(Remote Procedure Call)用于跨设备跨进程间的通信,在轻量系统软总线应用中,我们利用RPC能力实现了安全厨房项目中两个设备的关联控制,RPC服务注册的具体内容如下:

1.创建相关的静态服务对象;

static MiniService g_miniService = { .GetName = GetName, // 相关服务名为mini_sa_rpc .Initialize = Initialize, .MessageHandle = MessageHandle, .GetTaskConfig = GetTaskConfig, SERVER_IPROXY_IMPL_BEGIN, .Invoke = FeatureInvoke, // 对外提供Invoke方法,供RPC相关client端程序调用 IPROXY_END,}; 2.注册相关的服务和缺省对象;

SAMGR_GetInstance()->RegisterService((Service *)&g_miniService); SAMGR_GetInstance()->RegisterDefaultFeatureApi(MINI_SERVICE,GET_IUNKNOWN(g_miniService));

设备管理服务注册

如果没注册设备管理服务,那么相关软总线能力也就无从谈起。在轻量系统启动时,执行相关设备管理服务初始化动作,具体内容如下:

1)创建相关的静态服务对象;

static DeviceManagerSamgrService service = { .GetName = GetName, // 相关服务名为dev_mgr_svc .Initialize = Initialize, .MessageHandle = MessageHandle, .GetTaskConfig = GetTaskConfig,}; 2)注册相关的服务和缺省对象;

SAMGR_GetInstance()->RegisterService((Service *)&service)) ;SAMGR_GetInstance()->RegisterDefaultFeatureApi(DEVICE_MANAGER_SERVICE_NAME, GET_IUNKNOWN(service)); 3)执行相关初始化动作。DeviceManager服务的初始化函数将完成相关状态回调注册和传输通道初始化,然后执行相关Publish动作,做好接收发现消息的准备。

8feaaed0-fdf6-11ec-ba43-dac502259ad0.jpg

设备间RPC通信

在标准系统应用开发中,我们可以通过分布式数据库和启动远程Ability的方式实现设备之间的通信,而在轻量系统中则通过RPC的方法来实现。在前面的内容中我们讲了服务的概念,下面是拓展的相关原理图:

90071980-fdf6-11ec-ba43-dac502259ad0.png

Consumer:服务的消费者,调用服务提供的功能(对外接口)。

在完成软总线组网后,如果检测到燃气度数超标后,按如下步骤即可实现对智能通风设备的控制:

1.获取软总线网络中的相关节点信息

GetAllNodeDeviceInfo("com.ohos.devicemanagerui", &nodeInfo, &infoNum); 2.获取远程节点发布的mini_sa_rpc服务中对应的IUnknown方法;

IUnknown *miniDefApi = SAMGR_GetInstance()->GetRemoteDefaultFeatureApi(nodeInfo[0]->networkId, "mini_sa_rpc"); 3.查询服务所发布的相关能力,获取指向具体API接口的指针miniInterface;

miniDefApi->QueryInterface(miniDefApi, 0, (void **) &miniInterface); 4.调用相关mini_sa_rpc对外提供的Invoke能力;

miniInterface->Invoke(miniInterface, 1, &reply, NULL, NULL);

操作体验

1. 提前准备好安全厨房场景中的智能窗户通风设备和智能燃气告警设备,并完成相关的编译和应用安装动作;

2. 提前准备好正常工作的无线路由设备(请保证预设热点名称:test_wifi 密码:12345678;是否能连接互联网均可)

3. 将燃气检测设备和窗户通风设备上电,确认两个设备应用启动正常和操作正常;

4. 按如下步骤将通风设备、燃气检测设备组成一个软总线网络:

● 分别点击两个设备应用界面右上角的软总线配置图标,进入软总线配置界面;

● 点击智能燃气检测设备应用发现图标,间隔3S后点击发起认证图标;

● 点击智能通风设备软总线配置界面下的允许认证图标,正常情况下会显示一个6位数的PIN码;

● 点击智能燃气检测设备应用输入PIN码按钮,进入数字键盘输入PIN码;

● 分别点击两个应用软总线配置图标左上角的返回按键,进入设备控制界面。

5. 设置燃气检测设备的阈值低于实际读取的燃气数值,燃气检测应用进入警报界面的同时会控制电机工作,自动通风换气,保证家居的安全。待到实际燃气数值低于设置的阈值时,则关闭电机。

参考链接

本项目中涉及到的参考资料和相关文档路径如下:

欧智通BES2600WM开发板快速上手学习路径:

https://growing.openharmony.cn/mainPlay/learnPathMaps?id=17

轻量系统应用开发软总线视频课程:

https://www.bilibili.com/video/BV1BS4y1A7ry/?vd_source=fa133082ba4f0aaa5d2dae4f0a981ab3

设备管理模块文档:

https://gitee.com/openharmony/device_manager/blob/master/README_zh.md

智能燃气检测系统样例:

https://growing.openharmony.cn/mainPlay/detail?sampleId=3935

智能窗户通风系统样例:

https://growing.openharmony.cn/mainPlay/detail?sampleId=3936

总结

从本文中可以看到与标准系统一样应用都是调用设备管理模块提供的相关接口来实现的软总线发现、认证等功能,但是不同的地方在于标准系统使用了预制的DeviceManager_UI.hap来显示PIN码、输入PIN码。而轻量系统软总线应用中,相关PIN码显示、PIN码输入需要自己调用相关接口。

与标准系统软总线应用相比,目前轻量系统软总线应用只实现了轻量系统设备之前数据流转功能,轻量系统分布式拉起、分布式数据库等功能待后续更新迭代。下一步还将研究如何利用软总线来连接轻量系统和标准系统,敬请大家期待。

丰富多样的OpenHarmony开发样例离不开广大合作伙伴和开发者的贡献,如果你也想把自己开发的样例分享出来,欢迎提交到OpenHarmony知识体系SIG仓库。

审核编辑:何安

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 总线
    +关注

    关注

    10

    文章

    2713

    浏览量

    87223
  • OpenHarmony
    +关注

    关注

    23

    文章

    3311

    浏览量

    15159

原文标题:你玩过轻量系统软总线应用吗?

文章出处:【微信号:gh_e4f28cfa3159,微信公众号:OpenAtom OpenHarmony】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    STM32L431RCT6 CAN电后无法正常发送,但是能接收是什么原因?

    添加发送失败系统复位函数,发现系统复位后就能正常发送数据。 总体分析下来就感觉是电后CAN模块没有初始化好,但是同样的程序在其他6块板子
    发表于 04-12 08:01

    基于KNX总线技术设计的智能照明控制系统

    智能照明控制系统 安科瑞王璐月 +acrel66 1、概述   Acrel-Bus智能照明控制系统(以下简称系统),是基于KNX总线技术设计的控制
    的头像 发表于 03-26 09:51 285次阅读
    基于KNX<b class='flag-5'>总线</b>技术设计的智能照明控制<b class='flag-5'>系统</b>

    给大家讲讲嵌入式系统中I²C总线的时序

    I²C总线在嵌入式系统中很常见,今天就来给大家讲讲I²C总线的时序。
    的头像 发表于 02-23 09:47 659次阅读
    给大家讲讲嵌入式<b class='flag-5'>系统</b>中I²C<b class='flag-5'>总线</b>的时序

    CAN总线高层协议CANWeb现场总线源程序

    此开发板的PCB文件及Keil源程序基础,只需调用几个函数就能轻松、快捷开发自己的CANWeb总线产品,如多通道DI、DO、AI、AO模块、温度、压力现场智能仪表、电动调节阀、电磁阀、电量
    发表于 12-28 11:02

    如何消除EMC对总线系统的干扰?

    如何消除EMC对总线系统的干扰? EMC(电磁兼容性)是指不同电子设备在电磁环境中能够和谐共存的能力。现代社会中,我们被无数个电子设备所包围,这些设备会产生电磁辐射,并且相互之间也会产生干扰,从而
    的头像 发表于 12-11 16:44 527次阅读

    并行总线和串行总线的区别

    并行总线和串行总线的区别  并行总线和串行总线是计算机系统中常见的两种数据传输方式,它们有着不同的工作原理和应用场景。在这篇文章中,我将详细
    的头像 发表于 12-07 16:45 2017次阅读

    详解纯电动汽车的CAN总线系统

    CAN总线英文全称为Controller Area Network,即控制器局域网,是目前汽车上使用最广泛的总线之一。纯电动汽车一般装有7个CAN总线系统,各汽车制造公司的命名不一致,
    的头像 发表于 11-13 10:05 4948次阅读
    详解纯电动汽车的CAN<b class='flag-5'>总线</b><b class='flag-5'>系统</b>

    汽车CAN总线系统的挑战与设计

    CAN总线技术已在汽车上广泛应用,随着新能源车型以及自动驾驶技术的推广,总线问题也对汽车的安全带来风险挑战,本文从系统角度对CAN总线的电气、EMC、硬件以及软件等相关设计进行梳理,结
    的头像 发表于 11-03 10:17 670次阅读
    汽车CAN<b class='flag-5'>总线</b><b class='flag-5'>系统</b>的挑战与设计

    OpenHarmony开发板汇总

    Tiger(A311D)标准系统:DAYU200开发套件(RK3568)标准系统通扬帆富设备开发板(RK3399) 系统类型 OpenHarmony支持如下几种
    发表于 10-19 11:27

    嵌入式PLC系统研究和实现

    PLC要实现的功能封装在软件里,然后运行于硬件系统平台上。PLC综合了计算机和PLC的开关最控制、模拟量控制、逻辑运算、数值处理、网络通信等功能,通过一个多任务内核提供强大的指令集、快速准确的扫描
    发表于 09-25 07:15

    基于CAN总线的温度测控系统介绍

    ,而且能够将分布在不同地点的温度测控模块通过cAN现场总线连接起来,接入PC机进行集中监控和管理。本系统采用CAN现场总线进行通讯,由于一条cAN总线上的节点个数在理论
    发表于 09-19 06:45

    求助,所搭的IP核的通讯协议与总线支持的通讯协议(ICB)不同怎么转换?

    所搭的IP核的通讯协议与总线支持的通讯协议(ICB)不同怎么转换?
    发表于 08-17 07:05

    核移植到自己的FPGA板卡后,如何与FPGA的硬件模块进行交互?

    核移植到自己的FPGA板卡后,需要设计硬件模块,设计的硬件模块怎么与核通信呢?通过核的ICB总线吗?如果想把ICB总线转为AXI
    发表于 08-12 07:08

    什么是LIN总线?车载总线之LIN总线概述

    LIN(Local Interconnect Network)即局部连接网络,也被称为“局域网子系统”即LIN总线是CAN总线网络下的子系统,车上各个LIN
    发表于 07-26 10:12 8910次阅读
    什么是LIN<b class='flag-5'>总线</b>?车载<b class='flag-5'>总线</b>之LIN<b class='flag-5'>总线</b>概述

    STM32芯片内部的总线系统结构

    一、前言 本篇介绍STM32芯片内部的总线系统结构,嵌入式芯片内部的总线和计算机总线类似,先来看一下通常定义下计算机总线定义,即计算机的
    的头像 发表于 06-22 09:14 3058次阅读
    STM32芯片内部的<b class='flag-5'>总线</b><b class='flag-5'>系统</b>结构