public static (string result, CommonManufacturerType) ParseManufacturerData(BluetoothLEAdvertisementDataSection section, sbyte txPower) { CommonManufacturerType manufacturerType = CommonManufacturerType.Other; try { var bytes = section.Data.ToArray(); var dr = DataReader.FromBuffer(section.Data); dr.ByteOrder = ByteOrder.LittleEndian; // bluetooth defaults to little endian. var companyId = dr.ReadUInt16(); var companyName = GetBluetoothCompanyIdentifier(companyId); var sb = new StringBuilder(); sb.Append(companyName); sb.Append(": "); bool displayAsHex = true; switch (companyId) { case 0x4C: // Apple var appleIBeacon = AppleIBeacon.Parse(section, txPower); if (appleIBeacon.IsValid) { sb.Append(appleIBeacon.ToString()); sb.Append("\n"); displayAsHex = false; // we have a better display } else if (appleIBeacon.IsApple10) { manufacturerType = CommonManufacturerType.Apple10; } break; } if (displayAsHex) { while (dr.UnconsumedBufferLength > 0) { var b = dr.ReadByte().ToString("X2"); sb.Append(b); // As hex! sb.Append(' '); } sb.Append('\n'); } return(sb.ToString(), manufacturerType); } catch (Exception) { return("??\n", manufacturerType); } }
public static AppleIBeacon Parse(BluetoothLEAdvertisementDataSection section, sbyte RSSI) { AppleIBeacon retval = new AppleIBeacon(); try { var dr = DataReader.FromBuffer(section.Data); dr.ByteOrder = ByteOrder.LittleEndian; // bluetooth defaults to little endian. retval.CompanyId = dr.ReadUInt16(); // Will be 76 == 0x4c but that's explicitly not enforced here retval.BeaconType = dr.ReadByte(); retval.BeaconLen = dr.ReadByte(); switch (retval.BeaconType) { case 0x02: // See https://github.com/wrightLin/RaspiJob/blob/6004e46ec28535546add496eff0ed8d7947ed563/Beacons.Helper/Beacons.cs // See https://github.com/blueSense/hub-application/blob/59ab67c17cb71883cf19027bf62050b953644750/lib/bluesense-superhub/monitor/parsers/ibeacon.js if (retval.BeaconLen < 0x15) { return(retval); } byte[] guidBytes = new byte[16]; dr.ReadBytes(guidBytes); retval.BeaconGuid = new Guid(guidBytes); retval.Major = dr.ReadUInt16(); retval.Minor = dr.ReadUInt16(); retval.MeasuredPower = (sbyte)dr.ReadByte(); retval.MeasuredPower = RSSI; break; case 0x10: case 0x12: // TODO: how to handle a typical phone? break; default: break; //TODO: what value here? } } catch (Exception) { ; } return(retval); // if there was an exception, the beacon is invalid... }