[文章]用鸿蒙开发AI应用(八)JS框架访问内核层

阅读量0
0
3
`前言
上回说到,用C ++来写UI界面的开发效率不如JS + HTML来的高,但设备开发又免不了要通过内核态来操作硬件,这里我们就要先打通从JS框架到设备驱动之间的联系。本章基于HDF驱动和JS + CSS + HTML的技术上进行,相关内容可以回顾用鸿蒙开发AI应用(五)UI篇。

JS应用开发框架原理
在第六篇里,我们已经体验了一下使用JS开发界面的流程,这里简单分析ace的实现原理。
先看框架图,类小程序的Web应用先编译成js包,通过JS数据绑定来获取对象映射。其中观察者实现了一个极简的MVVC模型,用于将DOM上的对象分为4种类型(渲染,数据,styleSheet,功能),采用数据劫持机制分别挂载到观察者的原型函数上,并转换为C ++函数执行。
查看源码就会发现,JS的部分是极简的,JS引擎采用了JerryScript,每个标签对应了一个C ++的组件类。绝大部分功能实际都由C ++实现,包括事件注册和触发,页面路由,控件的更新,超时,文件操作,命令行输出等等...所有API的100%对接不禁让我想起一个一个指针。
进入C ++领域后就方便很多了,此时的ACE仍处于用户状态,用HDF上的消息机制可以触达内核,无非是再包装一层API的套娃操作。
内置模块
这里有一系列@ system.xxx的模块提供了访问APP,路由器,音频,传感器等设备的能力。ohos_module_config.h定义了JS框架中模块的别名到模块初始化函数的对应关系。其中app,dfx,路由器模块是必有的。
//配置信息内置OHOS平台的JS模块
常量模块OHOS_MODULES [] = {
#ifdef来ENABLE_MODULE_REQUIRE_TEST
    { “样品”,InitSampleModule},
#ENDIF
    { “应用程序”,InitAppModule}
#ifdef来FEATURE_MODULE_AUDIO
    { “音频”,InitAudioModule },
#endif // FEATURE_MODULE_AUDIO
    {“ dfx”,InitDfxModule},
    {“ router”,InitRouterModule},
#ifdef ENABLE_MODULE_CIPHER
    {“ cipher”,InitCipherModule},
#endif
};
实现ace模块
背景知识介绍完了,就可以根据业务的复杂程度来依葫芦画瓢的自定义ace模块封装功能,此处为了简化操作,我们直接在内置的app模块上挂载操作。
1.定义头文件
修改foundation / ace / frameworks / lite / src / core / modules / app_module.h,加入ToggleLed函数并初始化。
命名空间OHOS {
命名空间ACELite {
类的AppModule决赛:公共MemoryHeap {
市民:
    静态JSIValue ToggleLed(常量JSIValue thisVal,常量JSIValue *指定参数时,uint8_t argsNum);无效InitAppModule(JSIValue出口){     JSI :: SetModuleAPI(出口“的getInfo” ,AppModule :: GetInfo);     JSI :: SetModuleAPI(exports,“ terminate”,AppModule :: Terminate);     JSI :: SetModuleAPI(exports,“ toggleLed”,AppModule :: ToggleLed); } } //名称空间ACELite } //命名空间OHOS #endif // OHOS_ACELITE_APP_MODULE_H 2.调用HDF驱动









在foundation / ace / frameworks / lite / src / core / modules / app_module.cpp中加入,
的#include <fcntl.h>函数
的#include在<sys / stat.h>
#包括在<sys / ioctl.h>
的#include <unistd.h>中
的#include “hdf_***uf.h”
的#include “hdf_io_service_if.h”的#define LED_WRITE_READ 1 #定义lED_SERVICE “led_service” JSIValue的AppModule :: ToggleLed(常量JSIValue thisVal,常量JSIValue *指定参数时,uint8_t argsNum){     HILOG_ERROR(HILOG_MODULE_ACE, “LED按钮按下。”);     的printf( “LED按钮按下 n”);    结构HdfIoService * SERV = HdfIoServiceBind(LED_SERVICE,0);     如果(serv == NULL)    {         printf(“无法获得服务%s  n”,LED_SERVICE);         返回JSI :: CreateUndefined();     }
















    静态结构HdfDevEventlistener听者= {
        .callBack = OnDevEventReceived,C
        .priv =(无效*) “Service0”};    如果(!HdfDeviceRegisterEventListener(SERV,&听者)= HDF_SUCCESS)    {         printf的( “注册失败事件侦听器 n”个) ;         返回JSI :: CreateUndefined();     }    常量字符* send_cmd = “切换LED”;    如果(的SendEvent(SERV,send_cmd))    {         printf的( “失败发送事件 n”);         返回JSI :: CreateUndefined();     }    如果(HdfDeviceUnregisterEventListener(SERV,&听者))    {         printf的(”


















        返回JSI :: CreateUndefined();
    }     HdfIoServiceRecycle(SERV);    返回JSI :: CreateUndefined(); } 3.配置HDF头文件路径




修改foundation / ace / frameworks / lite / src / core / modules / BUILD.gn
include_dirs = [
    “预设”,
    “ maplejs”,
    “ // test / lite / testservice / include”,
    “ // vendor / huawei / watchgt / devkit / hal / include”,
    “ // foundation / distributedschedule / interfaces / innerkits / samgr_lite / communication / mpc / transport“,
    ” // foundation / distributedschedule / interfaces / innerkits / samgr_lite / communication / mpc“,
   
    ” // drivers / hdf / lite / include / host“,
    ” $ HDF_FRAMEWORKS / ability / ***uf / include ”,         
    “ $ HDF_FRAMEWORKS /核心/共享/包含”,
    “ $ HDF_FRAMEWORKS /核心/主机/包含”,
    “ $ HDF_FRAMEWORKS /核心/主机/包含”,
    “ $ HDF_FRAMEWORKS /包含/核心”,
    “$ HDF_FRAMEWORKS / include / utils”,
    “ $ HDF_FRAMEWORKS / utils / include”,
    “ $ HDF_FRAMEWORKS / include / osal”,
    “ $ HDF_FRAMEWORKS / adapter / syscall / include”,
    “ $ HDF_FRAMEWORKS / adapter / vnode / include”,
]
修改foundation / ace / frameworks / lite / BUILD.gn
config(“ ace_lite_config”){
  include_dirs = [
  ...
  ]
  
  include_dirs + = [
    “ // drivers / hdf / lite / include / host”,
    “ $ HDF_FRAMEWORKS / ability / ***uf / include”,         
    “ $ HDF_FRAMEWORKS / core / shared / include“,
    ” $ HDF_FRAMEWORKS / core / host / include“,
    ” $ HDF_FRAMEWORKS / core / master / include“,
    ” $ HDF_FRAMEWORKS / include / core“,
    ” $ HDF_FRAMEWORKS / include / utils“,
    ” $ HDF_FRAMEWORKS / utils /包括”,
    “ $ HDF_FRAMEWORKS /包含/ osal”,
    “ $ HDF_FRAMEWORKS /适配器/ syscall /包含”,
    “ $ HDF_FRAMEWORKS /适配器/ vnode /包含”,
  ]
}
shared_library(“ ace_lite”){
      
  public_deps = [
    “ // base / security / frameworks / crypto_lite / js / builtin:ace_kit_cipher”,
    “ // foundation / graphic / lite / frameworks / surface:surface”,
    “ // foundation / multimedia / frameworks / camera_lite:camera”,
    “ / / foundation / multimedia / frameworks / player_lite:player“,
    ” // foundation / multimedia / interfaces / kits / player_lite / js / builtin:audio_api“,
    ” // third_party / bounds_checking_function:libsec_shared“,
    ” // third_party / cJSON:cjson_shared ”,
    “ // third_party / jerryscript / jerry-core:jerry-core_shared”,
    “ // third_party / jerryscript / jerry-ext:jerry-ext_shared”,
    “ // third_party / jerryscript / jerry-libm:jerry-libm_shared”,
    ”// third_party / jerryscript / jerry-port / default:jerry-port-default_shared“,
    “// utils的/本地/精简版/ JS /内置:ace_utils_kits”,
    “// utils的/本地/精简版/ timer_task:ace_kit_timer”,    “//司机/ HDF /精简版/经理:hdf_core”,    “//司机/ hdf / lite / adapter / osal / posix:hdf_posix_osal“,  ] } 4.编译烧录python build.py my_hi3516dv300 -b调试




涉及到HDF驱动和ACE框架,就要重新完整烧录附件文件。

开发界面程序1。配置模块接口
前面我们在内置app模块上增加了函数taggleLed,对于DevEco Studio说是无法直接获取的,所以要先增加api接口。
修改 Huawei  Sdk  js  2.0.1.93  api  smartVision  @ system.app.d.ts文件
导出默认类App {
  / **
   *在应用程序的config.json文件中获取声明的信息。
   * /
  静态的getInfo():IAppInfo;   / **    *破坏电流的能力。   * /  静态终止():void;   / **    *旋转Led    * /   static toggleLed():void; } 2。页面触发





  






这里我们在之前的UI篇的程序中,借用一个滑动事件来触发此滑动Led的操作。
修改entry / src / main / js / default / pages / index / index.js
swiperChange(e){
    this.swiperPage = e.index;
    if(e.index == 0){
        this.iconcheckedColor ='#ffffff';
        this.iconUncheckedColor ='#262626';
    } else {
        this.iconcheckedColor ='#262626';
        this.iconUncheckedColor ='#ffffff';
    }
    //调用滑动Led函数
    app.toggleLed();
}
其中toggleLed这个函数名称要与之前ace模块初始化注册时,JSI :: SetModuleAPI中定义的字符串名称相匹配。

3.打包成堆
将应用打包成Hap改名为MyUILed.hap

4.安装到设备
具体nfs映射目录,参考前篇所述。
mkdir nfs
mount 192.168.1.52:/nfs / nfs nfs
cd nfs
./dev_tools/bin/bm set -s disable
./dev_tools/bin/bm install -p MyUILed.hap

5.运行程序
滑动主界面,看到Led灯切换就说明程序运行成功了。


简单总结一下整个流程,
  • 主页面索引,从'@ system.app'模块导入应用;
  • 事件中调用app.toggleLed();来发起操作;
  • 通过JS框架打包成MyUILed.hap(本质是一个zip包);
  • 安装到设备上后,就被解压还原成成JS代码;
  • 设备上的ace框架通过JSI :: SetModuleAPI,将JS代码通过关键字“ toggleLed”映射成对应的C ++函数AppModule :: ToggleLed;
  • AppModule :: ToggleLed函数中找到LED_SERVICE,发送HDF消息
  • 内核中HDF驱动收到消息后,真正执行了LED左右操作。


至此之后,鱼和熊掌是可以兼得了,我们既能高效的以类小程序方式来构建漂亮的UI部分,又能高效的用C ++来访问设备能够功能,可以为后续大量的AI密集计算铺平了道路。

资料下载
本期相关文件资料,可在公众号“深度觉醒”,后台回复:“ ohos08”,获取下载链接。

下一篇预告
最近更新DevEco设备工具2.0,
整合了很多hpm和hos命令,
下一篇,我们先来尝鲜一下新版的烧录工具,
敬请期待...


`
ace.gif

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友