Skip to content

Commit

Permalink
Add known SystemType to LegoWirelessProtocol (#99)
Browse files Browse the repository at this point in the history
- Known SystemType allows the protocol to react to HubAttachedIO w/
  the right static port data specified for a given device.
- Adjusted existing IPoweredUpDevice

#98 non-breaking (internal API, default values)
  • Loading branch information
tthiery authored Oct 5, 2020
1 parent d6a9987 commit 290a929
Show file tree
Hide file tree
Showing 18 changed files with 43 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/SharpBrick.PoweredUp/Devices/Current.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public Current(ILegoWirelessProtocol protocol, byte hubId, byte portId)
ObserveForPropertyChanged(_currentSMode.Observable, nameof(CurrentS), nameof(CurrentSPct));
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> @"
0B-00-43-3B-01-02-02-03-00-00-00
05-00-43-3B-02
Expand Down
2 changes: 1 addition & 1 deletion src/SharpBrick.PoweredUp/Devices/DynamicDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public async Task DiscoverAsync()
BuildModes();
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> Array.Empty<byte[]>();
}
}
2 changes: 1 addition & 1 deletion src/SharpBrick.PoweredUp/Devices/IPoweredUpDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ namespace SharpBrick.PoweredUp
public interface IPoweredUpDevice
{
bool IsConnected { get; }
IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion);
IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType);
}
}
2 changes: 1 addition & 1 deletion src/SharpBrick.PoweredUp/Devices/RgbLight.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ await _protocol.SendMessageAsync(new PortInputFormatSetupSingleMessage()
return response;
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> @"
0B-00-43-32-01-01-02-00-00-03-00
05-00-43-32-02
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public TechnicLargeLinearMotor(ILegoWirelessProtocol protocol, byte hubId, byte
: base(protocol, hubId, portId)
{ }

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> @"
0B-00-43-00-01-0F-06-1E-00-1F-00
07-00-43-00-02-0E-00
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public TechnicMediumHubAccelerometer(ILegoWirelessProtocol protocol, byte hubId,
ObserveForPropertyChanged(_gravityMode.Observable, nameof(Gravity));
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> @"
0B-00-43-61-01-02-02-03-00-00-00
05-00-43-61-02
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public TechnicMediumHubGestureSensor(ILegoWirelessProtocol protocol, byte hubId,
ObserveForPropertyChanged(_gestureMode.Observable, nameof(Gesture));
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> @"
0B-00-43-64-01-02-01-01-00-00-00
05-00-43-64-02
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public TechnicMediumHubGyroSensor(ILegoWirelessProtocol protocol, byte hubId, by
ObserveForPropertyChanged(_rotationMode.Observable, nameof(Rotation));
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> @"
0B-00-43-62-01-02-01-01-00-00-00
05-00-43-62-02
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public TechnicMediumHubTemperatureSensor(ILegoWirelessProtocol protocol, byte hu
ObserveForPropertyChanged(_temperatureMode.Observable, nameof(Temperature), nameof(TemperaturePct));
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> @"
0B-00-43-60-01-02-01-01-00-00-00
05-00-43-60-02
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public async Task<PortFeedback> TiltConfigOrientationAsync(TiltConfigOrientation
return response;
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> (softwareVersion.ToString(), hardwareVersion.ToString()) switch
{
("0.0.0.1", "0.0.0.1") =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public TechnicXLargeLinearMotor(ILegoWirelessProtocol protocol, byte hubId, byte
: base(protocol, hubId, portId)
{ }

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> @"
0B-00-43-02-01-0F-06-1E-00-1F-00
07-00-43-02-02-0E-00
Expand Down
10 changes: 7 additions & 3 deletions src/SharpBrick.PoweredUp/Devices/Voltage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ public Voltage(ILegoWirelessProtocol protocol, byte hubId, byte portId)
ObserveForPropertyChanged(_voltageSMode.Observable, nameof(VoltageS), nameof(VoltageSPct));
}

public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion)
=> @"
public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Version hardwareVersion, SystemType systemType)
=> ((softwareVersion, hardwareVersion, systemType) switch
{
(_, _, SystemType.LegoTechnic_MediumHub) => @"
0B-00-43-3C-01-02-02-03-00-00-00
05-00-43-3C-02
11-00-44-3C-00-00-56-4C-54-20-4C-00-00-00-00-00-00
Expand All @@ -52,6 +54,8 @@ public IEnumerable<byte[]> GetStaticPortInfoMessages(Version softwareVersion, Ve
0A-00-44-3C-01-04-6D-56-00-00
08-00-44-3C-01-05-10-00
0A-00-44-3C-01-80-01-01-04-00
".Trim().Split("\n").Select(s => BytesStringUtil.StringToData(s));
",
_ => throw new NotImplementedException(),
}).Trim().Split("\n").Select(s => BytesStringUtil.StringToData(s));
}
}
6 changes: 4 additions & 2 deletions src/SharpBrick.PoweredUp/Hubs/Hub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@ public abstract partial class Hub : IDisposable
private CompositeDisposable _compositeDisposable = new CompositeDisposable();
private readonly ILogger _logger;
private readonly IDeviceFactory _deviceFactory;
private readonly SystemType _knownSystemType;

public ILegoWirelessProtocol Protocol { get; private set; }
public byte HubId { get; private set; }
public IServiceProvider ServiceProvider { get; }
public bool IsConnected => Protocol != null;

public Hub(ILegoWirelessProtocol protocol, IDeviceFactory deviceFactory, ILogger<Hub> logger, IServiceProvider serviceProvider, Port[] knownPorts)
public Hub(ILegoWirelessProtocol protocol, IDeviceFactory deviceFactory, ILogger<Hub> logger, IServiceProvider serviceProvider, SystemType knownSystemType, Port[] knownPorts)
{
Protocol = protocol ?? throw new ArgumentNullException(nameof(protocol));
_deviceFactory = deviceFactory ?? throw new ArgumentNullException(nameof(deviceFactory));
ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
_knownSystemType = knownSystemType;
AddKnownPorts(knownPorts ?? throw new ArgumentNullException(nameof(knownPorts)));
_logger = logger;

Expand Down Expand Up @@ -59,7 +61,7 @@ public async Task ConnectAsync()
var expectedDevicesCompletedTask = ExpectedDevicesCompletedAsync();

_logger?.LogDebug("Connecting BluetoothKernel");
await Protocol.ConnectAsync();
await Protocol.ConnectAsync(_knownSystemType);

await expectedDevicesCompletedTask;
_logger?.LogDebug("Hub Attached IO expected devices completed");
Expand Down
2 changes: 1 addition & 1 deletion src/SharpBrick.PoweredUp/Hubs/TechnicMediumHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace SharpBrick.PoweredUp
public class TechnicMediumHub : Hub
{
public TechnicMediumHub(ILegoWirelessProtocol protocol, IDeviceFactory deviceFactory, ILogger<TechnicMediumHub> logger, IServiceProvider serviceProvider = default)
: base(protocol, deviceFactory, logger, serviceProvider, new Port[] {
: base(protocol, deviceFactory, logger, serviceProvider, SystemType.LegoTechnic_MediumHub, new Port[] {
new Port(0, nameof(A), true),
new Port(1, nameof(B), true),
new Port(2, nameof(C), true),
Expand Down
2 changes: 1 addition & 1 deletion src/SharpBrick.PoweredUp/Protocol/ILegoWirelessProtocol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace SharpBrick.PoweredUp.Protocol
{
public interface ILegoWirelessProtocol : IDisposable
{
Task ConnectAsync();
Task ConnectAsync(SystemType initialSystemType = default);
Task DisconnectAsync();

Task SendMessageAsync(LegoWirelessMessage message);
Expand Down
10 changes: 6 additions & 4 deletions src/SharpBrick.PoweredUp/Protocol/Knowledge/KnowledgeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public static Task ApplyDynamicProtocolKnowledge(LegoWirelessMessage message, Pr
hub.SystemType = msg.Payload;
break;
case HubAttachedIOForAttachedDeviceMessage msg:
hub = knowledge.Hub(msg.HubId);
port = knowledge.Port(msg.HubId, msg.PortId);

ResetProtocolKnowledgeForPort(msg.HubId, port.PortId, knowledge);
Expand All @@ -125,7 +126,7 @@ public static Task ApplyDynamicProtocolKnowledge(LegoWirelessMessage message, Pr
port.HardwareRevision = msg.HardwareRevision;
port.SoftwareRevision = msg.SoftwareRevision;

AddCachePortAndPortModeInformation(msg.IOTypeId, msg.HardwareRevision, msg.SoftwareRevision, port, knowledge, deviceFactory);
AddCachePortAndPortModeInformation(msg.IOTypeId, msg.HardwareRevision, msg.SoftwareRevision, hub, port, knowledge, deviceFactory);
break;
case HubAttachedIOForDetachedDeviceMessage msg:
port = knowledge.Port(msg.HubId, msg.PortId);
Expand All @@ -134,6 +135,7 @@ public static Task ApplyDynamicProtocolKnowledge(LegoWirelessMessage message, Pr
port.IsDeviceConnected = false;
break;
case HubAttachedIOForAttachedVirtualDeviceMessage msg:
hub = knowledge.Hub(msg.HubId);
port = knowledge.Port(msg.HubId, msg.PortId);
var partOfVirtual = knowledge.Port(msg.HubId, msg.PortAId);

Expand All @@ -143,7 +145,7 @@ public static Task ApplyDynamicProtocolKnowledge(LegoWirelessMessage message, Pr
port.HardwareRevision = partOfVirtual.HardwareRevision;
port.SoftwareRevision = partOfVirtual.SoftwareRevision;

AddCachePortAndPortModeInformation(msg.IOTypeId, partOfVirtual.HardwareRevision, partOfVirtual.SoftwareRevision, port, knowledge, deviceFactory);
AddCachePortAndPortModeInformation(msg.IOTypeId, partOfVirtual.HardwareRevision, partOfVirtual.SoftwareRevision, hub, port, knowledge, deviceFactory);

port.IsVirtual = true;
break;
Expand Down Expand Up @@ -176,13 +178,13 @@ public static Task ApplyDynamicProtocolKnowledge(LegoWirelessMessage message, Pr
return Task.CompletedTask;
}

private static void AddCachePortAndPortModeInformation(DeviceType type, Version hardwareRevision, Version softwareRevision, PortInfo port, ProtocolKnowledge knowledge, IDeviceFactory deviceFactory)
private static void AddCachePortAndPortModeInformation(DeviceType type, Version hardwareRevision, Version softwareRevision, HubInfo hub, PortInfo port, ProtocolKnowledge knowledge, IDeviceFactory deviceFactory)
{
var device = deviceFactory.Create(type);

if (device != null)
{
foreach (var message in device.GetStaticPortInfoMessages(hardwareRevision, softwareRevision).Select(b => MessageEncoder.Decode(b, null)))
foreach (var message in device.GetStaticPortInfoMessages(hardwareRevision, softwareRevision, hub.SystemType).Select(b => MessageEncoder.Decode(b, null)))
{
switch (message)
{
Expand Down
11 changes: 10 additions & 1 deletion src/SharpBrick.PoweredUp/Protocol/LegoWirelessProtocol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,17 @@ public LegoWirelessProtocol(BluetoothKernel kernel, ILogger<LegoWirelessProtocol
_upstreamSubject = new Subject<(byte[] data, LegoWirelessMessage message)>();
}

public async Task ConnectAsync()
public async Task ConnectAsync(SystemType knownSystemType = default)
{
// sets initial system type to provided value. This alllows sensitive IPoweredUpDevice to provide the right GetStaticPortInfo (even on initial HubAttachedIO before a HubProperty<SystemType> can be queried).
await KnowledgeManager.ApplyDynamicProtocolKnowledge(new HubPropertyMessage<SystemType>()
{
HubId = 0x00,
Operation = HubPropertyOperation.Update,
Property = HubProperty.SystemTypeId,
Payload = knownSystemType,
}, Knowledge, _deviceFactory);

await _kernel.ConnectAsync();

await _kernel.ReceiveBytesAsync(async data =>
Expand Down
6 changes: 3 additions & 3 deletions test/SharpBrick.PoweredUp.Test/Devices/VoltageTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class VoltageTest
public async Task Voltage_VoltageLObservable_Receive()
{
// arrange
var (protocol, mock) = CreateProtocolAndMock();
var (protocol, mock) = CreateProtocolAndMock(SystemType.LegoTechnic_MediumHub);

// announce voltage device in protocol
await mock.WriteUpstreamAsync(new HubAttachedIOForAttachedDeviceMessage()
Expand Down Expand Up @@ -69,7 +69,7 @@ await mock.WriteUpstreamAsync(new PortInputFormatSingleMessage()
}


internal (ILegoWirelessProtocol protocol, PoweredUpBluetoothCharacteristicMock mock) CreateProtocolAndMock()
internal (ILegoWirelessProtocol protocol, PoweredUpBluetoothCharacteristicMock mock) CreateProtocolAndMock(SystemType knownSystemType)
{
var serviceProvider = new ServiceCollection()
.AddLogging()
Expand All @@ -84,7 +84,7 @@ await mock.WriteUpstreamAsync(new PortInputFormatSingleMessage()

var protocol = serviceProvider.GetService<ILegoWirelessProtocol>();

protocol.ConnectAsync().Wait();
protocol.ConnectAsync(knownSystemType).Wait();

return (protocol, poweredUpBluetoothAdapterMock.MockCharacteristic);
}
Expand Down

0 comments on commit 290a929

Please sign in to comment.