Skip to content

Added Neighbors to the repeater hub and a screen to display the Neighbors #42

Merged
zjs81 merged 6 commits into
zjs81:mainfrom
wel97459:dev-neighbours
Jan 20, 2026
Merged

Added Neighbors to the repeater hub and a screen to display the Neighbors #42
zjs81 merged 6 commits into
zjs81:mainfrom
wel97459:dev-neighbours

Conversation

@wel97459

Copy link
Copy Markdown
Collaborator

Added neighbors to the repeater hub and a screen to display the neighbors.
Few things that have lose end:

  1. It only requests one packet of neighbors, starting at offset zero and asking for 15. on the reply of the first packet it gives you the number of neighbors available and how many it sent in the first packet.
  2. Map integration is need.

@zjs81 zjs81 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Code Review: PR #42 - Added Neighbors to the repeater hub

Files Changed:

  • lib/l10n/app_en.arb (+3 lines)
  • lib/screens/neighbours_screen.dart (+381 lines, new file)
  • lib/screens/repeater_hub_screen.dart (+22/-1 lines)
  • lib/widgets/snr_indicator.dart (+65 lines, new file)

Overview

This PR adds a new "Neighbors" feature to the repeater hub, allowing users to view zero-hop neighbors of a repeater. The implementation includes:

  • A new NeighboursScreen for displaying neighbor data
  • A reusable SNRIcon widget for signal-to-noise ratio visualization
  • Integration into the repeater hub navigation
  • English localization strings

Code Quality Issues

1. Inconsistent Indentation in lib/screens/neighbours_screen.dart:63-75

Current code:

    _frameSubscription = connector.receivedFrames.listen((frame) {
      if (frame.isEmpty) return;

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

    // Check if it's a binary response
    if (frame[0] == pushCodeBinaryResponse && listEquals(frame.sublist(2, 6), _tagData)) {
      _handleNeighboursResponse(context, connector, frame.sublist(6));
    }
  });
}

Should be:

    _frameSubscription = connector.receivedFrames.listen((frame) {
      if (frame.isEmpty) return;

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

      // Check if it's a binary response
      if (frame[0] == pushCodeBinaryResponse && listEquals(frame.sublist(2, 6), _tagData)) {
        _handleNeighboursResponse(context, connector, frame.sublist(6));
      }
    });
  }

Note: Also missing space after if keyword (if(frame[0]if (frame[0]).


2. Missing Newline at End of Files

Both new files are missing a trailing newline:

  • lib/screens/neighbours_screen.dart - ends with } on line 381
  • lib/widgets/snr_indicator.dart - ends with } on line 65

Fix: Add a blank line after the final closing brace in each file.


3. Unused Import in lib/screens/neighbours_screen.dart:4

Current code:

import 'package:meshcore_open/models/radio_settings.dart';

This import is not used anywhere in the file and should be removed.


4. Unused Instance Variables in lib/screens/neighbours_screen.dart:36-37

_timeEstment (line 37):

  • Typo in name: should be _timeEstimate
  • Assigned on line 68 but never read anywhere

_neighbourCount (line 36):

  • Assigned on line 131 but never read

Recommendation: Either remove these if unused, or add TODO comments if they're placeholders for future features (e.g., pagination).


Potential Bugs

1. Operator Precedence Issue in lib/screens/neighbours_screen.dart:307

Current code:

if (_isLoaded || _hasData && !(_parsedNeighbours == null || _parsedNeighbours!.isEmpty))

Due to operator precedence (&& binds tighter than ||), this evaluates as:

if (_isLoaded || (_hasData && !(_parsedNeighbours == null || _parsedNeighbours!.isEmpty)))

This means the card will show if _isLoaded is true, regardless of whether _parsedNeighbours has data.

Suggested fix:

if (_parsedNeighbours != null && _parsedNeighbours!.isNotEmpty)

2. Protocol Payload Needs Documentation in lib/screens/neighbours_screen.dart:158

Current code:

final frame = buildSendBinaryReq(
  repeater.publicKey, 
  payload: Uint8List.fromList([reqTypeGetNeighbours, 0x00, 0x0F, 0x00, 0x00, 0x00, _reqNeighboursKeyLen])
);

