我的项目概述

可能有些同学曾经接触过了规范零碎上的软总线利用开发,然而你玩过轻量零碎上的软总线利用吗?当初它来了。咱们利用OpenAtom OpenHarmony 3.1 Release(以下简称“OpenHarmony”)版本的轻量零碎软总线能力,将智能燃气检测设施和智能窗户通风设备组成一个轻量级分布式网络,实现设施之间的互相管制。
原理图如下:

当家中的燃气告警时,无需任何操作,间接管制窗户通风零碎中的电机工作。

开发阐明

从下面的视频中能够看到,相干案例设施的利用界面都能够分成外设交互页面和软总线操作页面两大块。在上面的零碎框图中能够看到相干页面和其依赖的相干轻量零碎能力。例如外设交互界面通过自定义JSI接口与设施硬件打交道,软总线操作界面则通过轻量零碎的设施治理能力、软总线能力来实现设施间的发现、认证、传输等软总线操作。
在上面的内容中咱们将以智能燃气告警器设施为例,将相干开发过程分成JS利用端开发、自定义JSI实现、开发板端代码三局部来阐明:

JS利用开发
燃气告警器JS利用是基于3.1 release版本,并联合方舟开发框架(ArkUI)、分布式组网等个性,应用JS语言开发的一款分布式平安厨房利用。为了体现了 OpenHarmony轻量级分布式个性,不仅须要思考页面该如何设计、利用怎么同外设交互,还须要思考两个轻量级设施间如何进行设施认证,设施间如何进行通信等问题。
所以在相干利用中设计了操作页面,报警页面以及设施认证页面。其中首页是设置燃气浓度阈值,以及显示以后燃气浓度;报警页面是当首页检测到以后燃气浓度达到或高于咱们设置的阈值时,会从首页跳转到报警界面;设施认证页面则是对两台设施进行分布式组网。
代码构造如下图:

外设交互页面开发

相干界面如上图所示,咱们将首页页面分成三个局部:顶部标签、燃气浓度显示、设置告警阈值。接下来是具体的解析内容:
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 状态打印        });    },

设施认证页面开发

相干界面如上图所示,咱们将设施认证步骤分成四个步骤:发现设施、发动认证、容许认证、输出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通信操作流程。

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

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

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动作,做好接管发现音讯的筹备。

设施间RPC通信
在规范零碎利用开发中,咱们能够通过分布式数据库和启动近程Ability的形式实现设施之间的通信,而在轻量零碎中则通过RPC的办法来实现。在后面的内容中咱们讲了服务的概念,上面是拓展的相干原理图:

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.c...
    轻量零碎利用开发软总线视频课程:
    https://www.bilibili.com/vide...
    设施治理模块文档:
    https://gitee.com/openharmony...
    智能燃气检测零碎样例:
    https://growing.openharmony.c...
    智能窗户通风零碎样例:
    https://growing.openharmony.c...

    总结

    从本文中能够看到与规范零碎一样利用都是调用设施治理模块提供的相干接口来实现的软总线发现、认证等性能,然而不同的中央在于规范零碎应用了预制的DeviceManager_UI.hap来显示PIN码、输出PIN码。而轻量零碎软总线利用中,相干PIN码显示、PIN码输出须要本人调用相干接口。
    与规范零碎软总线利用相比,目前轻量零碎软总线利用只实现了轻量零碎设施之前数据流转性能,轻量零碎分布式拉起、分布式数据库等性能待后续更新迭代。下一步还将钻研如何利用软总线来连贯轻量零碎和规范零碎,敬请大家期待。
    丰盛多样的OpenHarmony开发样例离不开宽广合作伙伴和开发者的奉献,如果你也想把本人开发的样例分享进去,欢送提交到OpenHarmony常识体系SIG仓库。
    共建开发样例参考https://gitee.com/openharmony...