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

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

3天内不再提示

基于鸿蒙开发的触摸屏控制LED

鸿蒙系统HarmonyOS 来源:51cto 作者:bluishfish 2021-04-16 15:30 次阅读

这一篇我们继续深入一点点,尝试打通从用户态UI到内核态HDF之间的联系。其中涉及到的调用关系比较复杂,建议在“用鸿蒙开发AI应用(五)HDF 驱动补光灯”的基础上阅读本文,HDF的相关细节这里就不在赘述了。

背景知识
用户程序框架子系统包含两个大的模块:Ability子系统和包管理子系统。

1. Ability子系统

pIYBAGB5O-2AJaIMAAEnRKm16s4052.png

1.1 Ability
Ability是系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability

Page类型的Ability:带有界面,为用户提供人机交互的能力。
Service类型的Ability:不带界面,为用户提供后台任务机制。
1.2 AbilitySlice
AbilitySlice是单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。

o4YBAGB5O_qAEaXvAAAY6m6FzAE694.png

1.3 生命周期
生命周期是Ability被调度到启动、激活、隐藏和退出等各个状态的的统称。

pIYBAGB5PAWAL_3uAABpLf4BFf0101.png

Ability生命周期各状态解析:

UNINITIALIZED:未初始状态,为临时状态,Ability被创建后会由UNINITIALIZED状态进入INITIAL状态;
INITIAL:初始化状态,也表示停止状态,表示当前Ability未运行,调用Start后进入INACTIVE,同时回调开发者的OnStart生命周期回调;
INACTIVE:未激活状态,表示当前窗口已显示但是无焦点状态,由于Window暂未支持焦点的概念,当前状态与ACTIVE一致。
ACTIVE:前台激活状态,表示当前窗口已显示,并获取焦点,Ability在退到后台之前先由ACTIVE状态进入INACTIVE状态;
BACKGROUND: 后台状态,表示当前Ability退到后台,Ability在被销毁后由BACKGROUND状态进入INITIAL状态,或者重新被激活后由BACKGROUND状态进入ACTIVE状态。
1.4 AbilityLoader
AbilityLoader负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。

1.5 AbilityManager
AbilityManager负责AbilityKit和Ability管理服务进行IPC的通信

1.6 EventHandler
EventHandler是AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。

1.7 Ability运行管理服务
Ability运行管理服务是用于协调各Ability运行关系、及生命周期进行调度的系统服务。

其中,服务启动模块负责Ability管理服务的启动、注册等。

服务接口管理模块负责Ability管理服务对外能力的管理。

进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。

生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。

连接管理模块是Ability管理服务对Service类型Ability连接管理的模块。

1.8 AppSpawn
AppSpawn是负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。

2. 包管理子系统
包管理子系统,是OpenHarmony为开发者提供的安装包管理框架。

o4YBAGB5PBGAVJToAADZsNeQIeo099.png

BundleKit:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化监听接口。
包扫描器:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。
包安装子模块:安装,卸载,升级一个包;包安装服务一个单独进程的用于创建删除安装目录,具有较高的权限。
包管理子模块:管理安装包相关的信息,存储持久化包信息。
包安全管理子模块:签名检查、权限授予、权限管理。

HDF驱动LED(可选)
之前在内核中已经注册过一个led_driver驱动,并以led_service服务发布,这一节稍微重构一下代码,功能上没有变化,我们快速过一遍,熟悉HDF的可以自行跳过。

1. 业务代码
先新建头文件vendorhuaweihdfledincludeled_ctrl.h。

#ifndef _LED_CTRL_H
#define _LED_CTRL_H

#include "hdf_device_desc.h"
#include "hdf_log.h"
#include "device_resource_if.h"
#include "osal_io.h"
#include "osal_mem.h"
#include "gpio_if.h"
#include "osal_irq.h"
#include "osal_time.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

extern int32_t CtlLED(int mode);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* _LED_CTRL_H */

再新建源文件 vendorhuaweihdfledled_ctrl.c

#include "led_ctrl.h"

#define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签

