示例#1
0
        protected virtual IDevice AddConnectedDevice(GattSession session)
        {
            var dev = new UwpDevice(session);

            this.connectedDevices.Add(dev);
            return(dev);
        }
        protected override bool WriteRequested(GattSession session, GattWriteRequest request)
        {
            byte[] receivedWrite;
            CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
            var receivedWriteHexString = Helpers.ToHexString(request.Value);

            QuickLockMainService parent = (QuickLockMainService)this.ParentService;

            //expected: 0066612666 (pcap), or 006661266600000000 (also correct)
            if ((request.Value.Length != 5) && (request.Value.Length != 9))
            {
                Debug.WriteLine($"Smart lock auth WriteRequested, but invalid format: {receivedWriteHexString} ({request.Value.Length})");
                //do not update Value, return
                OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
                return(true);
            }

            //check just the first byte and password, ignore rest if provided
            if ((receivedWrite[0] != 0x00) || (receivedWrite[1] != password[0]) || (receivedWrite[2] != password[1]) || (receivedWrite[3] != password[2]) || (receivedWrite[4] != password[3]))
            {
                Debug.WriteLine($"Smart lock auth WriteRequested: INVALID PASSWORD: {receivedWriteHexString} ({request.Value.Length})");
                //do not update Value, return
                OnPropertyChanged(new PropertyChangedEventArgs("InvalidPin"));
                return(true);
            }

            parent.UpdateAuthenticationState(true);
            OnPropertyChanged(new PropertyChangedEventArgs("AuthenticationState"));

            return(true);
        }
        // if received "01", send logs via notification from HistoryData characteristic
        protected override bool WriteRequested(GattSession session, GattWriteRequest request)
        {
            byte[] receivedWrite;
            CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
            var receivedWriteHexString = Helpers.ToHexString(request.Value);

            QuickLockHistoryService parent = (QuickLockHistoryService)this.ParentService;

            if ((request.Value.Length != 1) || (receivedWrite[0] != 0x01))
            {
                Debug.WriteLine($"Quicklock history cmd WriteRequested, but invalid format: {receivedWriteHexString} ({request.Value.Length})");
                //do not update Value, return
                OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
                return(true);
            }

            Debug.WriteLine($"Quicklock history cmd received, sending out logs");

            //    OnPropertyChanged(new PropertyChangedEventArgs("Logs"));

            // set the status characteristic and send notification
            parent.QuickLockHistoryData.SendLogs();

            return(true);
        }
示例#4
0
        /// <summary>
        /// Listen for a connection.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task StartListening()
        {
            try
            {
                // If already listening, do nothing
                if (IsListening)
                {
                    return;
                }

                // Create device
                var deviceInfo = await GetBluetoothDeviceInfo();

                device = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);

                device.ConnectionStatusChanged += Device_ConnectionStatusChanged;

                // Initiate connection
                gattSession = await GattSession.FromDeviceIdAsync(device.BluetoothDeviceId);

                gattSession.MaintainConnection = true;
            }
            catch
            {
                // Stop the device and rethrow exception
                StopListening();
                throw;
            }
        }
示例#5
0
        protected override bool WriteRequested(GattSession session, GattWriteRequest request)
        {
            byte[] receivedWrite;
            CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
            var receivedWriteHexString = Helpers.ToHexString(request.Value);

            if ((request.Value.Length != 6) || (receivedWrite[5] != 0xFF))
            {
                Debug.WriteLine($"Light Bulb color Write requested, INVALID INPUT: {receivedWriteHexString} ({request.Value.Length})");
                //send notification to user
                OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));

                //do not update Value, return
                return(true);
            }

            // ARGB request
            if (receivedWrite[0] == 0xAA)
            {
                ProcessARGB(receivedWrite);
            }

            // password protected request
            else if (receivedWrite[0] == 0xBE)
            {
                ProcessPassProtected(receivedWrite);
            }

            //send to scenario
            return(true);
        }
        private async Task CreateSession( )
        {
            _session?.Dispose( );

            _session = await GattSession.FromDeviceIdAsync(_device.BluetoothDeviceId);

            _session.MaintainConnection = true;
        }
示例#7
0
 protected virtual IDevice FindDevice(GattSession session)
 {
     foreach (var device in this.SubscribedDevices)
     {
         if (device.Uuid.ToString().Equals(session.DeviceId.Id))
         {
             return(device);
         }
     }
     return(null);
 }
