117 lines
2.7 KiB
Python
117 lines
2.7 KiB
Python
from time import sleep
|
|
from typing import Optional, List
|
|
|
|
from biopro.impl.gpio import P3Pin
|
|
from biopro.impl.interface_spi import SoftwareImplSpiInterface
|
|
from biopro.impl.led import LED, AbstractLEDKeyFrame
|
|
from biopro.util.console import WHITE
|
|
from biopro.util.logger import logging_verbose
|
|
from .socket import ServerThread
|
|
|
|
|
|
class LEDControlThread(ServerThread):
|
|
|
|
def __init__(self,
|
|
disable=False,
|
|
led_count=16,
|
|
refresh_mode=True):
|
|
super().__init__('LED', WHITE)
|
|
|
|
self._disable = disable or led_count <= 0
|
|
self._refresh_mode = refresh_mode
|
|
|
|
# LED
|
|
self._led_count = led_count
|
|
|
|
# SPI
|
|
self._spi: Optional[SoftwareImplSpiInterface] = None
|
|
|
|
if not disable:
|
|
self._spi = SoftwareImplSpiInterface(P3Pin.LED_SCL, P3Pin.LED_SDA)
|
|
|
|
self._led = LED(self._led_count, self._spi)
|
|
|
|
#
|
|
self._state = LED.POWER_ON
|
|
|
|
# player
|
|
self._track: List[AbstractLEDKeyFrame] = []
|
|
self._index = 0
|
|
|
|
@property
|
|
def is_disabled(self) -> bool:
|
|
return self._disable
|
|
|
|
@property
|
|
def state(self) -> str:
|
|
return self._state
|
|
|
|
@property
|
|
def led_count(self) -> int:
|
|
return self._led_count
|
|
|
|
@property
|
|
def refresh_mode(self) -> bool:
|
|
return self._refresh_mode
|
|
|
|
def setup(self) -> None:
|
|
super().setup()
|
|
|
|
self.set_state(self._state)
|
|
|
|
def shutdown(self) -> None:
|
|
self._led.light_off()
|
|
|
|
if self._spi is not None:
|
|
self._spi.close()
|
|
|
|
def routine(self, event = None) -> None:
|
|
if len(self._track) == 0:
|
|
event.wait(5)
|
|
else:
|
|
sleep_time = self._next_keyframe()
|
|
|
|
if sleep_time == 0.0:
|
|
event.wait(5)
|
|
else:
|
|
event.wait(sleep_time)
|
|
return None
|
|
|
|
@logging_verbose
|
|
def set_state(self, state: str):
|
|
if state in LED.COLOR:
|
|
self._state = state
|
|
|
|
c = LED.COLOR[state]
|
|
|
|
if isinstance(c, AbstractLEDKeyFrame):
|
|
self._led.update(c)
|
|
|
|
if self._refresh_mode:
|
|
self._track = [c]
|
|
else:
|
|
self._track.clear()
|
|
|
|
else:
|
|
self._track = list(c)
|
|
|
|
self._index = 0
|
|
|
|
def _next_keyframe(self, index: Optional[int] = None) -> float:
|
|
if index is not None:
|
|
self._index = index
|
|
else:
|
|
self._index += 1
|
|
index = self._index
|
|
|
|
try:
|
|
frame = self._track[index]
|
|
|
|
except IndexError:
|
|
self._index = 0
|
|
frame = self._track[0]
|
|
|
|
self._led.update(frame)
|
|
|
|
return frame.time
|