登山则情满于山,观海则意溢于海。这篇文章主要讲述#星光计划2.0# OpenHarmony3.0上采用ets开发HAP控制LED灯相关的知识,希望能为你提供帮助。
【本文正在参与51CTO HarmonyOS技术社区创作者激励计划-星光计划2.0】
@toc
1. 开发环境硬件:Hi3516DV300开发板
软件:OpenHarmony3.0系统
工具:DevEco Studio 3.0
2. 功能简介OpenHarmony3.0采用了方舟开发框架arkUI,支持了基于TS扩展的声明式开发范式eTS,本文使用ets开发语言,构造一个应用程序,实现通过上层HAP控制底层LED灯的亮与灭。
3. 实现原理如果在android上实现,需要通过java调用jni实现对底层的访问。但是在OpenHarmony上,HAP采用ets语言开发,没有发现嵌入到HAP当中的类JNI语言,但是系统也提供了一个访问底层的机制,叫做NAPI,不过这部分是在系统层实现的,不随HAP一起发布。我们想要实现控制LED灯的功能,是在NAPI部分通过C语言实现的,然后编译为xxx.z.so动态库,它向上层提供了一个控制接口。绿色LED灯对应GPIO2_3,计算出编号:2*8+3=19,所以直接控制gpio19下的value值就可以控制LED灯亮灭了。
4. 具体实现整个功能的实现分为了上层HAP应用开发和底层.z.so库的开发两部分。
4.1 应用的开发
1.在HUAWEI DevEco Studio中,创建一个 [Standard]Empty Ability ,
文章图片
开发语言选择 “eTS”,可以注意到API Version仅支持7,说明是在OpenHarmony3中新支持的,也仅在OpenHarmony3中支持,这些功能实际上都是测试版本,稳定了之后就会在HarmonyOS中使用了,但目前还没有发布。
文章图片
工程创建完毕后,我直接在pages目录结构下右击新建了一个ets page,取名led
文章图片
我们页面的样式、布局和控制全都在led.ets这个文件里了,不再像js分为css、hml和js三个文件。
Led.ets 文件内容
import led from @ohos.led@Entry
@Component
struct Led
@State private imgpath: string = app.media.ledoff
@State private isShow: boolean= falsebuild()
Flex( direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center )
Text(LED 灯控制)
.fontSize(25)
.fontWeight(FontWeight.Bold)
.margin(bottom: 30)
Image($r(app.media.ledoff))
.objectFit(ImageFit.Contain)
.width(150)
.height(150)
.visibility(this.isShow ? Visibility.None : Visibility.Visible)
Image($r(app.media.ledon))
.objectFit(ImageFit.Contain)
.width(150)
.height(150)
.visibility(this.isShow ? Visibility.Visible : Visibility.None)Flex( alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceEvenly )
Button(关闭,type: ButtonType.Capsule, stateEffect: true ).backgroundColor(0x317aff).width(150).height(50).backgroundColor("#aaaaaa")
.onClick((event: ClickEvent) =>
this.isShow = falseled.switchLed(19, 0);
)
Button(打开,type: ButtonType.Capsule, stateEffect: true ).backgroundColor(0x317aff).width(150).height(50)
.onClick((event: ClickEvent) =>
this.isShow = trueled.switchLed(19, 1);
).width("100%")
.margin( top: 50 ).width(100%)
.height(100%)
.padding(10)
放了两个图片,表示LED灯状态的,放在了代码的entry\\src\\main\\resources\\phone\\media目录,
文章图片
导入的ohos.led 库,是自己添加的NAPI层的动态库,后面会继续介绍。
在config.json文件中,记得把led.ets放到js部分pages数组的第一位,因为它是要显示的首页面。
代码中使用了两个Button组件,一个打开,一个关闭,因为在ets中还没有类似js中的switch的组件,
页面中有两个image组件,分别显示打开和关闭的图像,通过设置visibility属性来切换状态,本来想通过动态设置image的源来改变图像内容,但没找到有效的方法,应该是支持的,只是自己还没了解怎么用。
编译前记得一定要设置签名,否则编译出来的程序无法安装,
文章图片
最后可以编译程序了,
文章图片
生成的最终HAP在 build\\outputs\\hap\\debug\\phone\\entry-debug-standard-ark-signed.hap
4.2 动态库的开发
动态库需要在OpenHarmony源码中添加和编译,本文使用的是OpenHarmony3.0源码,
在foundation/ace/napi/sample目录下,复制一份native_module_demo,重命名为native_module_led,里面的文件也相应的修改名字,注意文件里调用也相应的修改成正确的名字,否则编译会报错。
文章图片
主要修改的文件有,
foundation/ace/napi/sample/native_module_led/BUILD.gn
foundation/ace/napi/sample/native_module_led/native_module_led.cpp
foundation/ace/napi/BUILD.gn
目录native_module_led下BUILD.gn文件:
import("//build/ohos.gni")ohos_shared_library("led")
include_dirs = [
"//third_party/node/src",
"//foundation/ace/napi/interfaces/kits",
]sources = [
"led_javascript_class.cpp",
"native_module_led.cpp",
]deps = [ "//foundation/ace/napi:ace_napi" ]relative_install_dir = "module"external_deps = [ "hiviewdfx_hilog_native:libhilog" ]subsystem_name = "ace"
part_name = "napi"
目录native_module_led下native_module_led.cpp文件修改部分摘要:
包含的头文件和宏定义,
#include <
stdlib.h>
// standard library 标准库函数头文件
#include <
stdio.h>
// standard input output 标准输入输出函数
#include <
stdint.h>
// 定义了扩展的整数类型和宏#include <
unistd.h>
// POSIX 系统 API 访问功能的头文件
#include <
fcntl.h>
// unix标准中通用的头文件 define O_WRONLY and O_RDONLY// #include <
string.h>
#define GPIO_DIR_IN (char*)"in"
#define GPIO_DIR_OUT (char*)"out"
#define GPIO_VAL_LOW 0
#define GPIO_VAL_HIGH 1
添加函数SwitchLed的具体实现,
static napi_value SwitchLed(napi_env env, napi_callback_info info)HILOG_INFO("hey, SwitchLed - 0");
size_t requireArgc = 2;
size_t argc = 2;
napi_value args[2] =nullptr ;
NAPI_CALL(env, napi_get_cb_info(env, info, &
argc, args, nullptr, nullptr));
NAPI_ASSERT(env, argc >
= requireArgc, "Wrong number of arguments");
napi_valuetype valuetype0;
NAPI_CALL(env, napi_typeof(env, args[0], &
valuetype0));
napi_valuetype valuetype1;
NAPI_CALL(env, napi_typeof(env, args[1], &
valuetype1));
NAPI_ASSERT(env, valuetype0 == napi_number &
&
valuetype1 == napi_number, "Wrong argument type. Numbers expected.");
uint32_t gpio;
NAPI_CALL(env, napi_get_value_uint32(env, args[0], &
gpio));
uint32_t val;
NAPI_CALL(env, napi_get_value_uint32(env, args[1], &
val));
char direction[100] = 0;
sprintf(direction,"echo out >
/sys/class/gpio/gpio%d/direction", gpio);
system(direction);
char value[100] = 0;
sprintf(value,"echo %d >
/sys/class/gpio/gpio%d/value", val, gpio);
system(value);
napi_value sum;
NAPI_CALL(env, napi_create_double(env, 1.0f, &
sum));
return sum;
初始化部分,
EXTERN_C_START
/*
* function for module exports
*/
static napi_value Init(napi_env env, napi_value exports)/*
* Properties define
*/
napi_property_descriptor desc[] =
DECLARE_NAPI_FUNCTION("add", Add),
DECLARE_NAPI_FUNCTION("minus", Minus),
DECLARE_NAPI_FUNCTION("switchLed", SwitchLed),
DECLARE_NAPI_FUNCTION("TestPromise", TestPromise),
DECLARE_NAPI_FUNCTION("TestPromiseOrAsyncCallback", TestPromiseOrAsyncCallback),
;
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
DemoJavascriptClassInit(env, exports);
return exports;
EXTERN_C_END
模块定义及注册,
/*
* Module define
*/
static napi_module ledModule =
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "led",
.nm_priv = ((void*)0),
.reserved =0 ,
;
/*
* Module register function
*/
extern "C" __attribute__((constructor)) void RegisterModule(void)napi_module_register(&
ledModule);
【#星光计划2.0# OpenHarmony3.0上采用ets开发HAP控制LED灯】目录napi下BUILD.gn文件,
group("napi_packages_test")
testonly = truedeps = [
"sample/native_module_demo:demo",
"sample/native_module_netserver:netserver",
"sample/native_module_storage:storage",
"test/unittest:unittest",
"sample/native_module_led:led",
]if (is_standard_system)
deps += [ "sample/native_module_ability:ability" ]
最后在源码根目录下执行编译命令,
生成的文件为
5. 系统设置需要授予应用访问gpio下export文件的权限,
device/hisilicon/hi3516dv300/build/rootfs/init.Hi3516DV300.cfg
"name" : "boot",
"cmds" : [
"write /sys/class/gpio/export 19",
"chmod 777 /sys/class/gpio/gpio19/direction",
"chmod 777 /sys/class/gpio/gpio19/value",
6. 系统部署 6.1 拷贝动态库
生成的.z.so动态库已经拷贝到PC上E:\\libled.z.so
PC串口控制台:
PC命令窗口cmd:
PC串口控制台:
6.2 安装应用
PC命令窗口cmd:
7. 应用测试点击打开按钮,LED图标变绿,同时LED灯亮,
文章图片
点击关闭按钮,LED图标变灰,同时LED灯灭。
文章图片
想了解更多关于鸿蒙的内容,请访问:
51CTO和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com/#bkwz
文章图片
推荐阅读
- 今日笔记!——分析Java应用性能
- 学妹问我Java枚举类与注解,我直接用这个搞定她!
- 阿里最新面试必备项之Java的String类,持续更新中!
- 面试官问(你做过什么Java线程池实践,我写了一篇博客给他看~)
- Java交流|面试最后一问(你有什么问题想问我吗())
- 图书查询管理进行需求分析及测试项测试子项分析
- 牛逼!不得不服,第一次有人把Java 反射机制讲解这么透!
- 利用selenium自动化实现搜索框输入内容
- 朝花夕拾 Mysql笔记2