NAPI篇【4】——NAPI应用点亮一个LED

news2024/9/19 10:50:45

        OpenHarmony的NAPI功能为开发者提供了JS与C/C++不同语言模块之间的相互访问,交互的能力,使得开发者使用C或者C++语言实现应用的关键功能。如操作开发板中某个GPIO节点的状态(OpenHarmony并没有提供直接操作GPIO口状态的API),点亮一个LED灯。

        本篇基于前3篇NAPI的讲解总结,做一个控制开发板上LED灯状态的应用作为完结篇。

一、环境准备

        设备:rk3568开发板

        开发环境:DevEco Studio4.0.0.600

二、NAPI函数编写

        1、基于NAPI的GPIO节点控制函数

        OpenHarmony并没有提供直接操作GPIO口状态的API。若需要控制开发板上LED灯的亮灭, 需要通过NAPI的方式,写一个可以查询GPIO口状态、一个可以对节点写1和一个可以对节点写0的函数。

(1)main目录如下:

(2)bq_function.cpp

#include "napi/native_api.h"
#include "napi/native_api.h"
#include <cstring>
#include <js_native_api.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>


using namespace std;
//对指定节点写1
static napi_value Bq_GPIO_On(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);

    char *ledPath = new char[150]{};
    size_t buffSize = 100;
    size_t realSize = 0;
    napi_get_value_string_utf8(env, args[0], ledPath, buffSize, &realSize);
    int fd;
    char *ret = new char[50]{};
    fd = open(ledPath, O_RDWR | O_TRUNC | O_NOCTTY);
    if (fd < 0) {
        strcpy(ret, "fail to open file");
    } else {
        strcpy(ret, "1");
        write(fd, "1", 1);
        close(fd);
    }
    napi_value returnValue = nullptr;
    napi_create_string_utf8(env, ret, strlen(ret), &returnValue);
    return returnValue;
}

//对指定节点写0
static napi_value Bq_GPIO_Off(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);

    char *ledPath = new char[150]{};
    size_t buffSize = 100;
    size_t realSize = 0;
    napi_get_value_string_utf8(env, args[0], ledPath, buffSize, &realSize);
    int fd;
    char *ret = new char[50]{};
    fd = open(ledPath, O_RDWR | O_TRUNC | O_NOCTTY);
    if (fd < 0) {
        strcpy(ret, "fail to open file");
    } else {
        strcpy(ret, "0");
        write(fd, "0", 1);
        close(fd);
    }
    napi_value returnValue = nullptr;
    napi_create_string_utf8(env, ret, strlen(ret), &returnValue);
    return returnValue;
}

//查询指定节点状态
static napi_value bq_GPIO_State(napi_env env, napi_callback_info info) {
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);

    char *ledPath = new char[150]{};
    size_t buffSize = 100;
    size_t realSize = 0;
    napi_get_value_string_utf8(env, args[0], ledPath, buffSize, &realSize);
    char *ret = new char[50]{};
    FILE *fp;
    char gpioValuePath[200];
    char gpioValue[2];

    // 构建GPIO口值文件路径
    snprintf(gpioValuePath, sizeof(gpioValuePath), "%s", ledPath);
    if (access(gpioValuePath, F_OK) == -1) {
        strcpy(ret, "Error: the GPIO is not exist");
        napi_value returnValue = nullptr;
        napi_create_string_utf8(env, ret, strlen(ret), &returnValue);
        return returnValue;
      
    }
    // 打开GPIO口值文件
    fp = fopen(gpioValuePath, "r");
    if (fp == NULL) {
        perror("Error opening GPIO value file");
        strcpy(ret, "Error opening GPIO value file");
    } else {
        // 读取GPIO口值
        if (fgets(gpioValue, sizeof(gpioValue), fp) == NULL) {
            perror("Error reading GPIO value");
            fclose(fp);
            strcpy(ret, "Error reading GPIO value");
        } else {

            strcpy(ret, gpioValue);
        }
    }
    fclose(fp);

    napi_value returnValue = nullptr;
    napi_create_string_utf8(env, ret, strlen(ret), &returnValue);
    return returnValue;
}


EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"bq_GPIO_On", nullptr, Bq_GPIO_On, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"bq_GPIO_Off", nullptr, Bq_GPIO_Off, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"bq_GPIO_State", nullptr, bq_GPIO_State, nullptr, nullptr, nullptr, napi_default, nullptr}};
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }

         2、NAPI函数与导出与配置

        (1)index.d.ts

export const bq_GPIO_On: (ledPath: string) =>  Promise<string>;//节点写1

export const bq_GPIO_Off: (ledPath: string) =>  Promise<string>;//节点写0

export const bq_GPIO_State: (ledPath: string) => Promise<string>;//节点状态查询

        (2)CMakeLists.txt

# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(Demo_Led)

set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})

include_directories(${NATIVERENDER_ROOT_PATH}
                    ${NATIVERENDER_ROOT_PATH}/include)

add_library(entry SHARED bq_func.cpp)
target_link_libraries(entry PUBLIC libace_napi.z.so)

        (3)build-profile.json5

        (4)oh-package.json5

三、Openharmony UI交互界面编写

        1、UI界面编写,NAPI函数引用

        (1)index.ets

        开发板控制LED灯节点地址为:/sys/class/leds/pilot_lamp/brightness

import NAPI from 'libentry.so';//引出NAPI接口
import promptAction from '@ohos.promptAction';
@Observed
class ledModel {
  public ledName: string //LED灯名称
  public ledAddress: string //LED灯的节点地址
  public ledState: boolean //LED灯状态
  public isLedExit: boolean //LED灯节点是否存在
  public ledStateCheck: string //检测返回值

  constructor(LedName: string, LedAddress: string, LedState: boolean = false, isLedExit: boolean = true, LedStateCheck: string = '') {
    this.ledName = LedName
    this.ledAddress = LedAddress
    this.ledState = LedState
    this.isLedExit = isLedExit
    this.ledStateCheck = LedStateCheck
  }
}
@Entry
@Component
struct Index {
  @State message: number = 0;
  @State led: ledModel = new ledModel('LED_Green',
    '/sys/class/leds/pilot_lamp/brightness')//开发板控制LED灯节点地址'/sys/class/leds/pilot_lamp/brightness'
  private setIntervalID: number = -1
  async ledCheck() {
    this.led.ledStateCheck = await NAPI.bq_GPIO_State(this.led.ledAddress)
    if (this.led.ledStateCheck === '1') {
      this.led.ledState = true
    } else if (this.led.ledStateCheck === 'Error: the GPIO is not exist') {
      this.led.isLedExit = false
    } else {
      this.led.ledState = false
    }
  }
  async aboutToAppear() {
    await this.ledCheck()
    //状态扫描
    this.setIntervalID = setInterval(async () => {
      await this.ledCheck()
    }, 500)
  }
  aboutToDisappear() {
    clearInterval(this.setIntervalID)
  }
  build() {
    Column() {
      Text("点亮一个LED灯")
        .size({ width: '100%', height: 35 })
        .margin({ top: 10, bottom: 10 })
        .textAlign(TextAlign.Center)
        .fontSize(30)
        .fontWeight(800)
      Column({ space: 10 }) {
        ledList({ item: this.led})
      }
      .margin({ top: 20, bottom: 10 })
      .size({ width: '50%', height: 50 })
      .justifyContent(FlexAlign.Start)
      .alignSelf(ItemAlign.Center)
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .size({ width: '100%', height: '100%' })
  }
}
@Component
struct ledList {
  @ObjectLink item: ledModel
  tip(str: string) {
    let show: string
    switch (str) {
      case "1":
        show = '已打开';
        break;
      case "0":
        show = '已关闭';
        break;
      default:
        show = `error: ${str}`
    }
    promptAction.showToast({
      message: show,
      duration: 800
    })
  }

  build() {
    Row() {
      Text(`${this.item.ledName}`)
        .size({ width: '70%', height: 35 })
        .fontSize(30)
        .fontWeight(700)
        .fontColor(this.item.isLedExit === true ? Color.Black : '#c9c9cd')
      Blank()
      Toggle({ type: ToggleType.Switch, isOn: this.item.ledState })
        .size({ width: 80, height: 35 })
        .enabled(this.item.isLedExit)
        .onChange(async (isOn) => {
          if (isOn) {
            let res: string = await NAPI.bq_GPIO_On(this.item.ledAddress)
            this.tip(res)
          } else {
            let res: string = await NAPI.bq_GPIO_Off(this.item.ledAddress)
            this.tip(res)
          }
        })
    }.width('100%')
  }
}

