Add a signal readout for the nearest repeater. With improvements to app bar and other UI polish. (#200)

* Refactor Cayenne LPP parsing with error handling and logging

- Added error handling and logging to the Cayenne LPP parsing methods to manage malformed data gracefully.
- Improved the structure of the parsing logic for better readability and maintainability.
- Updated the Contact model to include error handling during frame parsing.
- Refactored Channels, Contacts, Map, and Neighbours screens to utilize a new AppBarTitle widget for consistent app bar design.
- Enhanced the BatteryIndicator widget to display SNR information for direct repeaters.
- Introduced SNRUi class for better management of SNR icon and text representation.
- Improved error handling in PathTraceMap and Neighbours screens to log errors appropriately.

* Fix trace route bytes generation logic in Contact model

* Ignore advertisements from self in MeshCoreConnector

* Refactor PathTraceData to use List<double> for snrData and adjust data mapping in PathTraceMapScreen

* Add SNRIndicator to AppBar and refactor BatteryIndicator layout

* Enhance path management dialog to display direct repeaters with color coding based on signal strength

* Remove unused import from SNR indicator widget

* Update lib/models/contact.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update lib/connector/meshcore_connector.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update lib/connector/meshcore_connector.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update lib/screens/path_trace_map.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update lib/widgets/battery_indicator.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update lib/helpers/cayenne_lpp.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Refactor packet handling to skip only the RSSI byte for improved reliability

* Add SNR indicator localization and update UI references for nearby repeaters

* Handle loading state and error parsing in PathTraceMapScreen; update SNR indicator dialog content layout

* Throw an exception for unsupported LPP types in CayenneLpp class

* Refactor AppBarTitle widget to remove unused style parameter; update related screens to reflect changes
Improve SNR handling by adding validation for spreading factor range in snrUiFromSNR function
Update contact handling in MeshCoreConnector to fix variable naming and improve readability
Stop parsing unsupported LPP types in CayenneLpp to avoid misalignment

* Sort direct repeaters by last updated time and SNR; limit to top three for improved path management dialog

* Prevent notifications for chat and sensor adverts without a valid path

* Implement ranking system for direct repeaters based on SNR and recency; update related UI components to reflect changes

* Refactor localization keys for "neighbors" terminology across multiple languages

- Updated localization keys from "neighbours" to "neighbors" in the following files:
  - app_localizations_bg.dart
  - app_localizations_de.dart
  - app_localizations_en.dart
  - app_localizations_es.dart
  - app_localizations_fr.dart
  - app_localizations_it.dart
  - app_localizations_nl.dart
  - app_localizations_pl.dart
  - app_localizations_pt.dart
  - app_localizations_ru.dart
  - app_localizations_sk.dart
  - app_localizations_sl.dart
  - app_localizations_sv.dart
  - app_localizations_uk.dart
  - app_localizations_zh.dart
- Updated corresponding ARB files to reflect the changes in keys.
- Renamed the NeighboursScreen to NeighborsScreen in the chat and repeater hub screens for consistency.

* Adjust ranking calculation for direct repeaters by adding offset to SNR for improved accuracy

* Fix typo in variable name for second direct repeater in path management dialog

* Refactor ranking calculation for direct repeaters and update path handling in channel message screens

* Refactor path handling in ChannelMessagePathScreen to improve logic for outgoing messages and channel messages

* Fix AppBarTitle horizontal overflow with long titles (#187)

* Initial plan

* Wrap title Column in Expanded to prevent horizontal overflow in AppBarTitle

Co-authored-by: wel97459 <12990640+wel97459@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wel97459 <12990640+wel97459@users.noreply.github.com>

* Refactor AppBarTitle widget to simplify Text widget initialization

* Add "Show All Paths" feature to chat path management

- Implemented localization for "Show All Paths" in multiple languages (DE, EN, ES, FR, IT, NL, PL, PT, RU, SK, SL, SV, UK, ZH).
- Updated path management dialog to include a toggle for showing all paths.
- Refactored path history display logic to conditionally show paths based on the toggle state.
- Cleaned up unused print statements and improved code readability in path tracing and chat screens.

* Refactor FeatureToggleRow visibility in chat and path management dialogs based on repeaters list

* Remove unused import of 'dart:ffi' in path_trace_map.dart

* Refactor repeater management logic and update UI state handling in chat and path management dialogs

* Refactor RX data handling and improve repeater management logic in chat and path management dialogs

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wel97459 <12990640+wel97459@users.noreply.github.com>
This commit is contained in:
Winston Lowe
2026-02-20 20:27:38 -08:00
committed by GitHub
parent 0c4910e149
commit d2b693e5ce
49 changed files with 1956 additions and 914 deletions
+55 -1
View File
@@ -13,12 +13,22 @@ class BufferReader {
int readByte() => readBytes(1)[0];
Uint8List readBytes(int count) {
if (_pointer + count > _buffer.length) {
throw RangeError(
'Attempted to read $count bytes at offset $_pointer, but only $remaining bytes remaining in buffer of length ${_buffer.length}',
);
}
final data = _buffer.sublist(_pointer, _pointer + count);
_pointer += count;
return data;
}
void skipBytes(int count) {
if (_pointer + count > _buffer.length) {
throw RangeError(
'Attempted to skip $count bytes at offset $_pointer, but only $remaining bytes remaining in buffer of length ${_buffer.length}',
);
}
_pointer += count;
}
@@ -151,6 +161,7 @@ const int cmdGetContactByKey = 30;
const int cmdGetChannel = 31;
const int cmdSetChannel = 32;
const int cmdSendTracePath = 36;
const int cmdSetOtherParams = 38;
const int cmdGetRadioSettings = 57;
const int cmdGetTelemetryReq = 39;
const int cmdGetCustomVar = 40;
@@ -166,7 +177,7 @@ const int reqTypeGetStatus = 0x01;
const int reqTypeKeepAlive = 0x02;
const int reqTypeGetTelemetry = 0x03;
const int reqTypeGetAccessList = 0x05;
const int reqTypeGetNeighbours = 0x06;
const int reqTypeGetNeighbors = 0x06;
// Repeater response codes
const int respServerLoginOk = 0;
@@ -212,6 +223,30 @@ const int advTypeRepeater = 2;
const int advTypeRoom = 3;
const int advTypeSensor = 4;
// Payload Types
const int payloadTypeREQ =
0x00; // request (prefixed with dest/src hashes, MAC) (enc data: timestamp, blob)
const int payloadTypeRESPONSE =
0x01; // response to REQ or ANON_REQ (prefixed with dest/src hashes, MAC) (enc data: timestamp, blob)
const int payloadTypeTXTMSG =
0x02; // a plain text message (prefixed with dest/src hashes, MAC) (enc data: timestamp, text)
const int payloadTypeACK = 0x03; // a simple ack
const int payloadTypeADVERT = 0x04; // a node advertising its Identity
const int payloadTypeGRPTXT =
0x05; // an (unverified) group text message (prefixed with channel hash, MAC) (enc data: timestamp, "name: msg")
const int payloadTypeGRPDATA =
0x06; // an (unverified) group datagram (prefixed with channel hash, MAC) (enc data: timestamp, blob)
const int payloadTypeANONREQ =
0x07; // generic request (prefixed with dest_hash, ephemeral pub_key, MAC) (enc data: ...)
const int payloadTypePATH =
0x08; // returned path (prefixed with dest/src hashes, MAC) (enc data: path, extra)
const int payloadTypeTRACE = 0x09; // trace a path, collecting SNI for each hop
const int payloadTypeMULTIPART = 0x0A; // packet is one of a set of packets
const int payloadTypeCONTROL = 0x0B; // a control/discovery packet
//...
const int payloadTypeRawCustom =
0x0F; // custom packet as raw bytes, for applications with custom encryption, payloads, etc
// Sizes
const int pubKeySize = 32;
const int maxPathSize = 64;
@@ -788,3 +823,22 @@ Uint8List buildZeroHopContact(Uint8List pubKey) {
writer.writeBytes(pubKey);
return writer.toBytes();
}
// Build CMD_SET_OTHER_PARAMS frame
// Format: [cmd][allowAutoAddContacts][allowTelemetryFlags][advertLocationPolicy][multiAcks]
Uint8List buildSetOtherParamsFrame(
bool allowAutoAddContacts,
int allowTelemetryFlags,
int advertLocationPolicy,
int multiAcks,
) {
final writer = BufferWriter();
writer.writeByte(cmdSetOtherParams);
writer.writeByte(
allowAutoAddContacts ? 0x00 : 0x01,
); // Allow Auto Add Contacts
writer.writeByte(allowTelemetryFlags); // Allow Telemetry Flags
writer.writeByte(advertLocationPolicy); // Advertisement Location Policy
writer.writeByte(multiAcks); // Multi Acknowledgements
return writer.toBytes();
}