0

I'm running Windows version 10.0.16299.0, and building on Visual Studio C# 2017. I can successfully connect to an unpaired BLE device from a Windows Forms app, and get ValueChanged events (1 per second), but not for long. I usually stop receiving those events in 40 seconds or less - usually less.

I realize this is likely a dispose/GC issue, but I don't see how. The device, service, characteristics, and descriptors are all stored as member variables in the main form and should not get collected:

public partial class Form1 : Form
{
    private BluetoothLEDevice _device;
    private List<GattDeviceService> _services;
    private List<GattDescriptor> _descriptors = new List<GattDescriptor>();
    private List<GattCharacteristic> _characteristics = new List<GattCharacteristic>();

    private async void button1_Click(object sender, EventArgs e)
    {
        _device = await BluetoothLEDevice.FromIdAsync("BluetoothLE#BluetoothLE00:xx:xx:xx:xx:xx:xx:xx:xx:xx");

        var services = await _device.GetGattServicesAsync();
        foreach (var service in services.Services)
        {
            var chars = await service.GetCharacteristicsAsync();
            foreach (var ch in chars.Characteristics)
            {
                var descriptors = await ch.GetDescriptorsAsync();
                foreach (var desc in descriptors.Descriptors)
                {
                    if (desc.AttributeHandle == 15 || desc.AttributeHandle == 26)
                    {
                        _services.Add(service);
                        _descriptors.Add(desc);
                        _characteristics.Add(ch);

                        var writer = new DataWriter();
                        writer.WriteBytes(new byte[] { 1, 0 });
                        var buf = writer.DetachBuffer();

                        await desc.WriteValueAsync(buf);
                    }

                    ch.ValueChanged += ChOnValueChanged;
                }
            }
        }
    }

In my sample, I click a button to establish a connection and subscribe to events. Before you say that writing to the descriptor is not how you would do it - I know. The device uses non-standard descriptor IDs which is why I must write to them directly.

Note that everything works, including the writes - I get no errors. It's just that the ValueChanged event is no longer fired after a short duration, and I can't figure out what else I must "cache" in order to prevent objects from being disposed, assuming that's what the problem is.

Dan
  • 1,215
  • 1
  • 10
  • 22

1 Answers1

0

The problem is that because of the nested for each iterations you attach the characteristic_changed_event to multiple characteristics. That leads to unwanted behaviour.

The best way is to select the service that contains the wanted characteristic by UUID, then select the characteristic by UUID from that service.

If you insist on filtering by the wanted descriptor attribute handle, finish all the "for each-es" before attaching the characteristic_changed_event.

The characteristic to attach to is probably first in _characteristics list.

GrooverFromHolland
  • 971
  • 1
  • 11
  • 18
  • Huh? The same handler can be attached to as many different characteristic object ValueChanged events as you want. This is why the first parameter is a GattCharacteristic and not nothing. – Dan Feb 22 '18 at 20:17
  • Yes you can butt...If you keep attaching event handlers then it will be raised for each instance, so your event-handler is called multiple times for one event. – GrooverFromHolland Feb 22 '18 at 20:40
  • Right, this code was for question purposes only, and what you said would make sense if I was getting duplicate events. But in my case I stopped getting them entirely. – Dan Feb 22 '18 at 21:14