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)
-
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 frombricknil.hub.Hub.peripheral_message_loop()
See class description for explanation on how Combined Mode updates are done.
Returns: None
-
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