ble_framed_protocol 0.1.0 copy "ble_framed_protocol: ^0.1.0" to clipboard
ble_framed_protocol: ^0.1.0 copied to clipboard

Encode and decode XOR-checksummed framed-byte protocols common to industrial BLE devices (e-locks, GPS trackers, Nordic NUS clones). Configurable header and trailer bytes; pure Dart, no Flutter dependency.

ble_framed_protocol #

pub package License: MIT

Encode and decode XOR-checksummed framed-byte protocols common to industrial BLE devices — electronic locks, GPS trackers, smart-meter dongles, Nordic NUS clones. Pure Dart, no Flutter dependency.

The frame layout #

[HEADER bytes ...][CMD][LEN_H][LEN_L][PAYLOAD ...LEN bytes][XOR][TRAILER bytes ...]
  • Header — fixed magic bytes, default [0xAA, 0xBB].
  • CMD — single command byte (caller-defined).
  • LEN — big-endian 16-bit unsigned length of PAYLOAD.
  • PAYLOADLEN arbitrary bytes.
  • XOR — XOR of every byte from the frame start up to (but not including) the checksum byte.
  • Trailer — fixed magic bytes, default [0x0D, 0x0A] (CRLF).

If you've reverse-engineered the protocol of a Chinese-OEM e-lock or GPS tracker recently, this is probably the layout you found. Default bytes match the most common variant; custom magic bytes are configurable.

Install #

dart pub add ble_framed_protocol

Usage #

import 'dart:typed_data';
import 'package:ble_framed_protocol/ble_framed_protocol.dart';

final codec = FramedProtocol.standard;

// Encode a command for transmission.
final tx = codec.encode(
  Frame(
    cmdId: 0x01,
    payload: Uint8List.fromList([0x10, 0x20, 0x30]),
  ),
);
// → 0xAA 0xBB 0x01 0x00 0x03 0x10 0x20 0x30 0x13 0x0D 0x0A

// Decode a response from the device. Returns null on any framing error
// (bad header, bad trailer, length mismatch, bad checksum).
final rx = codec.decode(receivedBytes);
if (rx != null) {
  final responseCode = rx.payload.first;          // your domain split
  final responseData = rx.payload.sublist(1);     // (this lib stays
  print('cmd 0x${rx.cmdId.toRadixString(16)} → '  //  framing-only)
        '$responseCode / ${responseData.length} bytes');
}

Custom magic bytes #

final codec = FramedProtocol(
  headerBytes: const [0x55, 0xAA],
  trailerBytes: const [0xFF],
);

Any non-empty header/trailer works. The XOR checksum still covers everything up to its own position regardless of header/trailer length.

API #

Frame #

Field Type Notes
cmdId int Single byte, 0..0xFF.
payload Uint8List Bytes between LEN and XOR. May be empty.

FramedProtocol #

Method Returns Notes
encode(Frame) Uint8List Throws ArgumentError on out-of-range cmdId or oversized payload.
decode(Uint8List) Frame? Returns null on any framing/checksum error.
verifyChecksum(Uint8List) bool Cheap structural + checksum check, no allocation.
Static / constant Type Notes
FramedProtocol.standard FramedProtocol Default [0xAA, 0xBB] / [0x0D, 0x0A] codec.
FramedProtocol.maxPayloadSize int 0xFFFF — hard limit from the 16-bit length field.

Why "framing-only"? #

The library deliberately does not know about response codes, command enums, BCD time encoding, or device-specific status bits. Those vary by manufacturer. This package gives you a tested codec for the bytes on the wire — you build the typed command/response layer on top.

A typical higher layer (~30 lines per device) looks like:

class MyDeviceCommand {
  static Uint8List buildLock(Uint8List deviceId, Uint8List password) {
    final data = Uint8List(13)
      ..setRange(0, 6, deviceId)
      ..setRange(6, 12, password)
      ..[12] = 0x00;
    return FramedProtocol.standard.encode(
      Frame(cmdId: 0x01, payload: data),
    );
  }
}

Testing #

dart test

Tests cover round-trips at varied payload sizes (0, 1, 16, 255, 1024 bytes), custom magic bytes, and rejection of every malformed-frame variant: bad header, bad trailer, length mismatch, checksum mismatch, too-short input, oversized payload, out-of-range command id.

Example #

dart run example/encode_decode.dart

License #

MIT — see LICENSE.

0
likes
140
points
27
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Encode and decode XOR-checksummed framed-byte protocols common to industrial BLE devices (e-locks, GPS trackers, Nordic NUS clones). Configurable header and trailer bytes; pure Dart, no Flutter dependency.

Repository (GitHub)
View/report issues

Topics

#ble #bluetooth #protocol #framing #codec

License

MIT (license)

More

Packages that depend on ble_framed_protocol