Ejemplo n.º 1
0
    def __init__(self, service=None):
        _server_tx = StreamOut(
            uuid=VendorUUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
            timeout=5.0,
            buffer_size=512,
        )
        _server_rx = StreamIn(
            uuid=VendorUUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
            timeout=5.0,
            buffer_size=512,
        )

        super().__init__(service=service)
Ejemplo n.º 2
0
class CustomUART(Service):

    uuid = VendorUUID("8ba86973-935c-447c-91ad-bdcbad575f31")
    _server_rx = StreamIn(
        uuid=VendorUUID("8ba86974-935c-447c-91ad-bdcbad575f31"),
        timeout=1.0,
        buffer_size=64,
    )

    def __init__(self, service=None):
        # just steal the uuid code from MIDISerivce

        super().__init__(service=service)
        self.connectable = True
        self._rx = self._server_rx

    def read(self, nbytes=None):
        return self._rx.read(nbytes)
Ejemplo n.º 3
0
class CatPrinter(Service):

    uuid = StandardUUID(0xAE30)

    _tx = StreamIn(uuid=StandardUUID(0xAE01), timeout=1.0, buffer_size=256)

    def _write_data(self, buf):
        self._tx.write(buf)

    @property
    def bitmap_width(self):
        return 384

    def __init__(self, service=None):
        super().__init__(service=service)
        self._mode = None

    @property
    def mode(self):
        return self._mode

    @mode.setter
    def mode(self, value):
        if value == self.mode:
            return

        if value == MODE_TEXT:
            self._write_data(printtext)
        elif value == MODE_BITMAP:
            self._write_data(printimage)
        else:
            raise ValueError("Invalid mode %r" % value)

        self._mode = value

    def feed_lines(self, lines):
        buf = bytearray(paperfeed)
        buf[6] = lines & 0xFF
        buf[7] = lines >> 8
        buf[8] = checksum(buf, 6, 2)
        self._write_data(buf)

    def _print_common(self, text, reverse_bits=True):
        data = memoryview(text)
        while data:
            sz = min(112, len(data))
            sub_data = data[:sz]
            data = data[sz:]
            buf = bytearray(sz + 8)
            buf[0] = 0x51
            buf[1] = 0x78
            buf[2] = 0xA2
            buf[3] = 0x0
            buf[4] = sz
            buf[5] = 0
            if reverse_bits:
                buf[6:6 + sz] = bytes(mirrortable[c] for c in sub_data)
            else:
                buf[6:6 + sz] = sub_data
            buf[6 + sz] = checksum(buf, 6, len(sub_data))
            buf[6 + sz + 1] = 0xFF

            self._write_data(buf)

    def print_text(self, text):
        self.mode = MODE_TEXT
        self._print_common(text.encode("utf-8"))

    def print_line(self, text):
        self.print_text(text)
        self._print_common(b"\n")

    def print_bitmap_row(self, data, reverse_bits=True):
        self.mode = MODE_BITMAP
        self._print_common(data, reverse_bits)
Ejemplo n.º 4
0
class TransparentUARTService(Service):
    """
    Provide UART-like functionality via MicroChip

    :param int timeout:  the timeout in seconds to wait
      for the first character and between subsequent characters.
    :param int buffer_size: buffer up to this many bytes.
      If more bytes are received, older bytes will be discarded.
    """

    # pylint: disable=no-member
    uuid = VendorUUID("49535343-FE7D-4AE5-8FA9-9FAFD205E455")
    _server_tx = StreamOut(
        uuid=VendorUUID("49535343-1E4D-4BD9-BA61-23C647249616"),
        timeout=1.0,
        buffer_size=64,
    )
    _server_rx = StreamIn(
        uuid=VendorUUID("49535343-8841-43F4-A8D4-ECBE34729BB3"),
        timeout=1.0,
        buffer_size=64,
    )

    def __init__(self, service=None):
        super().__init__(service=service)
        self.connectable = True
        if not service:
            self._rx = self._server_rx
            self._tx = self._server_tx
        else:
            # If we're a client then swap the characteristics we use.
            self._tx = self._server_rx
            self._rx = self._server_tx

    def read(self, nbytes=None):
        """
        Read characters. If ``nbytes`` is specified then read at most that many bytes.
        Otherwise, read everything that arrives until the connection times out.
        Providing the number of bytes expected is highly recommended because it will be faster.

        :return: Data read
        :rtype: bytes or None
        """
        return self._rx.read(nbytes)

    def readinto(self, buf, nbytes=None):
        """
        Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
        that many bytes. Otherwise, read at most ``len(buf)`` bytes.

        :return: number of bytes read and stored into ``buf``
        :rtype: int or None (on a non-blocking error)
        """
        return self._rx.readinto(buf, nbytes)

    def readline(self):
        """
        Read a line, ending in a newline character.

        :return: the line read
        :rtype: bytes or None
        """
        return self._rx.readline()

    @property
    def in_waiting(self):
        """The number of bytes in the input buffer, available to be read."""
        return self._rx.in_waiting

    def reset_input_buffer(self):
        """Discard any unread characters in the input buffer."""
        self._rx.reset_input_buffer()

    def write(self, buf):
        """Write a buffer of bytes."""
        self._tx.write(buf)
