Created
November 19, 2024 05:01
-
-
Save xeron56/e288be428f3d091793d2beb5313fb71c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'dart:typed_data'; | |
void main() { | |
runApp(CANSimulatorApp()); | |
} | |
class CANSimulatorApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'CAN Message Simulator', | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: CANSimulatorHomePage(), | |
); | |
} | |
} | |
class CANSimulatorHomePage extends StatefulWidget { | |
@override | |
_CANSimulatorHomePageState createState() => _CANSimulatorHomePageState(); | |
} | |
class _CANSimulatorHomePageState extends State<CANSimulatorHomePage> { | |
final _formKey = GlobalKey<FormState>(); | |
final TextEditingController _pidController = TextEditingController(); | |
final TextEditingController _valueController = TextEditingController(); | |
int? _address; | |
BigInt? _data; | |
List<int>? _dataBytes; | |
void _simulateMessage() { | |
if (_formKey.currentState!.validate()) { | |
// Parse PID as hexadecimal | |
int pid = int.parse(_pidController.text, radix: 16); | |
// Parse value as decimal | |
int value = int.parse(_valueController.text); | |
// Simulate CAN message | |
Map<String, dynamic> result = CANSimulator.simulateCanMessage(pid, value); | |
setState(() { | |
_address = result['address']; | |
_data = result['data']; | |
_dataBytes = result['dataBytes']; | |
}); | |
} | |
} | |
@override | |
void dispose() { | |
_pidController.dispose(); | |
_valueController.dispose(); | |
super.dispose(); | |
} | |
String _formatHex(int value, int digits) { | |
return '0x' + value.toRadixString(16).toUpperCase().padLeft(digits, '0'); | |
} | |
String _formatHexBigInt(BigInt value, int digits) { | |
return '0x' + value.toRadixString(16).toUpperCase().padLeft(digits, '0'); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text('CAN Message Simulator'), | |
), | |
body: Padding( | |
padding: EdgeInsets.all(16.0), | |
child: SingleChildScrollView( | |
child: Column( | |
children: [ | |
// Input Form | |
Form( | |
key: _formKey, | |
child: Column( | |
children: [ | |
// PID Input | |
TextFormField( | |
controller: _pidController, | |
decoration: InputDecoration( | |
labelText: 'PID (Hexadecimal)', | |
hintText: 'e.g., 0C', | |
border: OutlineInputBorder(), | |
), | |
keyboardType: TextInputType.text, | |
validator: (value) { | |
if (value == null || value.isEmpty) { | |
return 'Please enter PID'; | |
} | |
final hexRegExp = RegExp(r'^[0-9A-Fa-f]+$'); | |
if (!hexRegExp.hasMatch(value)) { | |
return 'Enter a valid hexadecimal value'; | |
} | |
return null; | |
}, | |
), | |
SizedBox(height: 16.0), | |
// Value Input | |
TextFormField( | |
controller: _valueController, | |
decoration: InputDecoration( | |
labelText: 'Value (Decimal)', | |
hintText: 'e.g., 3000', | |
border: OutlineInputBorder(), | |
), | |
keyboardType: TextInputType.number, | |
validator: (value) { | |
if (value == null || value.isEmpty) { | |
return 'Please enter a value'; | |
} | |
if (int.tryParse(value) == null) { | |
return 'Enter a valid integer'; | |
} | |
return null; | |
}, | |
), | |
SizedBox(height: 16.0), | |
// Simulate Button | |
ElevatedButton( | |
onPressed: _simulateMessage, | |
child: Text('Simulate CAN Message'), | |
), | |
], | |
), | |
), | |
SizedBox(height: 24.0), | |
// Output Section | |
if (_address != null && _data != null && _dataBytes != null) | |
Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Text( | |
'Simulation Results:', | |
style: TextStyle( | |
fontSize: 18.0, | |
fontWeight: FontWeight.bold, | |
), | |
), | |
SizedBox(height: 12.0), | |
// 29-bit Address | |
Row( | |
children: [ | |
Text( | |
'29-bit Address: ', | |
style: TextStyle(fontWeight: FontWeight.bold), | |
), | |
Text(_formatHex(_address!, 8)), | |
], | |
), | |
SizedBox(height: 8.0), | |
// 64-bit Data | |
Row( | |
children: [ | |
Text( | |
'64-bit Data: ', | |
style: TextStyle(fontWeight: FontWeight.bold), | |
), | |
Text(_formatHexBigInt(_data!, 16)), | |
], | |
), | |
SizedBox(height: 8.0), | |
// Data Bytes | |
Text( | |
'Data Bytes: ', | |
style: TextStyle(fontWeight: FontWeight.bold), | |
), | |
Wrap( | |
spacing: 8.0, | |
children: _dataBytes! | |
.map((byte) => Chip( | |
label: Text(_formatHex(byte, 2)), | |
backgroundColor: Colors.blue.shade100, | |
)) | |
.toList(), | |
), | |
], | |
), | |
], | |
), | |
), | |
), | |
); | |
} | |
} | |
class CANSimulator { | |
// Simulate CAN message | |
static Map<String, dynamic> simulateCanMessage(int pid, int value) { | |
// 29-bit OBD-II address (e.g., 0x18DAF110) | |
int address = 0x18DAF110 & 0x1FFFFFFF; // Mask to 29 bits | |
// Prepare the data bytes | |
List<int> dataBytes = List.filled(8, 0); | |
// Number of additional data bytes (PID + 2 bytes of data) | |
dataBytes[0] = 0x04; | |
// Response Service ID (0x40 + Request Service ID) | |
int serviceId = 0x40 + 0x01; // Assuming service ID 0x01 for current data | |
dataBytes[1] = serviceId; | |
// PID | |
dataBytes[2] = pid & 0xFF; | |
// Value (assuming it fits into two bytes) | |
dataBytes[3] = (value >> 8) & 0xFF; // High byte | |
dataBytes[4] = value & 0xFF; // Low byte | |
// Combine data bytes into a 64-bit data field | |
BigInt data = BigInt.zero; | |
for (int i = 0; i < 8; i++) { | |
data |= BigInt.from(dataBytes[i]) << (56 - i * 8); | |
} | |
// Extract individual data bytes | |
List<int> individualBytes = []; | |
for (int i = 0; i < 8; i++) { | |
individualBytes.add(((data >> (56 - i * 8)) & BigInt.from(0xFF)).toInt()); | |
} | |
return { | |
'address': address, | |
'data': data, | |
'dataBytes': individualBytes, | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment