# SPDX-License-Identifier: MIT # Copyright (C) 2020 The Pybricks Authors from _thread import allocate_lock from errno import ECONNRESET from struct import pack, unpack from .bluetooth import ( BDADDR_ANY, ThreadingRFCOMMServer, ThreadingRFCOMMClient, StreamRequestHandler, ) def resolve(brick): """Fake resolver to get address from Bluetooth name. To connect to an EV3 server, you must specify its full address. """ return brick class Mailbox: def __init__(self, name, connection, encode=None, decode=None): """Object that represents a mailbox for sending an receiving messages from other connected devices. Arguments: name (str): The name of this mailbox. connection: A connection object that implements the mailbox connection interface. encode: A function that encodes an object into a bytes-like object. decode: A function that decodes an object from a bytes-like object. """ self.name = name self._connection = connection if encode: self.encode = encode if decode: self.decode = decode def encode(self, value): return value def decode(self, payload): return payload def read(self): """Reads the current value of the mailbox. Returns: The decoded value or ``None`` if the mailbox has never received a value. """ data = self._connection.read_from_mailbox(self.name) if data is None: return None return self.decode(data) def send(self, value, destination=None): """Sends a value to remote mailboxes with the same name as this mailbox. Arguments: value: The value to send. destination: The name or address of a specific device or ``None`` to broadcast to all connected devices. """ data = self.encode(value) self._connection.send_to_mailbox(destination, self.name, data) def wait(self): """Waits for the mailbox to receive a message.""" self._connection.wait_for_mailbox_update(self.name) def wait_new(self): """Waits for the mailbox to receive a message that is different from the current contents of the mailbox. Returns: The new value. (Same as return value of :meth:`read`.) """ old = self.read() while True: self.wait() new = self.read() if new != old: return new class LogicMailbox(Mailbox): """:class:`Mailbox` that holds a logic or boolean value. This is compatible with the "logic" message blocks in the standard EV3 firmware. """ def encode(self, value): return b"\x01" if value else b"\x00" def decode(self, payload): return bool(payload[0]) class NumericMailbox(Mailbox): """:class:`Mailbox` that holds a numeric or floating point value. This is compatible with the "numeric" message blocks in the standard EV3 firmware. """ def encode(self, value): return pack("