Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: Connect -> ConnectionLost -> Reconnect #849

Merged

Conversation

AskBojesen
Copy link
Contributor

@AskBojesen AskBojesen commented May 8, 2024

To fix: #826

demolog.txt

@AskBojesen AskBojesen marked this pull request as draft May 8, 2024 15:14
@AskBojesen AskBojesen changed the title Windows: Improve demo for Connect_ConnectionLost_Reconnect Windows: Connect_ConnectionLost_Reconnect May 8, 2024
@AskBojesen AskBojesen changed the title Windows: Connect_ConnectionLost_Reconnect Windows: Connect -> ConnectionLost -> Reconnect May 8, 2024
@AskBojesen AskBojesen marked this pull request as ready for review May 8, 2024 16:15
@janusw
Copy link
Member

janusw commented May 10, 2024

To fix: #826

@CodeMusher Does this fix the problem for you?

@CodeMusher
Copy link

@janusw I’ll try to check that tomorrow!

@CodeMusher
Copy link

@janusw @AskBojesen
Now I've tried to test the solution and it works much better now.

For some reason the line below in the Adapter.cs for Windows throws System.InvalidCastException
var conpar = nativeDevice.GetConnectionParameters();
It gives me the following StackTrace
at WinRT.IObjectReference.As[T](Guid iid)
at Windows.Devices.Bluetooth.BluetoothLEDevice.Make___objRef_global__Windows_Devices_Bluetooth_IBluetoothLEDevice6()
at Windows.Devices.Bluetooth.BluetoothLEDevice.get__objRef_global__Windows_Devices_Bluetooth_IBluetoothLEDevice6()
at Windows.Devices.Bluetooth.BluetoothLEDevice.GetConnectionParameters()
at Plugin.BLE.Windows.Adapter.Device_ConnectionStatusChanged(BluetoothLEDevice nativeDevice, Object args) in C:\git\GitHub\dotnet-bluetooth-le\Source\Plugin.BLE\Windows\Adapter.cs:line 139
at WinRT.EventSource_global__Windows_Foundation_TypedEventHandler_global__Windows_Devices_Bluetooth_BluetoothLEDevice__object.EventState.b__1_0(BluetoothLEDevice sender, Object args)
at ABI.Windows.Foundation.TypedEventHandler`2.Do_Abi_Invoke[TSenderAbi,TResultAbi](Void* thisPtr, TSenderAbi sender, TResultAbi args)
I needed to catch that exception to be able to continue. Strange, I don't think that thing isn't changed recently

@axa88
Copy link

axa88 commented May 11, 2024

I dont use the console demo or any other abstraction over the base library so perhaps my feedback isnt useful here, but...

Ive tested this pull and the problem i see with it is after the first Connect/Disconnect cycle, a subscription to either the Adapter.DeviceConnected and Adapater.DeviceDisconnected events will be lost.
Meaning while subsequent calls to Connect will connect, and subsequent calls to Disconnect will disconnect, subscription to their associated events are no longer called subsequently.

What can i say, it works now... i think VS has a bug in applying these nugets with similar version numbers... but what do i know...

@CodeMusher
Copy link

@axa88 I’ve not tested in the real application either, but if it is like you are describing it regarding the events then it’s not good.

@CodeMusher
Copy link

Now I've tried the PR a step up in the abstraction chain, that is my test application. It seems like I get both Adapter.DeviceConnected and Adapter.DeviceConnectionLost when I power cycle my peripheral. In my setup it seems to work!

@AskBojesen
Copy link
Contributor Author

AskBojesen commented May 13, 2024

@janusw @AskBojesen Now I've tried to test the solution and it works much better now.

For some reason the line below in the Adapter.cs for Windows throws System.InvalidCastException var conpar = nativeDevice.GetConnectionParameters(); It gives me the following StackTrace at WinRT.IObjectReference.As[T](Guid iid) at Windows.Devices.Bluetooth.BluetoothLEDevice.Make___objRef_global__Windows_Devices_Bluetooth_IBluetoothLEDevice6() at Windows.Devices.Bluetooth.BluetoothLEDevice.get__objRef_global__Windows_Devices_Bluetooth_IBluetoothLEDevice6() at Windows.Devices.Bluetooth.BluetoothLEDevice.GetConnectionParameters() at Plugin.BLE.Windows.Adapter.Device_ConnectionStatusChanged(BluetoothLEDevice nativeDevice, Object args) in C:\git\GitHub\dotnet-bluetooth-le\Source\Plugin.BLE\Windows\Adapter.cs:line 139 at WinRT.EventSource_global__Windows_Foundation_TypedEventHandler_global__Windows_Devices_Bluetooth_BluetoothLEDevice__object.EventState.b__1_0(BluetoothLEDevice sender, Object args) at ABI.Windows.Foundation.TypedEventHandler`2.Do_Abi_Invoke[TSenderAbi,TResultAbi](Void* thisPtr, TSenderAbi sender, TResultAbi args) I needed to catch that exception to be able to continue. Strange, I don't think that thing isn't changed recently

