Files
meshcore-sar/lib/services/buffer_reader.dart
Janez T 59de627289 feat: Add Packet Log Screen for BLE packet logging and exporting
- Implemented PacketLogScreen to display and filter BLE packet logs.
- Added functionality to export logs as CSV and text files.
- Introduced clipboard copy feature for hex data.
- Implemented clear logs functionality with confirmation dialog.
- Enhanced MeshCoreBleService to log TX and RX packets with descriptions.
- Added BufferReader methods for reading unsigned and signed 16-bit integers (big-endian).
- Updated CayenneLppParser to read values as big-endian.
- Created MessageStorageService for persisting messages to local storage.
- Enhanced map markers to display telemetry data including voltage, humidity, and pressure.
2025-10-14 15:27:18 +02:00

156 lines
4.1 KiB
Dart

import 'dart:typed_data';
import 'dart:convert';
/// Buffer reader for parsing MeshCore protocol binary data
class BufferReader {
final Uint8List _buffer;
int _offset = 0;
BufferReader(this._buffer);
/// Get remaining bytes count
int get remainingBytesCount => _buffer.length - _offset;
/// Check if there are bytes remaining
bool get hasRemaining => _offset < _buffer.length;
/// Get current offset
int get offset => _offset;
/// Set offset
set offset(int value) => _offset = value;
/// Read a single byte (uint8)
int readByte() {
if (_offset >= _buffer.length) {
throw Exception('Buffer overflow: attempting to read beyond buffer length');
}
return _buffer[_offset++];
}
/// Read a signed byte (int8)
int readInt8() {
final value = readByte();
return value > 127 ? value - 256 : value;
}
/// Read unsigned 16-bit integer (little-endian)
int readUInt16LE() {
if (_offset + 2 > _buffer.length) {
throw Exception('Buffer overflow: attempting to read beyond buffer length');
}
final value = _buffer[_offset] | (_buffer[_offset + 1] << 8);
_offset += 2;
return value;
}
/// Read signed 16-bit integer (little-endian)
int readInt16LE() {
final value = readUInt16LE();
return value > 32767 ? value - 65536 : value;
}
/// Read unsigned 16-bit integer (big-endian)
int readUInt16BE() {
if (_offset + 2 > _buffer.length) {
throw Exception('Buffer overflow: attempting to read beyond buffer length');
}
final value = (_buffer[_offset] << 8) | _buffer[_offset + 1];
_offset += 2;
return value;
}
/// Read signed 16-bit integer (big-endian)
int readInt16BE() {
final value = readUInt16BE();
return value > 32767 ? value - 65536 : value;
}
/// Read unsigned 32-bit integer (little-endian)
int readUInt32LE() {
if (_offset + 4 > _buffer.length) {
throw Exception('Buffer overflow: attempting to read beyond buffer length');
}
final value = _buffer[_offset] |
(_buffer[_offset + 1] << 8) |
(_buffer[_offset + 2] << 16) |
(_buffer[_offset + 3] << 24);
_offset += 4;
return value;
}
/// Read signed 32-bit integer (little-endian)
int readInt32LE() {
final value = readUInt32LE();
return value > 2147483647 ? value - 4294967296 : value;
}
/// Read a fixed number of bytes
Uint8List readBytes(int length) {
if (_offset + length > _buffer.length) {
throw Exception('Buffer overflow: attempting to read beyond buffer length');
}
final bytes = _buffer.sublist(_offset, _offset + length);
_offset += length;
return bytes;
}
/// Read remaining bytes
Uint8List readRemainingBytes() {
final bytes = _buffer.sublist(_offset);
_offset = _buffer.length;
return bytes;
}
/// Read null-terminated string (C-string) with max length
String readCString(int maxLength) {
if (_offset + maxLength > _buffer.length) {
throw Exception('Buffer overflow: attempting to read beyond buffer length');
}
final bytes = _buffer.sublist(_offset, _offset + maxLength);
_offset += maxLength;
// Find null terminator
int nullIndex = bytes.indexOf(0);
if (nullIndex == -1) {
nullIndex = maxLength;
}
// Decode string up to null terminator
return utf8.decode(bytes.sublist(0, nullIndex));
}
/// Read length-prefixed string (remaining bytes as UTF-8)
String readString() {
final bytes = readRemainingBytes();
return utf8.decode(bytes);
}
/// Peek at next byte without advancing offset
int peekByte() {
if (_offset >= _buffer.length) {
throw Exception('Buffer overflow: attempting to peek beyond buffer length');
}
return _buffer[_offset];
}
/// Skip bytes
void skip(int count) {
if (_offset + count > _buffer.length) {
throw Exception('Buffer overflow: attempting to skip beyond buffer length');
}
_offset += count;
}
/// Reset offset to beginning
void reset() {
_offset = 0;
}
@override
String toString() {
return 'BufferReader(length: ${_buffer.length}, offset: $_offset, remaining: $remainingBytesCount)';
}
}