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)
{
}
}
}