示例#8
0
        /// <summary>
        /// Read request callback to update the value
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        protected override bool ReadRequested(GattSession session, GattReadRequest request)
        {
            DataWriter writer = new DataWriter();

            int maxPayloadSize = session.MaxPduSize - 1;

            // make sure our source data is bigger than a single read request to make sure a ReadBlobRequest is done
            if (longCharacteristicData.Length < maxPayloadSize)
            {
                // This should not be required as the server should only be processing one request at a time
                // but it's better to be safe than sorry
                lock (dataLock)
                {
                    longCharacteristicData = new byte[(int)(maxPayloadSize * 2.5)];

                    for (int i = 0; i < longCharacteristicData.Length; i++)
                    {
                        longCharacteristicData[i] = (byte)(i % 10);
                    }
                }
            }

            // finish getting the read request
            int offset = (int)request.Offset;

            // calculate the size of the data we send back
            int chunk = Math.Min(maxPayloadSize, longCharacteristicData.Length - offset);

            Debug.WriteLine($"UpdateValue: payloadSize: {maxPayloadSize}, chunk {chunk}");

            // prep the data we send back
            var readValue = String.Empty;
            var buffer    = new byte[chunk];

            buffer.Initialize();

            // copy from source to target
            Array.Copy(longCharacteristicData, longCharacteristicReadOffset, buffer, 0, chunk);

            // write to our internal Value which will be used to send back the data
            writer.WriteBytes(buffer);

            readValue = buffer.BytesToString();
            Debug.WriteLine("MicrosoftReadLongCharacteristic: Read request value: {readValue}");

            // Update our characteristics value.
            Value = writer.DetachBuffer();

            // Respond back to the caller.
            request.RespondWithValue(Value);
            return(true);
        }
        public async void Connect(string id)
        {
            try
            {
                // BT_Code: BluetoothLEDevice.FromIdAsync must be called from a UI thread because it may prompt for consent.
                bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(id);

                if (bluetoothLeDevice == null)
                {
                    Log.d("Failed to connect to device.", NotifyType.ErrorMessage);
                    return;
                }

                bluetoothLeDevice.ConnectionStatusChanged += ConnectionStatusChangedHandler;

                mBluetoothGatt = await GattSession.FromDeviceIdAsync(bluetoothLeDevice.BluetoothDeviceId);

                mBluetoothGatt.MaintainConnection = true;
            }
            catch (Exception ex) when(ex.HResult == E_DEVICE_NOT_AVAILABLE)
            {
                Log.d("Bluetooth radio is not on.", NotifyType.ErrorMessage);
                return;
            }

            if (bluetoothLeDevice != null)
            {
                // Note: BluetoothLEDevice.GattServices property will return an empty list for unpaired devices. For all uses we recommend using the GetGattServicesAsync method.
                // BT_Code: GetGattServicesAsync returns a list of all the supported services of the device (even if it's not paired to the system).
                // If the services supported by the device are expected to change during BT usage, subscribe to the GattServicesChanged event.
                GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesForUuidAsync(RX_SERVICE_UUID);

                if (result.Status == GattCommunicationStatus.Success)
                {
                    _services.Clear();
                    _services.AddRange(result.Services);

                    Log.d(String.Format("Found {0} services", _services.Count), NotifyType.StatusMessage);
                    foreach (var service in _services)
                    {
                        Log.d("SERVICE: " + DisplayHelpers.GetServiceName(service));
                        GetCharachteristics(service);
                    }
                }
                else
                {
                    Log.d("Device unreachable", NotifyType.ErrorMessage);
                }
            }
        }
        public void Dispose()
        {
            if (mBluetoothGatt != null)
            {
                mBluetoothGatt.MaintainConnection = false;
                mBluetoothGatt.Dispose();
                mBluetoothGatt = null;
            }

            if (bluetoothLeDevice != null)
            {
                bluetoothLeDevice.Dispose();
                bluetoothLeDevice = null;
            }
        }
示例#11
0
 protected override bool WriteRequested(GattSession session, GattWriteRequest request)
 {
     //check if this is write command not write request
     if (request.Option == GattWriteOption.WriteWithResponse)
     {
         OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
         Debug.WriteLine("Write request");
     }
     else
     {
         Debug.WriteLine("Write command");
         Value = request.Value;
     }
     return(true);
 }
示例#12
0
 /// <summary>
 /// Stops the device from listening and resets.
 /// </summary>
 public void StopListening()
 {
     if (device != null)
     {
         OnDisconnect();
         gattSession?.Dispose();
         gattSession = null;
         if (device != null)
         {
             device.ConnectionStatusChanged -= Device_ConnectionStatusChanged;
         }
         device?.Dispose();
         device = null;
     }
 }
示例#13
0
        // GattSession

        private void OnSessionStatusChanged(GattSession session, GattSessionStatusChangedEventArgs args)
        {
            Utils.Info("OnSessionStatusChanged status: {0} error: {1}", args.Status.ToString(), args.Error.ToString());

            if (args.Status != GattSessionStatus.Closed)
            {
                return;
            }

            var context = mSubscribedCentrals.Where(ctx => ctx.client.Session.DeviceId.Id == session.DeviceId.Id).FirstOrDefault();

            if (context != null)
            {
                Utils.Info("disconnected: {0}", session.DeviceId.Id);
                RemoveCentral(context);
            }
        }
        /// <summary>Populate the portable session data model with Win objects</summary>
        /// <param name="session">The Windows GATT session</param>
        /// <param name="dataModel">The portable data model</param>
        private void BuildSessionDataModel(GattSession session, BLE_GattSession dataModel)
        {
            if (session != null)
            {
                dataModel.CanConnectionBeMaintained    = session.CanMaintainConnection;
                dataModel.ShouldConnectionBeMaintained = session.MaintainConnection;
                dataModel.MaxPDUSize    = session.MaxPduSize;
                dataModel.SessionStatus = (BLE_GattSessionStatus)session.SessionStatus;

                if (session.DeviceId != null)
                {
                    dataModel.DeviceId    = session.DeviceId.Id;
                    dataModel.IsClassic   = session.DeviceId.IsClassicDevice;
                    dataModel.IsLowEnergy = session.DeviceId.IsLowEnergyDevice;
                }
            }
        }
示例#15
0
        protected override bool WriteRequested(GattSession session, GattWriteRequest request)
        {
            var receivedWrite = Helpers.ToHexString(request.Value);

            // invalid input, discard
            if (!receivedWrite.Equals("00") && !receivedWrite.Equals("01"))
            {
                Debug.WriteLine($"Light Bulb cmd WriteRequested: INVALID INPUT: {receivedWrite} ({request.Value.Length})");
                //send notification to user
                OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
                //do not update Value, return
                return(true);
            }

            //check for macros blink challenge
            currentTime = DateTime.Now;
            span        = currentTime.Subtract(previousTime);
            Debug.WriteLine($"Time span from previoius write: {span.TotalMilliseconds} ms");
            previousTime = currentTime;
            // previus write less than 0.5s ago
            if (span.TotalMilliseconds < 500)
            {
                Debug.WriteLine("Time span less than 0.5s!");
                //check if previous value != current (light bulb swith)
                if (Value != request.Value)
                {
                    switchCounter++;
                    Debug.WriteLine($"Value switch - OK {switchCounter}");
                }
                else
                {
                    switchCounter = 0;
                }
            }

            if (switchCounter > 10)
            {
                OnPropertyChanged(new PropertyChangedEventArgs("BlinkPassed"));
            }

            // Set the characteristic Value
            Value = request.Value;

            return(true);
        }
示例#16
0
        protected override bool WriteRequested(GattSession session, GattWriteRequest request)
        {
            var service = base.ParentService as GattServicesLibrary.Services.AlertNotificationService;

            if (service != null)
            {
                AlertNotificationControlPointCommand command = new AlertNotificationControlPointCommand();
                var byteAccess = request.Value.ToArray();
                command.CommandId  = (CharacteristicParameterValues.AlertNotificationControlPointCommandId)byteAccess[0];
                command.CategotyId = (CharacteristicParameterValues.AlertCategoryId)byteAccess[1];

                service.ProcessCommand(command);

                Value = request.Value;
                request.Respond();
                return(true);
            }
            return(false);
        }
        protected override bool WriteRequested(GattSession session, GattWriteRequest request)
        {
            byte[] receivedWrite;
            CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
            var receivedWriteHexString = Helpers.ToHexString(request.Value);

            // valid format: one byte of length, followed by ascii hex username, and padded with 00 up to 15 bytes
            // for now just check the length and accept 15 chars only
            if ((request.Value.Length != 15))
            {
                Debug.WriteLine($"Quicklock username WriteRequested, wrong length: {receivedWriteHexString} ({request.Value.Length})");
                //do not update Value, return
                OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
                return(true);
            }

            // Set the characteristic Value to the value received
            Value = request.Value;
            return(true);
        }
