用鴻蒙開發AI應用(七)觸控螢幕控制LED

2021-02-20 深度覺醒
背景知識

用戶程序框架子系統包含兩個大的模塊:Ability子系統和包管理子系統。

1. Ability子系統1.1 Ability

Ability是系統調度應用的最小單元,是能夠完成一個獨立功能的組件,一個應用可以包含一個或多個Ability。Ability分為兩種類型:Page類型的Ability和Service類型的Ability

「Page類型的Ability」:帶有界面,為用戶提供人機互動的能力。「Service類型的Ability」:不帶界面,為用戶提供後臺任務機制。1.2 AbilitySlice

AbilitySlice是單個頁面及其控制邏輯的總和,是Page類型Ability特有的組件,一個Page類型的Ability可以包含多個AbilitySlice,此時,這些頁面提供的業務能力應當是高度相關的。

1.3 生命周期

生命周期是Ability被調度到啟動、激活、隱藏和退出等各個狀態的的統稱。

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為開發者提供的安裝包管理框架。

「BundleKit」:是包管理服務對外提供的接口,有安裝/卸載接口、包信息查詢接口、包狀態變化監聽接口。「包掃描器」:用來解析本地預製或者安裝的安裝包,提取裡面的各種信息,供管理子模塊進行管理,持久化。「包安裝子模塊」:安裝,卸載,升級一個包;「包安裝服務」一個單獨進程的用於創建刪除安裝目錄,具有較高的權限。「包管理子模塊」:管理安裝包相關的信息,存儲持久化包信息。「包安全管理子模塊」:籤名檢查、權限授予、權限管理。HDF驅動LED(可選)

之前在內核中已經註冊過一個led_driver驅動,並以led_service服務發布,這一節稍微重構一下代碼,功能上沒有變化,我們快速過一遍,熟悉HDF的可以自行跳過。

1. 業務代碼

先新建頭文件vendor\huawei\hdf\led\include\led_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 */

再新建源文件 vendor\huawei\hdf\led\led_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\n", 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\n", 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. 添加編譯文件

新建build\lite\config\subsystem\aafwk\BUILD.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開發的Ability1. 主頁面實現

新建源文件applications\sample\camera\myLedApp\src\main_ability.cpp

#include "main_ability.h"

namespace OHOS {
REGISTER_AA(MainAbility)

void MainAbility::OnStart(const Want &want)
{
printf("MainAbility::OnStart\n");
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\n");
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\n");
return HDF_FAILURE;
}
printf("%s: dev event received: %u %s\n", (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\n");
return 1;
}

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

if (!HdfSbufWriteString(data, eventData))
{
printf("fail to write sbuf\n");
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\n");
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
return ret;
}

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

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

2.4 加入點擊事件

每次點擊按鈕,向內核態發送一次消息。

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

struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE, 0);
if (serv == NULL)
{
printf("fail to get service %s\n", 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\n");
return false;
}

const char *send_cmd = "toggle LED";

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

if (HdfDeviceUnregisterEventListener(serv, &listener))
{
printf("fail to unregister listener\n");
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<UIViewGroup *>(tempView)->GetChildrenHead());
}
if (tempView->GetParent()) {
dynamic_cast<UIViewGroup *>(tempView->GetParent())->Remove(tempView);
}
delete tempView;
}
}

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

3. 編譯配置

新增 applications\sample\camera\myLedApp\BUILD.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. 應用配置文件

新建 applications\sample\camera\myLedApp\config.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
}
]
}
}

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

將系統燒錄到開發板上。

7. 打包應用

在 assets\entry\resources\base\media\目錄下放置一個icon.png作為啟動圖標。

將applications\sample\camera\myLedApp\config.json和 Z:\openharmony\out\my_hi3516dv300\dev_tools\led\libledability.so打包壓縮成zip包

改名為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

9. 運行程序
./nfs/dev_tools/bin/aa start -p com.bluishfish.ledability -n MainAbility


完美!

總結

整理一下思路,

我們先用AbilityKit繪製Ability頁面,在其button1上綁定一個按鈕事件;

觸發後,由用戶子系統尋找到led_server服務,向HDF框架發送消息;

內核驅動led_driver接收到消息後,調用底層GPIO控制LED翻轉,並將操作狀態以reply消息的形式傳回用戶側;

後續可以接著根據返回狀態更新下界面。

好了,在此基礎上美化下界面,接個繼電器做個智能家居的App應該不是難事了。

源碼下載

本期相關文件資料,可在公眾號「深度覺醒」,後臺回覆:「ohos07」,獲取下載連結。

