OpenHarmony 串口服务访问

news/发布时间2024/9/20 8:58:24

项目介绍

本文档是在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

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

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库,并且实现具体的异步回调功能

  1. 将libserialport_service_api.z.so复制到entry/libs/armeabi-a7v目录

  2. 将库的头文件复制到entry/src/main/cpp/include目录

  3. 继承SerialCallbackBase类,实现串口数据异步回调SerialAsyncCallback

    class SerialAsyncCallback: public SerialCallbackBase {
    public:SerialAsyncCallback() = default;~SerialAsyncCallback();// 通知回调事件void OnCallBackEvent() override;// 接收到串口数据void OnRecvData(const uint8_t *buffer, uint32_t length) override;...
    };
  4. 修改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)
  5. 在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;
    }
  6. 模块注册

    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);
    }
  7. eTS调用接口验证

    import serialHelper from "libserialhelper.so"...//打开串口this.tty /dev/ttyXRUSB0serialHelper.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

  1. 应用开发导读(ArkTS)
  2. ……

HarmonyOS 概念:https://qr21.cn/FV7h05

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

如何快速入门?:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. 构建第一个JS应用
  4. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发: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.……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.bcls.cn/fttU/9819.shtml

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

springcloud alibaba组件简介

一、Nacos 服务注册中心/统一配置中心 1、介绍 Nacos是一个配置中心&#xff0c;也是一个服务注册与发现中心。 1.1、配置中心的好处&#xff1a; &#xff08;1&#xff09;配置数据脱敏 &#xff08;2&#xff09;防止出错&#xff0c;方便管理 &#xff08;3&#xff…

前端开发——ElementUI组件的使用

文章目录 1. Tabs标签页2. 单选框 el-radio3. 复选框 el-checkbox4. 下拉框 el-select5. 表格 el-table6. 对话框 el-dialog7. 文字提示 el-tooltip8. 抽屉 el-drawer 1. Tabs标签页 <template><el-tabs v-model"activeName" tab-click"handleClick&q…

AI智能分析网关V4:抽烟/打电话/玩手机行为AI算法及场景应用

抽烟、打电话、玩手机是人们在日常生活中常见的行为&#xff0c;但这些行为在某些场合下可能会带来安全风险。因此&#xff0c;对于这些行为的检测技术及应用就变得尤为重要。今天来给大家介绍一下TSINGSEE青犀AI智能分析网关V4抽烟/打电话/玩手机检测算法及其应用场景。 将监控…

Mint_21.3 drawing-area和goocanvas的FB笔记(二)

一、goocanvas安装 Linux mint 21.3 库中带有 libgoocanvas-2.0-dev, 用sudo apt install libgoocanvas-2.0-dev 安装&#xff0c;安装完成后&#xff0c;检查一个 /usr/lib/x86_64-linux-gnu 下是否有libgoocanvas.so的软件链接。如果没有&#xff0c;或是 .so.x 等类似后面…

spring自定义事件监听器