示例#18
0
        protected override bool WriteRequested(GattSession session, GattWriteRequest request)
        {
            byte[] receivedWrite;
            CryptographicBuffer.CopyToByteArray(request.Value, out receivedWrite);
            var receivedWriteHexString = Helpers.ToHexString(request.Value);

            QuickLockMainService parent = (QuickLockMainService)this.ParentService;

            if (!parent.isAuthenticated)
            {
                Debug.WriteLine($"Quicklock cmd WriteRequested, but not authenticated {receivedWriteHexString} ({request.Value.Length})");
                //do not update Value, return
                OnPropertyChanged(new PropertyChangedEventArgs("Unauthenticated"));
                return(true);
            }

            if ((request.Value.Length != 1) || ((receivedWrite[0] != 0x00) && (receivedWrite[0] != 0x01)))
            {
                Debug.WriteLine($"Quicklock cmd WriteRequested, but invalid format {receivedWriteHexString} ({request.Value.Length})");
                //do not update Value, return
                OnPropertyChanged(new PropertyChangedEventArgs("InvalidRequest"));
                return(true);
            }

            Debug.WriteLine($"Quicklock cmd received: {receivedWriteHexString} ({request.Value.Length})");

            if (receivedWrite[0] == 00) // lock
            {
                Debug.WriteLine($"Locking!");
                parent.UpdateUnlockState(false);
            }
            else if (receivedWrite[0] == 01) // unlock
            {
                Debug.WriteLine($"Unlocking!");
                parent.UpdateUnlockState(true);
            }

            OnPropertyChanged(new PropertyChangedEventArgs("LockState"));

            return(true);
        }
示例#19
0
 private void OnSessionStatusChanged(GattSession sender, GattSessionStatusChangedEventArgs args)
 {
     Debug.WriteLine("DeviceConnection_Updated: " + sender.SessionStatus);
     OnConnectionChanged(sender.SessionStatus == GattSessionStatus.Active);
 }
示例#20
0
    public async void ConnectDevice(ulong addr)
    {
        string addrString = addr.ToString("X");

        Console.WriteLine("{0}: {1}",
                          addrString, loops.ContainsKey(addr) ? "Updating connection" : "Connecting");

        BluetoothLEDevice loop = await BluetoothLEDevice.FromBluetoothAddressAsync(addr);

        loop.ConnectionStatusChanged += ConnectionStatusHandler;

        // Maintain the connection (not sure this does anything)
        //Console.WriteLine("{0}: Maintaining connection ...", addrString);
        GattSession s =
            await GattSession.FromDeviceIdAsync(BluetoothDeviceId.FromId(loop.DeviceId));

        s.MaintainConnection = true;

        //Console.WriteLine("{0}: Getting services ...", addrString);
        GattDeviceServicesResult serviceResult =
            await loop.GetGattServicesAsync(BluetoothCacheMode.Uncached);

        foreach (GattDeviceService service in serviceResult.Services)
        {
            if (service.Uuid.Equals(loopService))
            {
                //Console.WriteLine("{0}: Finding characteristics ...", addrString);
                GattCharacteristicsResult charResult = await service.GetCharacteristicsAsync(BluetoothCacheMode.Uncached);

                foreach (GattCharacteristic characteristic in charResult.Characteristics)
                {
                    if (characteristic.Uuid.Equals(loopChar))
                    {
                        Subscribe(characteristic, addr);
                        // Prevent GC of the device and session
                        loops[addr] = loop;
                        break;
                    }
                }
            }
            else if (service.Uuid.Equals(GattServiceUuids.Battery))
            {
                GattCharacteristicsResult charResult = await service.GetCharacteristicsAsync(BluetoothCacheMode.Uncached);

                foreach (GattCharacteristic characteristic in charResult.Characteristics)
                {
                    if (!characteristic.Uuid.Equals(GattCharacteristicUuids.BatteryLevel))
                    {
                        continue;
                    }

                    GattReadResult batt = await characteristic.ReadValueAsync();

                    DataReader reader = DataReader.FromBuffer(batt.Value);
                    byte[]     input  = new byte[reader.UnconsumedBufferLength];
                    reader.ReadBytes(input);
                    Console.WriteLine("Loop battery: {0}%", input[0]);
                    break;
                }
            }
        }
    }
示例#21
0
 public UwpDevice(GattSession session)
 {
     this.Uuid = new Guid(session.DeviceId.Id);
 }
 protected virtual bool WriteRequested(GattSession session, GattWriteRequest request)
 {
     Debug.WriteLine("Request not completed by derrived class.");
     return(false);
 }
 /// <summary>
 /// Read request callback to update the value
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="args"></param>
 protected override bool ReadRequested(GattSession session, GattReadRequest request)
 {
     System.Diagnostics.Debug.WriteLine("Entering MSFTReadRequest.Characteristic_ReadRequested");
     UpdateValue();
     return(false);
 }
示例#24
0
 public Peripheral(GattSession session)
 {
     this.Uuid = new Guid(session.DeviceId.Id);
 }
示例#25
0
 internal Peripheral(BluetoothLEDevice device, GattSession session)
 {
     this.device  = device;
     this.session = session;
 }
 protected override bool ReadRequested(GattSession session, GattReadRequest request)
 {
     UpdateCurrentTimeValue();
     request.RespondWithValue(Value);
     return(true);
 }
示例#27
0
 public Peripheral(GattSession session)
 {
     this.Uuid = session.DeviceId.Id;
 }