Source code for bluedot.mock

from .btcomm import BluetoothServer, BluetoothClient, BluetoothAdapter
from .dot import BlueDot
from .threads import WrapThread
from .constants import PROTOCOL_VERSION

CLIENT_NAME = "Mock client"

class MockBluetoothAdapter(BluetoothAdapter):
    def __init__(self, device = "mock0", address = "00:00:00:00:00:00"):
        self._device = device
        self._address = address
        self._powered = True
        self._discoverable = False
        self._pairable = False
        self._pairing_thread = None

    @property
    def powered(self):
        return self._powered

    @powered.setter
    def powered(self, value):
        self._powered = value

    @property
    def discoverable(self):
        return self._discoverable

    @discoverable.setter
    def discoverable(self, value):
        self._discoverable = value

    @property
    def pairable(self):
        return self._pairable

    @pairable.setter
    def pairable(self, value):
        self._pairable = value

    @property
    def paired_devices(self):
        return [["01:01:01:01:01:01", "mock_device_1"], ["02:02:02:02:02:02", "mock_device_2"]]


[docs]class MockBluetoothServer(BluetoothServer): """ :class:`MockBluetoothServer` inherits from :class:`~.btcomm.BluetoothServer` but overrides ``__init__``, :meth:`start` , :meth:`stop` and :meth:`send_raw` to create a :class:`MockBluetoothServer` which can be used for testing and debugging. """ def __init__(self, data_received_callback, auto_start = True, device = "mock0", port = 1, encoding = "utf-8", power_up_device = False, when_client_connects = None, when_client_disconnects = None): super(MockBluetoothServer, self).__init__( data_received_callback, auto_start, device, port, encoding, power_up_device, when_client_connects, when_client_disconnects) self._mock_client = None
[docs] def start(self): self._running = True
[docs] def stop(self): self._running = False
[docs] def mock_client_connected(self, mock_client = None): """ Simulates a client connected to the :class:`~.btcomm.BluetoothServer`. :param MockBluetoothClient mock_client: The mock client to interact with, defaults to `None`. If `None`, client address is set to '99:99:99:99:99:99' """ self._mock_client = mock_client if not self._client_connected: if self._mock_client is None: client_address = "99:99:99:99:99:99" else: client_address = self._mock_client.adapter.address self._client_connected = True self._client_info = (client_address, self.port) #call the call back if self.when_client_connects: WrapThread(target=self.when_client_connects).start()
[docs] def mock_client_disconnected(self): """ Simulates a client disconnecting from the :class:`~.btcomm.BluetoothServer`. """ if self._client_connected: self._client_connected = False self._client_info = None if self._when_client_disconnects: WrapThread(target=self.when_client_disconnects).start()
[docs] def mock_client_sending_data(self, data): """ Simulates a client sending data to the :class:`~.btcomm.BluetoothServer`. """ if self._client_connected: self._data_received_callback(data)
def _send_data(self, data): if self._mock_client is not None: # call the data received callback if self._encoding: data = data.decode(self._encoding) self._mock_client.mock_server_sending_data(data) def _setup_adapter(self, device): self._adapter = MockBluetoothAdapter(device)
[docs]class MockBluetoothClient(BluetoothClient): """ :class:`MockBluetoothClient` inherits from :class:`~.btcomm.BluetoothClient` but overrides ``__init__``, :meth:`connect` and :meth:`send_raw` to create a :class:`MockBluetoothServer` which can be used for testing and debugging. Note - the `server` parameter should be an instance of :class:`MockBluetoothServer`. """ def __init__(self, server, data_received_callback, port = 1, device = "mock1", encoding = "utf-8", power_up_device = False, auto_connect = True): super(MockBluetoothClient, self).__init__( server, data_received_callback, port, device, encoding, power_up_device, auto_connect)
[docs] def connect(self): """ Connect to a Bluetooth server. """ self._server.mock_client_connected(self) self._connected = True
[docs] def disconnect(self): """ Disconnect from a Bluetooth server. """ self._server.mock_client_disconnected() self._connected = False
[docs] def mock_server_sending_data(self, data): """ Simulates a server sending data to the :class:`~.btcomm.BluetoothClient`. """ if self._connected: self._data_received_callback(data)
def _send_data(self, data): # send data to the server # call the data received callback if self._encoding: data = data.decode(self._encoding) self._server.mock_client_sending_data(data) def _setup_adapter(self, device): self._adapter = MockBluetoothAdapter(device, address = "11:11:11:11:11:11")
[docs]class MockBlueDot(BlueDot): """ :class:`MockBlueDot` inherits from :class:`BlueDot` but overrides :meth:`_create_server`, to create a :class:`~.mock.MockBluetoothServer` which can be used for testing and debugging. """ def _create_server(self): self._server = MockBluetoothServer( self._data_received, when_client_connects = self._client_connected, when_client_disconnects = self._client_disconnected, device = self.device, port = self.port, power_up_device = self._power_up_device, auto_start = False)
[docs] def mock_client_connected(self): """ Simulates a client connecting to the Blue Dot. :param string client_address: The mock client mac address, defaults to '11:11:11:11:11:11' """ self._server.mock_client_connected() # send protocol version to server self._server.mock_client_sending_data("3,{},{}\n".format(PROTOCOL_VERSION, CLIENT_NAME))
[docs] def mock_client_disconnected(self): """ Simulates a client disconnecting from the Blue Dot. """ self._server.mock_client_disconnected()
[docs] def mock_blue_dot_pressed(self, col, row, x, y): """ Simulates the Blue Dot being pressed. :param int col: The column position of the button :param int row: The row position of the button :param int x: The x position where the button was pressed :param int y: The y position where the button was pressed """ self._server.mock_client_sending_data("1,{},{},{},{}\n".format(col, row, x, y))
[docs] def mock_blue_dot_released(self, col, row, x, y): """ Simulates the Blue Dot being released. :param int col: The column position of the button :param int row: The row position of the button :param int x: The x position where the button was released :param int y: The y position where the button was released """ self._server.mock_client_sending_data("0,{},{},{},{}\n".format(col, row, x, y))
[docs] def mock_blue_dot_moved(self, col, row, x, y): """ Simulates the Blue Dot being moved. :param int col: The column position of the button :param int row: The row position of the button :param int x: The x position where the button was moved too :param int y: The y position where the button was moved too """ self._server.mock_client_sending_data("2,{},{},{},{}\n".format(col, row, x, y))
[docs] def launch_mock_app(self): """ Launches a mock Blue Dot app. The mock app reacts to mouse clicks and movement and calls the mock blue dot methods to simulates presses. This is useful for testing, allowing you to interact with Blue Dot without having to script mock functions. The mock app uses pygame which will need to be installed. """ self._mock_app_thread = WrapThread(target=self._launch_mock_app) self._mock_app_thread.start()
def _launch_mock_app(self): # imported here, so pygame is only a pre-requisite for the mock app from .app import BlueDotClient, ButtonScreen class MockBlueDotClient(BlueDotClient): def _run(self): button_screen = MockButtonScreen(self._screen, self._font, self._device, self._server, self._port, self._width, self._height) button_screen.run() class MockButtonScreen(ButtonScreen): def _connect(self): self.bt_client = MockBluetoothClient(self.server, self._data_received, device = self.device, auto_connect = True) MockBlueDotClient("mock2", self._server, self._port, None, None, None)