1

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)
    {
    }
    }
}
Static
  • 87
  • 8
  • It is because device paired and you read from cach. – Mike Petrichenko Aug 10 '20 at 08:35
  • They are not paired – Static Aug 10 '20 at 08:44
  • Does not matter cause you read from cache – Mike Petrichenko Aug 10 '20 at 08:50
  • 1
    Use ReadValueAsync(Uncached) – Mike Petrichenko Aug 10 '20 at 08:52
  • Ok, I used ReadValueAsync(Uncached) and it worked on all machine!!! Thanks for that. 1 last thing: i just changed ReadValueAsync() to ReadValueAsync(BluetoothCacheMode.Uncached). But now the reading takes about 3 seconds. the first 10-20 reading are fast as always, but then it slows down... Do i need to change anything else? – Static Aug 10 '20 at 11:05
  • That's OK because connection to device takes time. First read is always from cache.Yes, you to connect to devie before read values. But unfortunately we spent a lot of time to find out how to implement that. So that's your home work. – Mike Petrichenko Aug 10 '20 at 11:09
  • So, you are telling me it is not possible to read the characteristic value faster than every 3 seconds or so? That would make it impossible for me to use. Can't I have it work like it did cached on every machine? – Static Aug 10 '20 at 11:18
  • Why not, There is no problem to read it even each second. But in fact that is wrong wayt o use BLE device. Instead you must use Notifications or Indications. – Mike Petrichenko Aug 10 '20 at 11:25
  • There is no problem with reading it each second. Thats precisly what i need. My sensor writes values to the characteristic every second. If I read it every 3 seconds I miss a lot of readings. On the peripheral, I only have 1 characteristic in my service and that is set to notification. Shouldnt my central device be able to read it as soon as the value in the characteristic changes? Without the 3s lag? If yes, is there a reading function other than readvalueasync for notification? – Static Aug 10 '20 at 11:32
  • GattCharacteristic ValuChange event. – Mike Petrichenko Aug 10 '20 at 12:33
  • Ok that solved my Issue. Thanks for your help! – Static Aug 11 '20 at 05:34

0 Answers0