Code Monkey home page Code Monkey logo

powered-up's Introduction

SharpBrick.PoweredUp

SharpBrick.PoweredUp is a .NET implementation of the Bluetooth Low Energy Protocol for Lego Powered UP products.

Nuget license:MIT GitHub issues by-label GitHub issues by-label

Build-CI Build-Release

Features

  • Multiple Programming Models: SharpBrick.PoweredUp supports usage in a device model (hubs and devices as classes/properties; see examples below) or a protocol level (messages send up and down the Bluetooth Low Energy Protocol).
  • Typed Devices with explicit Functions: The SDK supports most commands described in the Lego Wireless Protocol in its typed devices (Motors, Lights, ..). They are self-describing to support a quick bootup of the SDK.
  • Dynamic Devices: The SDK can auto-discover new devices which are not yet known by the SDK. The device can be directly accessed either by writing data directly to a mode or receiving notification about value changes.
  • Awaitable Commands: Instead of waiting a defined amount of time for the devices to react, directly listens to the feedback messages the LEGO Wireless Protocol provides. No unecessary delays and race conditions.
  • Port Value Combined Mode: If supported by the device, the SDK allows you to configure the devices to combine multiple feedbacks of the same device within the same message (e.g. speed and absolute position of a motor).
  • Virtual Port Creation: Combine multiple devices of the same type into a virtual combined port. This allows synchronous access to multiple devices using the same message (e.g. using two motors for driving).
  • Deployment Model Verification: The SDK includes a model builder and a verification method to ensure that the wired devies are correctly reflecting the expectations in the program.
  • Tools: The poweredup CLI includes a device list feature, enumerating the metadata properties of the LEGO Wireless Protocol.
  • Support for multiple Bluetooth Stacks: Use either Microsoft WinRT, BlueGiga Bluetooth (Silicon's Lab BlueGiga-adapter, for example BLED112) or Xamarin using BLE.Plugin to talk to your Lego hubs.

Examples

Additional to code fragments below, look into the examples/SharpBrick.PoweredUp.Examples project (15+ examples).

using SharpBrick.PoweredUp;

using Microsoft.Extensions.DependencyInjection; // SharpBrick.PoweredUp uses the DI system
using Microsoft.Extensions.Logging; // SharpBrick.PoweredUp also logs stuff

Discovering Hubs

var serviceProvider = new ServiceCollection()
    .AddLogging()
    .AddPoweredUp()
    .AddWinRTBluetooth() // using WinRT Bluetooth on Windows (separate NuGet SharpBrick.PoweredUp.WinRT; others are available)
    .BuildServiceProvider();
    
var host = serviceProvider.GetService<PoweredUpHost>();

var hub = await host.DiscoverAsync<TechnicMediumHub>();
await hub.ConnectAsync();

Discovering Hubs for UI

var host = serviceProvider.GetService<PoweredUpHost>();

var cts = new CancellationTokenSource();
host.Discover(async hub =>
{
    await hub.ConnectAsync(); // to get some more properties from it

    // show in UI
}, cts.Token);

// Cancel Button => cts.Cancel();

Sending Commands to Ports and Devices of a Hub

See source code in examples/SharpBrick.PoweredUp.Examples for more examples.

// do hub discovery before

using (var technicMediumHub = hub as TechnicMediumHub)
{
    // optionally verify if everything is wired up correctly
    await technicMediumHub.VerifyDeploymentModelAsync(modelBuilder => modelBuilder
        .AddHub<TechnicMediumHub>(hubBuilder => hubBuilder
            .AddDevice<TechnicXLargeLinearMotor>(technicMediumHub.A)
        )
    );

    await technicMediumHub.RgbLight.SetRgbColorsAsync(0x00, 0xff, 0x00);

    var motor = technicMediumHub.A.GetDevice<TechnicXLargeLinearMotor>();

    await motor.GotoPositionAsync(45, 10, 100, PortOutputCommandSpecialSpeed.Brake);
    await Task.Delay(2000);
    await motor.GotoPositionAsync(-45, 10, 100, PortOutputCommandSpecialSpeed.Brake);

    await technicMediumHub.SwitchOffAsync();
}

Receiving values from Ports and Devices of a Hub (single value setup)

var motor = technicMediumHub.A.GetDevice<TechnicXLargeLinearMotor>();

await motor.SetupNotificationAsync(motor.ModeIndexAbsolutePosition, true);

// observe using System.Reactive
var disposable = motor.AbsolutePositionObservable.Subscribe(x => Console.WriteLine(x.SI));
// ... once finished observing (do not call immediately afterwards ;))
disposable.Dispose();

// OR manually observe it
Console.WriteLine(motor.AbsolutePosition);

Connecting to an unknown device

// deployment model verification with unknown devices
await technicMediumHub.VerifyDeploymentModelAsync(mb => mb
    .AddAnyHub(hubBuilder => hubBuilder
        .AddAnyDevice(0))
    );

var dynamicDeviceWhichIsAMotor = technicMediumHub.Port(0).GetDevice<DynamicDevice>();

// or also direct from a protocol
//var dynamicDeviceWhichIsAMotor = new DynamicDevice(technicMediumHub.Protocol, technicMediumHub.HubId, 0);

// discover the unknown device using the LWP (since no cached metadata available)
await dynamicDeviceWhichIsAMotor.DiscoverAsync();

// use combined mode values from the device
await dynamicDeviceWhichIsAMotor.TryLockDeviceForCombinedModeNotificationSetupAsync(2, 3);
await dynamicDeviceWhichIsAMotor.SetupNotificationAsync(2, true);
await dynamicDeviceWhichIsAMotor.SetupNotificationAsync(3, true);
await dynamicDeviceWhichIsAMotor.UnlockFromCombinedModeNotificationSetupAsync(true);

// get the individual modes for input and output
var powerMode = dynamicDeviceWhichIsAMotor.SingleValueMode<sbyte>(0);
var posMode = dynamicDeviceWhichIsAMotor.SingleValueMode<int>(2);
var aposMode = dynamicDeviceWhichIsAMotor.SingleValueMode<short>(3);

// use their observables to report values
using var disposable = posMode.Observable.Subscribe(x => Console.WriteLine($"Position: {x.SI} / {x.Pct}"));
using var disposable2 = aposMode.Observable.Subscribe(x => Console.WriteLine($"Absolute Position: {x.SI} / {x.Pct}"));

// or even write to them
await powerMode.WriteDirectModeDataAsync(0x64); // That is StartPower(100%) on a motor
await Task.Delay(2_000);
await powerMode.WriteDirectModeDataAsync(0x00); // That is Stop on a motor

Console.WriteLine($"Or directly read the latest value: {aposMode.SI} / {aposMode.Pct}%");

Connect to Hub and Send a Message and retrieving answers (directly on protocol layer)

var serviceProvider = new ServiceCollection()
    .AddLogging()
    .AddPoweredUp()
    .AddWinRTBluetooth()
    .BuildServiceProvider();

// getting utilities
var bt = serviceProvider.GetService<IPoweredUpBluetoothAdapter>();
var host = serviceProvider.GetService<PoweredUpHost>();

// discover a LWP bluetooth device 
var tcs = new TaskCompletionSource<ILegoWirelessProtocol>();

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();

Connecting with other Bluetooth Adapters

  • BlueGiga Adapter: Find more details in the docs about the needed configuration and the setup on Windows, Ubuntu or the Raspberry Pi.

Command Line Experience

Note: Due to upstream issues in the dotnet/sdk (issue) we are currently not providing the NuGet distributed dotnet tool. The CLI itself can be used by dotnet run -- when compiling this project directly.

The poweredup command line utility intends to allow the inspection of LEGO Wireless Protocol / Powered UP hubs and devices for their properties. It has utilities for ...

  • Enumerating all connected Devices including hub internal devices and emit their static self-description as they expose using the LEGO Wireless Protocol.

    poweredup device list
    
  • Binary dumping the self-description helps protocol implementors with a lack of devices to understand and try to implement the devices without having the physical device. Also the output is needed when programming the library to enable a fast bootup of the SDK.

    poweredup device dump-static-port -p 0
    
  • Pretty Print Binary Dumps: Help to convert a binary dump in a nice representation.

  • Use of other Bluetooth LE stack By default the CLI tools assumes the usage of WinRT. If used on another operating system or with another Bluetooth Adapter on Windows, the Bluetooth Adapter needs to be specified. Adapter might need additional configuration, see their details documentation.

    poweredup device list --BluetoothAdapter BlueGigaBLE
    

Installation Instruction

  1. Install the latest .NET on your machine (e.g. .NET 5).
  2. Install the poweredup dotnet utility using the following instruction
    // On Windows
    dotnet tool install --framework net5.0-windows10.0.19041.0 -g SharpBrick.PoweredUp.Cli
    
    // On Linux
    dotnet tool install --framework net5.0 -g SharpBrick.PoweredUp.Cli
    
  3. Start using the tool
    poweredup device list
    

SDK Status, Hardware Support, Contributions, ..

Basic Architecture within the SDK

+---------+
|         |
| Devices | <-+
|         |   |   +-----------------------+     +-------------+     +-----+
+---------+   +-> |                       |     |             |     |     |
                  | ILegoWirelessProtocol | <-> | BLE Adapter | <-> | BLE |
+---------+   +-> |    (w/ Knowlege)      |     |             |     |     |
|         |   |   +-----------------------+     +-------------+     +-----+
|   Hub   | <-+
|         |
+---------+

DI Container Elements

                                              PoweredUpHost +-------+
                                                   +                |
                                                   |                |
+-------------------- Scoped Service Provider ------------------------+
|                                                  |                | |
|                                                  v                +--->IPoweredUp
| LinearMidCalibration +                         HubFactory         | |  BluetoothAdapter
|                      |                                            | |
| TechnicMediumHub +---+-> LegoWirelessProtocol +-> BluetoothKernel + |
|             +                       +                               |
|             |                       |                               |
|             +-----------------------+--------> DeviceFactory        |
|                                                                     |
+---------------------------------------------------------------------+

Implementation Status

  • Bluetooth Adapter
    • .NET Core 3.1 (on Windows 10 using WinRT Bluetooth). Please use version v3.4.0 and consider upgrading to .NET 5
    • .NET 5 (on Windows 10 using WinRT Bluetooth) (⚠ v4.0 or later)
    • .NET 5 (on Windows 10 using BlueGiga Adapter) (⚠ v4.0 or later)
    • .NET 5 (on Linux using BlueGiga Adapter) (tested on Raspberry Pi 3, 4 and Ubuntu 20.04; ⚠ v4.0 or later)
    • UWP (most likely December 2021; UWP currently does not support .NET Standard 2.1 and C# 8.0+)
    • .NET Framework 4.8 (will never be supported; .NET Framework does not and will never support .NET Standard 2.1 and C# 8.0+)
    • Xamarin 5 (on Android using BLE.Plugin) (⚠ v4.0 or later)
    • Blazor/WebAssembly (on Browser using WebBluetooth; currently blocked by less than ideal GATT support on browsers, see 1, 2 and 3 )
  • Hub Model
    • Hubs
      • Ports
      • Properties
      • Alerts
      • Actions
      • Create Virtual Ports
      • Move Hub (88006)
      • Two Port Hub (88009)
      • Two Port Handset (88010)
      • Technic Medium Hub (88012)
      • MarioHub (set 71360)
      • Duplo Train Base (set 10874)
      • .. other hubs depend on availability of hardware / contributions
    • Devices
      • Technic Medium Hub (88012) - Rgb Light
      • Technic Medium Hub (88012) - Current
      • Technic Medium Hub (88012) - Voltage
      • Technic Medium Hub (88012) - Temperature Sensor 1 + 2
      • Technic Medium Hub (88012) - Accelerometer
      • Technic Medium Hub (88012) - Gyro Sensor
      • Technic Medium Hub (88012) - Tilt Sensor
      • Technic Medium Hub (88012) - Gesture Sensor (⚠ Usable but Gesture mapping is pending)
      • Move Hub (88006) - Rgb Light
      • Move Hub (88006) - Current
      • Move Hub (88006) - Voltage
      • Move Hub (88006) - Tilt
      • Move Hub (88006) - Internal Motors (Single and Virtual Port)
      • Two Port Hub (88009) - Rgb Light
      • Two Port Hub (88009) - Current
      • Two Port Hub (88009) - Voltage
      • Mario Hub (set 71360) - Accelerometer (Raw & Gesture) (⚠ Usable but Gesture mapping is a rough draft)
      • Mario Hub (set 71360) - TagSensor (Barcode & RGB)
      • Mario Hub (set 71360) - Pants
      • Mario Hub (set 71360) - Debug
      • Duplo Train Base (set 10874) - Motor
      • Duplo Train Base (set 10874) - Speaker
      • Duplo Train Base (set 10874) - Rgb Light
      • Duplo Train Base (set 10874) - ColorSensor
      • Duplo Train Base (set 10874) - Speedometer
      • Color Distance Sensor (88007) (⚠ v4.0 or later)
      • Medium Linear Motor (88008)
      • Remote Control Button (88010)
      • Remote Control RSSI (88010)
      • Train Motor (88011)
      • Technic Large Motor (88013)
      • Technic XLarge Motor (88014)
      • Technic Medium Angular Motor (Spike)
      • Technic Medium Angular Motor (Grey)
      • Technic Large Angular Motor (Spike)
      • Technic Large Angular Motor (Grey)
      • Technic Color Sensor
      • Technic Distance Sensor
      • Motor WeDo 2.0 Medium (21980)
      • .. other devices depend on availability of hardware / contributions
  • Protocol
  • Features
    • Dynamic Device
    • Deployment Verifier
  • Command Line (dotnet tool install -g SharpBrick.PoweredUp.Cli)
    • poweredup device list (discover all connected devices and their port (mode) properties)
    • poweredup device dump-static-port -p <port number> (see adding new devices tutorial)

SDKs in other programming languages

Resources

Contribution

SharpBrick is an organization intended to host volunteers willing to contribute to the SharpBrick.PoweredUp and related projects. Everyone is welcome (private and commercial entities). Please read our Code of Conduct before participating in our project.

The product is licensed under MIT License to allow a easy and wide adoption into prviate and commercial products.

Thanks ...

Thanks to @nathankellenicki, @dlech, @corneliusmunz, @KeyDecoder, @highstreeto, @Berdsen , @vuurbeving and @dkurok for their code, answers, testing and other important contributions.

powered-up's People

Contributors

berdsen avatar corneliusmunz avatar dkurok avatar highstreeto avatar keydecoder avatar mennolodder avatar rickjansen-dev avatar tthiery avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

powered-up's Issues

C# 9.0 Updates

  • Make Library nullable
  • Utilize data classes / records
  • Update regards pattern matching
    • is null / is not null
  • Activate .NET 5 SDK Code Analyzers
  • Remove unnecessary usings

Add Hub Alerts Observable

  • Move HubAlert.cs to Enum folder and change namespace to SharpBrick.PoweredUp (as it is exposed from now on)
  • Extend Hub.cs
  • Create an observable property of type IObservable<HubAlert>.
  • Wire the new observable property with the existing UpstreamMessages and filter only HubAlertMessage.

Adding CW and CCW as multiplier constants

Usage e.g.

await motor.StartSpeedAsync(CCW * 75);

If CCW and CW are not consistent in regards of usage across modes and devices, consider using a pattern similar to XNamespace.

Lesson learnt from #47

Create Message Tracing Function

  • Extract string representation from message-trace app
  • Add string representation to PoweredUpMessage.ToString() method
  • Add function to hookup with protocol for tracing

Investigate Gesture Sensor

The SPIKE Prime Hub can recognize taps on the device. Maybe also the TechnicMediumHub since it exposes the internal device.

Deployment Verifier

When you build a user interface or something related, you expect the connected sensors, actors and hubs to follow a pre-defined model (which you then control by your UI).

var model = new DeploymentModelBuilder()
                 .AddHub<TechnicMediumHub>(hubBuilder => hubBuilder
                     .AddDevice<TechnicLinearMotor>(hub => hub.A)
                     .AddDevice<TechnicXlargeLinearMotor>()
                 )
                .Build();

var errors = model.Verify(protocol);

// or reactive

var errorObservable = protocol.VerifyObservable(model);

With errors being something like ..

class DeploymentError
{
    int ErrorCode;
    byte HubId;
    byte? PortId;
    string Message;
}

Design - Port(Combined)Value encoding and consequences

  • PortValue and PortCombinedValue are encoding their payload data according to definitions set-up in PortInputFormat(Combined)Setup requests. As a result, the protocol decoder itself is stateful.
    • Port Knowledge has to be present already on the Protocol Level and not the Hub/Device Logic Models
    • The Protocol will need middlewares which can maintain the knowledge, irrelevant of the uses of the protocol
    • Since querying all many properties (PortInformation, PortModeInformation) take significant time and their properties are static by device type, hardcoded caching by device type/fw/hw is possible. An explicit discovery mode for unknown devices can be implemented as a "business function".
    • The remaining informaton (HubAttachedIO Attach/Detach, PortInputFormat) are user choices (in physical doing or software), their input is dynamic and needs implementation as middlewares.

Involved Messages

  • HubAttachedIOMessage (event Attached): existence and device type.

  • HubAttachedIOMessage (event Detached): removal of existence, port knowledge reset.

  • PortInputFormatSingleMessage: format description of the PortValueSingleMessage.

  • PortInputFormatCombinedModeMessage: format description of the PortValueCombinedModeMessage.

  • PortInformationMessage (mode info + mode combinations): basic device description (cachable).

  • PortModeInformationMessage (~10 properties): device property description (cachable).

Architecture Changes:

  • Establishment of a Knowledge Model SharpBrick.PoweredUp.Knowledge.
  • No introduction of a middleware stack in PoweredUPProtocol. Not yet needed.
  • Protocol function to lookup up knowledge.
  • Protocol function to update knowledge.
  • Business Function DiscoverPorts which acts on top of the PoweredUpProtocol but can access the knowledge

Investigate using System.Reactive for Hub/Device targeting pipelines

Needs

  • Hub and Devices need to consume the same PowerdUpProtocol with its two methods ReceiveMessageAsync (which is directly bound through to the BT stack) and SendMessageAsync. Multiple subscriptions are needed.
  • Devices are attached/detached dynamically creating the need for new pipelines
  • Devices should receive a filtered set of messages (no need for them to read the messages of other devices)
  • There are pipes in/out with correlation events occurring

Libraries

  • System.Reactive

    • push based
    • Does not work well with general purpose async/await behaviors => NO SHOW
    • buffering complicated
    • LINQ
    • Good subscription management
    • Can build pipelines dynamically on demand
    • Not Span capable
  • violetgrass/middleware

    • push based
    • async/await
    • No buffering
    • No LINQ
    • Exposes middleware pattern
    • Might be Span capable (if done right; cross checked with library)
    • Cannot branch dynamically => NEEDS extensions
    • No subscription management
  • IAsyncEnumerable / System.Linq.Async

    • pull based not pushed based => NO SHOW
    • LINQ
  • System.Threading.Channels

    • push based
    • buffering is available
    • No LINQ
    • needs an active consumer (a thread awaiting something) => that would not be reasonable on all devices when just updating properties => NO SHOW
    • Is used in kestrel e.g. for Quic packages

Decision & Rationale

?

Add generic option --trace to poweredup tool

  • Configure a ServiceCollection with logging
  • Add support for --trace option and adjust logging level by it
  • Add tracer to protocol setup
  • Add serviceProvider to hub and loggerfactory to WinRT adapter.
  • Move message-trace sample content (rgb, input, motor) into a mixed bag example
  • Deprecate message-trace project

Add TwoPortHub (88009)

  • Rename existing SharpBrick.PoweredUp.Hub into BaseHub
  • Add TwoPortHub (88009) like TechnicMediumHub

Note: Note to everyone: I do not have the hardware and have in the foreseeable future no interest in purchasing them. If you want support for this hardware in this library, please contribute. I will guide you through the process and assist with everything needed.

Dynamic Device

Use Cases

  • Implement fallback device for unknown devices (flag)
  • Implement fallback for known but not implemented devices (flag)
  • Use DynamicDevice.Discover in case GetStaticPortInformation does not have any information for typed device (aka. soft react to firmware updates).

Strategy

  • Create a sub class DynamicDevice which derives from Device
  • Add a discovery function as DynamicDevice.DiscoverAsync. Decision needed whether we auto-call it when discovered by HubAttachedIOMessage or by user before usage by user (since pretty expensive).
  • Add ConcurrentDictionary<byte,Mode> Modes to Device which is auto populated on Discovery (or on auto-playing knowledge into the device) ... so for existing devies these are auto-populated.
  • Add default observables, properties (SI, Raw, Pct) and WriteDirectMode method to Mode
  • Rewrite existing invocations to target Mode.

Should be non-breaking at the API surface.

Hub Await Initialization

During Intialization

  • Hub Properties (await all)
  • Known Devices
  • Observable for device changes (after protocol knowledge update)

Support

  • DeploymentVerfication achieved (#36)

WebAssembly Port

Enable the usage of the SharpBrick.PoweredUp library in Blazor on WebAssembly. For that a bridge between Blazor and WebBluetooth is required. After the bridge, an adapter to the SharpBrick.PoweredUp.Bluetooth interface is required.

Cleanup ServiceLocator pattern in favor of proper DI

  • Active Connection == own Scope
    • Create Scope in host during hub/protocol initialization
  • Move the following types to a AddScoped lifetime
    • BluetoothKernel (remove bluetoothAddress from constructor and move to ConnectAsync)
    • PoweredUpProtocol (add deviceFactory as a constructor argument and remove IServiceProvider service locator trap)
    • Rewrite DeviceFactory/HubFactory to use Transient types in the IServiceProvider. OPEN QUESTION: How to handle hubId and portId in an elegant way
    • Add constructor argument deviceFactory to hub.
  • Add interface to PoweredUpHost to wire up a protocol

non-breaking in theory

Add Tilt Sensor

  • Reading DEG
  • Reading IMP
  • Configuration (impact, orientation)
  • Do not implement factory reset

Make PoweredUp infrastructure adhere to HubId

Generally the library is not supporting multiple HubIds over the same bluetooth device/service/gatt profile.

  • CommonMessageHeaderEncoder.Encode hardcoded 0x00
  • Most Hubs, Devices do not encode their hub id into the commands
  • Host/Hubs need to recognize their associated HubId

... Many more issues

Implement guidance around absolute position and degrees

Knowledge dump

  • TachoMotor.StartSpeedForDegreesAsync support moving the motor by degrees. It operates relative of its current position.
  • AbsoluteMotor.GotoAbsolutePositionAsync allows moving the motor to an absolute position. It operates relative to a changeable zero position.
  • The input mode 2 (POS) is reflecting the position relative to a changeable zero position (firmware in-memory encoded)
  • The input mode 3 (APOS) is reflecting the position relative to marked zero position (physically encoded).
  • POS is resetable with PortOutputCommandPresetEncoderMessage, APOS not.
  • Technic(X)LargeLinearMotor / TechnicMediumHub do not remember their zero POS position.

Implementation

  • Encode PortOutputCommandPresetEncoderMessage
  • Add a AbsoluteMotor.GotoRealZeroAsync which moves the motor to align the position and the absolute position.
  • Add a TachoMotor.SetZeroAsync allowing to reseting the zero value to the current position.
  • Add comments to GotoAbsolutePosition and AbsolutePosition(Observable) explaining the behavior.

Design - Creating a single namespace for popular classes

  • Intention: Consumers should not need to search namespaces to discover an API
  • Solution:
    • Break namespace / folder alignment (e.g. sub folder Devices/Hubs despite all being in root namespace)
    • Move re-used types (mainly enums from Messages / Devices into the root namespace with separate folder Enums)
  • Rationale: Consumer usability is more important than code organization

Breaking Code Cleanup (v1.0)

  • Enum according to .NET Guidelines (flags plural, all other singular)
  • Enums of messages into global namespace (since also used by Functions, Devices, ..)
  • unit clarifications of all parameters (e.g. timeInMs)
  • remove abbreviations
  • add documentation
  • cleanup namespaces to allow regular users to only include one namespace
    • Remove Devices and Hub Namespace
    • Move Knowledge back into Protocol namespace
    • Move shared usage enums into root namespace

Design: Deployment Plan

When designing a model we want to ensure that a hub and devices are correctly connected. Model to verify the correct connections.

Implement Combined Mode Notification Enabling

  • Use code sample from message-trace and productize it
  • Expose a function Device.CheckCombinedModeSupport to test mode combinations on devices and return a valid combination mode index (so of the array of possible combinations, find the position which is closest to the requested set). Rationale over constants exposing supported combinations on types: An implementer might use an abstract parent type like AbsoluteMotor where valid combinations would need to be explicitly tested.

Design

Task<bool> Device.TryLockDeviceForCombinedModeNotificationSetupAsync(params byte[] modeIndices);
Task Device.SetupNotificationAsync(byte modeIndex, bool enabled, ulong deltaInterval);
Task Device.UnlockFromCombinedModeNotificationSetupAsync(bool enableUpdates);

Brain Teaser ;)

Devices exposes supported combination of modes (X) as an array. These combined modes (X) are the only possible ones from the hardware but the user can restrict to a subset of modes (Y) from a given supported combination mode ones (X). When activating a supported combination (X) from by using the index (Z) in the array (X). After the initial selection of the combined mode using the index (Z) and additional selection of modes (W), the user can now format a subset of the modes (Y).

When decoding the Input, the decoder needs to know selected modes (Y). However, the upstreamed value is bit pointered to the array of active mode/dataset (W).

@Mattze0815 fyi

Add full-cycle awaitable Invocations (e.g. SwitchOffHub)

Typically a command is send out (which is an async operation) and then confirmed by the device with an incoming message.

Currently most operations are executing just the initial send operation and leave the API users with the synchronization effort for awaiting the response.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.