4

跟着小白一起学鸿蒙--JS应用控制LED(十)

 1 year ago
source link: https://www.51cto.com/article/720991.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

跟着小白一起学鸿蒙--JS应用控制LED(十)

作者:王石 2022-10-20 16:40:16
Ace(foundation/arkui/ace_engine_lite)是OpenHarmony的轻量级系统所使用的UI框架子系统,为开发者提供JS-UI开发框架。包括.html,.css,.js。
328ca059318cfb5a2358667519cac0d2073dfb.png

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

在《#跟着小白一起学鸿蒙# [九] 写个简单的LED驱动》我们熟悉了如何在开源鸿蒙开发驱动应用,并通过hdc工具拷贝至开发板运行。在《#跟着小白一起学鸿蒙#[六]第一个hap应用》的文章里我们学会如何用IDE工具编写hap应用并他通过IDE工具安装至开发板运行。我们学会了hap程序的开发,但是hap程序是运行在标准系统的应用,对于轻量和小型系统我们应该如何进行开发呢?接下来我们需要学习下如何开发JS应用。

轻量、小型系统JS应用

Ace(foundation/arkui/ace_engine_lite)是OpenHarmony的轻量级系统所使用的UI框架子系统,为开发者提供JS-UI开发框架。包括.html,.css,.js。开发者可以通过DevEco工具进行开发。其中JS的引擎采用三方库里的JerryScript(jerryscript是IoT设备上的轻量级JS引擎,支持ECMAScript 5.1标准,适配低内存硬件,最小运行在64KB RAM和小于200KB的flash,提供C API)。关于jerryscript的详细介绍可以看如下参考链接(https://github.com/jerryscript-project/jerryscript )。

#冲刺创作新星# #跟着小白一起学鸿蒙# [十] JS应用控制LED-开源基础软件社区

详细的内容介绍在一下链接内可以看到官方的说明:

参考链接:https://gitee.com/openharmony/arkui_ace_engine_lite。

此样例参考小熊派设计,使用小熊派HM_Micro开发板进行验证。

JS-UI开发流程

graph LR
 --> 配置工程 --> 增加LED程序 --> 添加JSAPI接口

创建工程配置工程增加LED程序添加JSAPI接口编译运行。

建立[Lite]Empty Ability。

#冲刺创作新星# #跟着小白一起学鸿蒙# [十] JS应用控制LED-开源基础软件社区

配置工程。

#冲刺创作新星# #跟着小白一起学鸿蒙# [十] JS应用控制LED-开源基础软件社区

工程结构说明。

#冲刺创作新星# #跟着小白一起学鸿蒙# [十] JS应用控制LED-开源基础软件社区

工程目录主要在entry里,有以下内容:

  • .preview: 界面预览目录。
  • build: 工程编译目录。
  • src:包括i18n(国际化翻译路径),pages(界面目录,index.css, index.hml, index.js)。

工程预览。

#冲刺创作新星# #跟着小白一起学鸿蒙# [十] JS应用控制LED-开源基础软件社区

添加按键功能控制LED灯。

  • 修改index.hml
<div class="container">
    <text class="title">
        {{ $t('strings.hello') }} {{ title }}
    </text>

    <div class="rowcontainer">
        <text class="content" if="{{statu == '0'}}">[状态:{{ $t('strings.ledoff') }}]</text>
        <text class="content" if="{{statu == '1'}}">[状态:{{ $t('strings.ledon') }}]</text>
        <text class="content" onclick="ledon">
            {{ $t('strings.ledon') }}
        </text>
        <text class="content" onclick="ledoff">
            {{ $t('strings.ledoff') }}
        </text>
        <text class="content" onclick="ledtoggle">
            {{ $t('strings.ledtoggle') }}
        </text>
    </div>
    <text class="content" onclick="exit">
        {{ $t('strings.exit') }}
    </text>
</div>
  • 修改index.css
.container {
    width: 100%;
    height: 100%;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
.title {
    width: 200px;
    font-size: 30px;
    text-align: center;
}
.content{
    width: 200px;
    font-size: 30px;
    text-align: center;
}
.rowcontainer {
    width: 100%;
    height: 50%;
    flex-direction: row;
    justify-content: center;
    align-items: center;
}
  • 修改index.js
var led = {open:1,close:0,change:2}
import app from '@system.app';
export default {
    data: {
        title: "",
        statu:'0'
    },
    onInit() {
        this.title = this.$t('strings.world');
    },
    ledon(e) {
        let that = this
        console.info("ledon")
        app.ledcontrol({
            code:led.open,
            success(res){
                that.statu = res.led_status
            },
            fail(res,code){
                console.error("ledon error")
            },
            complete(){
                console.info("ledon complete")
            }
        })
    },
    ledoff(e) {
        let that = this
        console.info("ledoff")
        app.ledcontrol({
            code:led.close,
            success(res){
                that.statu = res.led_status
            },
            fail(res,code){
                console.error("ledoff error")
            },
            complete(){
                console.info("ledoff complete")
            }
        })
    },
    ledtoggle(e) {
        let that = this
        console.info("ledtoggle")
        app.ledcontrol({
            code:led.change,
            success(res){
                that.statu = res.led_status
            },
            fail(res,code){
                console.error("ledtoggle failed")
            },
            complete(){
                console.info("ledtoggle complete")
            }
        })
    },
    exit(e) {
        app.terminate()
    },
}
#冲刺创作新星# #跟着小白一起学鸿蒙# [十] JS应用控制LED-开源基础软件社区
  • 将代码编译成hap包:点击编辑器最左下角的OhosBuild Varilants,打开编译模式选择视图,编译模式分debug和release,选择release模式;
  • 点击编辑器上方菜单栏的Build->Build Hap(s)/App(s)->Build Hap(s),系统就会开始自动编译代码成hap包,等到下方Build Output无编译错误,就表示代码编译完成了。

增加JS的API接口。

  • 在app_module.h里增加接口
JSI::SetModuleAPI(exports, "ledcontrol", AppModule::ToggleLed);
  • 在app_module.cpp里增加接口实现
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"
#define LED_WRITE_READ 1
#define LED_SERVICE "hdf_led"
......
static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
    uint32_t value;
    HdfSbufReadUint32(data, &value);
    HILOG_ERROR(HILOG_MODULE_ACE,"%s: dev event received: %u %u\n", (char *)priv, id, value);

    return HDF_SUCCESS;
}
static int GpioWriteRead(struct HdfIoService *serv, int32_t eventData, int32_t *val)
{
    int ret = HDF_FAILURE;
    struct HdfSBuf *data = HdfSBufObtainDefaultSize();
    struct HdfSBuf *reply = HdfSBufObtainDefaultSize();

    if (data == NULL || reply == NULL) {
        HILOG_ERROR(HILOG_MODULE_ACE,"fail to obtain sbuf data\n");
        return ret;
    }
    if (!HdfSbufWriteUint8(data, (uint8_t)eventData))
    {
        HILOG_ERROR(HILOG_MODULE_ACE,"fail to write sbuf\n");
        HdfSBufRecycle(data);
        HdfSBufRecycle(reply);
        return ret;
    }
    ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE_READ, data, reply);
    if (ret != HDF_SUCCESS)
    {
        HILOG_ERROR(HILOG_MODULE_ACE,"fail to send service call\n");
        HdfSBufRecycle(data);
        HdfSBufRecycle(reply);
        return ret;
    }
    if (!HdfSbufReadInt32(reply, val))
    {
        HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service call reply\n");
        ret = HDF_ERR_INVALID_OBJECT;
        HdfSBufRecycle(data);
        HdfSBufRecycle(reply);
        return ret;
    }
    HILOG_ERROR(HILOG_MODULE_ACE,"Get reply is: %d\n", val);

    HdfSBufRecycle(data);
    HdfSBufRecycle(reply);
    return ret;
}
JSIValue AppModule::ToggleLed(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
{
    HILOG_ERROR(HILOG_MODULE_ACE, "led button pressed.");
    struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE);
    if (serv == NULL)
    {
        HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service2 %s\n", LED_SERVICE);
        return JSI::CreateUndefined();
    }
    if ((args == nullptr) || (argsNum == 0) || (JSI::ValueIsUndefined(args[0]))) {
        return JSI::CreateUndefined();
    }
    JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
    JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
    JSIValue complete = JSI::GetNamedProperty(args[0], CB_COMPLETE);

    int32_t num = (int32_t)JSI::GetNumberProperty(args[0], "code");

    int32_t replyData = 0;

    if (GpioWriteRead(serv, num, &replyData))
    {
        HILOG_ERROR(HILOG_MODULE_ACE,"fail to send event\n");
        JSI::CallFunction(fail, thisVal, nullptr, 0);
        JSI::CallFunction(complete, thisVal, nullptr, 0);
        JSI::ReleaseValueList(success, fail, complete);
        return JSI::CreateUndefined();
    }
    JSIValue result = JSI::CreateObject();
    JSI::SetNumberProperty(result, "led_status", replyData);
    JSIValue argv[ARGC_ONE] = {result};
    JSI::CallFunction(success, thisVal, argv, ARGC_ONE);
    JSI::CallFunction(complete, thisVal, nullptr, 0);
    JSI::ReleaseValueList(success, fail, complete, result);

    HdfIoServiceRecycle(serv);

    return JSI::CreateUndefined();
}
  • 在foundation\ace\ace_engine_lite\ace_lite.gni中添加HDF头文件路径