int32_t CtlLED(int mode)
{
    int32_t ret;
    uint16_t valRead;
    /* LED的GPIO管脚号 */
    // uint16_t gpio = 5 * 8 + 1;  // 红外补光灯
    uint16_t gpio = 2 * 8 + 3;  // 绿色指示灯
    // uint16_t gpio = 3 * 8 + 4;  // 红色指示灯

    /* 将GPIO管脚配置为输出 */
    ret = GpioSetDir(gpio, GPIO_DIR_OUT);
    if (ret != 0)
    {
        HDF_LOGE("GpioSerDir: failed, ret %d
", ret);
        return ret;
    }

    if (mode == -1)
    {
        // 翻转输出口
        (void)GpioRead(gpio, &valRead);
        ret = GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
    }
    else
    {
        ret = GpioWrite(gpio, mode);
    }

    if (ret != 0)
    {
        HDF_LOGE("GpioWrite: failed, ret %d
", ret);
        return ret;
    }
    return ret;
}

先完成对绿色指示灯的控制逻辑。

2. 驱动实现 在 huawei/hdf 目录下新建一个文件夹 led, 然后在其中新建一个源文件 led.c。

#include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件
#include "hdf_log.h"         // HDF 框架提供的日志接口头文件
#include "led_ctrl.h"

// #define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签
#define LED_WRITE_READ 1       // 读写操作码1

// Dispatch是用来处理用户态发下来的消息
int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    int32_t result = HDF_FAILURE;
    HDF_LOGE("Led driver dispatch");
    if (client == NULL || client->device == NULL)
    {
        HDF_LOGE("Led driver device is NULL");
        return HDF_ERR_INVALID_OBJECT;
    }

    switch (cmdCode)
    {
    case LED_WRITE_READ:
        const char *recv = HdfSbufReadString(data);
        if (recv != NULL)
        {
            HDF_LOGI("recv: %s", recv);
            result = CtlLED(-1);
            // result = CtlLED(GPIO_VAL_HIGH);
            if (!HdfSbufWriteInt32(reply, result))
            {
                HDF_LOGE("replay is fail");
            }
            return HdfDeviceSendEvent(client->device, cmdCode, data);
        }
        break;

    default:
        break;
    }
    return result;
}

//驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架
int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL)
    {
        HDF_LOGE("Led driver bind failed!");
        return HDF_ERR_INVALID_OBJECT;
    }
    static struct IDeviceIoService ledDriver = {
        .Dispatch = LedDriverDispatch,
    };

    deviceObject->service = (struct IDeviceIoService *)(&ledDriver);
    HDF_LOGD("Led driver bind success");
    return HDF_SUCCESS;
}


// 驱动自身业务初始的接口
int32_t HdfLedDriverInit(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL)
    {
        HDF_LOGE("Led driver Init failed!");
        return HDF_ERR_INVALID_OBJECT;
    }
    HDF_LOGD("Led driver Init success");
    return HDF_SUCCESS;
}

// 驱动资源释放的接口
void HdfLedDriverRelease(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL)
    {
        HDF_LOGE("Led driver release failed!");
        return;
    }

    HDF_LOGD("Led driver release success");
    return;
}

// 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
struct HdfDriverEntry g_ledDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "led_driver",
    .Bind = HdfLedDriverBind,
    .Init = HdfLedDriverInit,
    .Release = HdfLedDriverRelease,
};

// 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
HDF_INIT(g_ledDriverEntry);

3. 驱动编译 在 huawei/hdf/led 目录下新建编译文件 Makefile。

include $(LITEOSTOPDIR)/../../drivers/hdf/lite/lite.mk

MODULE_NAME := hdf_led_driver
LOCAL_SRCS += led_ctrl.c 
			  led.c 
              
LOCAL_INCLUDE := ./include
LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror
include $(HDF_DRIVER)

4. 编译结果链接到内核镜像 修改 huawei/hdf/hdf_vendor.mk 文件,添加以下代码

LITEOS_BASELIB += -lhdf_led_driver  #链接生成的静态库
LIB_SUBDIRS    += $(VENDOR_HDF_DRIVERS_ROOT)/led  #驱动代码Makefile的目录

5. 驱动配置 修改 vendor/hisi/hi35xx/hi3516dv300/config/device_info/device_info.hcs配置文件,添加驱动的设备描述。

