Skip to content

Added telemetry to repeater management#16

Merged
zjs81 merged 5 commits into
zjs81:mainfrom
wel97459:dev-telemetry
Jan 11, 2026
Merged

Added telemetry to repeater management#16
zjs81 merged 5 commits into
zjs81:mainfrom
wel97459:dev-telemetry

Conversation

@wel97459

@wel97459 wel97459 commented Jan 7, 2026

Copy link
Copy Markdown
Collaborator

Added telemetry to repeater management:

Screenshot_20260107_010212
Screenshot_20260107_010534

Telemetry is request with a binary request packet, and the returned data is parsed with cayenne_lpp.dart


Note

Introduces binary telemetry across the stack and refactors protocol I/O for safer frame handling.

  • Adds TelemetryScreen to request repeater telemetry via buildSendBinaryReq, handle pushCodeBinaryResponse, parse Cayenne LPP, and display channelized metrics
  • New Cayenne LPP helper (helpers/cayenne_lpp.dart) with encode utilities and robust parse/parseByChannel
  • Protocol refactor: introduces BufferReader/BufferWriter; rewrites frame builders to use them; adds command/push codes for telemetry/binary (cmdSendBinaryReq, pushCodeBinaryResponse, pushCodeTelemetryResponse)
  • Repeater hub gains Telemetry entry; Settings screen improves logging, parsing/validation of CLI get responses, and finer-grained refresh controls (e.g., TX power) with inline refresh buttons; some advanced options hidden pending implementation

Written by Cursor Bugbot for commit bc6c1f1. This will update automatically on new commits. Configure here.

Comment thread lib/helpers/buffer_reader.dart Outdated
import 'dart:convert';
import 'dart:typed_data';

class BufferReader {

@mtlynch mtlynch Jan 7, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is duplicating a lot of logic that's already available in lib/connector/meshcore_protocol.dart

@wel97459 wel97459 Jan 7, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its a lot cleaner approach to what is offered in meshcore_protocol.dart, and I have plans to use it even in side of meshcore_protocol.dart, and anywhere else that is currently using its functions

Comment thread lib/screens/telemetry_screen.dart
@zjs81

zjs81 commented Jan 8, 2026

Copy link
Copy Markdown
Owner

Very nice. I will review this later in the week and get it merged.

@zjs81 zjs81 self-assigned this Jan 11, 2026
… settings

- Move BufferReader/BufferWriter into meshcore_protocol.dart
- Refactor build functions to use BufferWriter
- Add content-based validation for CLI responses over LoRa
- Add individual refresh buttons for TX power and feature toggles
- Hide unimplemented features (Privacy Mode, Encrypted Advert Interval)
@zjs81 zjs81 merged commit 2495cd8 into zjs81:main Jan 11, 2026
1 check passed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

// Add more types as needed...
default:
// Unknown type: skip or handle error?
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parser corrupts data on unknown Cayenne LPP types

High Severity

The parseByChannel method uses continue in the default case when encountering an unknown type, but this doesn't consume the data bytes for that type. The buffer pointer remains at the unknown type's data payload, which will then be incorrectly interpreted as the next channel/type pair, corrupting all subsequent parsing. Many defined types like lppDigitalInput, lppAccelerometer, lppGyrometer, and lppSwitch aren't handled but could be sent by devices. The parse method correctly handles this by returning early on unknown types.

Fix in Cursor Fix in Web

_isLoaded = true;
_hasData = true;
});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing success recording for telemetry path results

Medium Severity

The _handleStatusResponse method doesn't call _recordStatusResult(true) when telemetry data is successfully received. The similar repeater_status_screen.dart calls _recordStatusResult(true) on success to track path quality, but here only failures are recorded (line 138). This breaks path result tracking for the telemetry feature, potentially affecting path selection optimization.

Fix in Cursor Fix in Web

void _handleStatusResponse(BuildContext context, Uint8List frame) {
setState(() {
_parsedTelemetry = CayenneLpp.parseByChannel(frame);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing mounted check before first setState call

Medium Severity

In _handleStatusResponse, the first setState on line 76 is called without checking if the widget is still mounted, while the second setState on line 88 has a mounted check. If the user navigates away from the TelemetryScreen while waiting for a telemetry response, the async callback will still fire and attempt to call setState on a disposed widget, throwing a "setState() called after dispose()" exception and crashing the app.

Fix in Cursor Fix in Web

if (frame[0] == respCodeSent) {
_tagData = frame.sublist(2, 6);
_timeEstment = frame.buffer.asByteData().getUint32(6, Endian.little);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing frame length check before accessing bytes

Medium Severity

The frame listener accesses frame.sublist(2, 6) and frame.buffer.asByteData().getUint32(6, Endian.little) when frame[0] == respCodeSent, but only checks frame.isEmpty. The connector's _handleMessageSent properly validates frame.length >= 10 before accessing these same bytes. If a truncated respCodeSent frame arrives (which would be safely ignored by the connector), this code would throw a RangeError and crash the app.

Fix in Cursor Fix in Web

@wel97459

Copy link
Copy Markdown
Collaborator Author

Thanks for fixing all my bug I didn't realize I had 😂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants