Пример #1
0
        private void OnDiscoveredPeripheral(object sender, CBDiscoveredPeripheralEventArgs e)
        {
            var device         = new BLEDevice(_managerWrapper, e.Peripheral);
            var rssi           = e.RSSI.Int32Value;
            var advertisements = BLEAdvertisement.Parse(e.AdvertisementData);

            RaiseDeviceDiscovered(device, rssi, advertisements);
        }
Пример #2
0
        public static IList <BLEAdvertisement> Parse(NSDictionary value)
        {
            var advertisements = new List <BLEAdvertisement>();

            foreach (var o in value.Keys)
            {
                var key = (NSString)o;
                if (key == CBAdvertisement.DataLocalNameKey)
                {
                    var data = NSData.FromString((NSString)value.ObjectForKey(key)).ToArray();
                    var item = new BLEAdvertisement(BLEAdvertisementType.CompleteLocalName, data);
                    advertisements.Add(item);
                }
                else if (key == CBAdvertisement.DataManufacturerDataKey)
                {
                    var data = ((NSData)value.ObjectForKey(key)).ToArray();
                    var item = new BLEAdvertisement(BLEAdvertisementType.ManufacturerSpecificData, data);
                    advertisements.Add(item);
                }
                else if (key == CBAdvertisement.DataServiceUUIDsKey)
                {
                    var array = (NSArray)value.ObjectForKey(key);
                    var datas = new List <NSData>();
                    for (nuint i = 0; i < array.Count; i++)
                    {
                        var uuid = array.GetItem <CBUUID>(i);
                        datas.Add(uuid.Data);
                    }
                    var data = datas.SelectMany(d => d.ToArray()).ToArray();
                    var item = new BLEAdvertisement(BLEAdvertisementType.CompleteServiceUUIDs128Bit, data);
                    advertisements.Add(item);
                }
                else if (key == CBAdvertisement.DataTxPowerLevelKey)
                {
                    //iOS stores TxPower as NSNumber. Get int value of number and convert it into a signed Byte
                    //TxPower has a range from -100 to 20 which can fit into a single signed byte (-128 to 127)
                    var byteValue = Convert.ToSByte(((NSNumber)value.ObjectForKey(key)).Int32Value);
                    //add our signed byte to a new byte array and return it (same parsed value as android returns)
                    var data = new byte[] { (byte)byteValue };
                    var item = new BLEAdvertisement(BLEAdvertisementType.TxPowerLevel, data);
                    advertisements.Add(item);
                }
                else if (key == CBAdvertisement.DataServiceDataKey)
                {
                    //Service data from CoreBluetooth is returned as a key/value dictionary with the key being
                    //the service uuid (CBUUID) and the value being the NSData (bytes) of the service
                    //This is where you'll find eddystone and other service specific data
                    var datas = (NSDictionary)value.ObjectForKey(key);
                    //There can be multiple services returned in the dictionary, so loop through them
                    foreach (CBUUID dataKey in datas.Keys)
                    {
                        //Get the service key in bytes (from NSData)
                        var keyData = dataKey.Data.ToArray();

                        //Service UUID's are read backwards (little endian) according to specs,
                        //CoreBluetooth returns the service UUIDs as Big Endian
                        //but to match the raw service data returned from Android we need to reverse it back
                        //Note haven't tested it yet on 128bit service UUID's, but should work
                        Array.Reverse(keyData);

                        //The service data under this key can just be turned into an arra
                        var dataValue = (NSData)datas.ObjectForKey(dataKey);
                        var valueData = dataValue.Length > 0 ? dataValue.ToArray() : new byte[0];

                        //Now we append the key and value data and return that so that our parsing matches the raw
                        //byte value returned from the Android library (which matches the raw bytes from the device)
                        var data = new byte[keyData.Length + valueData.Length];
                        Buffer.BlockCopy(keyData, 0, data, 0, keyData.Length);
                        Buffer.BlockCopy(valueData, 0, data, keyData.Length, valueData.Length);

                        var item = new BLEAdvertisement(BLEAdvertisementType.ServiceData, data);
                        advertisements.Add(item);
                    }
                }
                else if (key == CBAdvertisement.IsConnectable)
                {
                    // A Boolean value that indicates whether the advertising event type is connectable.
                    // The value for this key is an NSNumber object. You can use this value to determine whether a peripheral is connectable at a particular moment.
                    var byteValue = ((NSNumber)value.ObjectForKey(key)).ByteValue;
                    var data      = new byte[] { byteValue };
                    var item      = new BLEAdvertisement(BLEAdvertisementType.IsConnectable, data);
                    advertisements.Add(item);
                }
                else
                {
                    Debug.Write($"Parsing Advertisement: Ignoring Advertisement entry for key {key.ToString()}, since we don't know how to parse it yet. Maybe you can open a Pull Request and implement it :)");
                }
            }

            return(advertisements);
        }
Пример #3
0
        public static IList <BLEAdvertisement> Parse(byte[] value)
        {
            var records = new List <BLEAdvertisement>();

            var index = 0;

            while (index < value?.Length)
            {
                var length = value[index++];
                // Done once we run out of records
                // 1 byte for type and length-1 bytes for data
                if (length == 0)
                {
                    break;
                }
                var type = (BLEAdvertisementType)value[index];
                // Done if our record isn't a valid type
                if (type == 0)
                {
                    break;
                }
                // Advertisment record type not defined:
                if (!Enum.IsDefined(typeof(BLEAdvertisementType), type))
                {
                    Debug.WriteLine($"Advertisment record type not defined: {type}");
                    break;
                }

                //data length is length -1 because type takes the first byte
                var data = new byte[length - 1];
                Array.Copy(value, index + 1, data, 0, length - 1);

                // don't forget that data is little endian so reverse
                // Supplement to Bluetooth Core Specification 1
                // NOTE: all relevant devices are already little endian, so this is not necessary for any type except UUIDs
                switch (type)
                {
                case BLEAdvertisementType.CompleteServiceUUIDs128Bit:
                case BLEAdvertisementType.CompleteServiceUUIDs16Bit:
                case BLEAdvertisementType.CompleteServiceUUIDs32Bit:
                case BLEAdvertisementType.IncompleteServiceUUIDs128Bit:
                case BLEAdvertisementType.IncompleteServiceUUIDs16Bit:
                case BLEAdvertisementType.IncompleteServiceUUIDs32Bit:
                case BLEAdvertisementType.ServiceDataUUID128Bit:
                case BLEAdvertisementType.ServiceDataUUID16Bit:
                case BLEAdvertisementType.ServiceDataUUID32Bit:
                case BLEAdvertisementType.ServiceSolicitationUUIDs128Bit:
                case BLEAdvertisementType.ServiceSolicitationUUIDs16Bit:
                case BLEAdvertisementType.ServiceSolicitationUUIDs32Bit:
                    Array.Reverse(data);
                    break;
                }
                var record = new BLEAdvertisement(type, data);
                Debug.WriteLine(record.ToString());
                records.Add(record);
                // Advance
                index += length;
            }

            return(records);
        }