The code has been in there for a while - but it is new to 3.1 vs 3.0.

It is bad if an exception is thrown for the GetConnectionParameters(), because then the HandleConnectedDevice(connectedDevice) is not called (see below image)
@CodeMusher : Is it everytime you get this exception?
We could make a try'n'catch in the code when calling GetConnectionParameters, so the logic is still working

image

@janusw
Copy link
Member

janusw commented May 13, 2024

For some reason the line below in the Adapter.cs for Windows throws System.InvalidCastException
var conpar = nativeDevice.GetConnectionParameters();

Huh, that line as such looks rather innocent, and I don't really see why it would generate an InvalidCastException.

However BluetoothLEDevice.GetConnectionParameters is only available in Windows 11 (build 10.0.22000.0) and is guarded by a corresponding compile-time check. But I suspect we're missing a proper runtime API version check.

@CodeMusher Two questions:

  1. Which Windows version are you targeting in your application?
  2. Which Windows version are you actually running it on?

@CodeMusher
Copy link

@janusw You're right that it must be the runtime that messes it up

  1. Which Windows version are you targeting in your application?
    I target net8.0-windows10.0.22621.0 as that is what the WinConsole sample is using

  2. Which Windows version are you actually running it on?
    My laptop only runs 10.0.19045 so that must be what causing the problem.

@CodeMusher
Copy link

The tests I performed yesterday were power cycling the peripheral. These tests gave me
Adapter.DeviceConnected
Adapter.DeviceConnectionLost.

Today I tried to initiate disconnect from the app instead. I thought that would invoke a Adapter.DeviceDisconnected.
But it always invokes Adapter.DeviceConnectionLost.
Is that really what I should expect?

@AskBojesen
Copy link
Contributor Author

AskBojesen commented May 13, 2024

@janusw You're right that it must be the runtime that messes it up

  1. Which Windows version are you targeting in your application?
    I target net8.0-windows10.0.22621.0 as that is what the WinConsole sample is using
  2. Which Windows version are you actually running it on?
    My laptop only runs 10.0.19045 so that must be what causing the problem.

you need runtime check if running on Windows 10, or you must use another target than 10.0.22621
Unfortunately Windows has no check for runtime - you simply get exceptions has you saw!

I have made a runtime check as custom action for the installer for our desktop app to avoid running on eg. 10.0.19045

public static int CurrentBuild()
{
    var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
    var currentBuildStr = (string)reg.GetValue("CurrentBuild");
    var currentBuild = int.Parse(currentBuildStr);
    return currentBuild;
}

public override void Install(IDictionary stateSaver)
{
    // Environment.OSVersion.Version.Build does not work on .Net framework
    //int currentBuild = Environment.OSVersion.Version.Build;
    int currentBuild = CurrentBuild();
    LogText($"CurrentBuild = {currentBuild}");
    if (currentBuild < 22000)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("ILab can only run on Windows 11 and higher")
                  .AppendLine()
                  .AppendLine($"CurrentBuild is {currentBuild}, which must be higher or equal to 22000");
        throw new NotSupportedException(sb.ToString());
    }
    base.Install(stateSaver);
}

@AskBojesen
Copy link
Contributor Author

AskBojesen commented May 13, 2024

@CodeMusher : I get Adapter.DeviceDisconnected when testing with the winconsole client...

You Write: Disconnecting from app - which app on which platform?

See the first lines in the attached demolog.txt

Running: Connect -> Disconnect

18.10.11.085       DEMO - Disconnecting
18.10.11.085 Plugin.BLE - DisconnectDeviceNative from device with ID:  8C4B14C9C43A
18.10.14.191 Plugin.BLE - Device_ConnectionStatusChanged 8C4B14C9C43A Egoo RD123456 Disconnected
18.10.14.191 Plugin.BLE - DisconnectedPeripheral by user: Egoo RD123456
18.10.14.191       DEMO - Adapter_DeviceDisconnected 8C4B14C9C43A with name: Egoo RD123456
18.10.14.191 Plugin.BLE - DisconnectAsync Disconnected: 00000000-0000-0000-0000-8c4b14c9c43a Egoo RD123456
18.10.14.191       DEMO - Test_Connect_Disconnect done

