fromPacket static method
fromPacket creates a List<BleAdvertisement> from a raw message following this structure: MAC_ADDRESS;UNIX;LAT;LNG;ALT;MODEL;RSSI;MANUFACTURER+DATA;SERVICE+DATA;CRC16
Implementation
static List<BleAdvertisement> fromPacket(String raw) {
final parts = raw.split(';');
if (parts.isEmpty) return [];
if (parts.length == 1) return [];
// The parts should be divisible by 4, can be multiple groups
if (parts.length % 12 != 0) {
throw ParseException('Invalid advertisement definition');
}
// Separate each group
final List<BleAdvertisement> advertisements = [];
for (int i = 0; i < parts.length; i += 12) {
final rawMacAddress = parts[i];
final rawUnix = parts[i + 1];
final rawLatitude = parts[i + 2];
final rawLongitude = parts[i + 3];
final rawAltitude = parts[i + 4];
final model = parts[i + 5];
final deviceName = parts[i + 6];
final rawRssi = parts[i + 7];
final rawTxPower = parts[i + 8];
final rawManufacturerData = parts[i + 9];
final rawServiceData = parts[i + 10];
final receivedCrc = int.tryParse(parts[i + 11], radix: 16) ?? 0;
final calculatedCrc = calculateCrc('${parts.sublist(i, i + 11).join(';')};'.codeUnits);
if (receivedCrc != calculatedCrc) {
throw CrcException(
'Invalid CRC, expected ${receivedCrc.toRadixString(16)}, '
'got ${calculatedCrc.toRadixString(16)}',
);
}
final macParts = rawMacAddress.split('');
if (macParts.length != 12) {
throw MalformedException('Invalid MAC Address');
}
String macAddress = '';
for (int i = 0; i < macParts.length; i += 2) {
macAddress += '${macParts[i]}${macParts[i + 1]}';
if (i + 2 < macParts.length) {
macAddress += ':';
}
}
DateTime timestamp;
try {
timestamp = DateTime.fromMillisecondsSinceEpoch(int.parse(rawUnix) * 1000, isUtc: true);
} catch (e) {
throw MalformedException('Invalid timestamp');
}
double? latitude;
if (rawLatitude.isNotEmpty) {
latitude = double.tryParse(rawLatitude);
}
double? longitude;
if (rawLongitude.isNotEmpty) {
longitude = double.tryParse(rawLongitude);
}
double? altitude;
if (rawAltitude.isNotEmpty) {
altitude = double.tryParse(rawAltitude);
}
int rssi = int.tryParse(rawRssi) ?? 0;
int? txPower = int.tryParse(rawTxPower);
List<BleManufacturerData> manufacturerData = [];
for (String mfd in rawManufacturerData.split(',')) {
if (mfd.isEmpty) continue;
final subparts = mfd.split(':');
if (subparts.isEmpty) continue;
if (subparts.length != 2) {
throw MalformedException('Invalid manufacturer data "$mfd"');
}
final companyId = int.tryParse(subparts[0], radix: 16) ?? 0;
List<int> data = [];
for (int i = 0; i < subparts[1].length; i += 2) {
data.add(int.tryParse(subparts[1].substring(i, i + 2), radix: 16) ?? 0);
}
manufacturerData.add(BleManufacturerData(companyId: companyId, data: data));
}
List<BleServiceData> serviceData = [];
for (String sfd in rawServiceData.split(',')) {
if (sfd.isEmpty) continue;
final subparts = sfd.split(':');
if (subparts.isEmpty) continue;
if (subparts.length != 2) {
throw MalformedException('Invalid service data "$sfd"');
}
final uuid = int.tryParse(subparts[0], radix: 16) ?? 0;
List<int> data = [];
for (int i = 0; i < subparts[1].length; i += 2) {
data.add(int.tryParse(subparts[1].substring(i, i + 2), radix: 16) ?? 0);
}
serviceData.add(BleServiceData(uuid: uuid, data: data));
}
advertisements.add(
BleAdvertisement(
deviceName: deviceName,
macAddress: macAddress,
timestamp: timestamp,
rssi: rssi,
model: model,
latitude: latitude,
longitude: longitude,
altitude: altitude,
txPower: txPower,
manufacturerData: manufacturerData,
serviceData: serviceData,
),
);
}
return advertisements;
}