bricknil.sensor.peripheral

Base class for all sensors and motors

Classes

Peripheral(name[, port, capabilities]) Abstract base class for any Lego Boost/PoweredUp/WeDo peripherals

Members

class bricknil.sensor.peripheral.Peripheral(name, port=None, capabilities=[])[source]

Bases: bricknil.process.Process

Abstract base class for any Lego Boost/PoweredUp/WeDo peripherals

A LEGO sensor can provide either a single sensing capability, or a combined mode where it returns multiple sensing values. All the details can be found in the official protocol description.

  • Single capability - This is the easiest to handle:
    • Send a 0x41 Port Input Format Setup command to put the sensor port into the respective mode and activate updates
    • Read back the 0x45 Port Value(Single) messages with updates from the sensor on the respective mode
  • Multiple capabilities - This is more complicated because we need to put the sensor port into CombinedMode
    • Send a [0x42, port, 0x02] message to lock the port
    • Send multiple 0x41 messages to activate each capability/mode we want updates from
    • Send a [0x42, port, 0x01, ..] message with the following bytes:
      • 0x00 = Row entry 0 in the supported combination mode table
        (hard-coded for simplicity here because LEGO seems to only use this entry most of the time)
      • For each mode/capability, send a byte like the following:
        • Upper 4-bits is mode number
        • Lower 4-bits is the dataset number
        • For example, for getting RGB values, it’s mode 6, and we want all three datasets
          (for each color), so we’d add three bytes [0x60, 0x61, 0x62]. If you just wanted the Red value, you just append [0x60]
    • Send a [0x42, port, 0x03] message to unlock the port
    • Now, when the sensor sends back values, it uses 0x46 messages with the following byte sequence:
      • Port id
      • 16-bit entry where the true bits mark which mode has values included in this message
        (So 0x00 0x05 means values from Modes 2 and 0)
      • Then the set of values from the sensor, which are ordered by Mode number
        (so the sensor reading from mode 0 would come before the reading from mode 2)
      • Each set of values includes however many bytes are needed to represent each dataset
        (for example, up to 3 for RGB colors), and the byte-width of each value (4 bytes for a 32-bit int)
Parameters:
  • capabilities

    can be input in the following formats (where the number in the tuple can be a threshold to trigger updates)

    • [‘sense_color’, ‘sense_distannce’]
    • [capability.sense_color, capability.sense_distance]
    • [(‘sense_color’, 1), (‘sense_distance’, 2)]
  • name (str) – Human readable name
  • port (int) – Port to connect to (otherwise will connect to first matching peripheral with defined sensor_id)
port

Physical port on the hub this Peripheral attaches to

Type:int
sensor_name

Name coming out of const.DEVICES

Type:str
value

Sensor readings get dumped into this dict

Type:dict
message_handler

Outgoing message queue to BLEventQ that’s set by the Hub when an attach message is seen

Type:func
capabilites

Support capabilities

Type:list [ capability ]
thresholds

Integer list of thresholds for updates for each of the sensing capabilities

Type:list [ int ]
class Dataset(n, w, min, max)

Bases: tuple

Create new instance of Dataset(n, w, min, max)

max

Alias for field number 3

min

Alias for field number 2

n

Alias for field number 0

w

Alias for field number 1

activate_updates()[source]

Send a message to the sensor to activate updates

Called via an ‘attach’ message from bricknil.messages.Message.parse_attached_io() that triggers this call from bricknil.hub.Hub.peripheral_message_loop()

See class description for explanation on how Combined Mode updates are done.

Returns:None
send_message(msg, msg_bytes)[source]

Send outgoing message to BLEventQ

set_output(mode, value)[source]

Don’t change this unless you’re changing the way you do a Port Output command

Outputs the following sequence to the sensor
  • 0x00 = hub id from common header
  • 0x81 = Port Output Command
  • port
  • 0x11 = Upper nibble (0=buffer, 1=immediate execution), Lower nibble (0=No ack, 1=command feedback)
  • 0x51 = WriteDirectModeData
  • mode
  • value(s)
update_value(msg_bytes)[source]

Message from message_dispatch will trigger Hub to call this to update a value from a sensor incoming message Depending on the number of capabilities enabled, we end up with different processing:

If zero, then just set the self.value field to the raw message.

If one, then:
  • Parse the single sensor message which may have multiple data items (like an RGB color value)
  • self.value dict entry for this capability becomes a list of these values
If multiple, then:
  • Parse multiple sensor messages (could be any combination of the enabled modes)
  • Set each dict entry to self.value to either a list of multiple values or a single value