platform :: host {
    hostName = "platform_host";  // host名称,host节点是用来存放某一类驱动的容器
    priority = 50;  // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序

    device_led :: device {                  // led设备节点
        device0 :: deviceNode {             // led驱动的DeviceNode节点
            policy = 2;                     // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍
            priority = 100;                 // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序
            preload = 0;                    // 驱动按需加载字段
            permission = 0666;              // 驱动创建设备节点权限
            moduleName = "led_driver";      // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
            serviceName = "led_service";    // 驱动对外发布服务的名称,必须唯一
            deviceMatchAttr = "led_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
        }
    } 

编译用户程序框架子系统 1. 添加配置文件 在 build/lite/platform/hi3516dv300_liteos_a/platform.json中的subsystems字段下面添加appexecfwk和aafwk。

{
  "subsystem": "aafwk",
  "components": [
    {
      "component": "ability",
      "optional": "true",
      "dirs": [
        "foundation/aafwk"
      ],
      "targets": [
        "//foundation/aafwk/frameworks/ability_lite:aafwk_abilitykit_lite",
        "//foundation/aafwk/frameworks/ability_lite:aafwk_abilityMain_lite",
        "//foundation/aafwk/frameworks/abilitymgr_lite:aafwk_abilityManager_lite",
        "//foundation/aafwk/services/abilitymgr_lite:aafwk_services_lite"
      ],
      "features": [
        {"enable_ohos_appexecfwk_feature_ability": "true"}
      ],
      "deps": {
        "components": [
          "hilog_a",
          "bundle_mgr",
          "system_ability_manager",
          "distributed_schedule",
          "graphic",
          "utils",
          "ipc"
        ],
        "third_party": [
          "cjson",
          "bounds_checking_function"
        ]
      }
    }
  ]
},

{
  "subsystem": "appexecfwk",
  "components": [
    {
      "component": "bundle_mgr",
      "optional": "true",
      "dirs": [
        "foundation/appexecfwk"
      ],
      "targets": [
        "//foundation/appexecfwk/services/bundlemgr_lite:appexecfwk_services_lite",
        "//foundation/appexecfwk/frameworks/bundle_lite:appexecfwk_kits_lite"
      ],
      "features": [],
      "deps": {
        "components": [
          "iam",
          "app_verify",
          "hilog_a",
          "system_ability_manager",
          "global_resource_manager",
          "graphic",
          "utils"
        ],
        "third_party": [
          "cjson",
          "zlib"
        ]
      }
    }
  ]
},

2. 添加编译文件 新建buildliteconfigsubsystemaafwkBUILD.gn文件,

import("//build/lite/config/subsystem/lite_subsystem.gni")

lite_subsystem("aafwk") {
    subsystem_components = [
        "//foundation/aafwk/frameworks/ability_lite:aafwk_abilitykit_lite",
        "//foundation/aafwk/frameworks/abilitymgr_lite:aafwk_abilityManager_lite",
        "//foundation/aafwk/services/abilitymgr_lite:aafwk_services_lite",
    ]
}

新建/build/lite/config/subsystem/appexecfwk/BUILD.gn文件,

import("//build/lite/config/subsystem/lite_subsystem.gni")

lite_subsystem("appexecfwk") {
    subsystem_components = [
        "//foundation/appexecfwk/kits/appkit_lite:appexecfwk_kit_lite",
        "//foundation/appexecfwk/services/bundlemgr_lite:appexecfwk_services_lite",
    ]
}

3. 运行管理服务 用户程序框架有两个系统服务ability管理服务(abilityms)和(bundlems),两系统服务运行于foundation进程中。

abilityms和bundlems注册到sa_manager中,sa_manager运行于foundation进程中,sa_manager为abilityms和bundlems创建线程运行环境。

在foundation/distributedschedule/services/safwk_lite/BUILD.gn中添加对abilityms和bundlems

deps = [
    "...",
]
if (ohos_kernel_type == "liteos_a") {
    deps += [
        "...",
        "//foundation/aafwk/services/abilitymgr_lite:abilityms",
        "//foundation/appexecfwk/services/bundlemgr_lite:bundlems",
        "...",
    ]
}

基于AbilityKit开发的Ability 1. 主页面实现 新建源文件applicationssamplecameramyLedAppsrcmain_ability.cpp

#include "main_ability.h"

namespace OHOS {
REGISTER_AA(MainAbility)

void MainAbility::OnStart(const Want &want)
{
    printf("MainAbility::OnStart
");
    SetMainRoute("MainAbilitySlice");

    Ability::OnStart(want);
}

2. 分片页面 2.1 定义控件常量 新建源文件main_ability_slice.cpp, 屏幕大小为960x480

#include "main_ability_slice.h"

#include "ability_manager.h"
#include "components/ui_label.h"
#include "components/ui_label_button.h"
namespace OHOS
{
REGISTER_AS(MainAbilitySlice)

constexpr static int BUTTON1_POSITION_X = 380;
constexpr static int BUTTON1_POSITION_Y = 200;
constexpr static int BUTTON_WIDTH = 200;
constexpr static int BUTTON_HEIGHT = 80;
constexpr static int ROOT_VIEW_POSITION_X = 0;
constexpr static int ROOT_VIEW_POSITION_Y = 0;
constexpr static int ROOT_VIEW_WIDTH = 960;
constexpr static int ROOT_VIEW_HEIGHT = 480;
constexpr static uint8_t ROOT_VIEW_OPACITY = 255;
constexpr static uint8_t FONT_ID = 10;

constexpr static int BUTTON1_POSITION_X = 380;
constexpr static int BUTTON1_POSITION_Y = 200;
constexpr static int BUTTON_WIDTH = 200;
constexpr static int BUTTON_HEIGHT = 80;
constexpr static int ROOT_VIEW_POSITION_X = 0;
constexpr static int ROOT_VIEW_POSITION_Y = 0;
constexpr static int ROOT_VIEW_WIDTH = 960;
constexpr static int ROOT_VIEW_HEIGHT = 480;
constexpr static uint8_t ROOT_VIEW_OPACITY = 255;
constexpr static uint8_t FONT_ID = 10;
} // namespace OHOS

2.2 创建按钮和布局 在生命周期函数OnStart中,全屏放置一个rootView_,居中位置放置一个按钮button1。

void MainAbilitySlice::OnStart(const Want &want)
{
    printf("MainAbilitySlice::OnStart
");
    AbilitySlice::OnStart(want);
	
	auto button1 = new UILabelButton();
    button1->SetPosition(BUTTON1_POSITION_X, BUTTON1_POSITION_Y);
    button1->SetText("翻转 LED");
    button1->Resize(BUTTON_WIDTH, BUTTON_HEIGHT);
    button1->SetFontId(FONT_ID);
    button1->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
    button1->SetStyle(STYLE_TEXT_OPA, ROOT_VIEW_OPACITY);
    button1->SetStyle(STYLE_BACKGROUND_OPA, ROOT_VIEW_OPACITY);

    rootView_ = RootView::GetWindowRootView();
    rootView_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y);
    rootView_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT);

    rootView_->Add(button1);
    SetUIContent(rootView_);
}

2.3 实现驱动消息机制 这里顺便提一下,文档中DevSvcManagerClntGetService接口仅在内核态有效,可以方便的获取服务并直接调用。鸿蒙作为微内核的OS,想从用户态调用内核态函数,要么用框架的消息机制,要么自己用中断服务实现。

#define LED_WRITE_READ 1
#define LED_SERVICE "led_service"

static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
    const char *string = HdfSbufReadString(data);
    if (string == NULL)
    {
        printf("fail to read string in event data
");
        return HDF_FAILURE;
    }
    printf("%s: dev event received: %u %s
", (char *)priv, id, string);

    return HDF_SUCCESS;
}

static int SendEvent(struct HdfIoService *serv, const char *eventData)
{
    int ret = 0;
    struct HdfSBuf *data = HdfSBufObtainDefaultSize();
    if (data == NULL)
    {
        printf("fail to obtain sbuf data
");
        return 1;
    }

    struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
    if (reply == NULL)
    {
        printf("fail to obtain sbuf reply
");
        ret = HDF_DEV_ERR_NO_MEMORY;
        HdfSBufRecycle(data);
        return ret;
    }

    if (!HdfSbufWriteString(data, eventData))
    {
        printf("fail to write sbuf
");
        ret = HDF_FAILURE;
        HdfSBufRecycle(data);
        HdfSBufRecycle(reply);
        return ret;
    }

    ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE_READ, data, reply);
    if (ret != HDF_SUCCESS)
    {
        printf("fail to send service call
");
        HdfSBufRecycle(data);
        HdfSBufRecycle(reply);
        return ret;
    }

    int replyData = 0;
    if (!HdfSbufReadInt32(reply, &replyData))
    {
        printf("fail to get service call reply
");
        ret = HDF_ERR_INVALID_OBJECT;
        HdfSBufRecycle(data);
        HdfSBufRecycle(reply);
        return ret;
    }
    printf("Get reply is: %d
", replyData);

    HdfSBufRecycle(data);
    HdfSBufRecycle(reply);
    return ret;
}

2.4 加入点击事件 每次点击按钮,向内核态发送一次消息。

auto onClick = [this](UIView &view, const Event &event) -> bool {
    printf("led button pressed
");

    struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE, 0);
    if (serv == NULL)
    {
        printf("fail to get service %s
", LED_SERVICE);
        return false;
    }

    static struct HdfDevEventlistener listener = {
        .callBack = OnDevEventReceived,
        .priv = (void *)"Service0"};

    if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS)
    {
        printf("fail to register event listener
");
        return false;
    }

    const char *send_cmd = "toggle LED";

    if (SendEvent(serv, send_cmd))
    {
        printf("fail to send event
");
        return false;
    }

    if (HdfDeviceUnregisterEventListener(serv, &listener))
    {
        printf("fail to  unregister listener
");
        return false;
    }

    HdfIoServiceRecycle(serv);

    return true;
};

2.5 注销页面 在生命周期函数OnStop中,删除所有节点,回收系统资源。

void DeleteViewChildren(UIView *view)
{
    if (view == nullptr) {
        return;
    }
    while (view != nullptr) {
        UIView *tempView = view;
        view = view->GetNextSibling();
        if (tempView->IsViewGroup()) {
            DeleteViewChildren(dynamic_cast(tempView)->GetChildrenHead());
        }
        if (tempView->GetParent()) {
            dynamic_cast(tempView->GetParent())->Remove(tempView);
        }
        delete tempView;
    }
}

void MainAbilitySlice::OnStop()
{
    printf("MainAbilitySlice::OnStop
");
    AbilitySlice::OnStop();
    DeleteViewChildren(rootView_);
}

3. 编译配置 新增 applicationssamplecameramyLedAppBUILD.gn文件

import("//build/lite/config/component/lite_component.gni")
import("//build/lite/config/subsystem/aafwk/config.gni")

HDF_FRAMEWORKS = "//drivers/hdf/frameworks"
src_path = "//applications/sample/camera/myLedApp/src"

lite_library("ledability") {
    target_type = "shared_library"
    ldflags = [
        "-shared",
    ]
    sources = [
        "${src_path}/main_ability.cpp",
        "${src_path}/main_ability_slice.cpp",
    ]

    include_dirs = [
        ".",
        "//foundation/aafwk/frameworks/ability_lite/example/entry/src/main/cpp",
        "//foundation/aafwk/interfaces/innerkits/abilitymgr_lite",
        "//foundation/aafwk/interfaces/kits/ability_lite",
        "//foundation/aafwk/interfaces/kits/want_lite",
        "//foundation/appexecfwk/interfaces/kits/bundle_lite",
        "//foundation/appexecfwk/utils/bundle_lite",
        "//foundation/communication/interfaces/kits/ipc_lite",
        "//foundation/graphic/lite/interfaces/kits/config",
        "//foundation/graphic/lite/interfaces/kits/ui",
        "//foundation/graphic/lite/interfaces/kits/utils",
        "//kernel/liteos_a/kernel/common",
        "//kernel/liteos_a/kernel/include",
        "//drivers/hdf/lite/include/host",
        "$HDF_FRAMEWORKS/ability/sbuf/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/include",
        "$HDF_FRAMEWORKS/include/osal",
        "//kernel/liteos_a/platform/include",
        "$HDF_FRAMEWORKS/adapter/syscall/include",
        "$HDF_FRAMEWORKS/adapter/vnode/include",
    ]

    deps = [
        "//foundation/aafwk/frameworks/ability_lite:aafwk_abilitykit_lite",
        "//drivers/hdf/lite/manager:hdf_core",
        "//drivers/hdf/lite/adapter/osal/posix:hdf_posix_osal",
    ]

    defines = [
        "OHOS_APPEXECFWK_BMS_BUNDLEMANAGER",
    ]

    if (enable_ohos_appexecfwk_feature_ability == true) {
        deps += [
            "//foundation/graphic/lite/frameworks/ui:ui",
        ]
        defines += [
            "ENABLE_WINDOW=1",
            "ABILITY_WINDOW_SUPPORT"
        ]
    }
    output_dir = "$root_out_dir/dev_tools/led"
}

4. 应用配置文件 新建 applicationssamplecameramyLedAppconfig.json

{
    "app": {
        "bundleName": "com.bluishfish.ledability",
        "vendor": "huawei",
        "version": {
            "code": 1,
            "name": "1.0"
        },
       "apiVersion": {
          "compatible": 3,
          "target": 3
       }
    },
    "deviceConfig": {
        "default": {
            "keepAlive": false
        }
    },
    "module": {
        "deviceType": [
            "smartVision"
        ],
        "distro": {
            "deliveryWithInstall": true,
            "moduleName": "ledability",
            "moduleType": "entry"
        },
        "abilities": [{
            "name": "MainAbility",
            "icon": "assets/entry/resources/base/media/icon.png",
            "label": "Led Ability",
            "launchType": "standard",
            "type": "page",
            "visible": true
        }
        ]
    }
}

pIYBAGB5PDmAei8AAAW28OA8_Nw355.png

5. 板级编译配置 复制 build/lite/product/ipcamera_hi3516dv300.json,改名为my_hi3516dv300在子系统里加入

{
  "ohos_version": "OpenHarmony 1.0",
  "board": "hi3516dv300",
  "kernel": "liteos_a",
  "compiler": "clang",
  "subsystem": [
    {
      "name": "aafwk",
      "component": [
            "......",
            { "name": "ability_led", "dir": "//applications/sample/camera/myLedApp:ledability", "features": []}
        ]
"......"

6. 编译应用

python build.py my_hi3516dv300 -b debug

pIYBAGB5PEyAOaMFAAjowlNYmwI845.png

将系统烧录到开发板上。

7. 打包应用 在 assetsentry esourcesasemedia目录下放置一个icon.png作为启动图标。

将applicationssamplecameramyLedAppconfig.json和 Z:openharmonyoutmy_hi3516dv300dev_toolsledlibledability.so打包压缩成zip包

o4YBAGB5PFuASD0cAAKCDqA_DQE480.png

改名为ledability.hap ,复制到NFS共享目录

8. 安装Hap

mkdir nfs
mount 192.168.1.57:/nfs /nfs nfs
./nfs/dev_tools/bin/bm set -s disable
./nfs/dev_tools/bin/bm install -p ./nfs/ledability.hap

o4YBAGB5PGyAL6XaAAdvlK4yXMc748.png

9. 运行程序

./nfs/dev_tools/bin/aa start -p com.bluishfish.ledability -n MainAbility

完美!

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

    关注

    87

    文章

    30095

    浏览量

    268361
  • 鸿蒙系统
    +关注

    关注

    183

    文章

    2634

    浏览量

    66204
收藏 人收藏

    评论

    相关推荐

    触摸屏的工作原理

    触摸屏的工作原理 摘 要:简要介绍触摸屏的结构及工作原理,并以Burr-Brown公司的触摸屏控制芯片ADS7843为例,介绍触摸屏应用的
    发表于 03-26 16:22 79次下载

    触摸屏的应用与工作原理

    触摸屏的应用与工作原理 摘 要:简要介绍触摸屏的结构及工作原理,并以Burr-Brown公司的触摸屏控制芯片ADS7843为例,介绍触摸屏
    发表于 12-28 12:22 3032次阅读
    <b class='flag-5'>触摸屏</b>的应用与工作原理

    触摸屏原理详细解析

    触摸屏常识,触摸屏原理详细解析触摸屏知识与原理
    发表于 03-24 10:47 8893次阅读

    电阻式触摸屏,什么是电阻式触摸屏

    电阻式触摸屏,什么是电阻式触摸屏   这种触摸屏利用压力感应进行控制。电阻触摸屏的主要部分是一块与显示器表面非常配合的电
    发表于 03-24 11:02 5535次阅读

    什么是电容触摸屏

    什么是电容触摸屏 电容触摸屏图片 电容触摸屏的英文名称the introduction of Capa
    发表于 04-30 08:54 2151次阅读

    基于单片机的液晶显示触摸屏控制设计

    在分析液晶触摸屏的工作原理基础上,分析触摸屏专用控制器 ADS7846的工作原理与控制方式。 通过ADS7846与 MCU的API接口,给出 AT89S51的测量子程序流程图,提出
    发表于 11-09 16:14 17次下载

    触摸屏技术是谁发明的_触摸屏技术的发展历程

    什么是触摸屏技术 为了操作上的方便,人们用触摸屏来代替鼠标或键盘。 触摸屏触摸检测部件和触摸屏控制
    发表于 11-06 02:57 2.9w次阅读

    基于触摸屏控制LED彩色台灯控制系统的设计

    本系统是利用触摸屏控制的可调颜色的照明灯具。灯源为大功率超高亮三基色发光二极管组成。本设计最大的亮点是触摸屏上所指示的颜色与实际灯照出的颜色一致。到通过 C 语言程序对单片机的 PWM 功能进行
    发表于 11-06 11:24 8次下载
    基于<b class='flag-5'>触摸屏</b><b class='flag-5'>控制</b>的<b class='flag-5'>LED</b>彩色台灯<b class='flag-5'>控制</b>系统的设计

    组态王和触摸屏哪个好_组态王和触摸屏区别

    现在组态软件和触摸屏都是市场上边较成熟的产品,组态软件的出现并没有取代触摸屏触摸屏触摸屏的优势,组态软件有组态软件的特点。组态软件和触摸屏
    发表于 11-29 17:11 3.5w次阅读

    基于触摸屏LED驱动电路设计

    系统的总体框图如图1 所示。系统可有输入,输出,控制三部分组成,当触摸屏被按下触摸屏芯片读取触摸屏上X 轴与Y 轴的值,然后通过SPI 协议传送到
    发表于 06-12 15:40 4301次阅读
    基于<b class='flag-5'>触摸屏</b>的<b class='flag-5'>LED</b>驱动电路设计

    PLC触摸屏的作用_触摸屏是怎样控制PLC的

    PLC程序是用来控制电气设备传动的智能仪器,它需要工程人员利用编程语言编写程序,以实现各种控制方式。触摸屏程序可与PLC可编程序控制器直接连接,实现对可编程序
    发表于 05-21 10:46 1.9w次阅读

    触摸屏电容原理_触摸屏有哪些应用领域

    触摸屏是目前最友好的计算机用户接口界面,在消费电子产品的应用越来越广泛,触摸检测好装置和触摸屏控制器,触摸屏装置过程中对检测装置的机械结构造
    发表于 06-26 16:59 2557次阅读

    触摸屏电容的原理,触摸屏有哪些应用领域

    瑞翔数码触摸屏电容原理 触摸屏是目前最友好的计算机用户接口界面,在消费电子产品的应用越来越广泛,触摸检测好装置和触摸屏
    发表于 03-18 17:24 2998次阅读

    modbus触摸屏

    modbus触摸屏是指支持Modbus通讯协议的触摸屏,它可以通过串口或网络与其他设备进行通讯,从而实现对其他设备的控制和监测。Modbus触摸屏通常用于工业自动化、智能家居、智能大厦
    的头像 发表于 06-28 09:34 1556次阅读
    modbus<b class='flag-5'>触摸屏</b>

    电容触摸屏原理 电容触摸屏和电阻触摸屏有什么区别

    电容触摸屏和电阻触摸屏是两种常见的触摸屏技术,它们在原理、结构和应用方面都有很大的区别。下面将详细介绍电容触摸屏的原理、结构和特点,并与电阻触摸屏
    的头像 发表于 01-22 16:13 4046次阅读