Consolidate BufferReader/Writer, add response validation for repeater 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)
This commit is contained in:
zjs81
2026-01-11 13:44:01 -07:00
parent ffce582b3b
commit bc6c1f1fab
6 changed files with 515 additions and 466 deletions
-103
View File
@@ -1,103 +0,0 @@
import 'dart:convert';
import 'dart:typed_data';
class BufferReader {
int pointer = 0;
final Uint8List buffer;
BufferReader(Uint8List data) : buffer = Uint8List.fromList(data);
int getRemainingBytesCount() {
return buffer.length - pointer;
}
int readByte() {
return readBytes(1)[0];
}
Uint8List readBytes(int count) {
final data = buffer.sublist(pointer, pointer + count);
pointer += count;
return data;
}
Uint8List readRemainingBytes() {
return readBytes(getRemainingBytesCount());
}
String readString() {
return utf8.decode(readRemainingBytes());
}
String readCString(int maxLength) {
final value = <int>[];
final bytes = readBytes(maxLength);
for (final byte in bytes) {
// if we find a null terminator character, we have reached the end of the cstring
if (byte == 0) {
return utf8.decode(Uint8List.fromList(value));
}
value.add(byte);
}
return utf8.decode(Uint8List.fromList(value));
}
int readInt8() {
final bytes = readBytes(1);
return ByteData.view(bytes.buffer).getInt8(0);
}
int readUInt8() {
final bytes = readBytes(1);
return ByteData.view(bytes.buffer).getUint8(0);
}
int readUInt16LE() {
final bytes = readBytes(2);
return ByteData.view(bytes.buffer).getUint16(0, Endian.little);
}
int readUInt16BE() {
final bytes = readBytes(2);
return ByteData.view(bytes.buffer).getUint16(0, Endian.big);
}
int readUInt32LE() {
final bytes = readBytes(4);
return ByteData.view(bytes.buffer).getUint32(0, Endian.little);
}
int readUInt32BE() {
final bytes = readBytes(4);
return ByteData.view(bytes.buffer).getUint32(0, Endian.big);
}
int readInt16LE() {
final bytes = readBytes(2);
return ByteData.view(bytes.buffer).getInt16(0, Endian.little);
}
int readInt16BE() {
final bytes = readBytes(2);
return ByteData.view(bytes.buffer).getInt16(0, Endian.big);
}
int readInt32LE() {
final bytes = readBytes(4);
return ByteData.view(bytes.buffer).getInt32(0, Endian.little);
}
int readInt24BE() {
// read 24-bit (3 bytes) big endian integer
var value = (readByte() << 16) | (readByte() << 8) | readByte();
// convert 24-bit signed integer to 32-bit signed integer
// 0x800000 is the sign bit for a 24-bit value
// if it's set, value is negative in 24-bit two's complement
if ((value & 0x800000) != 0) {
value -= 0x1000000;
}
return value;
}
}
-57
View File
@@ -1,57 +0,0 @@
import 'dart:convert';
import 'dart:typed_data';
class BufferWriter {
final BytesBuilder _builder = BytesBuilder();
Uint8List toBytes() {
return _builder.toBytes();
}
void writeBytes(Uint8List bytes) {
_builder.add(bytes);
}
void writeByte(int byte) {
_builder.addByte(byte);
}
void writeUInt16LE(int num) {
final bytes = Uint8List(2);
final data = ByteData.view(bytes.buffer);
data.setUint16(0, num, Endian.little);
writeBytes(bytes);
}
void writeUInt32LE(int num) {
final bytes = Uint8List(4);
final data = ByteData.view(bytes.buffer);
data.setUint32(0, num, Endian.little);
writeBytes(bytes);
}
void writeInt32LE(int num) {
final bytes = Uint8List(4);
final data = ByteData.view(bytes.buffer);
data.setInt32(0, num, Endian.little);
writeBytes(bytes);
}
void writeString(String string) {
writeBytes(Uint8List.fromList(utf8.encode(string)));
}
void writeCString(String string, int maxLength) {
final bytes = Uint8List(maxLength);
final encodedString = utf8.encode(string);
for (var i = 0; i < maxLength && i < encodedString.length; i++) {
bytes[i] = encodedString[i];
}
// ensure the last byte is always a null terminator
bytes[maxLength - 1] = 0;
writeBytes(bytes);
}
}
+3 -4
View File
@@ -1,6 +1,5 @@
import 'dart:typed_data';
import 'buffer_reader.dart';
import 'buffer_writer.dart';
import '../connector/meshcore_protocol.dart';
class CayenneLpp {
static const int lppDigitalInput = 0; // 1 byte
@@ -84,7 +83,7 @@ class CayenneLpp {
final buffer = BufferReader(bytes);
final telemetry = <Map<String, dynamic>>[];
while (buffer.getRemainingBytesCount() >= 2) {
while (buffer.remaining >= 2) {
final channel = buffer.readUInt8();
final type = buffer.readUInt8();
@@ -193,7 +192,7 @@ class CayenneLpp {
final buffer = BufferReader(bytes);
final Map<int, Map<String, dynamic>> channels = {};
while (buffer.getRemainingBytesCount() >= 2) {
while (buffer.remaining >= 2) {
final channel = buffer.readUInt8();
final type = buffer.readUInt8();