更新
This commit is contained in:
parent
2ddf1bbad5
commit
3bde6954a1
@ -26,10 +26,10 @@ flutter build windows
|
||||
## 二、功能
|
||||
|
||||
1. 展示
|
||||
1.1 座椅调节
|
||||
1.2 座椅按摩
|
||||
1.3 座椅加热
|
||||
1.4 座椅通风
|
||||
1. 座椅调节
|
||||
1. 座椅按摩
|
||||
1. 座椅加热
|
||||
1. 座椅通风
|
||||
2. 报文
|
||||
3. 日志
|
||||
4. 设置
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'can_fd_msg.dart';
|
||||
|
||||
//CAN设备状态抽象类
|
||||
class CANDev {
|
||||
//CAN设备名称
|
||||
@ -15,6 +17,8 @@ class CANDev {
|
||||
//设备句柄
|
||||
int devhandle=0;
|
||||
|
||||
int errCounter=0;
|
||||
|
||||
CANDev({
|
||||
required this.devname,
|
||||
required this.devchannel,
|
||||
@ -43,14 +47,14 @@ abstract class AbstractCANDevice {
|
||||
List<CANDev> getDeviceList();
|
||||
|
||||
// 启动CAN设备
|
||||
bool start();
|
||||
bool start({required int canIndex,required int canChannel , required int baudrate});
|
||||
|
||||
// 停止CAN设备
|
||||
bool stop();
|
||||
bool stop({required int canIndex});
|
||||
|
||||
// 发送CAN消息
|
||||
Future<bool> sendMessage(List<int> data);
|
||||
Future<bool> sendMessage({required int canIndex, required int canChannel, required int canid,required List<int> data});
|
||||
|
||||
// 接收CAN消息
|
||||
Stream<List<int>> receiveMessage();
|
||||
Stream<CanFdMsg> receiveMessage({required int canIndex, required int canChannel});
|
||||
}
|
24
lib/CanLib/can_fd_msg.dart
Normal file
24
lib/CanLib/can_fd_msg.dart
Normal file
@ -0,0 +1,24 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
final class CanFdMsg extends Struct {
|
||||
@Uint32()
|
||||
external int id; // 报文ID,bit[30]-RTR,bit[31]-IDE,bit[28..0]-ID
|
||||
|
||||
@Uint8()
|
||||
external int dlc; // 数据字节长度,可设置为-0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64
|
||||
|
||||
@Uint8()
|
||||
external int flags; // bit[0]-BRS,bit[1]-ESI,bit[2]-FDF,bit[6..5]-Channel,bit[7]-RXD
|
||||
|
||||
@Uint8()
|
||||
external int res0; // 保留
|
||||
|
||||
@Uint8()
|
||||
external int res1; // 保留
|
||||
|
||||
@Uint32()
|
||||
external int timeStamp; // 帧接收或者发送时的时间戳,单位为10us
|
||||
|
||||
@Array<Uint8>(64)
|
||||
external Array<Uint8> data;
|
||||
}
|
49
lib/CanLib/canfd_init_config.dart
Normal file
49
lib/CanLib/canfd_init_config.dart
Normal file
@ -0,0 +1,49 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
final class CanFdInitConfig extends Struct {
|
||||
/// 0-正常模式,1-自发自收模式
|
||||
@Uint8()
|
||||
external int mode;
|
||||
|
||||
/// 0-禁止ISO CRC,1-使能ISO CRC
|
||||
@Uint8()
|
||||
external int isocrcEnable;
|
||||
|
||||
/// 0-禁止重发,1-无限制重发
|
||||
@Uint8()
|
||||
external int retrySend;
|
||||
|
||||
/// 0-不接入内部120欧终端电阻,1-接入内部120欧终端电阻
|
||||
@Uint8()
|
||||
external int resEnable;
|
||||
|
||||
/// 仲裁段波特率参数, 波特率=40M/NBT_BRP*(1+NBT_SEG1+NBT_SEG2)
|
||||
@Uint8()
|
||||
external int nbtBRP;
|
||||
|
||||
@Uint8()
|
||||
external int nbtSEG1;
|
||||
|
||||
@Uint8()
|
||||
external int nbtSEG2;
|
||||
|
||||
@Uint8()
|
||||
external int nbtSJW;
|
||||
|
||||
/// 数据段波特率参数, 波特率=40M/DBT_BRP*(1+DBT_SEG1+DBT_SEG2)
|
||||
@Uint8()
|
||||
external int dbtBRP;
|
||||
|
||||
@Uint8()
|
||||
external int dbtSEG1;
|
||||
|
||||
@Uint8()
|
||||
external int dbtSEG2;
|
||||
|
||||
@Uint8()
|
||||
external int dbtSJW;
|
||||
|
||||
/// 预留字段
|
||||
@Array<Uint8>(8)
|
||||
external Array<Uint8> res0;
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
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';
|
||||
@ -96,27 +98,147 @@ bool initialize() {
|
||||
}
|
||||
|
||||
@override
|
||||
bool start() {
|
||||
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() {
|
||||
// 实现停止逻辑
|
||||
return true;
|
||||
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(List<int> data) {
|
||||
// 实现发送消息逻辑
|
||||
return Future.value(true);
|
||||
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<List<int>> receiveMessage() {
|
||||
// 实现接收消息逻辑
|
||||
return Stream.empty();
|
||||
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!);
|
||||
}
|
||||
|
||||
|
||||
|
95
lib/device_managge.dart
Normal file
95
lib/device_managge.dart
Normal file
@ -0,0 +1,95 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DeviceManagementDialog extends StatelessWidget {
|
||||
const DeviceManagementDialog({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 定义CAN设备ID、CAN通道和波特率的选项列表
|
||||
final List<String> canDeviceIds = ['ID1', 'ID2', 'ID3'];
|
||||
final List<String> canChannels = ['通道1', '通道2'];
|
||||
final List<String> baudRates = ['500K', '115200', '250000'];
|
||||
|
||||
// 定义选中的值的状态变量
|
||||
String selectedCanDeviceId = canDeviceIds[0];
|
||||
String selectedCanChannel = canChannels[0];
|
||||
String selectedBaudRate = baudRates[0];
|
||||
|
||||
return AlertDialog(
|
||||
title: const Text('设备管理'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// CAN设备ID下拉框
|
||||
DropdownButton<String>(
|
||||
value: selectedCanDeviceId,
|
||||
onChanged: (newValue) {
|
||||
if (newValue != null) {
|
||||
selectedCanDeviceId = newValue;
|
||||
}
|
||||
},
|
||||
items: canDeviceIds.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
// CAN通道下拉框
|
||||
DropdownButton<String>(
|
||||
value: selectedCanChannel,
|
||||
onChanged: (newValue) {
|
||||
if (newValue != null) {
|
||||
selectedCanChannel = newValue;
|
||||
}
|
||||
},
|
||||
items: canChannels.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
// 波特率下拉框
|
||||
DropdownButton<String>(
|
||||
value: selectedBaudRate,
|
||||
onChanged: (newValue) {
|
||||
if (newValue != null) {
|
||||
selectedBaudRate = newValue;
|
||||
}
|
||||
},
|
||||
items: baudRates.map<DropdownMenuItem<String>>((String value) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: value,
|
||||
child: Text(value),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
// 刷新按钮
|
||||
TextButton(
|
||||
child: const Text('刷新'),
|
||||
onPressed: () {
|
||||
// 这里可以添加刷新的逻辑
|
||||
},
|
||||
),
|
||||
// 连接按钮
|
||||
TextButton(
|
||||
child: const Text('连接'),
|
||||
onPressed: () {
|
||||
// 这里可以添加连接的逻辑
|
||||
},
|
||||
),
|
||||
// 关闭按钮
|
||||
TextButton(
|
||||
child: const Text('关闭'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'Page/display_page.dart';
|
||||
import 'Page/message_page.dart';
|
||||
import 'Page/log_page.dart';
|
||||
import 'device_managge.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
@ -107,6 +108,19 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
_scaffoldKey.currentState?.openDrawer();
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return const DeviceManagementDialog();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: Text(widget.title),
|
||||
),
|
||||
|
Loading…
x
Reference in New Issue
Block a user