The magic bytes are unexplained. Following the pattern in meshcore_protocol.dart where frame builders have comments explaining their format:

Suggestion - add a helper function in lib/connector/meshcore_protocol.dart:

// Build neighbours request payload
// Format: [req_type][offset_lo][offset_hi][count_lo][count_hi][reserved][key_len]
Uint8List buildGetNeighboursPayload({
  int offset = 0,
  int count = 15,
  int keyLen = 4,
}) {
  return Uint8List.fromList([
    reqTypeGetNeighbours,
    offset & 0xFF,
    (offset >> 8) & 0xFF,
    count & 0xFF,
    (count >> 8) & 0xFF,
    0x00, // reserved
    keyLen,
  ]);
}

Then use it in neighbours_screen.dart:

final frame = buildSendBinaryReq(
  repeater.publicKey,
  payload: buildGetNeighboursPayload(),
);

3. Unused Function in lib/widgets/snr_indicator.dart:3-19

Current code:

List<double> getLoRaMinimumSNR(int spreadingFactor) {
  switch (spreadingFactor) {
    case 7:
      return [4.0, -2.0, -4.0, -6.0];
    // ...
  }
}

This function is defined but never called. The SNRIcon widget has a default snrLevels but doesn't use this function.

Recommendation: Either remove it until needed, or wire it up:

SNRIcon(
  snr: snr,
  snrLevels: getLoRaMinimumSNR(currentSpreadingFactor),
)

Style Issues

1. Redundant Widget Nesting in lib/screens/neighbours_screen.dart:352-368

Current code:

Widget _buildInfoRow(String label, String value, double snr) {
  return Padding(
    padding: const EdgeInsets.symmetric(vertical: 3),
    child: Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Expanded(
          child: ListTile(
            contentPadding: EdgeInsets.zero,
            title: Text(label, style: const TextStyle(fontWeight: FontWeight.w500)),
            subtitle: Text(value),
            trailing: SNRIcon(snr: snr),
          ),
        ),
      ],
    ),
  );
}

The Row with a single Expanded child is unnecessary.

Should be:

Widget _buildInfoRow(String label, String value, double snr) {
  return Padding(
    padding: const EdgeInsets.symmetric(vertical: 3),
    child: ListTile(
      contentPadding: EdgeInsets.zero,
      title: Text(label, style: const TextStyle(fontWeight: FontWeight.w500)),
      subtitle: Text(value),
      trailing: SNRIcon(snr: snr),
    ),
  );
}

2. Incorrect Comment in lib/screens/repeater_hub_screen.dart:148

Current code:

const SizedBox(height: 12),
// Settings button
_buildManagementCard(
  context,
  icon: Icons.group,
  title: l10n.repeater_neighbours,

Should be:

const SizedBox(height: 12),
// Neighbours button
_buildManagementCard(

Summary

Priority Issue File Line
High Indentation & spacing in listener callback neighbours_screen.dart 63-75
High Operator precedence may cause wrong display logic neighbours_screen.dart 307
Medium Unused import (radio_settings.dart) neighbours_screen.dart 4
Medium Unused variables (_neighbourCount, _timeEstment) neighbours_screen.dart 36-37
Medium Unused function getLoRaMinimumSNR() snr_indicator.dart 3-19
Medium Magic bytes need documentation (consider helper in meshcore_protocol.dart) neighbours_screen.dart 158
Low Missing trailing newlines Both new files EOF
Low Redundant Row/Expanded wrapper neighbours_screen.dart 352-368
Low Wrong comment ("Settings" → "Neighbours") repeater_hub_screen.dart 148

Overall this adds useful functionality for viewing repeater neighbors! The main items to address are the indentation fix and the boolean logic clarification.

zjs81 added 3 commits January 19, 2026 19:09
- Added `untranslated.json` to track untranslated messages.
- Updated localization keys in various language files to use camelCase format for consistency.
- Modified `neighbours_screen.dart` to reference updated localization keys.
@zjs81 zjs81 merged commit f790604 into zjs81:main Jan 20, 2026
6 checks passed
@wel97459 wel97459 deleted the dev-neighbours branch March 7, 2026 09:53
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.

2 participants