@CodeMusher
Copy link

@AskBojesen > you need runtime check if running on Windows 10, or you must use another target than 10.0.22621 Unfortunately Windows has no check for runtime - you simply get exceptions has you saw!

I have made a runtime check as custom action for the installer for our desktop app to avoid running on eg. 10.0.19045

Ok, I'll keep that in mind, missed that one.

@janusw
Copy link
Member

janusw commented May 13, 2024

@janusw You're right that it must be the runtime that messes it up

  1. Which Windows version are you targeting in your application?
    I target net8.0-windows10.0.22621.0 as that is what the WinConsole sample is using
  2. Which Windows version are you actually running it on?
    My laptop only runs 10.0.19045 so that must be what causing the problem.

Thanks for the info. This indeed confirms my suspicion.

you need runtime check if running on Windows 10, or you must use another target than 10.0.22621 Unfortunately Windows has no check for runtime - you simply get exceptions has you saw!

Well, I think the library should better guard the version-dependent code by a runtime check and only execute it if it's supported (see https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/version-adaptive-apps).

For BluetoothLEDevice.GetConnection one needs to check for UniversalApiContract v14 AFAICS.

@CodeMusher
Copy link

@AskBojesen > Disconnecting from app - which app on which platform?

It is my test app running on top of your library on Windows. I've checked the old code and it seems like it does something else than how it is done in the WinConsole.
So I believe the issue is on my side this time.

@AskBojesen
Copy link
Contributor Author

@janusw You're right that it must be the runtime that messes it up

  1. Which Windows version are you targeting in your application?
    I target net8.0-windows10.0.22621.0 as that is what the WinConsole sample is using
  2. Which Windows version are you actually running it on?
    My laptop only runs 10.0.19045 so that must be what causing the problem.

Thanks for the info. This indeed confirms my suspicion.

you need runtime check if running on Windows 10, or you must use another target than 10.0.22621 Unfortunately Windows has no check for runtime - you simply get exceptions has you saw!

Well, I think the library should better guard the version-dependent code by a runtime check and only execute it if it's supported (see https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/version-adaptive-apps).

For BluetoothLEDevice.GetConnection one needs to check for UniversalApiContract v14 AFAICS.

I agree - that it is dangerous as it is now - I got a nasty surprise myself trying to run the desktop app on Windows 10.
But @janusw : Can we keep focus on this PR for the original connection lost issue - and create another PR for Windows Runtime awareness ?

@AskBojesen
Copy link
Contributor Author

@CodeMusher , @axa88 : Can you please confirm, that the original issue for this PR is solved?

Original issue: not connection lost of lost without client request

@AskBojesen
Copy link
Contributor Author

AskBojesen commented May 14, 2024

Note: open issues not fixed in this PR:

When this PR is approved and merged, then I will look into the three issues above.

@axa88
Copy link

axa88 commented May 14, 2024

@CodeMusher , @axa88 : Can you please confirm, that the original issue for this PR is solved?

Original issue: not connection lost of lost without client request

@AskBojesen
Im unable to confirm anything regarding this issue. With this build it doesn't take much more than 2 connect/disconnect cycles before my device is left in an unusable state which will no longer connect/disconnect as reported elsewhere.

I can report the first connect/disconnect/lost cycle does appear to work, just not anything further.

@CodeMusher
Copy link

CodeMusher commented May 15, 2024 via email

Copy link
Member

@janusw janusw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe my initial issue is solved by this.

Alright, then let's merge it. The modification of the library itself is rather simple, after all, and ok with me.

@janusw janusw merged commit c894e46 into dotnet-bluetooth-le:master May 15, 2024
3 checks passed
@AskBojesen AskBojesen deleted the demo_connection_lost_reconnect branch May 16, 2024 07:09
@axa88
Copy link

axa88 commented May 17, 2024

Note: open issues not fixed in this PR:

* [Windows: Check OS version runtime #852](https://github.com/dotnet-bluetooth-le/dotnet-bluetooth-le/issues/852)

* [WinUI Call to `DisconnectDeviceAsync` may not complete. #850](https://github.com/dotnet-bluetooth-le/dotnet-bluetooth-le/issues/850)

* [Disconnect hangs sometimes on Windows #788](https://github.com/dotnet-bluetooth-le/dotnet-bluetooth-le/issues/788)

When this PR is approved and merged, then I will look into the three issues above.

Perhaps consider closing #717 as well, arguably qualifies to be closed already but surely after you address the above...
you might take a look at #619 as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Windows: More than one lost connection does not work correctly
4 participants