diff --git a/lib/connector/meshcore_protocol.dart b/lib/connector/meshcore_protocol.dart index f9241e8..a4faf0e 100644 --- a/lib/connector/meshcore_protocol.dart +++ b/lib/connector/meshcore_protocol.dart @@ -127,6 +127,7 @@ const int cmdSendStatusReq = 27; const int cmdGetContactByKey = 30; const int cmdGetChannel = 31; const int cmdSetChannel = 32; +const int cmdSendTracePath = 36; const int cmdGetRadioSettings = 57; const int cmdGetTelemetryReq = 39; const int cmdGetCustomVar = 40; @@ -176,6 +177,7 @@ const int pushCodeLoginSuccess = 0x85; const int pushCodeLoginFail = 0x86; const int pushCodeStatusResponse = 0x87; const int pushCodeLogRxData = 0x88; +const int pushCodeTraceData = 0x89; const int pushCodeNewAdvert = 0x8A; const int pushCodeTelemetryResponse = 0x8B; const int pushCodeBinaryResponse = 0x8C; @@ -708,3 +710,18 @@ Uint8List buildSendBinaryReq(Uint8List repeaterPubKey, {Uint8List? payload}) { } return writer.toBytes(); } + +//Build a trace request frame +//[cmd][tag x4][auth x4][flag][payload] +Uint8List buildTraceReq(int tag, int auth, int flag, {Uint8List? payload}) +{ + final writer = BufferWriter(); + writer.writeByte(cmdSendTracePath); + writer.writeUInt32LE(tag); + writer.writeUInt32LE(auth); + writer.writeByte(flag); + if (payload != null && payload.isNotEmpty) { + writer.writeBytes(payload); + } + return writer.toBytes(); +} \ No newline at end of file diff --git a/lib/screens/contacts_screen.dart b/lib/screens/contacts_screen.dart index e91cd94..02faff5 100644 --- a/lib/screens/contacts_screen.dart +++ b/lib/screens/contacts_screen.dart @@ -752,7 +752,20 @@ class _ContactsScreenState extends State child: Column( mainAxisSize: MainAxisSize.min, children: [ - if (isRepeater) + if (isRepeater) ...[ + ListTile( + leading: const Icon(Icons.radar, color: Colors.green), + title: Text("Ping"), + onTap: () async { + final frame = buildTraceReq( + DateTime.now().millisecondsSinceEpoch ~/ 1000, + 0, + 0, + payload: contact.publicKey.sublist(0,1), + ); + await connector.sendFrame(frame); + } + ), ListTile( leading: const Icon(Icons.cell_tower, color: Colors.orange), title: Text(context.l10n.contacts_manageRepeater), @@ -761,7 +774,20 @@ class _ContactsScreenState extends State _showRepeaterLogin(context, contact); }, ) - else if (isRoom) ...[ + ]else if (isRoom) ...[ + ListTile( + leading: const Icon(Icons.radar, color: Colors.green), + title: Text("Ping"), + onTap: () async { + final frame = buildTraceReq( + DateTime.now().millisecondsSinceEpoch ~/ 1000, + 0, + 0, + payload: contact.publicKey.sublist(0,1), + ); + await connector.sendFrame(frame); + } + ), ListTile( leading: const Icon(Icons.room, color: Colors.blue), title: Text(context.l10n.contacts_roomLogin), diff --git a/lib/services/ble_debug_log_service.dart b/lib/services/ble_debug_log_service.dart index a53ad5d..07ac689 100644 --- a/lib/services/ble_debug_log_service.dart +++ b/lib/services/ble_debug_log_service.dart @@ -156,6 +156,8 @@ class BleDebugLogService extends ChangeNotifier { return 'CMD_GET_RADIO_SETTINGS'; case cmdSetCustomVar: return 'CMD_SET_CUSTOM_VAR'; + case cmdSendTracePath: + return 'CMD_SEND_TRACE_PATH'; default: return null; } @@ -195,6 +197,8 @@ class BleDebugLogService extends ChangeNotifier { return 'RESP_CODE_CHANNEL_INFO'; case respCodeRadioSettings: return 'RESP_CODE_RADIO_SETTINGS'; + case pushCodeTraceData: + return 'PUSH_CODE_TRACE_DATA'; default: return null; }