ace_lite_include_dirs += [    
    ......    
    "//drivers/framework/ability/sbuf/include",
    "//drivers/framework/include/core",
    "//drivers/framework/include/utils",
    "//drivers/adapter/uhdf/posix/include",
]
  • 添加编译依赖
修改foundation\ace\ace_engine_lite\frameworks\BUILD.gn,在public_deps中添加以下代码
"//drivers/adapter/uhdf/manager:hdf_core",
修改foundation\ace\ace_engine_lite\test\ace_test_config.gni,在extra_deps中添加以下代码
"//drivers/adapter/uhdf/manager:hdf_core",
  1. 基于JS扩展的类Web开发范式的方舟开发框架,采用经典的HML、CSS、JavaScript三段式开发方式。使用HML标签文件进行布局搭建,使用CSS文件进行样式描述,使用JavaScript文件进行逻辑处理。UI组件与数据之间通过单向数据绑定的方式建立关联,当数据发生变化时,UI界面自动触发更新。此种开发方式,更接近Web前端开发者的使用习惯,快速将已有的Web应用改造成方舟开发框架应用。主要适用于界面较为简单的中小型应用开发;
  2. 通过appmodule调用framework层接口,然后通过framework接口调用Hdf接口。

这样我们就有了自己的driver和配置,后面的章节我们会讲如何在hap应用里调用驱动接口。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

责任编辑:jianghua 来源: 51CTO开源基础软件社区

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK