#物联网征文# 系统服务- OpenHarmony 串口服务访问
Posted 开源基础软件社区官方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#物联网征文# 系统服务- OpenHarmony 串口服务访问相关的知识,希望对你有一定的参考价值。
作者:邱云
项目介绍
本文档是在eTS项目hap包中实现串口访问的使用说明,通过JS接口开放给上层应用使用。
一、开发环境准备
安装OpenHarmony SDK
1. 在DevEco Studio菜单栏选择Tools->SDK Manager
2. OpenHarmony SDK选项中选择配备API版本进行安装
二、创建eTS项目
创建支持Native C++的eTS项目
三、NAPI库相关
生成串口NAPI库
1. 添加文件src/main/cpp/types/libserialhelper/serialhelper.d.ts
/*
* Copyright (C) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import AsyncCallback, Callback from "basic";
declare namespace serialHelper
/**
* Open serial port.
* @param dev Indicates the serial port dev.
*/
function openSerial(dev:string, callback: AsyncCallback<void>): void;
function openSerial(dev:string): Promise<void>;
/**
* Close serial port.
* @param dev Indicates the serial port dev.
*/
function closeSerial(dev:string, callback: AsyncCallback<void>): void;
function closeSerial(dev:string): Promise<void>;
export default serialHelper;
2. 添加文件src/main/cpp/types/libserialhelper/package.json
"name": "libserialhelper.so",
"types": "./serialhelper.d.ts"
3. 根据serialhelper.d.ts文件生成对应的c++源码
方式一:手动编写src/main/cpp/serial_helper.cpp
```c++
struct AsyncCallInfo
napi_env env = nullptr;
napi_ref callbackRef = nullptr;
napi_deferred deferred = nullptr;
napi_async_work work = nullptr;
void data = nullptr;
;
static void AsyncCallFinish(AsyncCallInfo asyncCallInfo, int32_t result, napi_value *asyncResult)
if (asyncCallInfo->deferred)
if (result == 0)
napi_resolve_deferred(asyncCallInfo->env, asyncCallInfo->deferred,
asyncResult[1]==nullptr?asyncResult[0]:asyncResult[1]);
else
napi_reject_deferred(asyncCallInfo->env, asyncCallInfo->deferred, asyncResult[0]);
else
napi_value callback = nullptr;
napi_get_reference_value(asyncCallInfo->env, asyncCallInfo->callbackRef, &callback);
napi_call_function(asyncCallInfo->env, nullptr, callback, CALLBACK_ARGV_CNT, asyncResult, nullptr);
napi_delete_reference(asyncCallInfo->env, asyncCallInfo->callbackRef);
```c++
static napi_value Call_OpenSerial(napi_env env, napi_callback_info info)
size_t argc = 0;
napi_value args[DEFAULT_ARG_COUNT] = 0;
napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
...
napi_value resourceName = nullptr;
napi_create_string_utf8(env, "x_napi_tool", NAPI_AUTO_LENGTH, &resourceName);
napi_create_async_work(env, nullptr, resourceName,
[](napi_env env, void* data)
AsyncCallInfo* asyncCallInfo = (AsyncCallInfo*)data;
OpenSerialValue* openValue = (OpenSerialValue*)asyncCallInfo->data;
//openValue->out = SerialClient::GetInstance()->OpenSerial(openValue->dev);
,
[](napi_env env, napi_status status, void* data)
AsyncCallInfo* asyncCallInfo = (AsyncCallInfo*)data;
OpenSerialValue* openValue = (OpenSerialValue*)asyncCallInfo->data;
napi_value asyncResult[CALLBACK_ARGV_CNT]=nullptr, nullptr;
napi_create_int32(env, openValue->out, &asyncResult[0]);
AsyncCallFinish(asyncCallInfo, openValue->out,asyncResult);
napi_delete_async_work(env, asyncCallInfo->work);
delete openValue;
delete asyncCallInfo;
,
(void*)asyncCallInfo, &asyncCallInfo->work);
napi_queue_async_work(env, asyncCallInfo->work);
return retValue;
方式二:使用NAPI框架生成工具生成 工具链接
1)将serialhelper.d.ts、basic.d.ts复制到同一目录中,创建out目录
2)执行./napi_generator-linux -f serialhelper.d.ts -o out
3)将生成的源码文件复制到src/main/cpp
4. make文件:src/main/cpp/CMakeList.txt
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(XComponent)
set(NATIVERENDER_ROOT_PATH $CMAKE_CURRENT_SOURCE_DIR)
include_directories($NATIVERENDER_ROOT_PATH)
add_library(serialhelper SHARED serial_helper.cpp)
target_link_libraries(serialhelper PUBLIC libace_napi.z.so libc++.a)
5. 添加项目依赖
entry/package.json
"devDependencies":
"@types/libserialhelper.so": "file:./src/main/cpp/types/libserialhelper"
entry/package-lock.json
"dependencies":
"@types/libserialhelper.so":
"version": "file:src/main/cpp/types/libserialhelper",
"dev": true
6. 编译生成
修改编译项entry/build-profile.json5:
"buildOption":
"externalNativeOptions":
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "-v -DOHOS_STL=c++_shared",
"abiFilters": [
"armeabi-v7a",
],
"cppFlags": "",
四、实现串口异步回调
添加串口IPC客户端libserialport_service_api.z.so库,并且实现具体的异步回调功能
-
将libserialport_service_api.z.so复制到entry/libs/armeabi-a7v目录
-
将库的头文件复制到entry/src/main/cpp/include目录
-
继承SerialCallbackBase类,实现串口数据异步回调SerialAsyncCallback
```c++
class SerialAsyncCallback: public SerialCallbackBase
public:
SerialAsyncCallback() = default;
~SerialAsyncCallback();// 通知回调事件
void OnCallBackEvent() override;
// 接收到串口数据
void OnRecvData(const uint8_t *buffer, uint32_t length) override;
...
; -
修改src/main/cpp/CMakeList.txt文件
# the minimum version of CMake. cmake_minimum_required(VERSION 3.4.1) project(XComponent) set(NATIVERENDER_ROOT_PATH $CMAKE_CURRENT_SOURCE_DIR) include_directories($NATIVERENDER_ROOT_PATH $NATIVERENDER_ROOT_PATH/include ) link_directories($NATIVERENDER_ROOT_PATH/../../../libs/$CMAKE_OHOS_ARCH_ABI) add_library(serialhelper SHARED serial_helper.cpp x_napi_tool.cpp serial_async_callback.cpp) target_link_libraries(serialhelper PUBLIC libace_napi.z.so libc++.a libhilog_ndk.z.so libuv.so libserialport_service_api.z.so)
-
在napi函数中调用api函数,使用NAPI框架生成工具生成OpenSerial代码,如下:
```c++
struct OpenSerial_value_struct
std::string in0;
int32_t out;
;void OpenSerial_execute(XNapiTool pxt, void data)
OpenSerial_value_struct vio = (OpenSerial_value_struct )data;
vio->out = get_serial_client()->OpenSerial(vio->in0);void OpenSerial_complete(XNapiTool pxt, void data)
OpenSerial_value_struct vio = (OpenSerial_value_struct )data;
napi_value result = nullptr;
result = NUMBER_C_2_JS(pxt, Int32, vio->out);
napi_value args[XNapiTool::ARGV_CNT] = result, nullptr;
pxt->FinishAsync(vio->out, args);
delete vio;
napi_value OpenSerial_middle(napi_env env, napi_callback_info info)
XNapiTool *pxt = std::make_unique<XNapiTool>(env, info).release();
if (pxt->IsFailed())
napi_value err = pxt->GetError();
delete pxt;
return err;struct OpenSerial_value_struct *vio = new OpenSerial_value_struct();
pxt->SwapJs2CUtf8(pxt->GetArgv(0), vio->in0);
napi_value result = pxt->StartAsync(OpenSerial_execute, vio, OpenSerial_complete,
pxt->GetArgc() == 2 ? pxt->GetArgv(1) : nullptr);
if (pxt->IsFailed())
result = pxt->GetError();
return result; -
模块注册
```c++
static napi_value init(napi_env env, napi_value exports)
std::shared_ptr<XNapiTool> pxt = std::make_shared<XNapiTool>(env, exports);
//js函数与C++函数映射
pxt->DefineFunction("setOptions", OHOS::SerialPort::SetOptions_middle);
pxt->DefineFunction("openSerial", OHOS::SerialPort::OpenSerial_middle);
pxt->DefineFunction("closeSerial", OHOS::SerialPort::CloseSerial_middle);
pxt->DefineFunction("clearBuffer", OHOS::SerialPort::ClearBuffer_middle);
pxt->DefineFunction("sendData", OHOS::SerialPort::SendData_middle);
pxt->DefineFunction("recvData", OHOS::SerialPort::RecvData_middle);
pxt->DefineFunction("transmit", OHOS::SerialPort::Transmit_middle);
pxt->DefineFunction("on", OHOS::SerialPort::on_middle);
pxt->DefineFunction("off", OHOS::SerialPort::off_middle);
pxt->DefineFunction("setGPIODirection", OHOS::SerialPort::setGPIODirection_middle);
pxt->DefineFunction("setGPIOValue", OHOS::SerialPort::setGPIOValue_middle);
pxt->DefineFunction("getGPIOValue", OHOS::SerialPort::getGPIOValue_middle);
return exports;static napi_module g_serialHelper_Module =
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = init,
.nm_modname = "serialhelper",
.nm_priv = ((void )0),
.reserved = (void )0,
;extern "C" attribute((constructor)) void Register_serialHelper_Module(void)
napi_module_register(&g_serialHelper_Module); -
eTS调用接口验证
import serialHelper from "libserialhelper.so" ... //打开串口this.tty /dev/ttyXRUSB0 serialHelper.openSerial(this.tty).then(()=> HiLog.i(TAG, "serial openSerial " + this.tty + " success") this.status = 开 ).catch((error)=> HiLog.i(TAG, "openSerial " + this.tty + " failed:" + error) ); ... //设置为异步 serialHelper.on("/dev/ttyXRUSB0", (data) => var dataString = ""; for (var i = 0; i < data.length; i++) dataString += String.fromCharCode(data[i]); HiLog.i(TAG, "ttyXRUSB0 len:" + data.length + " data:" + dataString); )
应用启动后点击"打开/dev/ttyXRUSB0"按钮查看输出日志,出现serialport_client与serial_service_impl标志,表示访问串口服务成功
项目完整源码地址
更多原创内容请关注:中软国际 HarmonyOS 技术团队
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
以上是关于#物联网征文# 系统服务- OpenHarmony 串口服务访问的主要内容,如果未能解决你的问题,请参考以下文章
#物联网征文# OpenHarmony -ArkUI(ETS)之WiFi简单的连接操作
#物联网征文# OpenHarmony - WLAN 接口组件功能