mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Enhance BLE packet logging with opcode names and descriptions
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
import '../services/meshcore_opcode_names.dart';
|
||||||
|
|
||||||
/// Represents a logged BLE packet with timestamp and metadata
|
/// Represents a logged BLE packet with timestamp and metadata
|
||||||
class BlePacketLog {
|
class BlePacketLog {
|
||||||
@@ -21,26 +22,46 @@ class BlePacketLog {
|
|||||||
return rawData.map((b) => b.toRadixString(16).padLeft(2, '0')).join(' ');
|
return rawData.map((b) => b.toRadixString(16).padLeft(2, '0')).join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get opcode name for this packet
|
||||||
|
String get opcodeName {
|
||||||
|
if (responseCode == null) return 'N/A';
|
||||||
|
return MeshCoreOpcodeNames.getOpcodeName(
|
||||||
|
responseCode!,
|
||||||
|
isTx: direction == PacketDirection.tx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get full opcode description (name + hex code)
|
||||||
|
String get opcodeDescription {
|
||||||
|
if (responseCode == null) return 'N/A';
|
||||||
|
return MeshCoreOpcodeNames.getOpcodeDescription(
|
||||||
|
responseCode!,
|
||||||
|
isTx: direction == PacketDirection.tx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Get short summary of the packet
|
/// Get short summary of the packet
|
||||||
String get summary {
|
String get summary {
|
||||||
final dir = direction == PacketDirection.rx ? 'RX' : 'TX';
|
final dir = direction == PacketDirection.rx ? 'RX' : 'TX';
|
||||||
final code = responseCode != null ? '0x${responseCode!.toRadixString(16).padLeft(2, '0')}' : 'N/A';
|
final code = responseCode != null ? '0x${responseCode!.toRadixString(16).padLeft(2, '0')}' : 'N/A';
|
||||||
return '[$dir] Code: $code, Size: ${rawData.length} bytes';
|
final name = responseCode != null ? opcodeName : '';
|
||||||
|
return '[$dir] $name Code: $code, Size: ${rawData.length} bytes';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to CSV format for export
|
/// Convert to CSV format for export
|
||||||
String toCsvRow() {
|
String toCsvRow() {
|
||||||
final dir = direction == PacketDirection.rx ? 'RX' : 'TX';
|
final dir = direction == PacketDirection.rx ? 'RX' : 'TX';
|
||||||
final code = responseCode?.toString() ?? '';
|
final code = responseCode?.toString() ?? '';
|
||||||
|
final name = responseCode != null ? opcodeName : '';
|
||||||
final hex = hexData;
|
final hex = hexData;
|
||||||
final desc = description ?? '';
|
final desc = description ?? '';
|
||||||
return '${timestamp.toIso8601String()},$dir,${rawData.length},$code,"$hex","$desc"';
|
return '${timestamp.toIso8601String()},$dir,${rawData.length},$name,$code,"$hex","$desc"';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to human-readable log format
|
/// Convert to human-readable log format
|
||||||
String toLogString() {
|
String toLogString() {
|
||||||
final dir = direction == PacketDirection.rx ? 'RX' : 'TX';
|
final dir = direction == PacketDirection.rx ? 'RX' : 'TX';
|
||||||
final code = responseCode != null ? ' [0x${responseCode!.toRadixString(16).padLeft(2, '0')}]' : '';
|
final code = responseCode != null ? ' [$opcodeDescription]' : '';
|
||||||
final desc = description != null ? ' - $description' : '';
|
final desc = description != null ? ' - $description' : '';
|
||||||
return '${timestamp.toIso8601String()} [$dir]$code ${rawData.length} bytes: $hexData$desc';
|
return '${timestamp.toIso8601String()} [$dir]$code ${rawData.length} bytes: $hexData$desc';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class _PacketLogScreenState extends State<PacketLogScreen> {
|
|||||||
|
|
||||||
// Create CSV content
|
// Create CSV content
|
||||||
final buffer = StringBuffer();
|
final buffer = StringBuffer();
|
||||||
buffer.writeln('Timestamp,Direction,Size (bytes),Code,Hex Data,Description');
|
buffer.writeln('Timestamp,Direction,Size (bytes),Opcode Name,Code,Hex Data,Description');
|
||||||
for (final log in logs) {
|
for (final log in logs) {
|
||||||
buffer.writeln(log.toCsvRow());
|
buffer.writeln(log.toCsvRow());
|
||||||
}
|
}
|
||||||
@@ -439,19 +439,16 @@ class _PacketLogCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
if (log.description != null)
|
Flexible(
|
||||||
Flexible(
|
child: Text(
|
||||||
child: Text(
|
log.responseCode != null ? log.opcodeName : 'N/A',
|
||||||
log.description!,
|
style: const TextStyle(
|
||||||
style: const TextStyle(fontSize: 14),
|
fontSize: 14,
|
||||||
overflow: TextOverflow.ellipsis,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
)
|
overflow: TextOverflow.ellipsis,
|
||||||
else
|
|
||||||
Text(
|
|
||||||
'Code: ${log.responseCode != null ? "0x${log.responseCode!.toRadixString(16).padLeft(2, '0')}" : "N/A"}',
|
|
||||||
style: const TextStyle(fontSize: 14),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
subtitle: Column(
|
subtitle: Column(
|
||||||
@@ -516,7 +513,7 @@ class _PacketLogCard extends StatelessWidget {
|
|||||||
if (log.responseCode != null)
|
if (log.responseCode != null)
|
||||||
_InfoChip(
|
_InfoChip(
|
||||||
icon: Icons.tag,
|
icon: Icons.tag,
|
||||||
label: 'Code: 0x${log.responseCode!.toRadixString(16).padLeft(2, '0')} (${log.responseCode})',
|
label: log.opcodeDescription,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import '../models/ble_packet_log.dart';
|
|||||||
import 'buffer_reader.dart';
|
import 'buffer_reader.dart';
|
||||||
import 'buffer_writer.dart';
|
import 'buffer_writer.dart';
|
||||||
import 'meshcore_constants.dart';
|
import 'meshcore_constants.dart';
|
||||||
|
import 'meshcore_opcode_names.dart';
|
||||||
|
|
||||||
/// Callback types for MeshCore events
|
/// Callback types for MeshCore events
|
||||||
typedef OnContactCallback = void Function(Contact contact);
|
typedef OnContactCallback = void Function(Contact contact);
|
||||||
@@ -226,37 +227,41 @@ class MeshCoreBleService {
|
|||||||
throw Exception('Not connected');
|
throw Exception('Not connected');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
print('📝 [BLE] Writing ${data.length} bytes to RX characteristic...');
|
// Extract command code from first byte
|
||||||
print(' RX Characteristic properties: ${_rxCharacteristic!.properties}');
|
final commandCode = data.isNotEmpty ? data[0] : null;
|
||||||
|
final opcodeName = commandCode != null
|
||||||
|
? MeshCoreOpcodeNames.getCommandName(commandCode)
|
||||||
|
: 'UNKNOWN';
|
||||||
|
final opcodeHex = commandCode != null
|
||||||
|
? '0x${commandCode.toRadixString(16).padLeft(2, '0').toUpperCase()}'
|
||||||
|
: 'N/A';
|
||||||
|
|
||||||
|
print('📤 [TX] Sending command: $opcodeName ($opcodeHex)');
|
||||||
|
print(' Data size: ${data.length} bytes');
|
||||||
|
print(' Hex: ${data.map((b) => b.toRadixString(16).padLeft(2, '0')).join(' ')}');
|
||||||
|
|
||||||
// Check if the characteristic supports write without response
|
// Check if the characteristic supports write without response
|
||||||
final supportsWriteWithoutResponse = _rxCharacteristic!.properties.writeWithoutResponse;
|
final supportsWriteWithoutResponse = _rxCharacteristic!.properties.writeWithoutResponse;
|
||||||
final supportsWrite = _rxCharacteristic!.properties.write;
|
final supportsWrite = _rxCharacteristic!.properties.write;
|
||||||
|
|
||||||
print(' Supports writeWithoutResponse: $supportsWriteWithoutResponse');
|
|
||||||
print(' Supports write: $supportsWrite');
|
|
||||||
|
|
||||||
if (supportsWriteWithoutResponse) {
|
if (supportsWriteWithoutResponse) {
|
||||||
print(' Using write without response');
|
|
||||||
await _rxCharacteristic!.write(data, withoutResponse: true);
|
await _rxCharacteristic!.write(data, withoutResponse: true);
|
||||||
} else if (supportsWrite) {
|
} else if (supportsWrite) {
|
||||||
print(' Using write with response');
|
|
||||||
await _rxCharacteristic!.write(data, withoutResponse: false);
|
await _rxCharacteristic!.write(data, withoutResponse: false);
|
||||||
} else {
|
} else {
|
||||||
throw Exception('Characteristic does not support write operations');
|
throw Exception('Characteristic does not support write operations');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log TX packet (extract command code from first byte)
|
// Log TX packet
|
||||||
final commandCode = data.isNotEmpty ? data[0] : null;
|
|
||||||
_logPacket(data, PacketDirection.tx, responseCode: commandCode);
|
_logPacket(data, PacketDirection.tx, responseCode: commandCode);
|
||||||
|
|
||||||
// Increment TX packet counter and trigger activity indicator
|
// Increment TX packet counter and trigger activity indicator
|
||||||
_txPacketCount++;
|
_txPacketCount++;
|
||||||
onTxActivity?.call();
|
onTxActivity?.call();
|
||||||
|
|
||||||
print('✅ [BLE] Write successful');
|
print('✅ [TX] Command sent successfully');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('❌ [BLE] Write error: $e');
|
print('❌ [TX] Write error: $e');
|
||||||
onError?.call('Write error: $e');
|
onError?.call('Write error: $e');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
@@ -265,11 +270,9 @@ class MeshCoreBleService {
|
|||||||
/// Handle incoming data from TX characteristic
|
/// Handle incoming data from TX characteristic
|
||||||
void _onDataReceived(List<int> data) {
|
void _onDataReceived(List<int> data) {
|
||||||
try {
|
try {
|
||||||
print('📥 [BLE] Received ${data.length} bytes from TX characteristic');
|
|
||||||
|
|
||||||
// Handle empty data
|
// Handle empty data
|
||||||
if (data.isEmpty) {
|
if (data.isEmpty) {
|
||||||
print(' ⚠️ Empty data received, ignoring');
|
print('⚠️ [RX] Empty data received, ignoring');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,12 +282,17 @@ class MeshCoreBleService {
|
|||||||
_rxPacketCount++;
|
_rxPacketCount++;
|
||||||
onRxActivity?.call();
|
onRxActivity?.call();
|
||||||
|
|
||||||
print(' Raw data: ${data.map((b) => b.toRadixString(16).padLeft(2, '0')).join(' ')}');
|
|
||||||
|
|
||||||
final reader = BufferReader(dataBytes);
|
final reader = BufferReader(dataBytes);
|
||||||
final responseCode = reader.readByte();
|
final responseCode = reader.readByte();
|
||||||
print(' Response code: $responseCode (0x${responseCode.toRadixString(16)})');
|
|
||||||
print(' Remaining bytes: ${reader.remainingBytesCount}');
|
// Get opcode name for logging
|
||||||
|
final opcodeName = MeshCoreOpcodeNames.getOpcodeName(responseCode, isTx: false);
|
||||||
|
final opcodeHex = '0x${responseCode.toRadixString(16).padLeft(2, '0').toUpperCase()}';
|
||||||
|
|
||||||
|
print('📥 [RX] Received: $opcodeName ($opcodeHex)');
|
||||||
|
print(' Data size: ${data.length} bytes');
|
||||||
|
print(' Hex: ${data.map((b) => b.toRadixString(16).padLeft(2, '0')).join(' ')}');
|
||||||
|
print(' Payload: ${reader.remainingBytesCount} bytes');
|
||||||
|
|
||||||
// Log RX packet (before processing so we capture everything)
|
// Log RX packet (before processing so we capture everything)
|
||||||
_logPacket(dataBytes, PacketDirection.rx, responseCode: responseCode);
|
_logPacket(dataBytes, PacketDirection.rx, responseCode: responseCode);
|
||||||
@@ -808,31 +816,20 @@ class MeshCoreBleService {
|
|||||||
|
|
||||||
/// Send AppStart command
|
/// Send AppStart command
|
||||||
Future<void> _sendAppStart() async {
|
Future<void> _sendAppStart() async {
|
||||||
print('📤 [BLE] Preparing AppStart command...');
|
|
||||||
final writer = BufferWriter();
|
final writer = BufferWriter();
|
||||||
writer.writeByte(MeshCoreConstants.cmdAppStart);
|
writer.writeByte(MeshCoreConstants.cmdAppStart);
|
||||||
writer.writeByte(1); // appVer
|
writer.writeByte(1); // appVer
|
||||||
writer.writeBytes(Uint8List(6)); // reserved
|
writer.writeBytes(Uint8List(6)); // reserved
|
||||||
writer.writeString('MeshCore SAR'); // appName
|
writer.writeString('MeshCore SAR'); // appName
|
||||||
final data = writer.toBytes();
|
await _writeData(writer.toBytes());
|
||||||
print(' Command: ${MeshCoreConstants.cmdAppStart}');
|
|
||||||
print(' Data length: ${data.length} bytes');
|
|
||||||
await _writeData(data);
|
|
||||||
print('✅ [BLE] AppStart command sent');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send DeviceQuery command
|
/// Send DeviceQuery command
|
||||||
Future<void> _sendDeviceQuery() async {
|
Future<void> _sendDeviceQuery() async {
|
||||||
print('📤 [BLE] Preparing DeviceQuery command...');
|
|
||||||
final writer = BufferWriter();
|
final writer = BufferWriter();
|
||||||
writer.writeByte(MeshCoreConstants.cmdDeviceQuery);
|
writer.writeByte(MeshCoreConstants.cmdDeviceQuery);
|
||||||
writer.writeByte(MeshCoreConstants.supportedCompanionProtocolVersion);
|
writer.writeByte(MeshCoreConstants.supportedCompanionProtocolVersion);
|
||||||
final data = writer.toBytes();
|
await _writeData(writer.toBytes());
|
||||||
print(' Command: ${MeshCoreConstants.cmdDeviceQuery}');
|
|
||||||
print(' Protocol version: ${MeshCoreConstants.supportedCompanionProtocolVersion}');
|
|
||||||
print(' Data length: ${data.length} bytes');
|
|
||||||
await _writeData(data);
|
|
||||||
print('✅ [BLE] DeviceQuery command sent');
|
|
||||||
await _sendAppStart();
|
await _sendAppStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
188
lib/services/meshcore_opcode_names.dart
Normal file
188
lib/services/meshcore_opcode_names.dart
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
import 'meshcore_constants.dart';
|
||||||
|
|
||||||
|
/// Maps MeshCore protocol opcodes to human-readable names
|
||||||
|
class MeshCoreOpcodeNames {
|
||||||
|
/// Get command name from opcode
|
||||||
|
static String getCommandName(int opcode) {
|
||||||
|
switch (opcode) {
|
||||||
|
case MeshCoreConstants.cmdAppStart:
|
||||||
|
return 'APP_START';
|
||||||
|
case MeshCoreConstants.cmdSendTxtMsg:
|
||||||
|
return 'SEND_TXT_MSG';
|
||||||
|
case MeshCoreConstants.cmdSendChannelTxtMsg:
|
||||||
|
return 'SEND_CHANNEL_TXT_MSG';
|
||||||
|
case MeshCoreConstants.cmdGetContacts:
|
||||||
|
return 'GET_CONTACTS';
|
||||||
|
case MeshCoreConstants.cmdGetDeviceTime:
|
||||||
|
return 'GET_DEVICE_TIME';
|
||||||
|
case MeshCoreConstants.cmdSetDeviceTime:
|
||||||
|
return 'SET_DEVICE_TIME';
|
||||||
|
case MeshCoreConstants.cmdSendSelfAdvert:
|
||||||
|
return 'SEND_SELF_ADVERT';
|
||||||
|
case MeshCoreConstants.cmdSetAdvertName:
|
||||||
|
return 'SET_ADVERT_NAME';
|
||||||
|
case MeshCoreConstants.cmdAddUpdateContact:
|
||||||
|
return 'ADD_UPDATE_CONTACT';
|
||||||
|
case MeshCoreConstants.cmdSyncNextMessage:
|
||||||
|
return 'SYNC_NEXT_MESSAGE';
|
||||||
|
case MeshCoreConstants.cmdSetRadioParams:
|
||||||
|
return 'SET_RADIO_PARAMS';
|
||||||
|
case MeshCoreConstants.cmdSetTxPower:
|
||||||
|
return 'SET_TX_POWER';
|
||||||
|
case MeshCoreConstants.cmdResetPath:
|
||||||
|
return 'RESET_PATH';
|
||||||
|
case MeshCoreConstants.cmdSetAdvertLatLon:
|
||||||
|
return 'SET_ADVERT_LAT_LON';
|
||||||
|
case MeshCoreConstants.cmdRemoveContact:
|
||||||
|
return 'REMOVE_CONTACT';
|
||||||
|
case MeshCoreConstants.cmdShareContact:
|
||||||
|
return 'SHARE_CONTACT';
|
||||||
|
case MeshCoreConstants.cmdExportContact:
|
||||||
|
return 'EXPORT_CONTACT';
|
||||||
|
case MeshCoreConstants.cmdImportContact:
|
||||||
|
return 'IMPORT_CONTACT';
|
||||||
|
case MeshCoreConstants.cmdReboot:
|
||||||
|
return 'REBOOT';
|
||||||
|
case MeshCoreConstants.cmdGetBatteryVoltage:
|
||||||
|
return 'GET_BATTERY_VOLTAGE';
|
||||||
|
case MeshCoreConstants.cmdSetTuningParams:
|
||||||
|
return 'SET_TUNING_PARAMS';
|
||||||
|
case MeshCoreConstants.cmdDeviceQuery:
|
||||||
|
return 'DEVICE_QUERY';
|
||||||
|
case MeshCoreConstants.cmdExportPrivateKey:
|
||||||
|
return 'EXPORT_PRIVATE_KEY';
|
||||||
|
case MeshCoreConstants.cmdImportPrivateKey:
|
||||||
|
return 'IMPORT_PRIVATE_KEY';
|
||||||
|
case MeshCoreConstants.cmdSendRawData:
|
||||||
|
return 'SEND_RAW_DATA';
|
||||||
|
case MeshCoreConstants.cmdSendLogin:
|
||||||
|
return 'SEND_LOGIN';
|
||||||
|
case MeshCoreConstants.cmdSendStatusReq:
|
||||||
|
return 'SEND_STATUS_REQ';
|
||||||
|
case MeshCoreConstants.cmdGetChannel:
|
||||||
|
return 'GET_CHANNEL';
|
||||||
|
case MeshCoreConstants.cmdSetChannel:
|
||||||
|
return 'SET_CHANNEL';
|
||||||
|
case MeshCoreConstants.cmdSignStart:
|
||||||
|
return 'SIGN_START';
|
||||||
|
case MeshCoreConstants.cmdSignData:
|
||||||
|
return 'SIGN_DATA';
|
||||||
|
case MeshCoreConstants.cmdSignFinish:
|
||||||
|
return 'SIGN_FINISH';
|
||||||
|
case MeshCoreConstants.cmdSendTracePath:
|
||||||
|
return 'SEND_TRACE_PATH';
|
||||||
|
case MeshCoreConstants.cmdSetOtherParams:
|
||||||
|
return 'SET_OTHER_PARAMS';
|
||||||
|
case MeshCoreConstants.cmdSendTelemetryReq:
|
||||||
|
return 'SEND_TELEMETRY_REQ';
|
||||||
|
case MeshCoreConstants.cmdSendBinaryReq:
|
||||||
|
return 'SEND_BINARY_REQ';
|
||||||
|
default:
|
||||||
|
return 'CMD_UNKNOWN';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get response name from opcode
|
||||||
|
static String getResponseName(int opcode) {
|
||||||
|
switch (opcode) {
|
||||||
|
case MeshCoreConstants.respOk:
|
||||||
|
return 'OK';
|
||||||
|
case MeshCoreConstants.respErr:
|
||||||
|
return 'ERROR';
|
||||||
|
case MeshCoreConstants.respContactsStart:
|
||||||
|
return 'CONTACTS_START';
|
||||||
|
case MeshCoreConstants.respContact:
|
||||||
|
return 'CONTACT';
|
||||||
|
case MeshCoreConstants.respEndOfContacts:
|
||||||
|
return 'END_OF_CONTACTS';
|
||||||
|
case MeshCoreConstants.respSelfInfo:
|
||||||
|
return 'SELF_INFO';
|
||||||
|
case MeshCoreConstants.respSent:
|
||||||
|
return 'SENT';
|
||||||
|
case MeshCoreConstants.respContactMsgRecv:
|
||||||
|
return 'CONTACT_MSG_RECV';
|
||||||
|
case MeshCoreConstants.respChannelMsgRecv:
|
||||||
|
return 'CHANNEL_MSG_RECV';
|
||||||
|
case MeshCoreConstants.respCurrTime:
|
||||||
|
return 'CURR_TIME';
|
||||||
|
case MeshCoreConstants.respNoMoreMessages:
|
||||||
|
return 'NO_MORE_MESSAGES';
|
||||||
|
case MeshCoreConstants.respExportContact:
|
||||||
|
return 'EXPORT_CONTACT';
|
||||||
|
case MeshCoreConstants.respBatteryVoltage:
|
||||||
|
return 'BATTERY_VOLTAGE';
|
||||||
|
case MeshCoreConstants.respDeviceInfo:
|
||||||
|
return 'DEVICE_INFO';
|
||||||
|
case MeshCoreConstants.respPrivateKey:
|
||||||
|
return 'PRIVATE_KEY';
|
||||||
|
case MeshCoreConstants.respDisabled:
|
||||||
|
return 'DISABLED';
|
||||||
|
case MeshCoreConstants.respChannelInfo:
|
||||||
|
return 'CHANNEL_INFO';
|
||||||
|
case MeshCoreConstants.respSignStart:
|
||||||
|
return 'SIGN_START';
|
||||||
|
case MeshCoreConstants.respSignature:
|
||||||
|
return 'SIGNATURE';
|
||||||
|
default:
|
||||||
|
return 'RESP_UNKNOWN';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get push notification name from opcode
|
||||||
|
static String getPushName(int opcode) {
|
||||||
|
switch (opcode) {
|
||||||
|
case MeshCoreConstants.pushAdvert:
|
||||||
|
return 'ADVERT';
|
||||||
|
case MeshCoreConstants.pushPathUpdated:
|
||||||
|
return 'PATH_UPDATED';
|
||||||
|
case MeshCoreConstants.pushSendConfirmed:
|
||||||
|
return 'SEND_CONFIRMED';
|
||||||
|
case MeshCoreConstants.pushMsgWaiting:
|
||||||
|
return 'MSG_WAITING';
|
||||||
|
case MeshCoreConstants.pushRawData:
|
||||||
|
return 'RAW_DATA';
|
||||||
|
case MeshCoreConstants.pushLoginSuccess:
|
||||||
|
return 'LOGIN_SUCCESS';
|
||||||
|
case MeshCoreConstants.pushLoginFail:
|
||||||
|
return 'LOGIN_FAIL';
|
||||||
|
case MeshCoreConstants.pushStatusResponse:
|
||||||
|
return 'STATUS_RESPONSE';
|
||||||
|
case MeshCoreConstants.pushLogRxData:
|
||||||
|
return 'LOG_RX_DATA';
|
||||||
|
case MeshCoreConstants.pushTraceData:
|
||||||
|
return 'TRACE_DATA';
|
||||||
|
case MeshCoreConstants.pushNewAdvert:
|
||||||
|
return 'NEW_ADVERT';
|
||||||
|
case MeshCoreConstants.pushTelemetryResponse:
|
||||||
|
return 'TELEMETRY_RESPONSE';
|
||||||
|
case MeshCoreConstants.pushBinaryResponse:
|
||||||
|
return 'BINARY_RESPONSE';
|
||||||
|
default:
|
||||||
|
return 'PUSH_UNKNOWN';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get opcode name for any code (tries to determine type automatically)
|
||||||
|
static String getOpcodeName(int opcode, {bool isTx = false}) {
|
||||||
|
// If TX (sent to device), it's a command
|
||||||
|
if (isTx) {
|
||||||
|
return getCommandName(opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If RX (received from device), determine if it's a push or response
|
||||||
|
if (opcode >= 0x80) {
|
||||||
|
return getPushName(opcode);
|
||||||
|
} else {
|
||||||
|
return getResponseName(opcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get full opcode description with code in hex
|
||||||
|
static String getOpcodeDescription(int opcode, {bool isTx = false}) {
|
||||||
|
final name = getOpcodeName(opcode, isTx: isTx);
|
||||||
|
final hex = '0x${opcode.toRadixString(16).padLeft(2, '0').toUpperCase()}';
|
||||||
|
return '$name ($hex)';
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshCoreOpcodeNames._(); // Private constructor to prevent instantiation
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user