def __init__(self, redraw_last_image_func): self.__redraw_last_image_func = redraw_last_image_func self.__spi_bus = self.__get_spi_bus_from_ptdm() self.__device = None self.lock = PTLock("miniscreen") self.__ptdm_subscribe_client = None self.__setup_subscribe_client() atexit.register(self.__clean_up)
def test_acquire_locks_all_instances(self): lock1 = PTLock(self.__dummy_lock_id) lock2 = PTLock(self.__dummy_lock_id) lock1.acquire() for lock in (lock1, lock2): self.assertTrue(lock.is_locked()) lock1.release()
def __init__(self, device_path: str, device_address: int): self._device_path = device_path self._device_address = device_address self._post_read_delay = 0.020 self._post_write_delay = 0.020 self._lock = PTLock(f"i2c_{device_address:#0{4}x}") self._read_device = None self._write_device = None
def test_is_locked_method(self): lock1 = PTLock(self.__dummy_lock_id) lock2 = PTLock(self.__dummy_lock_id) lock1.acquire() for lock in (lock1, lock2): self.assertTrue(lock.is_locked()) lock1.release() for lock in (lock1, lock2): self.assertFalse(lock.is_locked())
def test_acquire_locks_thread_until_unlocked(self): def acquire_lock(_lock: PTLock): _lock.acquire() lock = PTLock(self.__dummy_lock_id) lock.acquire() lock2 = PTLock(self.__dummy_lock_id) thread = Thread(target=acquire_lock, args=[lock2]) thread.start() self.assertTrue(thread.is_alive()) lock.release() thread.join() self.assertFalse(thread.is_alive())
def acquire_lock(_lock: PTLock): _lock.acquire()
def test_release_an_unlocked_lock_returns_false(self): lock = PTLock(self.__dummy_lock_id) self.assertFalse(lock.release())
def test_release_a_locked_lock_by_other_object_fails(self): lock1 = PTLock(self.__dummy_lock_id) self.assertTrue(lock1.acquire()) lock2 = PTLock(self.__dummy_lock_id) self.assertFalse(lock2.release())
def test_release_a_locked_lock_by_same_object_returns_true(self): lock = PTLock(self.__dummy_lock_id) self.assertTrue(lock.acquire()) self.assertTrue(lock.release())
def test_acquire_an_already_acquired_lock_by_same_object_fails(self): lock = PTLock(self.__dummy_lock_id) self.assertTrue(lock.acquire()) self.assertFalse(lock.acquire())
def test_acquire_success(self): lock = PTLock(self.__dummy_lock_id) self.assertTrue(lock.acquire())
def test_chmod_is_called_if_file_doesnt_exist(self, exists_mock): _ = PTLock(self.__dummy_lock_id) exists_mock.assert_called_once_with(self.lock_file_path) mock_os.chmod.assert_called_once_with(self.lock_file_path, 146)
def test_instance_opens_file(self, m): _ = PTLock(self.__dummy_lock_id) m.assert_called_with(self.lock_file_path, "w")
class OledDeviceController: SPI_DEVICE = 0 SPI_BUS_SPEED_HZ = 8000000 SPI_TRANSFER_SIZE = 4096 # TODO: drop 'redraw last image' logic at v1.0.0 # # this is only necessary to support users with SPI0 on device # with older SDK version that only supported SPI1 def __init__(self, redraw_last_image_func): self.__redraw_last_image_func = redraw_last_image_func self.__spi_bus = self.__get_spi_bus_from_ptdm() self.__device = None self.lock = PTLock("miniscreen") self.__ptdm_subscribe_client = None self.__setup_subscribe_client() atexit.register(self.__clean_up) def __setup_subscribe_client(self): def on_spi_bus_changed(parameters): self.__spi_bus = int(parameters[0]) self.reset_device() self.__redraw_last_image_func() self.__ptdm_subscribe_client = PTDMSubscribeClient() self.__ptdm_subscribe_client.initialise( {Message.PUB_OLED_SPI_BUS_CHANGED: on_spi_bus_changed} ) self.__ptdm_subscribe_client.start_listening() def __clean_up(self): try: self.__ptdm_subscribe_client.stop_listening() except Exception: pass def __set_controls(self, controlled_by_pi): message = Message.from_parts( Message.REQ_SET_OLED_CONTROL, [str(int(controlled_by_pi))] ) with PTDMRequestClient() as request_client: request_client.send_message(message) def __setup_device(self): if getenv("PT_MINISCREEN_SYSTEM", "0") != "1": self.lock.acquire() atexit.register(self.reset_device) self.__device = sh1106( serial_interface=spi( port=self.__spi_bus, device=self.SPI_DEVICE, bus_speed_hz=self.SPI_BUS_SPEED_HZ, transfer_size=self.SPI_TRANSFER_SIZE, gpio_DC=17 if self.__spi_bus == 1 else 7, # Always use CE1 gpio_RST=None, ), rotate=0, ) def __get_spi_bus_from_ptdm(self): message = Message.from_parts(Message.REQ_GET_OLED_SPI_BUS) with PTDMRequestClient() as request_client: response = request_client.send_message(message) return int(response.parameters[0]) ############################## # Public methods ############################## def device_is_active(self): return self.lock.is_locked() def reset_device(self): self.__device = None if self.device_is_active(): self.lock.release() def get_device(self): if self.__device is None: self.__setup_device() return self.__device def set_control_to_pi(self): self.__set_controls(controlled_by_pi=True) def set_control_to_hub(self): self.__set_controls(controlled_by_pi=False) @property def spi_bus(self): return self.__spi_bus @spi_bus.setter def spi_bus(self, bus): """Request SPI bus change from pi-top device manager.""" assert bus in range(0, 2) if self.__spi_bus == bus: return message = Message.from_parts(Message.REQ_SET_OLED_SPI_BUS, [str(bus)]) with PTDMRequestClient() as request_client: request_client.send_message(message)