RP-01_Flutter/lib/CanLib/toomoss_can.dart
2025-04-30 17:01:25 +08:00

245 lines
10 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'abstract_can_device.dart';
import 'device_info.dart';
import 'canfd_init_config.dart';
import 'can_fd_msg.dart';
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'package:logging/logging.dart';
import 'dart:io';
class ToomossCAN extends AbstractCANDevice {
final Logger _logger = Logger('ToomossCAN');
late DynamicLibrary _dll;
bool _loadDll = false;
List<CANDev> _deviceList = [];
@override
bool initialize() {
// 加载USB2XXX.dll
try {
_dll = DynamicLibrary.open('USB2XXX.dll');
_logger.info("Load DLL success");
_loadDll = true;
}
catch (e) {
_logger.severe('Failed to load USB2XXX.dll: $e');
//记录当前工作路径
_logger.severe('Current working directory: ${Directory.current.path}');
return false;
}
return true;
}
@override
int refresh() {
// 实现刷新逻辑
if(_loadDll == false) {
_logger.info('refresh error:Failed to load USB2XXX.dll');
_logger.info(_loadDll.toString());
return 0;
}
_logger.info('刷新设备列表');
final usbScanDevice = _dll.lookupFunction<Int32 Function(Pointer<Int32>), int Function(Pointer<Int32>)>('USB_ScanDevice');
final devHandle = calloc<Int32>(20);
final deviceCount = usbScanDevice(devHandle);
if (deviceCount > 0) {
_logger.info('当前找到的设备数为: $deviceCount');
for (int i = 0; i < deviceCount; i++) {
final devHandleValue = devHandle[i];
final devGetDeviceInfo = _dll.lookupFunction<Bool Function(Int32, Pointer<ToomossDeviceInfo>, Pointer<Uint8>), bool Function(int, Pointer<ToomossDeviceInfo>, Pointer<Uint8>)>('DEV_GetDeviceInfo');
final devInfo = calloc<ToomossDeviceInfo>();
final funcStr = calloc<Uint8>(256);
final success = devGetDeviceInfo(devHandleValue, devInfo, funcStr);
if (success) {
//final firmwareName = devInfo.ref.firmwareName.cast<Utf8>().toDartString();
//final buildDate = devInfo.ref.buildDate.toDartString();
//final hardwareVersion = devInfo.ref.hardwareVersion;
final firmwareVersion = devInfo.ref.firmwareVersion;
final serialNumber = List<int>.generate(3, (index) => devInfo.ref.serialNumber[index]);
//final functions = devInfo.ref.Functions;
//final funcStrDart = funcStr.toDartString();
final int typp1 = (devHandleValue>>28)&0x0F;
final int typp2 = (devHandleValue>>24)&0x0F;
final toomossDevModel = '0${typp1}0$typp2';//型号
_deviceList.add(CANDev(
devname: 'Toomoss-$toomossDevModel',
devsn: serialNumber.map((num) => num.toRadixString(16).padLeft(2, '0')).join(''),
devchannel: 2, //
runstatus: false,
devhandle: devHandleValue,
firmwareversion: '${(firmwareVersion >> 24) & 0xFF}.${(firmwareVersion >> 16) & 0xFF}.${firmwareVersion & 0xFFFF}',
));
} else {
_logger.severe('Failed to get device info for device $i ,device id 0x${devHandleValue.toRadixString(16).toUpperCase()}');
}
calloc.free(devInfo);
calloc.free(funcStr);
}
} else {
_logger.info('无设备连接');
_deviceList.clear();
}
calloc.free(devHandle);
if(deviceCount > 0) {
// 遍历设备列表,输出每个设备的具体信息
for (var device in _deviceList) {
_logger.info('设备名称: ${device.devname}, 设备序列号: ${device.devsn}, 设备通道数: ${device.devchannel}, 运行状态: ${device.runstatus}, 设备句柄: ${device.devhandle.toRadixString(16).toUpperCase()}, 固件版本: ${device.firmwareversion}');
}
}
return deviceCount;
}
@override
List<CANDev> getDeviceList() {
// 实现获取设备列表逻辑
return _deviceList;
}
@override
bool start({required int canIndex,required int canChannel , required int baudrate}) {
// 实现启动逻辑
try {
final canfdInit = _dll.lookupFunction<Int32 Function(Int32, Uint8, Pointer<CanFdInitConfig>), int Function(int, int, Pointer<CanFdInitConfig>)>('CANFD_Init');
// 假设这里使用第一个设备的句柄,可根据实际情况修改
if (_deviceList.isNotEmpty) {
var canConfig = calloc<CanFdInitConfig>(); // 初始化 CANFD_INIT_CONFIG
canConfig.ref.mode = 0; // 正常模式
canConfig.ref.isocrcEnable = 0; // 禁用 ISO CRC
canConfig.ref.retrySend = 0; // 禁止重发
canConfig.ref.resEnable = 1; // 接入内部 120 欧终端电阻
canConfig.ref.nbtBRP = 1; // 仲裁段波特率参数
canConfig.ref.nbtSEG1 = 59; // 仲裁段波特率参数
canConfig.ref.nbtSEG2 = 20; // 仲裁段波特率参数
canConfig.ref.nbtSJW = 2; // 仲裁段波特率参数
canConfig.ref.dbtBRP = 2; // 数据段波特率参数
canConfig.ref.dbtSEG1 = 29; // 数据段波特率参数
canConfig.ref.dbtSEG2 = 10; // 数据段波特率参数
canConfig.ref.dbtSJW = 2; // 数据段波特率参数
final result = canfdInit(_deviceList[canIndex].devhandle, canChannel, canConfig);
calloc.free(canConfig); // 释放内存
if (result != 1) {
_logger.severe('CANFD_Init 初始化失败,返回值: $result');
return false;
}
//初始化成功
_logger.info('CANFD_Init 初始化成功,返回值: $result');
_deviceList[canIndex].channelstatus[canChannel] = true;
_deviceList[canIndex].runstatus = true;
} else {
_logger.severe('无可用设备,无法初始化 CANFD_Init');
return false;
}
} catch (e) {
_logger.severe('调用 CANFD_Init 时发生异常: $e');
return false;
}
return true;
}
@override
bool stop({required int canIndex}) {
try {
if (_loadDll && _deviceList.isNotEmpty) {
final usbCloseDevice = _dll.lookupFunction<Bool Function(Int32), bool Function(int)>('USB_CloseDevice');
final result = usbCloseDevice(_deviceList[canIndex].devhandle);
if (!result) {
_logger.severe('USB_CloseDevice 调用失败,设备句柄: ${_deviceList[canIndex].devhandle.toRadixString(16).toUpperCase()}');
}
return result;
} else {
_logger.severe('无法调用 USB_CloseDevice可能 DLL 未加载或无可用设备。');
return false;
}
} catch (e) {
_logger.severe('调用 USB_CloseDevice 时发生异常: $e');
return false;
}
}
@override
Future<bool> sendMessage({required int canIndex, required int canChannel, required int canid,required List<int> data}) {
if(_deviceList[canIndex].runstatus == false || _deviceList[canIndex].channelstatus[canChannel] == false) {
return Future.value(false);//设备/通道未启动
}
try {
final canfdSendMsg = _dll.lookupFunction<Int32 Function(Int32, Uint8, Pointer<CanFdMsg>, Uint32), int Function(int, int, Pointer<CanFdMsg>, int)>('CANFD_SendMsg');
if (_deviceList.isNotEmpty) {
final devHandle = _deviceList[canIndex].devhandle;
var canMsg = calloc<CanFdMsg>();
canMsg.ref.id = canid;
canMsg.ref.dlc = data.length.toUnsigned(8);
for (int i = 0; i < data.length; i++) {
canMsg.ref.data[i] = data[i].toUnsigned(8);
}
final result = canfdSendMsg(devHandle, canChannel, canMsg, 1);
calloc.free(canMsg);
if (result >= 0) {
//_logger.info('CANFD_SendMsg 发送成功,返回值: $result');
_deviceList[canIndex].errCounter = 0;
return Future.value(true);
} else {
/*
//函数返回值错误信息定义
#define CANFD_SUCCESS (0) //函数执行成功
#define CANFD_ERR_NOT_SUPPORT (-1) //适配器不支持该函数
#define CANFD_ERR_USB_WRITE_FAIL (-2) //USB写数据失败
#define CANFD_ERR_USB_READ_FAIL (-3) //USB读数据失败
#define CANFD_ERR_CMD_FAIL (-4) //命令执行失败
*/
_logger.severe('CANFD_SendMsg 发送失败,返回值: $result');
_deviceList[canIndex].errCounter++;
if(_deviceList[canIndex].errCounter > 5) {
_deviceList[canIndex].channelstatus[canChannel] = false;
_deviceList[canIndex].runstatus = false;
}
return Future.value(false);
}
} else {
_logger.severe('无可用设备,无法调用 CANFD_SendMsg');
return Future.value(false);
}
} catch (e) {
_logger.severe('调用 CANFD_SendMsg 时发生异常: $e');
_deviceList[canIndex].channelstatus[canChannel] = false;
_deviceList[canIndex].runstatus = false;
return Future.value(false);
}
}
@override
Stream<CanFdMsg> receiveMessage({required int canIndex, required int canChannel}) {
return Stream.periodic(Duration(milliseconds: 10), (_) {
if(_deviceList[canIndex].runstatus == false || _deviceList[canIndex].channelstatus[canChannel] == false) {
return null;
}
try {
final canfdGetMsg = _dll.lookupFunction<Int32 Function(Int32, Uint8, Pointer<CanFdMsg>, Int32), int Function(int, int, Pointer<CanFdMsg>, int)>('CANFD_GetMsg');
final bufferSize = 100;
final canMsgs = calloc<CanFdMsg>(bufferSize);
final result = canfdGetMsg(_deviceList[canIndex].devhandle, canChannel, canMsgs, bufferSize);
if (result > 0) {
List<CanFdMsg> messages = [];
for (int i = 0; i < result; i++) {
// 复制消息数据,避免内存释放后访问问题
final msgCopy = calloc<CanFdMsg>();
msgCopy.ref = canMsgs[i];
messages.add(msgCopy.ref);
}
calloc.free(canMsgs);
return messages;
} else {
calloc.free(canMsgs);
return null;
}
} catch (e) {
_logger.severe('调用 CANFD_GetMsg 时发生异常: $e');
return null;
}
}).where((messages) => messages != null).expand((messages) => messages!);
}
}