diff --git a/BrickController2/BrickController2.Tests/UI/Images/DeviceImagesResourceTests.cs b/BrickController2/BrickController2.Tests/UI/Images/DeviceImagesResourceTests.cs index 5c4044f1e..1d691a228 100644 --- a/BrickController2/BrickController2.Tests/UI/Images/DeviceImagesResourceTests.cs +++ b/BrickController2/BrickController2.Tests/UI/Images/DeviceImagesResourceTests.cs @@ -76,6 +76,7 @@ private static DeviceImageRegistry CreateRegistry() var registry = new DeviceImageRegistry(); registry.Register(DeviceType.BuWizz2, "buwizz_image.png", "buwizz_image_small.png"); registry.Register(DeviceType.RemoteControl, "remotecontrol_image_small.png", "remotecontrol_image_small.png"); + registry.Register(DeviceType.Infrared, "powerfunctions_image.png", "powerfunctions_image_small.png"); return registry; } } diff --git a/BrickController2/BrickController2/DeviceManagement/BluetoothAdvertisingDevice.cs b/BrickController2/BrickController2/DeviceManagement/BluetoothAdvertisingDevice.cs index 2620908b3..1e192bb35 100644 --- a/BrickController2/BrickController2/DeviceManagement/BluetoothAdvertisingDevice.cs +++ b/BrickController2/BrickController2/DeviceManagement/BluetoothAdvertisingDevice.cs @@ -9,7 +9,7 @@ namespace BrickController2.DeviceManagement /// /// Baseclass of Bluetooth LE Advertising devices /// - internal abstract class BluetoothAdvertisingDevice : Device + internal abstract class BluetoothAdvertisingDevice : Device, IBluetoothDevice { /// /// BluetoothAdvertisingDeviceHandler diff --git a/BrickController2/BrickController2/DeviceManagement/BluetoothDevice.cs b/BrickController2/BrickController2/DeviceManagement/BluetoothDevice.cs index 2b1e3d8fc..f25c4c35c 100644 --- a/BrickController2/BrickController2/DeviceManagement/BluetoothDevice.cs +++ b/BrickController2/BrickController2/DeviceManagement/BluetoothDevice.cs @@ -6,7 +6,7 @@ namespace BrickController2.DeviceManagement { - internal abstract class BluetoothDevice : Device + internal abstract class BluetoothDevice : Device, IBluetoothDevice { protected readonly IBluetoothLEService _bleService; diff --git a/BrickController2/BrickController2/DeviceManagement/DI/DeviceManagementModule.cs b/BrickController2/BrickController2/DeviceManagement/DI/DeviceManagementModule.cs index f9e9d3741..24c17c5c5 100644 --- a/BrickController2/BrickController2/DeviceManagement/DI/DeviceManagementModule.cs +++ b/BrickController2/BrickController2/DeviceManagement/DI/DeviceManagementModule.cs @@ -11,13 +11,11 @@ public class DeviceManagementModule : Module protected override void Load(ContainerBuilder builder) { builder.RegisterType().As().SingleInstance(); - builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); builder.RegisterType().As().SingleInstance(); - builder.RegisterType().Keyed(DeviceType.Infrared); builder.RegisterType().Keyed(DeviceType.CircuitCubes); builder.RegisterType().Keyed(DeviceType.PfxBrick); diff --git a/BrickController2/BrickController2/DeviceManagement/DeviceFactoryData.cs b/BrickController2/BrickController2/DeviceManagement/DeviceFactoryData.cs index cd94e88f2..72183f18b 100644 --- a/BrickController2/BrickController2/DeviceManagement/DeviceFactoryData.cs +++ b/BrickController2/BrickController2/DeviceManagement/DeviceFactoryData.cs @@ -19,6 +19,7 @@ public DeviceFactoryData(TVendor vendor, string name, string address, byte[] dev public DeviceType DeviceType => TDevice.Type; + public bool IsAvailable => Vendor.IsAvailable; public TVendor Vendor { get; } public string Name { get; } public string Address { get; } diff --git a/BrickController2/BrickController2/DeviceManagement/DeviceManager.cs b/BrickController2/BrickController2/DeviceManagement/DeviceManager.cs index e542dccb8..406cb30b4 100644 --- a/BrickController2/BrickController2/DeviceManagement/DeviceManager.cs +++ b/BrickController2/BrickController2/DeviceManagement/DeviceManager.cs @@ -12,7 +12,6 @@ namespace BrickController2.DeviceManagement internal class DeviceManager : NotifyPropertyChangedSource, IDeviceManager { private readonly IBluetoothDeviceManager _bluetoothDeviceManager; - private readonly IInfraredDeviceManager _infraredDeviceManager; private readonly IDeviceRepository _deviceRepository; private readonly DeviceFactory _deviceFactory; private readonly IMainThreadService _uiThreadService; @@ -25,14 +24,12 @@ internal class DeviceManager : NotifyPropertyChangedSource, IDeviceManager public DeviceManager( IBluetoothDeviceManager bluetoothDeviceManager, - IInfraredDeviceManager infraredDeviceManager, IDeviceRepository deviceRepository, DeviceFactory deviceFactory, IMainThreadService uiThreadService, ILogger logger) { _bluetoothDeviceManager = bluetoothDeviceManager; - _infraredDeviceManager = infraredDeviceManager; _deviceRepository = deviceRepository; _deviceFactory = deviceFactory; _uiThreadService = uiThreadService; @@ -88,12 +85,7 @@ public async Task ScanAsync(CancellationToken token) try { - var infraScan = _infraredDeviceManager.ScanAsync(CreateDeviceAsync!, token); - var bluetoothScan = _bluetoothDeviceManager.ScanAsync(CreateDeviceAsync!, token); - - await Task.WhenAll(infraScan, bluetoothScan); - - return infraScan.Result && bluetoothScan.Result; + return await _bluetoothDeviceManager.ScanAsync(CreateDeviceAsync!, token); } catch (Exception) { diff --git a/BrickController2/BrickController2/DeviceManagement/IBluetoothDevice.cs b/BrickController2/BrickController2/DeviceManagement/IBluetoothDevice.cs new file mode 100644 index 000000000..9e2ccbba6 --- /dev/null +++ b/BrickController2/BrickController2/DeviceManagement/IBluetoothDevice.cs @@ -0,0 +1,6 @@ +namespace BrickController2.DeviceManagement +{ + internal interface IBluetoothDevice + { + } +} diff --git a/BrickController2/BrickController2/DeviceManagement/IDeviceFactoryData.cs b/BrickController2/BrickController2/DeviceManagement/IDeviceFactoryData.cs index 5af67008b..4441d3d4d 100644 --- a/BrickController2/BrickController2/DeviceManagement/IDeviceFactoryData.cs +++ b/BrickController2/BrickController2/DeviceManagement/IDeviceFactoryData.cs @@ -5,6 +5,7 @@ namespace BrickController2.DeviceManagement { public interface IDeviceFactoryData { + bool IsAvailable { get; } DeviceType DeviceType { get; } string Name { get; } string Address { get; } diff --git a/BrickController2/BrickController2/DeviceManagement/IInfraredDeviceManager.cs b/BrickController2/BrickController2/DeviceManagement/IInfraredDeviceManager.cs deleted file mode 100644 index 9602ba020..000000000 --- a/BrickController2/BrickController2/DeviceManagement/IInfraredDeviceManager.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Threading.Tasks; - -namespace BrickController2.DeviceManagement -{ - internal interface IInfraredDeviceManager : IDeviceScanner - { - Task ConnectDevice(InfraredDevice device); - Task DisconnectDevice(InfraredDevice device); - - void SetOutput(InfraredDevice device, int channel, int value); - } -} diff --git a/BrickController2/BrickController2/DeviceManagement/PowerFunctions/IPowerFunctionsManager.cs b/BrickController2/BrickController2/DeviceManagement/PowerFunctions/IPowerFunctionsManager.cs new file mode 100644 index 000000000..baaabe278 --- /dev/null +++ b/BrickController2/BrickController2/DeviceManagement/PowerFunctions/IPowerFunctionsManager.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; + +namespace BrickController2.DeviceManagement.PowerFunctions +{ + internal interface IPowerFunctionsManager + { + Task ConnectDevice(PowerFunctionsDevice device); + Task DisconnectDevice(PowerFunctionsDevice device); + + void SetOutput(PowerFunctionsDevice device, int channel, int value); + } +} diff --git a/BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctions.cs b/BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctions.cs new file mode 100644 index 000000000..07a4e511b --- /dev/null +++ b/BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctions.cs @@ -0,0 +1,37 @@ +using Autofac; +using BrickController2.DeviceManagement.DI; +using BrickController2.DeviceManagement.Vendors; +using BrickController2.PlatformServices.Infrared; + +namespace BrickController2.DeviceManagement.PowerFunctions; + +/// +/// Vendor for Power Functions devices +/// +internal class PowerFunctions : Vendor +{ + private IInfraredService? _infraredService; + + public override string VendorName => "LEGO"; + + public override bool IsAvailable => _infraredService != null && _infraredService.IsInfraredSupported && _infraredService.IsCarrierFrequencySupported(PowerFunctionsManager.IR_FREQUENCY); + + protected override void Register(VendorBuilder builder) + { + // device manager + builder.ContainerBuilder.RegisterType().As().SingleInstance(); + + builder.ContainerBuilder.RegisterBuildCallback(scope => + { + _infraredService = scope.Resolve(); + }); + + // manually added devices + builder.RegisterDevice() + .WithImages("powerfunctions_image.png", "powerfunctions_image_small.png") + .WithDeviceFactory("0", "PF Infra 1") + .WithDeviceFactory("1", "PF Infra 2") + .WithDeviceFactory("2", "PF Infra 3") + .WithDeviceFactory("3", "PF Infra 4"); + } +} diff --git a/BrickController2/BrickController2/DeviceManagement/InfraredDevice.cs b/BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctionsDevice.cs similarity index 60% rename from BrickController2/BrickController2/DeviceManagement/InfraredDevice.cs rename to BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctionsDevice.cs index 03ecd0f1f..a54452922 100644 --- a/BrickController2/BrickController2/DeviceManagement/InfraredDevice.cs +++ b/BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctionsDevice.cs @@ -3,19 +3,22 @@ using System.Threading; using System.Threading.Tasks; -namespace BrickController2.DeviceManagement +namespace BrickController2.DeviceManagement.PowerFunctions { - internal class InfraredDevice : Device + internal class PowerFunctionsDevice : Device, IDeviceType { - private readonly IInfraredDeviceManager _infraredDeviceManager; + private readonly IPowerFunctionsManager _powerFunctionsManager; - public InfraredDevice(string name, string address, byte[] deviceData, IInfraredDeviceManager infraredDeviceManager, IDeviceRepository deviceRepository) + public PowerFunctionsDevice(string name, string address, byte[] deviceData, IPowerFunctionsManager powerFunctionsManager, IDeviceRepository deviceRepository) : base(name, address, deviceRepository) { - _infraredDeviceManager = infraredDeviceManager; + _powerFunctionsManager = powerFunctionsManager; } - public override DeviceType DeviceType => DeviceType.Infrared; + public static DeviceType Type => DeviceType.Infrared; + + public static string TypeName => "Power Functions"; + public override DeviceType DeviceType => Type; public override int NumberOfChannels => 2; public override async Task ConnectAsync( @@ -28,7 +31,7 @@ public override async Task ConnectAsync( { DeviceState = DeviceState.Connecting; - var result = await _infraredDeviceManager.ConnectDevice(this); + var result = await _powerFunctionsManager.ConnectDevice(this); DeviceState = result == DeviceConnectionResult.Ok ? DeviceState.Connected : DeviceState.Disconnected; return result; @@ -38,7 +41,7 @@ public override async Task DisconnectAsync() { DeviceState = DeviceState.Disconnecting; - await _infraredDeviceManager.DisconnectDevice(this); + await _powerFunctionsManager.DisconnectDevice(this); DeviceState = DeviceState.Disconnected; } @@ -49,7 +52,7 @@ public override void SetOutput(int channel, float value) value = CutOutputValue(value); var intValue = (int)(7 * value); - _infraredDeviceManager.SetOutput(this, channel, intValue); + _powerFunctionsManager.SetOutput(this, channel, intValue); } } } diff --git a/BrickController2/BrickController2/DeviceManagement/InfraredDeviceManager.cs b/BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctionsManager.cs similarity index 85% rename from BrickController2/BrickController2/DeviceManagement/InfraredDeviceManager.cs rename to BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctionsManager.cs index 2b2cd24eb..22a07696d 100644 --- a/BrickController2/BrickController2/DeviceManagement/InfraredDeviceManager.cs +++ b/BrickController2/BrickController2/DeviceManagement/PowerFunctions/PowerFunctionsManager.cs @@ -4,11 +4,11 @@ using BrickController2.PlatformServices.Infrared; using BrickController2.Helpers; -namespace BrickController2.DeviceManagement +namespace BrickController2.DeviceManagement.PowerFunctions { - internal class InfraredDeviceManager : IInfraredDeviceManager + internal class PowerFunctionsManager : IPowerFunctionsManager { - private const int IR_FREQUENCY = 38000; + public const int IR_FREQUENCY = 38000; private const int IR_MARK_US = 158; private const int IR_START_GAP_US = 1026; @@ -29,33 +29,12 @@ internal class InfraredDeviceManager : IInfraredDeviceManager private Task? _irTask; private CancellationTokenSource? _irTaskCancelationTokenSource; - public InfraredDeviceManager(IInfraredService infraredService) + public PowerFunctionsManager(IInfraredService infraredService) { _infraredService = infraredService; } - public async Task ScanAsync(Func deviceFoundCallback, CancellationToken token) - { - using (await _asyncLock.LockAsync()) - { - if (_infraredService.IsInfraredSupported && _infraredService.IsCarrierFrequencySupported(IR_FREQUENCY)) - { - for (int i = 0; i < 4; i++) - { - if (token.IsCancellationRequested) - { - break; - } - - await deviceFoundCallback(DeviceType.Infrared, $"PF Infra {i + 1}", $"{i}", null); - } - } - } - - return true; - } - - public async Task ConnectDevice(InfraredDevice device) + public async Task ConnectDevice(PowerFunctionsDevice device) { using (await _asyncLock.LockAsync()) { @@ -74,7 +53,7 @@ public async Task ConnectDevice(InfraredDevice device) } } - public async Task DisconnectDevice(InfraredDevice device) + public async Task DisconnectDevice(PowerFunctionsDevice device) { using (await _asyncLock.LockAsync()) { @@ -91,7 +70,7 @@ public async Task DisconnectDevice(InfraredDevice device) } } - public void SetOutput(InfraredDevice device, int channel, int value) + public void SetOutput(PowerFunctionsDevice device, int channel, int value) { if (int.TryParse(device.Address, out int address)) { diff --git a/BrickController2/BrickController2/DeviceManagement/Vendors/Vendor.cs b/BrickController2/BrickController2/DeviceManagement/Vendors/Vendor.cs index 76cd92c49..24fd0b357 100644 --- a/BrickController2/BrickController2/DeviceManagement/Vendors/Vendor.cs +++ b/BrickController2/BrickController2/DeviceManagement/Vendors/Vendor.cs @@ -12,6 +12,8 @@ public abstract class Vendor : Module, IVendorModule { public abstract string VendorName { get; } + public virtual bool IsAvailable => true; + protected abstract void Register(VendorBuilder builder); protected sealed override void Load(ContainerBuilder builder) diff --git a/BrickController2/BrickController2/UI/Controls/DeviceChannelSelector.xaml b/BrickController2/BrickController2/UI/Controls/DeviceChannelSelector.xaml index 530242b2b..dd974e99b 100644 --- a/BrickController2/BrickController2/UI/Controls/DeviceChannelSelector.xaml +++ b/BrickController2/BrickController2/UI/Controls/DeviceChannelSelector.xaml @@ -132,8 +132,8 @@ - - + + @@ -141,13 +141,13 @@ - + - + - + diff --git a/BrickController2/BrickController2/UI/Controls/DeviceChannelSelector.xaml.cs b/BrickController2/BrickController2/UI/Controls/DeviceChannelSelector.xaml.cs index 04a3fa1dd..5f1c68c2b 100644 --- a/BrickController2/BrickController2/UI/Controls/DeviceChannelSelector.xaml.cs +++ b/BrickController2/BrickController2/UI/Controls/DeviceChannelSelector.xaml.cs @@ -29,8 +29,8 @@ public DeviceChannelSelector() BuWizz3Channel3.Command = new SafeCommand(() => SelectedChannel = 3); BuWizz3Channel4.Command = new SafeCommand(() => SelectedChannel = 4); BuWizz3Channel5.Command = new SafeCommand(() => SelectedChannel = 5); - InfraredChannel0.Command = new SafeCommand(() => SelectedChannel = 0); - InfraredChannel1.Command = new SafeCommand(() => SelectedChannel = 1); + PowerFunctionsChannel0.Command = new SafeCommand(() => SelectedChannel = 0); + PowerFunctionsChannel1.Command = new SafeCommand(() => SelectedChannel = 1); PoweredUpChannel0.Command = new SafeCommand(() => SelectedChannel = 0); PoweredUpChannel1.Command = new SafeCommand(() => SelectedChannel = 1); BoostChannelA.Command = new SafeCommand(() => SelectedChannel = 0); @@ -173,7 +173,7 @@ private void OnDeviceChanged(Device device) SbrickLightSection.IsVisible = deviceType == DeviceType.SBrickLight; BuWizzSection.IsVisible = deviceType == DeviceType.BuWizz || deviceType == DeviceType.BuWizz2; BuWizz3Section.IsVisible = deviceType == DeviceType.BuWizz3; - InfraredSection.IsVisible = deviceType == DeviceType.Infrared; + PowerFunctionsSection.IsVisible = deviceType == DeviceType.Infrared; PoweredUpSection.IsVisible = deviceType == DeviceType.PoweredUp; BoostSection.IsVisible = deviceType == DeviceType.Boost; TechnicHubSection.IsVisible = deviceType == DeviceType.TechnicHub; @@ -222,8 +222,8 @@ private void OnSelectedChannelChanged(int selectedChannel) BuWizz3Channel3.SelectedChannel = selectedChannel; BuWizz3Channel4.SelectedChannel = selectedChannel; BuWizz3Channel5.SelectedChannel = selectedChannel; - InfraredChannel0.SelectedChannel = selectedChannel; - InfraredChannel1.SelectedChannel = selectedChannel; + PowerFunctionsChannel0.SelectedChannel = selectedChannel; + PowerFunctionsChannel1.SelectedChannel = selectedChannel; PoweredUpChannel0.SelectedChannel = selectedChannel; PoweredUpChannel1.SelectedChannel = selectedChannel; BoostChannelA.SelectedChannel = selectedChannel; diff --git a/BrickController2/BrickController2/UI/Images/infrared_image.png b/BrickController2/BrickController2/UI/Images/powerfunctions_image.png similarity index 100% rename from BrickController2/BrickController2/UI/Images/infrared_image.png rename to BrickController2/BrickController2/UI/Images/powerfunctions_image.png diff --git a/BrickController2/BrickController2/UI/Images/infrared_image_small.png b/BrickController2/BrickController2/UI/Images/powerfunctions_image_small.png similarity index 100% rename from BrickController2/BrickController2/UI/Images/infrared_image_small.png rename to BrickController2/BrickController2/UI/Images/powerfunctions_image_small.png diff --git a/BrickController2/BrickController2/UI/ViewModels/ChannelSetupPageViewModel.cs b/BrickController2/BrickController2/UI/ViewModels/ChannelSetupPageViewModel.cs index 4f1c08ddc..bff63327e 100644 --- a/BrickController2/BrickController2/UI/ViewModels/ChannelSetupPageViewModel.cs +++ b/BrickController2/BrickController2/UI/ViewModels/ChannelSetupPageViewModel.cs @@ -101,7 +101,7 @@ public override async void OnAppearing() _isDisappearing = false; base.OnAppearing(); - if (Device.DeviceType != DeviceType.Infrared) + if (Device is IBluetoothDevice) { if (!await _deviceManager.IsBluetoothOnAsync()) { diff --git a/BrickController2/BrickController2/UI/ViewModels/DevicePageViewModel.cs b/BrickController2/BrickController2/UI/ViewModels/DevicePageViewModel.cs index 710220d36..baa1c040b 100644 --- a/BrickController2/BrickController2/UI/ViewModels/DevicePageViewModel.cs +++ b/BrickController2/BrickController2/UI/ViewModels/DevicePageViewModel.cs @@ -88,7 +88,7 @@ public override async void OnAppearing() _isDisappearing = false; base.OnAppearing(); - if (Device.DeviceType != DeviceType.Infrared) + if (Device is IBluetoothDevice) { if (!await _deviceManager.IsBluetoothOnAsync()) { diff --git a/BrickController2/BrickController2/UI/ViewModels/ManualDeviceListPageViewModel.cs b/BrickController2/BrickController2/UI/ViewModels/ManualDeviceListPageViewModel.cs index ddf253ca1..627f0425c 100644 --- a/BrickController2/BrickController2/UI/ViewModels/ManualDeviceListPageViewModel.cs +++ b/BrickController2/BrickController2/UI/ViewModels/ManualDeviceListPageViewModel.cs @@ -56,6 +56,7 @@ public ManualDeviceListPageViewModel( var groups = manualDeviceManager.FactoryDataList // apply ordering per vendor and device type + .Where(o => o.IsAvailable) .OrderBy(o => o.VendorName) .ThenBy(o => o.DeviceTypeName) .GroupBy(o => (o.VendorName, o.DeviceType, o.DeviceTypeName), x => new DeviceEntry(x, GetDeviceInstance(x))); diff --git a/BrickController2/BrickController2/UI/ViewModels/PlayerPageViewModel.cs b/BrickController2/BrickController2/UI/ViewModels/PlayerPageViewModel.cs index aa671f200..6c0de58d0 100644 --- a/BrickController2/BrickController2/UI/ViewModels/PlayerPageViewModel.cs +++ b/BrickController2/BrickController2/UI/ViewModels/PlayerPageViewModel.cs @@ -101,7 +101,7 @@ public override async void OnAppearing() _isDisappearing = false; base.OnAppearing(); - if (_devices.Any(d => d.DeviceType != DeviceType.Infrared) && !await _deviceManager.IsBluetoothOnAsync()) + if (_devices.Any(d => d is IBluetoothDevice) && !await _deviceManager.IsBluetoothOnAsync()) { await _dialogService.ShowMessageBoxAsync( Translate("Warning"),