Bluetooth LE - Characteristic Values only read once

1.5k Views Asked by At

I am developing a Windows app, that reads values from a characteristic. Its a very simple task, and i managed to write working code. Everything does what it should - but only on my development PC. I have written a C# class dll, using .Net 4.8, on Win10 that connects to my device and reads out a value. My app is vb6. The other functionalities of my app work just fine. The problem I am having is: When I install my app on another PC it isnt working. The app connects to my peripheral, reads out the characteristic value, but in the next readings, the value stays the same. It is always the same until I reconnect. That means the value only gets updated when I reconnect the device. Using "MS Bluetooth LE Lab" I dont get this issue on the target machine. The code of my DLL is the following:

using SDKTemplate;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.Storage.Streams;
using System.Threading.Tasks;
using System.Runtime.Remoting.Messaging;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using Nito.AsyncEx.Synchronous;

namespace BleSirLo
{
    public class Programm
    {

        public static byte[] ret = new byte[6];
        static void Main(string[] args)
        {
            Programm p = new Programm();
            Task t = MainAsync(args);
            t.Wait();
            return;
        }
        // MainAsync zum Aufrufen von Async Funktionen aus einer Static Main heraus
        static async Task MainAsync(string[] args)
        {
            Programm p = new Programm();
            p.StartBleDeviceWatcher();
        }

        private List<DeviceInformation> UnknownDevices = new List<DeviceInformation>();
        private List<DeviceInformation> _knownDevices = new List<DeviceInformation>();
        private IReadOnlyList<GattCharacteristic> characteristics;
        private IReadOnlyList<GattDeviceService> services;

        private GattDeviceService currentSelectedService = null;
        private GattCharacteristic currentSelectedCharacteristic = null;

        private DeviceWatcher deviceWatcher;

        public bool done = false;
        
        //Reader ist die synchrone Funktion, die für ihren Rückgabewert von aussen aufgerufen wird.  
        public byte[] Reader(Programm p)
        {
            Byte[] result;
            Task<Byte[]> task = p.ReadBuffer();
            try
            {
                result = task.WaitAndUnwrapException();   //Ein Wert wird aus einer asynchronen Funktion geholt
                return result;
            }
            catch
            {                
                result = new Byte[] { 0, 0, 0, 0, 0, 0 }; //Dieser catch ist für die Wiederverbindungsfunktion essenziell, wenn Bluetooth unterbrochen und wieder verbunden wird.
                return result;
            }
          
        }
        //Hier wird nach BluetoothLE kompatiblen Geräten gesucht
        public bool StartBleDeviceWatcher()
        {
            // Additional properties we would like about the device.
            // Property strings are documented here https://msdn.microsoft.com/en-us/library/windows/desktop/ff521659(v=vs.85).aspx
            string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected", "System.Devices.Aep.Bluetooth.Le.IsConnectable" };

            // BT_Code: Example showing paired and non-paired in a single query.
            string aqsAllBluetoothLEDevices = "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")";

            deviceWatcher =
                    DeviceInformation.CreateWatcher(
                        aqsAllBluetoothLEDevices,
                        requestedProperties,
                        DeviceInformationKind.AssociationEndpoint);

            // Diese Events werden automatisch aufgerufen, wenn das entsprechende passiert
            // Register event handlers before starting the watcher.
            deviceWatcher.Added += DeviceWatcher_Added;
            deviceWatcher.Updated += DeviceWatcher_Updated;
            deviceWatcher.Removed += DeviceWatcher_Removed;
            deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
            deviceWatcher.Stopped += DeviceWatcher_Stopped;

            _knownDevices.Clear();
            deviceWatcher.Start();
            System.Threading.Thread.Sleep(2000);
            if (currentSelectedCharacteristic != null)
                return true;
            else
                return false;
        }

        //Wenn ein Gerät gefunden wird, wird DeviceWatcher_Added aufgerufen, mit dem Namen unseres Geräts verglichen und wenn der Name gleich ist, verbunden
        private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation deviceInfo)
        {
            if (sender == deviceWatcher)
            {
                if ((deviceInfo.Name == "SimpleBLEPeripheral") || (deviceInfo.Name == "Ei Gude, Wie?"))
                {
                    sender.Stop();
                    ConnectDevice(deviceInfo);
                }
            }
        }
        private void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate deviceInfo)
        {
        }
        private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate deviceInfo)
        {
        }
        private void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
        {
        }
        private void DeviceWatcher_Stopped(DeviceWatcher sender, object args)
        {
        }

        //trigger StartBleDeviceWatcher() to start bluetoothLe Operation

        private async Task<bool> ConnectDevice(DeviceInformation deviceInfo)
        {
            //get bluetooth device information
            BluetoothLEDevice bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);
            //Respond(bluetoothLeDevice.ConnectionStatus.ToString());

            //get its services
            GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesAsync();

            //verify if getting success 
            if (result.Status == GattCommunicationStatus.Success)
            {
                //store device services to list
                services = result.Services;

                //loop each services in list
                foreach (var serv in services)
                {
                    //get serviceName by converting the service UUID
                    string ServiceName = Utilities.ConvertUuidToShortId(serv.Uuid).ToString();

                    //if current servicename matches the input service name / 65520 = 0xFFF0
                    if (ServiceName == "65520") //ServiceTxtBox.Text)
                    {
                        //store the current service
                        currentSelectedService = serv;

                        //get the current service characteristics
                        GattCharacteristicsResult resultCharacterics = await serv.GetCharacteristicsAsync();

                        //verify if getting characteristics is success 
                        if (resultCharacterics.Status == GattCommunicationStatus.Success)
                        {
                            //store device services to list
                            characteristics = resultCharacterics.Characteristics;

                            //loop through its characteristics
                            foreach (var chara in characteristics)
                            {
                                //get CharacteristicName by converting the current characteristic UUID
                                string CharacteristicName = Utilities.ConvertUuidToShortId(chara.Uuid).ToString();

                                //if current CharacteristicName matches the input characteristic name / 65524 = 0xFFF4
                                if (CharacteristicName == "65524")//CharacteristicsTxtBox.Text)
                                {
                                    //store the current characteristic
                                    currentSelectedCharacteristic = chara;
                                    //stop method execution  
                                    done = true;
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            return false;
        }

        //Funktion ließt die Charakteristik und übergibt sie asynchron
        public async Task<Byte[]> ReadBuffer()
        {
            if (currentSelectedService != null && currentSelectedCharacteristic != null)
            {
                GattCharacteristicProperties properties = currentSelectedCharacteristic.CharacteristicProperties;

                //if selected characteristics has read property
                if (properties.HasFlag(GattCharacteristicProperties.Read))
                {
                    //read value asynchronously
                    GattReadResult result = await currentSelectedCharacteristic.ReadValueAsync();
                    if (result.Status == GattCommunicationStatus.Success)
                    {
                        var reader = DataReader.FromBuffer(result.Value);                      
                        reader.ReadBytes(ret);
                        return ret;
                    }
                 return null;
                }
             return null;
            }
         return null;
        }

    private void Response_TextChanged(object sender, EventArgs e)
    {
    }
    }
}
0

There are 0 best solutions below