HarmonyOS 鸿蒙Next中桥接C语言使用Modbus控制的问题
HarmonyOS 鸿蒙Next中桥接C语言使用Modbus控制的问题
桥接c/cpp 这个文件和原理不太懂 能不能详细说一下
比如我要往对应192.168.1.200 里面 M7000 寄存器写一个 1或者0
根据之前的案例看不太懂 跑不通
问题1每个文件以及里面的调用逻辑太复杂 看不懂

这里文件调用顺序是什么 ? index.d.ts->brdgeModbus.app->napi_init.cpp 吗??



上传了CPP压缩包(不知道为什么zip不能上传 ,改成zip解压)
以下是调用代码
onPageShow(): void {
//开启一个显示时间的定时器
//每次页面显示时候开启定时器,参数1是调用更新时间的函数,1000是1000毫秒,后面还需要onPageHide配合实现页面不显示就不用定时器更新时间节省资源
clearInterval(this.timeID) //启动的时候先清一次
this.timeID = setInterval(() => {
this.updateTimeDate()
getContext().eventHub.emit('传连接状态')//每一秒钟发送一个检测有没有连接的更新请求
}, 1000) //setInterval 整体拿到的是一个timeid,下面要用
// 心跳包定时器(每5秒发送一次心跳)
setInterval(() => {
// 发送心跳包到M7000寄存器
try {
this.sendHeartbeat()
} catch (error) {
console.error('心跳包定时器执行异常:', error);
}
}, 5000)
//连接图标
//注册了一个监听事件,来了'传ip和port参数值'这个消息就执行后面的函数
getContext().eventHub.on('传ip和port参数值', (velue:object) => {
this.ip = velue['ip'];
this.port = velue['port'] //把高级设置里面的ip和port 传过来
try {
this.status = testNapi.init_connect(this.ip,Number(this.port)) //modbus初始化
console.info('监听到了传ip和port参数值',velue['ip'],velue['port'])
} catch (error) {
console.error('初始化连接时发生异常:', error);
this.status = -1;
}
})
try {
this.status= testNapi.init_connect(this.ip,Number(this.port)) //状态
} catch (error) {
console.error('初始化连接时发生异常:', error);
this.status = -1;
}
// let status = testNapi.init_connect(this.ip,Number(this.port)) //modbus初始化
// testNapi.init_connect(this.ip,Number(this.port)) 调用文件顺序:
// ETS层调用 (入口)
// 文件: /Users/MD/DevEcoStudioProjects/BendOS_Local/entry/src/main/ets/pages/MainPage.ets
// 代码: import testNapi from 'libentry.so'
// 调用: testNapi.init_connect(this.ip,Number(this.port))
// Node-API桥接层
// 文件: /Users/MD/DevEcoStudioProjects/BendOS_Local/entry/src/main/cpp/modbus/bridgeModbus.cpp
// 函数: init_connect (N-API包装函数)
// 当前实现: 临时返回成功(1),未实际调用底层函数
// 头文件声明
// 文件: /Users/MD/DevEcoStudioProjects/BendOS_Local/entry/src/main/cpp/include/modbus/main.h
// 声明: int modbusInitConnect(const char* ip,int port);
// 实际实现层
// 文件: /Users/MD/DevEcoStudioProjects/BendOS_Local/entry/src/main/cpp/src/modbus/main.c
// 函数: modbusInitConnect (实际的Modbus连接实现)
// 功能: 创建Modbus TCP连接,设置参数,连接设备等
// 类型定义
// 文件: /Users/MD/DevEcoStudioProjects/BendOS_Local/entry/src/main/cpp/types/libentry/index.d.ts
// 定义: export const init_connect: (ip: string, b: number) => number;
// 构建配置
// 文件: /Users/MD/DevEcoStudioProjects/BendOS_Local/entry/src/main/cpp/modbus/CMakeLists.txt
// 配置: 定义如何编译链接生成libentry.so
// 注意: bridgeModbus.cpp中的init_connect函数是临时实现,直接返回成功(1),并未实际调用test_main.c中的modbusInitConnect函数。如果需要实际的Modbus连接功能,需要修改bridgeModbus.cpp中的init_connect函数来调用modbusInitConnect。
//注册了一个监听事件,来了'传连接状态'这个消息就执行后面的函数
getContext().eventHub.on('传连接状态', () => {
console.info('监听到了传连接状态')
try {
// 简化连接检查逻辑
// 只有在当前未连接时才尝试重新连接
if (!this.rightTopIconList[0].isSelect) {
this.status = testNapi.init_connect(this.ip,Number(this.port)) //modbus初始化
if(this.status===1){
this.rightTopIconList[0].isSelect = true; //已连接就更新这个rightTopIconList[0]的 状态 isSelect是 @Trace修饰的
console.info(`modbus已连接`, `ip:${this.ip}`, `port:${this.port}`);
}else {
this.rightTopIconList[0].isSelect = false;
console.error(`'modbus未连接,需要重新连接`, `status:${this.status}`, `ip:${this.ip}`, `port:${this.port}`);
}
} else {
console.info('当前已连接,跳过重复连接检查')
}
} catch (error) {
console.error('连接状态检查时发生异常:', error);
// 发生异常,标记为未连接
this.rightTopIconList[0].isSelect = false;
}
})
}
// 发送心跳包到M7000寄存器
private sendHeartbeat() {
// 检查是否已连接
if (!this.rightTopIconList[0].isSelect) {
console.info('设备未连接,跳过心跳包发送');
return;
}
// 计算M继电器的Modbus线圈地址 = 0x0800 + 继电器编号 M7000寄存器地址 = 0x0800 + 继电器编号 modbus要的是绝对地址
const coilAddr = 0x0800 + this.HEARTBEAT_REGISTER;
// 使用定义的常量发送心跳包
console.info(`发送心跳包到M${this.HEARTBEAT_REGISTER}寄存器(线圈地址: ${coilAddr}),值为${this.HEARTBEAT_VALUE}`)
// 调用C++层的函数来实际发送心跳包
try {
this.heartbeatResult = testNapi.send_heartbeat(coilAddr, this.HEARTBEAT_VALUE);
if (this.heartbeatResult === 1) {
console.info('心跳包发送成功');
// 心跳包发送成功,确保连接状态为已连接
this.rightTopIconList[0].isSelect = true;
} else {
console.error('心跳包发送失败,返回值:', this.heartbeatResult);
// 心跳包发送失败,标记为未连接
this.rightTopIconList[0].isSelect = false;
}
} catch (error) {
console.error('发送心跳包时发生异常:', error);
// 发生异常,标记为未连接
this.rightTopIconList[0].isSelect = false;
}
}
最终效果是没有反应 如果可以 可以试一下在两个电脑上一个客户端 一个服务端 试一下
更多关于HarmonyOS 鸿蒙Next中桥接C语言使用Modbus控制的问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者您好,可以采取以下方式解决:
【解决方案】 HarmonyOS创建的Native工程目录结构参考文档C++工程目录结构。
根据您的问题回答如下:
-
ArkTS调用Native顺序:ArkTS层(so导入以及调用)->index.d.ts(头文件)->napi_init.cpp(接口暴露)->具体的功能实现函数;
-
napi_init.cpp文件内的函数暴露出去给到index.d.ts文件;
-
ArkTS侧调用Native侧的函数:
Native工程编译运行时,Native侧代码最终会以so的形式被ArkTS侧调用,ArkTS侧的导入形式如下:
import ${抽象名} from '${so名}'
具体NAPI相关使用可以参考NDK开发导读和使用Node-API实现跨语言交互开发流程。
更多关于HarmonyOS 鸿蒙Next中桥接C语言使用Modbus控制的问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在鸿蒙Next中,桥接C语言使用Modbus控制可通过鸿蒙NDK调用C库实现。鸿蒙提供Native API支持C/C++代码集成,允许直接使用Modbus的C语言库进行串口或TCP通信。开发者需在Native层封装Modbus协议栈,通过HarmonyOS的驱动框架操作硬件接口。注意鸿蒙Next的HDF驱动模型可管理设备资源,确保Modbus主从设备通信稳定。具体实现涉及创建Native工程、导入Modbus库、编写桥接代码及调用鸿蒙Native接口进行数据交互。
在HarmonyOS Next中通过Node-API桥接C/C++实现Modbus控制
核心是理解桥接层的作用和调用链路。从你的代码看,问题主要出在桥接层没有正确调用底层Modbus函数。
桥接文件调用顺序
- index.d.ts - TypeScript类型声明,定义ArkTS可调用的接口
- bridgeModbus.cpp - Node-API桥接层,将ArkTS调用转发到C函数
- napi_init.cpp - 模块初始化,注册函数到Node-API
- main.c - 实际的Modbus TCP实现
问题分析
从代码注释看,bridgeModbus.cpp中的init_connect函数只是临时返回1,没有实际调用modbusInitConnect。同样,send_heartbeat函数可能也存在类似问题。
解决方案
需要修改bridgeModbus.cpp,确保桥接函数正确调用底层C函数:
// 在bridgeModbus.cpp中
napi_value InitConnect(napi_env env, napi_callback_info info) {
// 解析参数
size_t argc = 2;
napi_value args[2];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// 获取IP和端口
char ip[16];
size_t ip_len;
napi_get_value_string_utf8(env, args[0], ip, sizeof(ip), &ip_len);
int32_t port;
napi_get_value_int32(env, args[1], &port);
// 实际调用底层Modbus函数
int result = modbusInitConnect(ip, port);
// 返回结果给ArkTS
napi_value napi_result;
napi_create_int32(env, result, &napi_result);
return napi_result;
}
关键检查点
- 确保CMakeLists.txt正确链接所有源文件
- 验证libmodbus库是否正确引入和编译
- 检查网络权限配置
- 确认M7000寄存器对应的Modbus线圈地址计算正确
桥接层的核心作用就是参数转换和函数转发,需要确保每个桥接函数都正确调用了对应的底层C函数实现。


