build static method

Future<MiIOPacket> build(
  1. int deviceId,
  2. List<int> token, {
  3. Map<String, dynamic>? payload,
  4. int? stamp,
})

Build an outgoing packet.

Implementation

static Future<MiIOPacket> build(
  final int deviceId,
  final List<int> token, {
  final Map<String, dynamic>? payload,
  int? stamp,
}) async {
  assert(token.length == 16);
  stamp ??= MiIO.instance.stampOf(deviceId) ?? 600;

  Uint8List binary;
  if (payload != null) {
    // Variable sized payload.
    final binPayload = await encrypt(
      utf8.encode(jsonEncode(payload)),
      token,
    );
    binary = Uint8List(0x20 + binPayload.length)..setAll(0x20, binPayload);
  } else {
    // Header only packet.
    binary = Uint8List(0x20);
  }

  // 2 bytes magic.
  binary[0] = magic >> 8;
  binary[1] = magic & 0xFF;

  // 2 bytes length.
  binary[2] = binary.length >> 8;
  binary[3] = binary.length & 0xFF;

  // 4 bytes unknown field `0x00000000`.
  binary.fillRange(4, 8, 0);

  // 4 bytes device ID.
  var deviceIdToWrite = deviceId;
  for (var i = 11; i >= 8; --i, deviceIdToWrite >>= 8) {
    binary[i] = deviceIdToWrite & 0xFF;
  }

  // 4 bytes stamp.
  var stampToWrite = stamp;
  for (var i = 15; i >= 12; --i, stampToWrite >>= 8) {
    binary[i] = stampToWrite & 0xFF;
  }

  // Initialize checksum field with token.
  binary.setAll(16, token);

  // 16 bytes MD5 checksum.
  final checksum = md5.convert(binary).bytes;
  binary.setAll(16, checksum);

  return MiIOPacket._(
    length: binary.length,
    unknown: 0x00000000,
    deviceId: deviceId,
    stamp: stamp,
    token: token,
    checksum: checksum,
    payload: payload,
    binary: binary,
  );
}