class MicrophoneService(AdafruitService): # pylint: disable=too-few-public-methods """Digital microphone data.""" uuid = AdafruitService.adafruit_service_uuid(0xB00) sound_samples = Characteristic( uuid=AdafruitService.adafruit_service_uuid(0xB01), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, max_length=512, ) """ Array of 16-bit sound samples, varying based on period. If num_channel == 2, the samples alternate left and right channels. """ number_of_channels = Uint8Characteristic( uuid=AdafruitService.adafruit_service_uuid(0xB02), properties=Characteristic.READ, write_perm=Attribute.NO_ACCESS, ) """1 for mono, 2 for stereo (left and right)""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class GestureService(AdafruitService): # pylint: disable=too-few-public-methods """Gesture sensor.""" UP = 1 # pylint: disable=invalid-name """swipe up""" DOWN = 2 """swipe down""" LEFT = 3 """swipe left""" RIGHT = 4 """swipe right""" uuid = AdafruitService.adafruit_service_uuid(0xF00) gesture = Uint8Characteristic( uuid=AdafruitService.adafruit_service_uuid(0xF01), properties=(Characteristic.READ | Characteristic.NOTIFY), read_perm=Attribute.OPEN, write_perm=Attribute.NO_ACCESS, ) """ 0: no gesture 1: swipe up (`UP`) 2: swipe down (`DOWN`) 3: swipe left (`LEFT`) 4: swipe right (`RIGHT`) """ measurement_period = AdafruitService.measurement_period_charac(0) """Initially 0: send notification only on changes. -1 means stop reading."""
class QuaternionService(AdafruitService): # pylint: disable=too-few-public-methods """Quaternion values.""" uuid = AdafruitService.adafruit_service_uuid(0xD00) quaternion = StructCharacteristic( "<ffff", uuid=AdafruitService.adafruit_service_uuid(0xD01), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Tuple (qw, qx, qy, qz) of float quaternion values.""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms.""" calibration_in = StructCharacteristic( "<fffffffff", uuid=AdafruitService.adafruit_service_uuid(0xD02), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """ 9-tuple of floats sent to client for calibration calculation: acceleration x, y, z, # in m/s^2 gyro x, y, z, # in rad/s magnetic x, y, z, # in microteslas """ calibration_out = StructCharacteristic( "<fffffffffffffffffff", uuid=AdafruitService.adafruit_service_uuid(0xD03), properties=(Characteristic.WRITE), read_perm=Attribute.NO_ACCESS, ) """
class TemperatureService(AdafruitService): # pylint: disable=too-few-public-methods """Temperature sensor.""" uuid = AdafruitService.adafruit_service_uuid(0x100) temperature = FloatCharacteristic( uuid=AdafruitService.adafruit_service_uuid(0x101), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Temperature in degrees Celsius (float).""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class LightSensorService(AdafruitService): # pylint: disable=too-few-public-methods """Light sensor value.""" uuid = AdafruitService.adafruit_service_uuid(0x300) light_level = FloatCharacteristic( uuid=AdafruitService.adafruit_service_uuid(0x301), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Uncalibrated light level (float)""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class BarometricPressureService(AdafruitService): # pylint: disable=too-few-public-methods """Barometric pressure value.""" uuid = AdafruitService.adafruit_service_uuid(0x800) pressure = FloatCharacteristic( uuid=AdafruitService.adafruit_service_uuid(0x801), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Barometric pressure in hectoPascals (hPa) (float)""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class HumidityService(AdafruitService): # pylint: disable=too-few-public-methods """Humidity sensor value.""" uuid = AdafruitService.adafruit_service_uuid(0x700) humidity = FloatCharacteristic( uuid=AdafruitService.adafruit_service_uuid(0x701), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Relative humidity as a percentage, 0.0% - 100.0% (float)""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class GyroscopeService(AdafruitService): # pylint: disable=too-few-public-methods """Gyroscope values.""" uuid = AdafruitService.adafruit_service_uuid(0x400) gyro = StructCharacteristic( "<fff", uuid=AdafruitService.adafruit_service_uuid(0x401), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Tuple (x, y, z) float gyroscope values, in rad/s""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class MagnetometerService(AdafruitService): # pylint: disable=too-few-public-methods """Magnetometer values.""" uuid = AdafruitService.adafruit_service_uuid(0x500) magnetic = StructCharacteristic( "<fff", uuid=AdafruitService.adafruit_service_uuid(0x501), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Tuple (x, y, z) float magnetometer values, in micro-Teslas (uT)""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class AccelerometerService(AdafruitService): # pylint: disable=too-few-public-methods """Accelerometer values.""" uuid = AdafruitService.adafruit_service_uuid(0x200) acceleration = StructCharacteristic( "<fff", uuid=AdafruitService.adafruit_service_uuid(0x201), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Tuple (x, y, z) float acceleration values, in m/s^2""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class ColorSensorService(AdafruitService): # pylint: disable=too-few-public-methods """Color sensor value.""" uuid = AdafruitService.adafruit_service_uuid(0xA00) acceleration = StructCharacteristic( "<HHH", uuid=AdafruitService.adafruit_service_uuid(0xA01), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Tuple (r, g, b) red/green/blue color values, each in range 0-65535 (16 bits)""" measurement_period = AdafruitService.measurement_period_charac() """Initially 1000ms."""
class ToneService(AdafruitService): """Play tones.""" uuid = AdafruitService.adafruit_service_uuid(0xC00) _tone_packet = _TonePacket() """ Tuple of (frequency: 16 bits, in Hz, duration: 32 bits, in msecs). If frequency == 0, a tone being played is turned off. if duration == 0, play indefinitely. """ def __init__(self, service=None): super().__init__(service=service) self._tone_packet_buf = bytearray(_TonePacket.format_size) @property def tone(self): """Return (frequency, duration), or None if no value available""" buf = self._tone_packet_buf if self._tone_packet.readinto(buf) == 0: # No new values available. return None return struct.unpack(_TonePacket.format, buf) def play(self, frequency, duration): """ Frequency is in Hz. If frequency == 0, a tone being played is turned off. Duration is in seconds. If duration == 0, play indefinitely. """ self._tone_packet = struct.pack( _TonePacket.format, frequency, 0 if duration == 0 else int(duration * 1000 + 0.5), )
class ProximityService(AdafruitService): # pylint: disable=too-few-public-methods """Status of buttons and switches on the board.""" uuid = AdafruitService.adafruit_service_uuid(0xE00) proximity = Uint16Characteristic( uuid=AdafruitService.adafruit_service_uuid(0xE01), properties=(Characteristic.READ | Characteristic.NOTIFY), read_perm=Attribute.OPEN, write_perm=Attribute.NO_ACCESS, ) """ A higher number indicates a closer distance to the sensor. The value is unit-less. """ measurement_period = AdafruitService.measurement_period_charac(0) """Initially 0: send notification only on changes. -1 means stop reading."""
class EnvironmentalSensingService(Service): uuid = StandardUUID(0x181a) """Initially 10s.""" measurement_period = Int32Characteristic( uuid=AdafruitService.adafruit_service_uuid(0x0001), properties=(Characteristic.READ | Characteristic.WRITE), initial_value=10000, ) """Temperature in degrees Celsius (Uint16).""" temperature = Int16Characteristic( uuid=StandardUUID(0x2a6e), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Relative humidity as a percentage, 0.0% - 100.0% (Uint16)""" humidity = Uint16Characteristic( uuid=StandardUUID(0x2a6f), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Barometric pressure in hectoPascals (hPa) (Uint16)""" pressure = Uint16Characteristic( uuid=StandardUUID(0x2a6d), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, ) """Uncalibrated light level (Uint16)""" light_level = Uint16Characteristic( uuid=StandardUUID(0x2a77), properties=(Characteristic.READ | Characteristic.NOTIFY), write_perm=Attribute.NO_ACCESS, )
class AddressablePixelService(AdafruitService): """Control of NeoPixels, DotStars, etc.""" uuid = AdafruitService.adafruit_service_uuid(0x900) pixel_pin = Uint8Characteristic( uuid=AdafruitService.adafruit_service_uuid(0x901), properties=(Characteristic.READ | Characteristic.WRITE), ) """Send data out on this pin.""" pixel_pin_type = Uint8Characteristic( uuid=AdafruitService.adafruit_service_uuid(0x902), properties=(Characteristic.READ | Characteristic.WRITE), ) pixel_buffer_size = Uint16Characteristic( uuid=AdafruitService.adafruit_service_uuid(0x904), properties=(Characteristic.READ | Characteristic.WRITE), initial_value=_PixelPacket.MAX_LENGTH, ) """ 0 = WS2812 (NeoPixel), 800kHz 1 = SPI (APA102: DotStar) """ _pixel_packet = _PixelPacket() """Pixel-setting data.""" def __init__(self, service=None): self._pixel_packet_buf = bytearray(_PixelPacket.MAX_LENGTH) super().__init__(service=service) @property def values(self): """Return a tuple (start, write_now, data) corresponding to the different parts of ``_pixel_packet``. """ buf = self._pixel_packet_buf num_read = self._pixel_packet.readinto(buf) # pylint: disable=no-member if num_read == 0: # No new values available return None return PixelValues( struct.unpack_from("<H", buf)[0], bool(buf[2] & 0x1), buf[3:num_read], )
class ButtonService(AdafruitService): """Status of buttons and switches on the board.""" uuid = AdafruitService.adafruit_service_uuid(0x600) pressed = Uint32Characteristic( uuid=AdafruitService.adafruit_service_uuid(0x601), properties=(Characteristic.READ | Characteristic.NOTIFY), read_perm=Attribute.OPEN, write_perm=Attribute.NO_ACCESS, ) """ bit 0: slide switch: 1 for left; 0 for right bit 1: 1 if button A is pressed bit 2: 1 if button B is pressed other bits are available for future buttons and switches """ measurement_period = AdafruitService.measurement_period_charac(0) """Initially 0: send notification only on changes. -1 means stop reading.""" def set_pressed(self, switch, button_a, button_b): """Update the pressed value all at once.""" pressed = 0 if switch: pressed |= 0x1 if button_a: pressed |= 0x2 if button_b: pressed |= 0x4 if pressed != self.pressed: self.pressed = pressed @property def switch(self): """``True`` when the slide switch is set to the left; ``False`` when to the right.""" return bool(self.pressed & 0x1) @property def button_a(self): """``True`` when Button A is pressed.""" return bool(self.pressed & 0x2) @property def button_b(self): """``True`` when Button B is pressed.""" return bool(self.pressed & 0x4)
class _TonePacket(ComplexCharacteristic): uuid = AdafruitService.adafruit_service_uuid(0xC01) format = "<HI" format_size = struct.calcsize(format) def __init__(self): super().__init__( properties=Characteristic.WRITE, read_perm=Attribute.NO_ACCESS, max_length=self.format_size, fixed_length=True, ) def bind(self, service): """Binds the characteristic to the given Service.""" bound_characteristic = super().bind(service) return PacketBuffer(bound_characteristic, buffer_size=1)
class ExplorationService(AdafruitService): # robot searches for sun uuid = AdafruitService.adafruit_service_uuid(0x550) _exploration_packet = _ExplorationPacket() def __init__(self, service=None): super().__init__(service=service) self._exploration_packet_buf = bytearray( _ExplorationPacket.format_size) @property def exploration(self): buf = self._exploration_packet_buf if self._exploration_packet.readinto(buf) == 0: # No new values available. return None return struct.unpack(_ExplorationPacket.format, buf) def explore(self, go, stop): self._exploration_packet = struct.pack(_ExplorationPacket.format, go, stop)
class _PixelPacket(ComplexCharacteristic): """ start: uint16: start writing data into buffer at this byte number (byte, not pixel) flags: uint8: bit 0: 0 = don't write to pixels yet 1 = write entire buffer to pixels now data: raw array of data for all pixels, in proper color order for type of pixel """ MAX_LENGTH = 512 uuid = AdafruitService.adafruit_service_uuid(0x903) def __init__(self): super().__init__( properties=Characteristic.WRITE, read_perm=Attribute.NO_ACCESS, max_length=self.MAX_LENGTH, ) def bind(self, service): """Binds the characteristic to the given Service.""" bound_characteristic = super().bind(service) return _bleio.PacketBuffer(bound_characteristic, buffer_size=1)
class DriveService(AdafruitService): # Make robo go zoom zoom uuid = AdafruitService.adafruit_service_uuid(0x220) _drive_packet = _DrivePacket() def __init__(self, service=None): super().__init__(service=service) self._drive_packet_buf = bytearray(_DrivePacket.format_size) @property def drive(self): """Return (forward, backward, left, right), or None if no value available""" buf = self._drive_packet_buf if self._drive_packet.readinto(buf) == 0: # No new values available. return None return struct.unpack(_DrivePacket.format, buf) def move(self, forward, backward, left, right): self._drive_packet = struct.pack( _DrivePacket.format, forward, backward, left, right )