        2、效果展示

        (1)LED灭

        (2)LED亮

四、工程代码

见附件

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue-Cli 创建vue2.0 + TypeScript 项目

这里写目录标题 一、创建项目名称二、选择 Manually select features三、勾选配置项四、选择vue版本五、其它配置 一、创建项目名称 vue create 项目名称&#xff08;项目名字不能含义大写字母&#xff09;二、选择 Manually select features &#xff08;按箭头上下进行移动…

万物皆对象,你信吗?

**内存空间和数据都消失&#xff0c;数据怎么会消失的&#xff1f;**空间没了&#xff0c;数据自然也跟着消失。因为数据就是在空间里面的。就像宇宙大爆炸&#xff0c;我们还能存在嘛&#xff0c;是不是已经undefined了。「一块小内存上有2种数据类型」 内部存储的数据 地址值…

使用Fiddler如何创造大量数据

在调试和分析网络流量时&#xff0c;您是否曾为无法深入了解请求和响应的数据而感到困惑&#xff1f;如果有一种工具可以帮助您轻松抓取和分析网络流量&#xff0c;您的工作效率将大大提升。Fiddler正是这样一款功能强大的抓包工具&#xff0c;广受开发者和测试人员的青睐。 Fi…

专业140+总分400+武汉理工大学855信号与系统考研经验电子信息与通信工程,真题,大纲,参考书

专业855信号与系统140&#xff0c;总分400&#xff0c;今年顺利上岸武汉理工大学&#xff0c;总结一下自己的复习经历&#xff0c;希望对报考武理工的同学有所帮助。专业课&#xff1a;855信号与系统 首先教材&#xff1a; 《信号与系统》高等教育出版社 作者&#xff1a;刘泉…

详解三种常用标准化 Batch Norm Layer Norm RMSNorm

参考&#xff1a; BN究竟起了什么作用&#xff1f;一个闭门造车的分析《动手学深度学习》7.5 节 深度学习中&#xff0c;归一化是常用的稳定训练的手段&#xff0c;CV 中常用 Batch Norm&#xff1b; Transformer 类模型中常用 layer norm&#xff0c;而 RMSNorm 是近期很流行…

Pyppeteer原理介绍和入门尝试

pyppeteer仓库地址&#xff1a;https://github.com/miyakogi/pyppeteer puppeteer仓库地址&#xff1a;https://github.com/search?qpuppeteer&typerepositories 因为有些网页是可以检测到是否是使用了selenium。并且selenium所谓的保护机制不允许跨域cookies保存以及登…

JavaScript的学习之事件的简介

目录 一、事件是什么 二、如何处理事件 一、事件是什么 定义&#xff1a;事件就是浏览器和用户之间的交互行为。 例如&#xff1a;点击按钮、鼠标移动、关闭窗口等。 二、如何处理事件 我们可以在对应的事件属性中设置一些JS行为&#xff0c;当事件触发的时候会将这些代码执行…

java的输入流FileInput Stream类

一、定义 使用InputStream类的FileInputStream子类实现文本文件内容的读取。 二、常用构造方法 三、使用FileInput Stream类按多字节读取数据 1.示例 2、分析 四、常见错误 今天的总结就到这里啦&#xff0c;拜拜&#xff01;

Windows操作系统安装mysql数据库(zip安装包)

MySQL是目前最为流行的开放源码的数据库&#xff0c;是完全网络化的跨平台的关系型数据库系统&#xff0c;它是由瑞典MySQLAB公司开发&#xff0c;目前属于Oracle公司。任何人都能从Internet下载MySQL软件&#xff0c;而无需支付任费用&#xff0c;并且“开放源码”意味着任何人…

活动预告|探索 LLM 大模型的小型化 —— 微软 Phi3在 NVIDIA Jetson 与 NIM 平台的最佳实践

在当前高速发展的人工智能领域&#xff0c;如何高效的部署和优化 SLM (小型的大模型) 成为关键。随着微软 Phi-3 系列模型的发布&#xff0c;让 SLM 在 NVIDIA Jetson 边缘计算平台上的部署成为可能。同时 Phi-3 系列模型已在 NVIDIA NIM 平台提供加速的推理服务。 NVIDIA NIM…

msvcp120.dll丢失怎么办,找不到msvcp120.dll的多种解决方法

最近&#xff0c;我在运行一个程序时遇到了一个错误&#xff0c;系统提示找不到msvcp120.dll文件&#xff0c;无法继续执行代码。这让我感到非常困扰&#xff0c;因为这个问题导致我无法正常运行这个程序。经过一番搜索和尝试&#xff0c;我找到了几种修复这个问题的方法&#…

ONLYOFFICE 桌面编辑器 8.1重磅来袭:全新功能提升您的办公效率

文章目录 前言ONLYOFFICE 桌面编辑器8.1一、PDF编辑&#xff1a;告别“头痛”时刻二、幻灯片版式&#xff1a;秒变“设计大师”三、无缝切换&#xff1a;办公界的“快速通道”四、语言支持&#xff1a;全球通吃的“翻译官”五、 隐藏“连接到云”板块&#xff1a;摆脱“云”的束…

RocketMQ如何添加JVM监控

这里是小奏,觉得文章不错可以关注公众号小奏技术 JVM监控选型 本次JVM监控我们采用prometheus官方提供的jmx_exporter来实现 RocketMQJVM开发 整体目录 1. 新增agent目录 我们在distribution目录新增一个agent模块&#xff0c;然后添加两个文件 jmx_prometheus_javaagent-…

Mysql索引底层数据结构——Java全栈知识(28)

Mysql索引底层数据结构 1、什么是索引 索引在项目中还是比较常见的&#xff0c;它是帮助MySQL高效获取数据的数据结构&#xff0c;主要是用来提高数据检索的效率&#xff0c;降低数据库的IO成本&#xff0c;同时通过索引列对数据进行排序&#xff0c;降低数据排序的成本&…

低价可转债崩盘,发生了什么?

下跌不在于“出库”&#xff0c;甚至不在于“风险”。问题更多在于交易层面&#xff0c;何时能积聚更多的左侧资金并成功过渡至右侧。 低价券怎么了&#xff1f; 如果说6月初主要是小微盘品种的退市风险&#xff0c;后来是一些评级下调的品种&#xff0c;到本周&#xff0c;已…

【Godot4自学手册】第四十二节实现拖拽进行物品交换和数量叠加

这一节我们主要学习背包系统中的物品拖拽后&#xff0c;物品放到新的位置&#xff0c;或交换物品位置&#xff0c;如果两个物品属于同一物品则数量相加。具体效果如下&#xff1a; 一、修改item.tscn场景 给item.tscn场景的根节点Item添加Label子节点&#xff0c;命名为Numv…

【计算机视觉】人脸算法之图像处理基础知识(六)

图像直方图 图像直方图是描述图像中像素强度分布的一种统计图表&#xff0c;它是图像处理和计算机视觉领域中一个非常基础且重要的概念。图像直方图通常用于分析图像的亮度、对比度特性&#xff0c;以及在图像增强、阈值分割、特征提取等多种图像处理任务。 import cv2 impor…

HTTPS 代理的优点和缺点是什么?

HTTPS&#xff08;超文本安全传输协议&#xff09;作为一种基于HTTP加上SSL安全层的网络通信协议&#xff0c;已经成为互联网上广泛使用的IP协议之一。它在保证信息安全和隐私方面具有很多优势&#xff0c;但也存在一些缺点。接下来&#xff0c;我们就来探究一下HTTPS协议的优缺…

日牵物流装备受邀盛装亮相2024长三角快递物流供应链与技术装备展览会(杭州)

日牵物流装备受邀盛装亮相2024长三角快递物流供应链与技术装备展览会&#xff0c;为物流节省每一个铜板&#xff0c;3C馆A21与您相约&#xff01; 日牵物流装备始建于1995年&#xff0c;总部坐落于辽宁省大连市&#xff0c;是一家集科研开发、生产制造、销售服务于一体的现代化…

HTML5【新特性总结】

HTML5【新特性总结】 HTML5 的新增特性主要是针对于以前的不足&#xff0c;增加了一些新的标签、新的表单和新的表单属性等。 这些新特性都有兼容性问题&#xff0c;基本是 IE9 以上版本的浏览器才支持&#xff0c;如果不考虑兼容性问题&#xff0c;可以大量使用这些新特性。…