From ac3dde4cab29f9d63ef159325984433f7ed8dcc6 Mon Sep 17 00:00:00 2001 From: "T. Thiery" Date: Sun, 11 Feb 2024 21:52:21 +0100 Subject: [PATCH] Add Protocol Only Example (#202) - Add Protocol Only Example #199 non-breaking --- .vscode/launch.json | 11 ++++ README.md | 60 +++++++++---------- .../Program.cs | 51 ++++++++++++++++ ...Brick.PoweredUp.ExampplesOnProtocol.csproj | 27 +++++++++ powered-up.sln | 15 +++++ 5 files changed, 133 insertions(+), 31 deletions(-) create mode 100644 examples/SharpBrick.PoweredUp.ExampplesOnProtocol/Program.cs create mode 100644 examples/SharpBrick.PoweredUp.ExampplesOnProtocol/SharpBrick.PoweredUp.ExampplesOnProtocol.csproj diff --git a/.vscode/launch.json b/.vscode/launch.json index 1c15e68..1475e8c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,6 +18,17 @@ "console": "integratedTerminal", "stopAtEntry": false }, + { + "name": "example app - protocol", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/examples/SharpBrick.PoweredUp.ExampplesOnProtocol/bin/Debug/net8.0-windows10.0.19041.0/SharpBrick.PoweredUp.ExampplesOnProtocol.dll", + "args": [], + "cwd": "${workspaceFolder}/examples/SharpBrick.PoweredUp.ExampplesOnProtocol", + "console": "integratedTerminal", + "stopAtEntry": false + }, { "name": "poweredup device list", "type": "coreclr", diff --git a/README.md b/README.md index 8bb064d..98fd9ba 100644 --- a/README.md +++ b/README.md @@ -150,50 +150,48 @@ Console.WriteLine($"Or directly read the latest value: {aposMode.SI} / {aposMode ## Connect to Hub and Send a Message and retrieving answers (directly on protocol layer) -***Note**: The `ILegoWirelessProtocol` class was renamed in 3.0. Previously it is known as `IPoweredUpProtocol`.* - ````csharp - var serviceProvider = new ServiceCollection() .AddLogging() .AddPoweredUp() - .AddWinRTBluetooth() // using WinRT Bluetooth on Windows (separate NuGet SharpBrick.PoweredUp.WinRT) + .AddWinRTBluetooth() .BuildServiceProvider(); -using (var scope = serviceProvider.CreateScope()) // create a scoped DI container per intented active connection/protocol. If disposed, disposes all disposable artifacts. -{ - // init BT layer with right bluetooth address - scope.ServiceProvider.GetService().BluetoothAddress = bluetoothAddress; +// getting utilities +var bt = serviceProvider.GetService(); +var host = serviceProvider.GetService(); - var protocol = scope.GetService(); +// discover a LWP bluetooth device +var tcs = new TaskCompletionSource(); - await protocol.ConnectAsync(); // also connects underlying BT connection - - using disposable = protocol.UpstreamMessages.Subscribe(message => +bt.Discover(async deviceInfo => +{ + if (!tcs.Task.IsCompleted) { - if (message is HubPropertyMessage msg) - { - Console.WriteLine($"Hub Property - {msg.Property}: {msg.Payload}"); - } - }); + var p = host.CreateProtocol(deviceInfo); - await protocol.SendMessageAsync(new HubPropertyMessage() { - Property = HubProperty.AdvertisingName, - Operation = HubPropertyOperation.RequestUpdate - }); + tcs.SetResult(p); + } +}); - Console.Readline(); // allow the messages to be processed and displayed. (alternative: SendMessageReceiveResultAsync, SendPortOutputCommandAsync, ..) +var protocol = await tcs.Task; - // fun with light on hub 0 and built-in LED on port 50 - var rgbLight = new RgbLight(protocol, 0, 50); - await rgbLight.SetRgbColorsAsync(0x00, 0xff, 0x00); +// connect the protocol +await protocol.ConnectAsync(); - // fun with motor on hub 0 and port 0 - var motor = new TechnicXLargeLinearMotor(protocol, 0, 0); - await motor.GotoPositionAsync(45, 10, 100, PortOutputCommandSpecialSpeed.Brake); - await Task.Delay(2000); - await motor.GotoPositionAsync(-45, 10, 100, PortOutputCommandSpecialSpeed.Brake); -} +// send a raw message which should work with ANY motor connected to a hub +var response = await protocol.SendPortOutputCommandAsync(new PortOutputCommandStartPowerMessage( + 0, // PORT A + PortOutputCommandStartupInformation.ExecuteImmediately, PortOutputCommandCompletionInformation.CommandFeedback, + 100 +) +{ + HubId = 0, // as if we ever see another one +}); + +await Task.Delay(2000); + +await protocol.DisconnectAsync(); ```` ## Connecting with other Bluetooth Adapters diff --git a/examples/SharpBrick.PoweredUp.ExampplesOnProtocol/Program.cs b/examples/SharpBrick.PoweredUp.ExampplesOnProtocol/Program.cs new file mode 100644 index 0000000..d932a5b --- /dev/null +++ b/examples/SharpBrick.PoweredUp.ExampplesOnProtocol/Program.cs @@ -0,0 +1,51 @@ +using SharpBrick.PoweredUp; + +using Microsoft.Extensions.DependencyInjection; // SharpBrick.PoweredUp uses the DI system +using Microsoft.Extensions.Logging; +using SharpBrick.PoweredUp.Bluetooth; +using SharpBrick.PoweredUp.Protocol; +using SharpBrick.PoweredUp.Protocol.Messages; // SharpBrick.PoweredUp also logs stuff + +var serviceProvider = new ServiceCollection() + .AddLogging() + .AddPoweredUp() +#if WINDOWS + .AddWinRTBluetooth() // using WinRT Bluetooth on Windows (separate NuGet SharpBrick.PoweredUp.WinRT; others are available) +#endif + .BuildServiceProvider(); + +// getting utilities +var bt = serviceProvider.GetService(); +var host = serviceProvider.GetService(); + +// discover a LWP bluetooth device +var tcs = new TaskCompletionSource(); + +bt.Discover(async deviceInfo => +{ + if (!tcs.Task.IsCompleted) + { + var p = host.CreateProtocol(deviceInfo); + + tcs.SetResult(p); + } +}); + +var protocol = await tcs.Task; + +// connect the protocol +await protocol.ConnectAsync(); + +// send a raw message which should work with ANY motor connected to a hub +var response = await protocol.SendPortOutputCommandAsync(new PortOutputCommandStartPowerMessage( + 0, // PORT A + PortOutputCommandStartupInformation.ExecuteImmediately, PortOutputCommandCompletionInformation.CommandFeedback, + 100 +) +{ + HubId = 0, // as if we ever see another one +}); + +await Task.Delay(2000); + +await protocol.DisconnectAsync(); \ No newline at end of file diff --git a/examples/SharpBrick.PoweredUp.ExampplesOnProtocol/SharpBrick.PoweredUp.ExampplesOnProtocol.csproj b/examples/SharpBrick.PoweredUp.ExampplesOnProtocol/SharpBrick.PoweredUp.ExampplesOnProtocol.csproj new file mode 100644 index 0000000..b5012ec --- /dev/null +++ b/examples/SharpBrick.PoweredUp.ExampplesOnProtocol/SharpBrick.PoweredUp.ExampplesOnProtocol.csproj @@ -0,0 +1,27 @@ + + + + Exe + net8.0-windows10.0.19041.0;net8.0 + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + + diff --git a/powered-up.sln b/powered-up.sln index 5dd7711..a00256c 100644 --- a/powered-up.sln +++ b/powered-up.sln @@ -24,6 +24,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpBrick.PoweredUp.BlueGi EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpBrick.PoweredUp.TestScript", "test\SharpBrick.PoweredUp.TestScript\SharpBrick.PoweredUp.TestScript.csproj", "{2A100817-6E86-4E58-8183-0EA7F49C0848}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpBrick.PoweredUp.ExampplesOnProtocol", "examples\SharpBrick.PoweredUp.ExampplesOnProtocol\SharpBrick.PoweredUp.ExampplesOnProtocol.csproj", "{3B91CDE6-66AA-47F5-B65A-DC0D580F202B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -130,6 +132,18 @@ Global {2A100817-6E86-4E58-8183-0EA7F49C0848}.Release|x64.Build.0 = Release|Any CPU {2A100817-6E86-4E58-8183-0EA7F49C0848}.Release|x86.ActiveCfg = Release|Any CPU {2A100817-6E86-4E58-8183-0EA7F49C0848}.Release|x86.Build.0 = Release|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Debug|x64.ActiveCfg = Debug|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Debug|x64.Build.0 = Debug|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Debug|x86.ActiveCfg = Debug|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Debug|x86.Build.0 = Debug|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Release|Any CPU.Build.0 = Release|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Release|x64.ActiveCfg = Release|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Release|x64.Build.0 = Release|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Release|x86.ActiveCfg = Release|Any CPU + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -143,6 +157,7 @@ Global {F66A2B09-84B6-477D-9B15-926E771C7D80} = {62C31C3D-8ACF-4ED3-A3D8-225536F3AC6D} {E0DC0096-D7F1-4995-833D-9A6C0C3F8F98} = {62C31C3D-8ACF-4ED3-A3D8-225536F3AC6D} {2A100817-6E86-4E58-8183-0EA7F49C0848} = {39B30145-497F-4AEB-A014-BBF27DA0651A} + {3B91CDE6-66AA-47F5-B65A-DC0D580F202B} = {F4D84196-5E85-41FE-9C39-38BD8F78E84D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {34AA1641-ACED-43ED-A0DD-BA88E43A67A8}