#物联网征文#系统服务-openharmony串口服务访问(代码片段)

开源基础软件社区官方 开源基础软件社区官方     2022-12-01     646

关键词:

作者:邱云

项目介绍

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

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

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

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

    ```c++
    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代码,如下:

    ```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;

  6. 模块注册

    ```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);

  7. 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开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

本文正在参加物联网有奖征文活动

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com/#bkwz

#物联网征文#openharmony-wlan接口组件功能(代码片段)

作者:乔李臻项目简介通过实现一个简单的运行在Hi3516DV300开发板上的命令行WiFi连接控制程序,介绍在OpenHarmony中可用的WiFi接口功能,了解如何用其实现一些常见的WiFi的功能,希望能通过本篇文章,为使用wifi的接口功能提供一... 查看详情

#物联网征文#openharmony-arkui(ets)之wifi简单的连接操作(代码片段)

作者:张呈前言WIFI是大家日常必不可少需求,在OpenHarmony的开发中,系统提供了一系列完整的API,在万物互联的这个概念下,相信涉及到wifi功能操作的需求会越来越多,今日分享的是用ets来实现简单的wifi连接操作,可以实现扫... 查看详情

openharmony与pegasus物联网开发套件简介

1.1OpenHarmony简介OpenHarmony是由开放原子开源基金会(OpenAtomFoundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,基于开源的方式,搭建一个智能终端设备操作系统的框架和平台,促... 查看详情

基于openharmony的储物精灵

基于openharmony的储物精灵一.项目简介1.产品描述基于openharmony的智能柜物管理系统,可用于不同场景的环境下通过终端检索到物品的出入库信息与通过鸿蒙特性来赋能储物精灵。储物精灵NFC版:这是一个智慧储物系统,终端可以... 查看详情

征文活动投稿前端开发者入门物联网福音,haas510如何连接物联网平台(代码片段)

...xff0c;USB串口软件:win7x64,vscode 目录1.在阿里云物联网平台注册产品和设备 2.编写设备上云源代码3.烧录程序到开发板 4.运行效果5.关于HaaS1.在阿里云物联网平台注册产品和设备注册产品和设备是为了做本文介绍的实验&#x... 查看详情

#物联网征文#基于sma线圈驱动的仿尺蠖肠胃诊察机器人(代码片段)

...度学习的病灶识别系统4.3基于HarmonyOS的人机交互界面4.4物联网系统实现4.4.1感知层4.4.2传输层4.4.3控制层4.4.4软件及开 查看详情

#物联网征文#小熊派设备开发实战

(1)各种编译环境的搭建与安装​先解压小熊派VMware镜像,导入打开虚拟机,输入密码进入,打开终端查看IP地址,然后打开安装的MobaXterm工具连接登录,​然后把文件使用RaiDrive工具远程到windows上,添加ftp登录等待映射成功,... 查看详情

openharmony源码编译与下载(代码片段)

开发环境:开发系统:Ubuntu20.04开发板:Pegasus物联网开发板MCU:Hi3861OpenHarmony版本:3.0.1-LTS3.1OpenHarmony源码编译Pegasus物联网开发板基于华为海思Hi3861芯片,对应的产品名字是wifiiot_hispark_pegasus。接下来编译wi... 查看详情

openharmony源码编译与下载(代码片段)

开发环境:开发系统:Ubuntu20.04开发板:Pegasus物联网开发板MCU:Hi3861OpenHarmony版本:3.0.1-LTS3.1OpenHarmony源码编译Pegasus物联网开发板基于华为海思Hi3861芯片,对应的产品名字是wifiiot_hispark_pegasus。接下来编译wi... 查看详情

#物联网征文#ffhhi3516dv300驱动开发——编写led灯控制程序(代码片段)

Hi3516DV300驱动开发——编写LED灯控制程序前言概述前面的文章只是涉及到内核态驱动程序的实现,并未涉及到用户态应用程序,以及用户态应用程序与内核态驱动程序之间的数据交互流程,在本示例将演示如何在开发板上运行一... 查看详情

猿创征文|不会代码也能玩开发?基于华为云iot快速实现0代码体验物联网设备上云

文章目录前言一、物联网设备上云背景介绍二、实验环境准备三、智慧烟感器上云体验3.1、选择向导式极速体验3.2、对智慧烟感器进行产品定义3.3、定义目标设备标识码、注册设备3.4、根据需要选择设备演示包3.5、下载、解压设... 查看详情

物联网服务nodejs-5天学习第三天实战篇②——基于物联网的wifi自动打卡考勤系统(代码片段)

【NodeJs-5天学习】第三天实战篇②——基于物联网的WiFi自动打卡考勤系统1.前言2.实现思路2.1NodeJs服务器代码2.1.1对接Express服务器2.1.2对接Mac地址处理2.1.3对接飞书群处理2.2ESP8266代码2.3测试效果2.3.1串口打印日志2.3.2NodeJs服务器打... 查看详情

猿创征文|不会代码也能玩开发?基于华为云iot快速实现0代码体验物联网设备上云

文章目录前言一、物联网设备上云背景介绍二、实验环境准备三、智慧烟感器上云体验3.1、选择向导式极速体验3.2、对智慧烟感器进行产品定义3.3、定义目标设备标识码、注册设备3.4、根据需要选择设备演示包3.5、下载、解压设... 查看详情

物联网必学清单

当然有!物联网(IoT)是一个非常热门的领域,涉及到数据采集、通信和智能设备等多个方面。在成为物联网专家的道路上,以下是一些建议和资源:1.学习基础知识熟悉物联网的基本概念,了解主要的应用场景和技术挑战。学... 查看详情

采用esp8266+mqtt+云服务器+mysql的物联网温湿度检测系统(代码片段)

...数据情况3.Mysql数据存储情况五、总结前言一般在做与物联网相关的项目ÿ 查看详情

物联网28.物联网开发-安全性

安全性设计随着物联网的普及,人们开始担心能否保证其安全性。就物联网服务来说,有各种各样的设备要连接到网络,因此也就大大增加了遭到外部攻击的风险,比如联网的监控摄像头被黑导致影像被盗,... 查看详情

物联网28.物联网开发-安全性

安全性设计随着物联网的普及,人们开始担心能否保证其安全性。就物联网服务来说,有各种各样的设备要连接到网络,因此也就大大增加了遭到外部攻击的风险,比如联网的监控摄像头被黑导致影像被盗,... 查看详情

物联网框架serversuperio

1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍《连载|物联网框架ServerSuperIO教程》1.4种通讯模式机制。《连载|物联网框架ServerSuperIO教程》2.服务实例的配置参数说明《连载|物联网框架ServerSuperIO教程》-3.设备驱动介绍《连载|物... 查看详情