1. 创建自定义事件 import org.springframework.context.ApplicationEvent; import java.util.List;public class CollectionCreateEvent extends ApplicationEvent {private List<String> fileList;public CollectionCreateEvent(Object source,List<String> file…

Centos 7.5 上nginx设置开机自启动

nginx的安装目录 &#xff1a; /usr/local/nginx 一、没有设置开机自启动前&#xff0c;需要执行/usr/local/nginx/sbin/nginx 启动 二、接下来&#xff0c;我们设置开机自启动&#xff0c;就不用手动启动nginx了 1、cd /usr/lib/systemd/system/ 2、vi nginx.service [un…

零成本建站方案之Github Pages

之前的文章中介绍了如何申请AWS免费服务器并使用WordPress来搭建个人网站&#xff0c;今天给大家介绍一种无需任何硬件资源&#xff0c;也就是不需要准备服务器就可以搭建一个网站的方案&#xff0c;那就是使用github pages来搭建一个静态网站。 第一步&#xff0c;需要准备一个…

C语言第三十三弹---动态内存管理(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 动态内存管理 1、为什么要有动态内存分配 2、malloc和free 2.1、malloc 2.2、free 3、calloc和realloc 3.1、calloc 3.2、realloc 4、常见的动态内存的错…

Linux添加用户分组练习

一、复制/etc/skel目录为/home/tuser1&#xff08;/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限&#xff09;。 cp -a /etc/skel /home/tuser1 chown -R tuser1:tuser1 /home/tuser1 chmod -R 700 /home/tuser1 二、编辑/etc/group文件&#xff0c;添加组h…

IPD(集成产品开发)—核心思想

企业发展到一定阶段就会遇到管理瓶颈&#xff0c;IPD流程是一种高度结构化的产品开发流程&#xff0c;它集成了业界很多优秀的产品开发方法论&#xff0c;像搭积木一样的组合成一种非常有效的流程。如果我们能根据企业的规模和行业特点&#xff0c;对全流程的IPD进行合适的裁剪…

【音视频处理】使用ffmpeg实现多个视频合成一个视频(按宫格视图)

先上结果 环境 硬件&#xff1a;通用PC 系统&#xff1a;Windows 测试有效 软件&#xff1a;ffmpeg 解决 0、命令 ffmpeg.exe -i input1.mp4 -i input2.mp4 -i input3.mp4 -i input4.mp4 -filter_complex "[0:v]scaleiw/2:ih/2,pad2*iw:2*ih[a]; [1:v]scaleiw/2:ih/2…

136. 只出现一次的数字【简单】

136. 只出现一次的数字【简单】 题目描述&#xff1a; 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题&#xff0c;且该算法只使…

今年国内石油需求稳中有升,巡检机器人助力石油行业可持续发展

前言&#xff1a;全球能源市场出现普遍回落趋势&#xff0c;其中石油价格下降近20%&#xff0c;而天然气和煤炭价格更是下跌超过50%。此外&#xff0c;碳酸锂和光伏组件价格也纷纷下降超过50%。这种价格下滑对于全球经济的持续增长&#xff0c;尤其是控制通货膨胀方面&#xff…

golang学习6,glang的web的restful接口传参

1.get传参 //get请求 返回json 接口传参r.GET("/getJson/:id", controller.GetUserInfo) 1.2.接收处理 package controllerimport "github.com/gin-gonic/gin"func GetUserInfo(c *gin.Context) {_ c.Param("id")ReturnSucess(c, 200, &quo…

如何在 VM 虚拟机中安装 Windows Server 2012 操作系统保姆级教程(附链接)

一、 VMware Workstation 虚拟机 若没有安装 VM 虚拟机可以参考下篇文章进行安装&#xff1a; VM 虚拟机安装教程https://eclecticism.blog.csdn.net/article/details/135713915 二、Windows Server 2012 镜像 点击链接下载镜像 下载链接https://pan.baidu.com/s/16nRHgyE…

Flask入门二(Flask的CBV、模版语法、请求和响应)

文章目录 一、Flask的CBV1.CBV的写法2.as_view的执行流程3.Login.as_view(name‘index’) name到底有什么用&#xff1f;4.CBV中得methods作用 二、模版语法1.渲染变量2.变量的循环3.逻辑判断 三、请求和响应 一、Flask的CBV 1.CBV的写法 from flask import Flask app Flask…

Stable Diffusion 解析:探寻 AI 绘画背后的科技神秘

AI 绘画发展史 在谈论 Stable Diffusion 之前&#xff0c;有必要先了解 AI 绘画的发展历程。 早在 2012 年&#xff0c;华人科学家吴恩达领导的团队训练出了当时世界上最大的深度学习网络。这个网络能够自主学习识别猫等物体&#xff0c;并在短短三天时间内绘制出了一张模糊但…

微信小程序 ---- 慕尚花坊 收货地址

收货地址 收货地址列表新增收货地址编辑收货地址删除收货地址 01. 定义新增参数以及封装接口 API 思路分析&#xff1a; 点击新建地址按钮&#xff0c;需要跳转到新增地址页面 因为新增和编辑收货地址页面是同一个页面&#xff0c;我们需要在这个页面处理新增和编辑功能&a…

应用存储与持久化数据卷

1、PV 引入场景&#xff1a; ① Deployment 管理的 pod&#xff0c;在做镜像升级的过程中&#xff0c;会产生新的 pod并且删除旧的 pod &#xff0c;新旧 pod 之间如何复用数据&#xff1f; ② 宿主机宕机的时候&#xff0c;如何实现带卷迁移&#xff1f; ③ 多个 pod 之间&…

亚信安慧AntDB-M的扩展功能(三)

销毁函数&#xff1a; void My_SUM_deinit(UDF_INIT *initid) { //清理工作 } 假设编译生成的动态库名字是&#xff1a;my_sum_udf.so。 使用CREATE FUNCTION命令创建函数&#xff1a; CREATE FUNCTION My_SUM RETURNS INTEGER SONAME my_sum_udf.so; 使用UDF: SELECT My…
推荐文章