class AppleNotificationCenterService(Service):
    """Notification service.

    Documented by Apple here:
      https://developer.apple.com/library/archive/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Specification/Specification.html

    """

    uuid = VendorUUID("7905F431-B5CE-4E99-A40F-4B1E122D00D0")

    control_point = StreamIn(
        uuid=VendorUUID("69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9"))
    data_source = StreamOut(
        uuid=VendorUUID("22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB"),
        buffer_size=1024)
    notification_source = StreamOut(
        uuid=VendorUUID("9FBF120D-6301-42D9-8C58-25E699A21DBD"),
        buffer_size=8 * 100)

    def __init__(self, service=None):
        super().__init__(service=service)
        self._active_notifications = {}

    def _update(self):
        # Pylint is incorrectly inferring the type of self.notification_source so disable no-member.
        while self.notification_source.in_waiting > 7:  # pylint: disable=no-member
            buffer = self.notification_source.read(8)  # pylint: disable=no-member
            event_id, event_flags, category_id, category_count, nid = struct.unpack(
                "<BBBBI", buffer)
            if event_id == 0:
                self._active_notifications[nid] = Notification(
                    nid,
                    event_flags,
                    category_id,
                    category_count,
                    control_point=self.control_point,
                    data_source=self.data_source,
                )
                yield self._active_notifications[nid]
            elif event_id == 1:
                self._active_notifications[nid].update(event_flags,
                                                       category_id,
                                                       category_count)
                yield None
            elif event_id == 2:
                self._active_notifications[nid].removed = True
                del self._active_notifications[nid]
                yield None

    def wait_for_new_notifications(self, timeout=None):
        """Waits for new notifications and yields them. Returns on timeout, update, disconnect or
           clear."""
        start_time = time.monotonic()
        while timeout is None or timeout > time.monotonic() - start_time:
            try:
                new_notification = next(self._update())
            except StopIteration:
                return
            if new_notification:
                yield new_notification

    @property
    def active_notifications(self):
        """A dictionary of active notifications keyed by id."""
        for _ in self._update():
            pass
        return self._active_notifications
Ejemplo n.º 6
0
class NameService(Service):
    uuid = StandardUUID(0xfeef)
    _disp_rx = StreamIn(uuid=StandardUUID(0xfeee), timeout=1.0, buffer_size=8192)

    def __init__(self):
        super().__init__()
        self._bitmap = displayio.Bitmap(badge.display.width, badge.display.height, 2)
        self._palette = displayio.Palette(2)
        self._palette[0] = 0x000000
        self._palette[1] = 0xffffff
        self._offset = 0
        self._bufsize = 0
        self._ledstate = False
     
    def update(self):
        while self._disp_rx.in_waiting > 0:
            if self._bufsize == 0:
                value = int.from_bytes(self._disp_rx.read(1), 'little')
                if value == 0:
                    self._finish_update()
                    continue
                self._bufsize = value & 0x7f
                if value & 0x80:
                    self._offset = None
            if self._offset is None and self._disp_rx.in_waiting >= 2:
                self._offset = int.from_bytes(self._disp_rx.read(2), 'little')
            if self._bufsize > 0 and self._offset is not None:
                data = self._disp_rx.read(min(self._bufsize, self._disp_rx.in_waiting))
                self._bufsize -= len(data)
                for i in range(len(data)):
                    for bit in range(8):
                        self._bitmap[self._offset*8+bit] = 1 if data[i] & (1 << bit) else 0
                    self._offset += 1
                self._ledstate = not self._ledstate
                badge.pixels.fill((0, 0, 0x10 * self._ledstate))
                # TODO: once we have partial refresh, it'd be nice to draw the new pixels
                # on screen as we receive them

    def _store_bitmap(self):
        try:
            storage.remount('/', False)
        except:
            pass
        try:
            bitmap_save('/nametag.bmp', self._bitmap)
        except Exception as err:
            print("Couldn't save file: {}".format(err))
        try:
            storage.remount('/', True)
        except:
            pass
    
    def _finish_update(self):
        print("Update done!")
        self._offset = 0
        self._bufsize = 0
        self._ledstate = False
        badge.pixels.fill((0, 0x10, 0))
        frame = displayio.Group()
        frame.append(displayio.TileGrid(self._bitmap, pixel_shader=self._palette))
        badge.display.show(frame)
        while badge.display.time_to_refresh > 0:
            pass
        badge.display.refresh()
        self._store_bitmap()