Skip to content

Discussion surrounding a new paradigm for talking to attached devices #49

@nathankellenicki

Description

@nathankellenicki

Something which has been on my mind for a while (which recently came up in a not-entirely-unrelated issue) has been a new paradigm for talking to devices attached to hubs.

Problem Space

Here are a few examples of the current design, and where it falls short.

hub.setMotorSpeed("A", 50);

This method allows you to start running the motor attached to port "A" at a speed 50 constantly. It does no checking against the type of device actually attached to the port, and therefore may or may not work. For example, it will work just fine with an attached light (setting the brightness to half), but will fail against a color sensor.

If device type checking would be added, it would be a lengthy list of compatible devices, which could potentially get out of date as new devices are added.

Similarly:

hub.setLightBrightness("A", 50);

Pretty much does the same as the above, but with less logic. For example setMotorSpeed() changes the underlying command depending on the attached motor and hub combination. However this doesn't - so it may set a motor running at half speed, it may not.

This method is used for rotating a tacho motor to a specified angle:

hub.setMotorAngle("A", 50, 100);

It won't work against non-tacho motors, so a device type check is done at the start of the method (see above comment). As new devices are released with this capability, the method needs to be changed to add more devices to the device check. A similar problem exists with setAbsoluteSpeed().

Another example is for setting the color of the LED on the hub. This is done like so:

hub.setLEDColor(Consts.Color.PINK);

However the color of the LED on attached color sensor can also be changed, which this library doesn't support at the moment. Were it to support it, what would the solution be? Do we add an optional port argument to the method? Or do we create an entirely new method named something along the lines of setLEDColorOnColorSensor()? Neither seem ideal.

Current Proposal

Having thought about this for a little while, an approach that keeps coming to me is to create an individual class for each device, such as SimpleMotor, TrainMotor, BoostMotor, Light, DistanceSensor, TiltSensor, etc.

When one is attached to a hub, an "attach" event is emitted as normal, however instead of having the type id as a parameter, it would contain an instance of the device class, like so:

hub.on("attach", (port, device) => {
    console.log(`Device attached - port ${port}, type ${device.type}`);
    if (device instanceof Light) {
        const light = device;
        light.setBrightness(50); // Set half brightness
    } else if (device instanceof BoostMotor) {
        const motor = device;
        motor.rotateByAngle(66, 100); // Rotate by 66 degrees at full speed
    }
});

Or, you could retrieve the device from the hub:

hub.getDeviceAtPort("A").setBrightness(50); // Assuming the device on port A is a light

Having an individual class for each device or device type would also allow greater control of the various modes each device supports, which while already supported by this library through the subscribe method, is not at all bug free.

For example, the following examples could be implemented:

colorSensor.enableProximityMode();

Which would result in proximity events being emitted. Or:

colorSensor.enableCountMode();

Which would result in count events being emitted.

Or even combining them (and subsequently separating them) using the ability of the LEGO Wireless Protocol to combine modes:

colorSensor.enableProximityMode();
colorSensor.enableCountMode();

Which could result in both events being emitted, or even a new combined event (proximityAndCount) with the values of both.

And then:

colorSensor.disableCountMode();

Dynamically reverting to proximity events only.

Closing

This solution doesn't solve all problems, and could be quite tricky to implement. For example taking care to prevent modes being combined that can't be combined. However any further thoughts or suggestions by anyone is interested is welcome. :)

(cc'ing previous participants @nutki, @aileo, @dlech)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions