Skip to content

Commit 08f1ad5

Browse files
committed
Add PortInputFromat(Setup)Single|CombinedMode
- Add Encoders for PortInputFormatCombinedMode - Add Encoders for PortInputFormatSetupCombinedMode
1 parent 18a3761 commit 08f1ad5

13 files changed

+286
-19
lines changed

README.md

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ SharpBrick.PoweredUp is a .NET implementation of the BlueTooth Low Energy Protoc
1212

1313
***Note:** This is the current message driven interface. In future there will be a component model allowing a more comfortable access*
1414

15-
## Discover Hubs
15+
## Discover Hubs (using raw bluetooth kernel)
1616

1717
````csharp
1818
var poweredUpBluetoothAdapter = new WinRTPoweredUpBluetoothAdapter();
@@ -35,7 +35,7 @@ Console.ReadLine();
3535
cts.Cancel(); // cancels the scanning process
3636
````
3737

38-
## Connect to Hub and Send a Message (and retrieving answers)
38+
## Connect to Hub and Send a Message and retrieving answers (using raw bluetooth kernel and messages)
3939

4040
````csharp
4141
using (var kernel = new BluetoothKernel(poweredUpBluetoothAdapter, bluetoothAddress, loggerFactory.CreateLogger<BluetoothKernel>()))
@@ -61,7 +61,7 @@ using (var kernel = new BluetoothKernel(poweredUpBluetoothAdapter, bluetoothAddr
6161
}
6262
````
6363

64-
## VISION: Future Hub Based Model
64+
## VISION: Hub Based Model
6565

6666
````csharp
6767
var host = new PoweredUpHost();
@@ -86,15 +86,23 @@ using (var hub = await host.FindHub<TechnicMediumHub>(bluetoothAddresss: 1234))
8686

8787
- Bluetooth Adapter
8888
- [X] .NET Core 3.1 (on Windows 10 using WinRT)
89-
- Library uses `Span<T>` therefore not supported in WinRT until arrival of .NET 5.
89+
- Library uses `Span<T>` therefore not supported in .NET Framework 1.0-4.8 and UWP Apps until arrival of .NET 5 (WinForms and WPF work in .NET Core 3.1)
9090
- Library uses WinRT for communication therefore only Windows 10
91-
- [ ] Xamarin.Essentials
92-
- [ ] Blazor / WebBluetooth
91+
- [ ] Xamarin (on iOS / Android using Xamarin.Essentials)
92+
- [ ] Blazor (on Browser using WebBluetooth)
9393
- Hub Model
9494
- Hubs
9595
- [ ] Technic Medium Hub
9696
- .. other hubs depend on availability of hardware / contributions
9797
- Devices
98+
- [ ] Technic Medium Hub - Rgb Light
99+
- [ ] Technic Medium Hub - Current
100+
- [ ] Technic Medium Hub - Voltage
101+
- [ ] Technic Medium Hub - Temperature Sensor 1
102+
- [ ] Technic Medium Hub - Temperature Sensor 2
103+
- [ ] Technic Medium Hub - Accelerometer
104+
- [ ] Technic Medium Hub - Gyro Sensor
105+
- [ ] Technic Medium Hub - Tilt Sensor
98106
- [ ] Technic XLarge Motor
99107
- [ ] Technic Large Motor
100108
- Message Encoder
@@ -107,21 +115,21 @@ using (var hub = await host.FindHub<TechnicMediumHub>(bluetoothAddresss: 1234))
107115
- [X] [3.7. Hub Alerts](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#hub-alerts)
108116
- [X] [3.8. Hub Attached I/O](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#hub-attached-i-o)
109117
- [X] [3.9. Generic Error Messages](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#generic-error-messages)
110-
- ~~[ ] [3.10. H/W NetWork Commands](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#h-w-network-commands)~~
111-
- ~~[ ] [3.11. F/W Update - Go Into Boot Mode](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#f-w-update-go-into-boot-mode)~~
112-
- ~~[ ] [3.12. F/W Update Lock memory](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#f-w-update-lock-memory)~~
113-
- ~~[ ] [3.13. F/W Update Lock Status Request](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#f-w-update-lock-status-request)~~
114-
- ~~[ ] [3.14. F/W Lock Status](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#f-w-lock-status)~~
118+
- [ ] ~~[3.10. H/W NetWork Commands](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#h-w-network-commands)~~
119+
- [ ] ~~[3.11. F/W Update - Go Into Boot Mode](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#f-w-update-go-into-boot-mode)~~
120+
- [ ] ~~[3.12. F/W Update Lock memory](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#f-w-update-lock-memory)~~
121+
- [ ] ~~[3.13. F/W Update Lock Status Request](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#f-w-update-lock-status-request)~~
122+
- [ ] ~~[3.14. F/W Lock Status](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#f-w-lock-status)~~
115123
- [X] [3.15. Port Information Request](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-information-request)
116124
- [X] [3.16. Port Mode Information Request](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-mode-information-request)
117125
- [X] [3.17. Port Input Format Setup (Single)](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-input-format-setup-single)
118-
- [ ] [3.18. Port Input Format Setup (CombinedMode)](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-input-format-setup-combinedmode)
126+
- [X] [3.18. Port Input Format Setup (CombinedMode)](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-input-format-setup-combinedmode)
119127
- [X] [3.19. Port Information](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-information)
120128
- [X] [3.20. Port Mode Information](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-mode-information)
121129
- [ ] [3.21. Port Value (Single)](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-value-single)
122130
- [ ] [3.22. Port Value (CombinedMode)](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-value-combinedmode)
123131
- [X] [3.23. Port Input Format (Single)](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-input-format-single)
124-
- [ ] [3.24. Port Input Format (CombinedMode)](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-input-format-combinedmode)
132+
- [X] [3.24. Port Input Format (CombinedMode)](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-input-format-combinedmode)
125133
- [ ] [3.25. Virtual Port Setup](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#virtual-port-setup)
126134
- [ ] [3.26. Port Output Command](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#port-output-command)
127135
- [ ] [3.27. Output Command 0x81 - Motor Sub Commands [0x01-0x3F]](https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#output-command-0x81-motor-sub-commands-0x01-0x3f)

examples/message-trace/Program.cs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ await kernel.ReceiveBytesAsync(async data =>
7070
PortInformationForModeInfoMessage msg => $"Port Information - Port {msg.PortId} Total Modes {msg.TotalModeCount} / Capabilities Output:{msg.OutputCapability}, Input:{msg.InputCapability}, LogicalCombinable:{msg.LogicalCombinableCapability}, LogicalSynchronizable:{msg.LogicalSynchronizableCapability} / InputModes: {msg.InputModes:X}, OutputModes: {msg.InputModes:X}",
7171
PortInformationForPossibleModeCombinationsMessage msg => $"Port Information (combinations) - Port {msg.PortId} Combinations: {string.Join(",", msg.ModeCombinations.Select(x => x.ToString("X")))}",
7272
PortInputFormatSingleMessage msg => $"Port Input Format (Single) - Port {msg.PortId}, Mode {msg.Mode}, Threshold {msg.DeltaInterval}, Notification {msg.NotificationEnabled}",
73+
PortInputFormatCombinedModeMessage msg => $"Port Input Format (Combined Mode) - Port {msg.PortId} UsedCombinationIndex {msg.UsedCombinationIndex} Enabled {msg.MultiUpdateEnabled} Configured Modes {string.Join(",", msg.ConfiguredModeDataSetIndex)}",
7374
UnknownMessage msg => $"Unknown Message Type: {(MessageType)msg.MessageType} Length: {msg.Length} Content: {BytesStringUtil.DataToString(data)}",
7475
var unknown => $"{unknown.MessageType} (not yet formatted)",
7576
};
@@ -86,12 +87,10 @@ await kernel.ReceiveBytesAsync(async data =>
8687
// await kernel.SendBytesAsync(request);
8788

8889
// logger.LogInformation("Request PortInformation (ModeInfo)");
89-
// request = MessageEncoder.Encode(new PortInformationRequestMessage() { PortId = 0, InformationType = PortInformationType.ModeInfo });
90-
// await kernel.SendBytesAsync(request);
90+
// await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInformationRequestMessage() { PortId = 99, InformationType = PortInformationType.ModeInfo }));
9191

9292
// logger.LogInformation("Request PortInformation (ModeCombinations)");
93-
// request = MessageEncoder.Encode(new PortInformationRequestMessage() { PortId = 0, InformationType = PortInformationType.PossibleModeCombinations });
94-
// await kernel.SendBytesAsync(request);
93+
// await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInformationRequestMessage() { PortId = 99, InformationType = PortInformationType.PossibleModeCombinations }));
9594

9695
// logger.LogInformation("Request PortModeInformation(s)");
9796
// await kernel.SendBytesAsync(MessageEncoder.Encode(new PortModeInformationRequestMessage() { PortId = 0, Mode = 0, InformationType = PortModeInformationType.ValueFormat }));
@@ -113,7 +112,9 @@ await kernel.ReceiveBytesAsync(async data =>
113112

114113
// await kernel.SendBytesAsync(BytesStringUtil.StringToData("09-00-81-00-11-07-64-64-00")); // 3.27.5
115114

116-
await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInputFormatSetupSingleMessage() { PortId = 0, Mode = 0x03, DeltaInterval = 5, NotificationEnabled = true }));
115+
// await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInputFormatSetupSingleMessage() { PortId = 0, Mode = 0x03, DeltaInterval = 5, NotificationEnabled = true }));
116+
117+
await SetupPortInCombinedMode(kernel);
117118

118119
Console.ReadLine();
119120

@@ -123,5 +124,58 @@ await kernel.ReceiveBytesAsync(async data =>
123124
Console.ReadLine();
124125
}
125126
}
127+
128+
private static async Task SetupPortInCombinedMode(BluetoothKernel kernel)
129+
{
130+
await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInputFormatSetupCombinedModeMessage()
131+
{
132+
PortId = 0,
133+
SubCommand = PortInputFormatSetupCombinedSubCommand.LockDeviceForSetup,
134+
}));
135+
136+
await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInputFormatSetupCombinedModeForSetModeDataSetMessage()
137+
{
138+
PortId = 0,
139+
SubCommand = PortInputFormatSetupCombinedSubCommand.SetModeAndDataSetCombination,
140+
CombinationIndex = 0, // should refer 0b0000_0000_0000_1110 => SPEED POS APOS
141+
ModeDataSets = new PortInputFormatSetupCombinedModeModeDataSet[] {
142+
new PortInputFormatSetupCombinedModeModeDataSet() { Mode = 0x01, DataSet = 0, },
143+
new PortInputFormatSetupCombinedModeModeDataSet() { Mode = 0x02, DataSet = 0, },
144+
new PortInputFormatSetupCombinedModeModeDataSet() { Mode = 0x03, DataSet = 0, },
145+
}
146+
}));
147+
148+
await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInputFormatSetupSingleMessage()
149+
{
150+
PortId = 0,
151+
Mode = 0x01,
152+
DeltaInterval = 10,
153+
NotificationEnabled = true,
154+
}));
155+
156+
await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInputFormatSetupSingleMessage()
157+
{
158+
PortId = 0,
159+
Mode = 0x02,
160+
DeltaInterval = 10,
161+
NotificationEnabled = true,
162+
}));
163+
164+
165+
await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInputFormatSetupSingleMessage()
166+
{
167+
PortId = 0,
168+
Mode = 0x03,
169+
DeltaInterval = 10,
170+
NotificationEnabled = true,
171+
}));
172+
173+
174+
await kernel.SendBytesAsync(MessageEncoder.Encode(new PortInputFormatSetupCombinedModeMessage()
175+
{
176+
PortId = 0,
177+
SubCommand = PortInputFormatSetupCombinedSubCommand.UnlockAndStartWithMultiUpdateEnabled,
178+
}));
179+
}
126180
}
127181
}

src/SharpBrick.PoweredUp/Protocol/Formatter/MessageEncoder.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ public static byte[] Encode(PoweredUpMessage message)
1818
PortInformationRequestMessage msg => MessageType.PortInformationRequest,
1919
PortModeInformationRequestMessage msg => MessageType.PortModeInformationRequest,
2020
PortInputFormatSetupSingleMessage msg => MessageType.PortInputFormatSetupSingle,
21+
PortInputFormatSetupCombinedModeMessage msg => MessageType.PortInputFormatSetupCombinedMode,
2122
PortInformationMessage msg => MessageType.PortInformation,
2223
PortModeInformationMessage msg => MessageType.PortModeInformation,
2324
PortInputFormatSingleMessage msg => MessageType.PortInputFormatSingle,
25+
PortInputFormatCombinedModeMessage msg => MessageType.PortInputFormatCombinedMode,
2426
_ => throw new NotImplementedException(),
2527
};
2628

@@ -50,9 +52,11 @@ private static IMessageContentEncoder CreateEncoder(MessageType messageType)
5052
MessageType.PortInformationRequest => new PortInformationRequestEncoder(),
5153
MessageType.PortModeInformationRequest => new PortModeInformationRequestEncoder(),
5254
MessageType.PortInputFormatSetupSingle => new PortInputFormatSetupSingleEncoder(),
55+
MessageType.PortInputFormatSetupCombinedMode => new PortInputFormatSetupCombinedModeEncoder(),
5356
MessageType.PortInformation => new PortInformationEncoder(),
5457
MessageType.PortModeInformation => new PortModeInformationEncoder(),
5558
MessageType.PortInputFormatSingle => new PortInputFormatSingleEncoder(),
59+
MessageType.PortInputFormatCombinedMode => new PortInputFormatCombinedModeEncoder(),
5660
_ => null,
5761
};
5862

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Linq;
3+
using SharpBrick.PoweredUp.Protocol.Messages;
4+
5+
namespace SharpBrick.PoweredUp.Protocol.Formatter
6+
{
7+
public class PortInputFormatCombinedModeEncoder : IMessageContentEncoder
8+
{
9+
public ushort CalculateContentLength(PoweredUpMessage message)
10+
=> throw new NotImplementedException();
11+
12+
public PoweredUpMessage Decode(in Span<byte> data)
13+
{
14+
ushort bitMask = BitConverter.ToUInt16(data.Slice(2, 2));
15+
16+
return new PortInputFormatCombinedModeMessage()
17+
{
18+
PortId = data[0],
19+
UsedCombinationIndex = (byte)(data[1] & 0b0000_0111),
20+
MultiUpdateEnabled = (byte)(data[1] & 0b1000_0000) > 0,
21+
ConfiguredModeDataSetIndex = Enumerable.Range(0, 16).Select(pos =>
22+
(bitMask & (0x01 << pos)) > 0 ? pos : -1
23+
).Where(mdi => mdi >= 0).ToArray(),
24+
};
25+
}
26+
27+
public void Encode(PoweredUpMessage message, in Span<byte> data)
28+
=> throw new NotImplementedException();
29+
30+
}
31+
32+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using SharpBrick.PoweredUp.Protocol.Messages;
3+
4+
namespace SharpBrick.PoweredUp.Protocol.Formatter
5+
{
6+
public class PortInputFormatSetupCombinedModeEncoder : IMessageContentEncoder
7+
{
8+
public ushort CalculateContentLength(PoweredUpMessage message)
9+
=> (ushort)(message is PortInputFormatSetupCombinedModeForSetModeDataSetMessage setMessage ? 3 + setMessage.ModeDataSets.Length : 2);
10+
11+
public PoweredUpMessage Decode(in Span<byte> data)
12+
=> throw new NotImplementedException();
13+
14+
public void Encode(PoweredUpMessage message, in Span<byte> data)
15+
=> Encode(message as PortInputFormatSetupCombinedModeMessage ?? throw new ArgumentException(nameof(message)), data);
16+
public void Encode(PortInputFormatSetupCombinedModeMessage message, in Span<byte> data)
17+
{
18+
data[0] = message.PortId;
19+
data[1] = (byte)message.SubCommand;
20+
21+
if (message is PortInputFormatSetupCombinedModeForSetModeDataSetMessage setMessage)
22+
{
23+
data[2] = setMessage.CombinationIndex;
24+
for (int idx = 0; idx < setMessage.ModeDataSets.Length; idx++)
25+
{
26+
byte flag = (byte)(
27+
((setMessage.ModeDataSets[idx].Mode & 0b0000_1111) << 4) +
28+
(setMessage.ModeDataSets[idx].DataSet & 0b0000_1111)
29+
);
30+
31+
data[3 + idx] = flag;
32+
}
33+
}
34+
}
35+
}
36+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace SharpBrick.PoweredUp.Protocol.Messages
2+
{
3+
public class PortInputFormatCombinedModeMessage : PoweredUpMessage
4+
{
5+
public byte PortId { get; set; }
6+
public byte UsedCombinationIndex { get; set; }
7+
public bool MultiUpdateEnabled { get; set; }
8+
public int[] ConfiguredModeDataSetIndex { get; set; }
9+
}
10+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace SharpBrick.PoweredUp.Protocol.Messages
2+
{
3+
public class PortInputFormatSetupCombinedModeMessage : PoweredUpMessage
4+
{
5+
public byte PortId { get; set; }
6+
public PortInputFormatSetupCombinedSubCommand SubCommand { get; set; }
7+
}
8+
9+
public class PortInputFormatSetupCombinedModeForSetModeDataSetMessage : PortInputFormatSetupCombinedModeMessage
10+
{
11+
public byte CombinationIndex { get; set; }
12+
public PortInputFormatSetupCombinedModeModeDataSet[] ModeDataSets { get; set; }
13+
}
14+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace SharpBrick.PoweredUp.Protocol.Messages
2+
{
3+
public class PortInputFormatSetupCombinedModeModeDataSet
4+
{
5+
public byte Mode { get; set; }
6+
public byte DataSet { get; set; }
7+
}
8+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace SharpBrick.PoweredUp.Protocol.Messages
2+
{
3+
public enum PortInputFormatSetupCombinedSubCommand : byte
4+
{
5+
SetModeAndDataSetCombination = 0x01,
6+
LockDeviceForSetup = 0x02,
7+
UnlockAndStartWithMultiUpdateEnabled = 0x03,
8+
UnlockAndStartWithMultiUpdateDisabled = 0x04,
9+
ResetSensor = 0x06,
10+
}
11+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace SharpBrick.PoweredUp.Protocol.Messages
2+
{
3+
public class PortValueSingleMessage : PoweredUpMessage
4+
{
5+
public byte PortId { get; set; }
6+
public byte[] InputValue { get; set; }
7+
}
8+
}

0 commit comments

Comments
 (0)