相關焦點

  • 觸控螢幕原理介紹
    觸控螢幕又稱為「觸控屏」、「觸控面板」,是一種可接收觸頭等輸入訊號的感應式液晶顯示裝置;當接觸了屏幕上的圖形按鈕時,屏幕上的觸覺反饋系統可根據預先編程的程式驅動各種連結裝置,可用以取代機械式的按鈕面板,並藉由液晶顯示畫面製造出生動的影音效果,其主要應用領域為手機、平板電腦、收銀機、工業領域等。
  • 鴻蒙系統日誌工具HiLog的使用方法!
    我們需要通過列印一條條日誌來掌握程序運行的狀態,下面我們就來講解鴻蒙系統中的 HiLog 日誌工具的具體使用方法。①使用 HiLog 前必須在 HiLog 的一個輔助類 HiLogLabel 中定義日誌類型、服務域和標記。
  • 鴻蒙生態圈究竟利好了誰 | 衣公子
    今天的人已經不記得了,當年反對的聲音有多強烈。 反對者的理由是,4G投資巨大,是個天文數字。而且,3G燒了那麼多錢終於有了起色,完全夠用,這個時候上4G是重複建設是面子工程。 還有個理由,中國在通信產業上,一直是唯唯諾諾的跟隨者。說到底,對中國人沒信心。 但是,到今天,所有人都在稱讚中國果敢的4G戰略。
  • 內核教程|觸控螢幕原理介紹
    二、常見觸控螢幕分類目前市面上主要有幾種類型的觸控螢幕:電阻式,表面電容式和感應電容式觸控螢幕,表面聲波式,紅外式,以及彎曲波式、有源數字轉換器式和光學成像式觸控螢幕。其中又可以為兩類,一類需要ITO,比如前三種觸控螢幕,另一類的結構中不需要ITO, 比如後幾種屏。目前市場上,使用ITO材料的電阻式觸控螢幕和電容式觸控螢幕應用最為廣泛。
  • 用Python控制Arduino
    下位機是直接控制設備獲取設備狀況的計算機。上位機發出的命令首先給下位機,下位機根據命令直接控制相應設備。下位機不時讀取設備狀態數據(一般為模擬量),轉換成數位訊號反饋給上位機。簡而言之:上下位機通過程序實現交互,不需要人工參與,一定程度上兩者可以相互轉化。
  • 威綸觸控螢幕圖文教程
    使用人機界面還可以使機器的配線標準化、簡單化,同時也能減少PLC控制器所需的I/O點數,降低生產的成本同時由於面板控制的小型化及高性能,相對的提高了整套設備的附加價值。觸控螢幕作為一種新型的人機界面,從一出現就受到關注,它的簡單易用,強大的功能及優異的穩定性使它非常適合用於工業環境,甚至可以用於日常生活之中,應用非常廣泛,比如:自動化停車設備、自動洗車機、天車升降控制、生產線監控等,甚至可用於智能大廈管理、會議室聲光控制、溫度調整…… 1.
  • 好用的七款安卓模擬器推薦一波
    今天小編整理了七款安卓模擬器向大家推薦一下,僅供參考。 一:藍疊模擬器BlueStacksBlueStacks安卓模擬器是市面上兼容性最好的安卓模擬器,它能讓您手機上的應用在電腦端windows作業系統上完美運行,就如同用電腦操作手機一般,無論是qq微信等聊天工具,還是時空獵人、刀塔傳奇等手機遊戲,都能用藍疊安卓模擬器BlueStacks使用。
  • 淺析紅外線LED晶片的應用
    普通的的紅外線led外形和一般的可見光LED相似,但卻是發出紅外線。其管壓一般降約1.4v,工作電流一般小於20mA。為了適應不同的工作電壓,迴路中常常串有限流電阻。
  • 【嵌入式AI開發&Maxim篇六】美信Maxim78000Evaluation Kit 進階開發之指紋識別
    上篇:【嵌入式AI開發&Maxim篇五】美信Maxim78000Evaluation Kit AI進階開發之人臉識別介紹了使用Maxim78000Evaluation Kit進行常用的人臉識別實戰開發,部署我們自己的AI模型。本篇進行繼續實戰,基於知識蒸餾網絡部署更複雜的指紋識別算法模型。關注公眾號獲取最新資訊。
  • 如何使用 React、Firebase 和 Alan AI 構建語音控制的 Todo 應用
    為了構建這個基於語音的 Todo 應用程式,我們將使用三個主要工具:那麼,讓我們開始吧。如何使用 React 創建 Todo 應用 UI讓我們首先創建一個 React 應用程式。(或名稱),例如基於語音的 Todo 應用程式或你選擇的任何內容。
  • 用單片機控制飛彈?
    一、前言 前幾天和一個在某研究所的髮小聊天,他說:現在的航空、航天和飛彈等武器裝備中,控制系統幾乎都是用單片機,而不是嵌入式系統。乍一聽,和我們的直覺有矛盾啊:那麼高大上的設備,其中的控制邏輯一定很複雜,不用嵌入式系統怎麼來完成那麼複雜的功能控制啊?
  • 用英偉達Jetson Nano運行PyTorch & Fast.ai丨手把手教程+第三方工具
    造機器人、造小車、在家裡DIY一個語音控制的窗簾,都得先裝輪子。如果你使用的框架是PyTorch,那你最好再裝一個Fast.ai。Fast.ai是在PyTorch上非常好用的深度學習庫,來自MOOC平臺Fast.ai,只要一個API,就包含了所有常見的深度學習應用。那麼,拿到Jetson Nano之後,如何把輪子部署上去呢?
  • AI在這一周學會了很多事,都是什麼? | 一周 AI 頭條
    https://futurism.com/a-new-ai-can-write-music-as-well-as-a-human-composer/Nvidia與博世合作開發自動駕駛汽車的AI系統 | 牽手 |
  • LED模組大革命!軟模組震撼來襲
    品質高,可實現單點維修,維修成本較低;高亮度,死燈率低,節能省電;無縫拼接,能把模塊之間的拼接誤差控制在正負0.1mm以內,可根據用戶的需求做成任意形狀;平整度好,採用矽膠,手感柔和手指划過無突出;支持實時轉播,以DVI、HDMI、3G/HD/SD三速SDI高清顯示模式,適用於電視錄像節目、VCD或DVD及現場實況等室內場所;線路板穩定,線路板採用波峰焊工藝,具有綠油隔氧層
  • 用單片機控制飛彈?單片機yyds
    前幾天和一個在某研究所的髮小聊天,他說:現在的航空、航天和飛彈等武器裝備中,控制系統幾乎都是用單片機,而不是嵌入式系統。由於其發展非常迅速,舊的單片機的定義已不能滿足,所以在很多應用場合被稱為範圍更廣的微控制器;2. 嵌入式系統嵌入式系統(Embedded System),是一種嵌入機械或電氣系統內部、具有專一功能和實時計算性能的計算機系統。嵌入式系統常被用於高效控制許多常見設備,被嵌入的系統通常是包含數字硬體和機械部件的完整設備,例如汽車的防鎖死剎車系統。
  • 泰雷茲集成式觸控螢幕獲得認證可用於裝載商用飛機
    2019年11月,泰雷茲為空客A350駕駛艙開發的集成式觸控螢幕獲得歐洲航空安全局(EASA)認證,成為全球首款獲得認證可用於裝載商用飛機的觸控螢幕
  • 觸控螢幕概念萌芽;CASE 之父出生;Ask.com 誕生 | 歷史上的今天
    Turing)合作開發了另一臺早期計算機「自動計算機器」的原型;監督了另一臺機器 SWAC(標準西部自動計算機)的開發;1950 年 8 月 17 日,在赫斯基的領導下,西部標準自動計算機(SWAC)在加州大學洛杉磯分校投入運行。隨後,赫斯基在 1954 年設計了 G-15,這臺 430 公斤的機器是現代筆記本電腦的前身,被認為是世界上第一臺個人電腦。
  • 鴻蒙蝴蝶雲APP功能講解
    鴻蒙蝴蝶雲北鬥定位建群功能,通過北鬥衛星可以定位到用戶當前所在的村或社區,區域群沒有人數限制,全國14億人都可以容納在一個群裡。即使是新入群,也可以查看入群之前的所有文字、圖片消息,這是目前市面上社交軟體所不具備的功能。
  • 華為作業系統或將國內命名「鴻蒙OS」海外命名「方舟OS」
    這一系統在國內市場將命名為「鴻蒙OS」,在海外市場命名為「方舟OS」,該系統或將在8月或9月推出。華為鴻蒙系統(圖取自Huawei Central)隨著華為鴻蒙商標現身國家知識產權局商標局中國商標網,華為自研系統一事漸漸浮出水面。
  • 首款搭載鴻蒙的行動裝置或將誕生,麒麟1020採用5納米製程,年度旗艦機即將面世
    運行鴻蒙OS 2.0的Mate Watch智能手錶或同時發布。2020年上半年基本過完,消費電子市場即將迎來激烈廝殺的下半年。根據業內消息,華為下半年發布的高端旗艦機Mate40系列,將與蘋果的iPhone 12正面相遇。上半年華為發布了P40系列旗艦機,取得優秀的銷售成績,擊敗了一眾競爭對手,在手機市場上的份額進一步擴大。