赞
踩
本文档是在eTS项目hap包中实现串口访问的使用说明,通过JS接口开放给上层应用使用。
/* * 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;
{
"name": "libserialhelper.so",
"types": "./serialhelper.d.ts"
}
方式一:手动编写src/main/cpp/serial_helper.cpp
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); } }
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
# 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)
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
}
}
修改编译项entry/build-profile.json5:
"buildOption": {
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "-v -DOHOS_STL=c++_shared",
"abiFilters": [
"armeabi-v7a",
],
"cppFlags": "",
}
}
将libserialport_service_api.z.so复制到entry/libs/armeabi-a7v目录
将库的头文件复制到entry/src/main/cpp/include目录
继承SerialCallbackBase类,实现串口数据异步回调SerialAsyncCallback
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代码,如下:
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; }
模块注册
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 NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。