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); }
/// <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; } }
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; }
protected virtual IDevice FindDevice(GattSession session) { foreach (var device in this.SubscribedDevices) { if (device.Uuid.ToString().Equals(session.DeviceId.Id)) { return(device); } } return(null); }
/// <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; } }
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); }
/// <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; } }
// 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; } } }
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); }
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); }
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); }
private void OnSessionStatusChanged(GattSession sender, GattSessionStatusChangedEventArgs args) { Debug.WriteLine("DeviceConnection_Updated: " + sender.SessionStatus); OnConnectionChanged(sender.SessionStatus == GattSessionStatus.Active); }
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; } } } }
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); }
public Peripheral(GattSession session) { this.Uuid = new Guid(session.DeviceId.Id); }
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); }
public Peripheral(GattSession session) { this.Uuid = session.DeviceId.Id; }