def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(0.05, self.config.get('interval', 0))) self.minHotspots = self.config.get('min_hotspots', 2) self.maxHotspots = self.config.get('max_hotspots', 16) self.hotspotStep = self.config.get('hotspot_step', 2) self.hotspots = self.config.get('hotspots', 6) self.minValue = self.config.get('min_value', 20) self.maxValue = self.config.get('max_value', 200) self.valueStep = self.config.get('value_step', 2) self.value = self.config.get('value', 40) self.barDelay = self.config.get('bar_delay', 1.0) self.main_frame = [[0 for x in range(self.height + 2)] for y in range(self.width + 2)] self.back_frame = [[0 for x in range(self.height + 2)] for y in range(self.width + 2)] self.hotspotBar = ProgressBar(ProgressBar.HORIZONTAL, self.minHotspots, self.maxHotspots, self.hotspots, 4, (self.height - 8) / 2, self.width - 8, 8) self.valueBar = ProgressBar(ProgressBar.VERTICAL, self.minValue, self.maxValue, self.value, (self.width - 8) / 2, 2, 8, self.height - 4) self.visibleBar = None self.visibleBarTimestamp = None
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.minInterval = self.config.get('min_interval', 0.1) self.maxInterval = self.config.get('max_interval', 1.0) self.intervalStep = (self.maxInterval - self.minInterval) / 9 self.level = 5 self.timer = SafeTimer(self.on_timer, self.maxInterval - self.intervalStep * self.level) self.snake = None self.dx = 0 self.dy = 0 self.apple = None self.score = 0 self.gameOver = False self.btn = None self.gameWidth = self.width self.gameHeight = self.height - 6 self.main_font = [x for x in ProportionalFont(MICRO_LETTERS, 2)] self.main_font[ord('\t')] = [0x00] self.clock = MiniClock(0, 0) self.clock.x = self.width - self.clock.width
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.minInterval = self.config.get('min_interval', 0.1) self.maxInterval = self.config.get('max_interval', 1.0) self.intervalStep = self.config.get('interval_step', 0.1) self.intervalBarDelay = self.config.get('interval_bar_delay', 1.0) self.interval = self.config.get('interval', 0.3) self.interval = min(self.interval, self.maxInterval) self.interval = max(self.interval, self.minInterval) self.lastIntervalChange = None self.timer = SafeTimer(self.on_timer, self.interval) self.cells = None self.new_cells = None self.intervalBar = ProgressBar(ProgressBar.HORIZONTAL, -self.maxInterval, -self.minInterval, -self.interval, 4, (self.height - 8) / 2, self.width - 8, 8)
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(0.1, self.config.get('interval', 0))) self.x = self.width / 2 self.y = self.height / 2
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.busNumber = config.get('smbus', 0) self.timer = SafeTimer(self.on_timer, max(1, self.config.get('interval', 0))) self.measureCycles = config.get('measure_cycles', 10) self.measureDelay = config.get('measure_delay', 0.01) self.smbus = None
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(600, self.config.get('interval', 0))) self.approxSize = self.config.get('approx_size', 6) self.historySize = self.config.get('history_size', 144) self.deltaMin = self.config.get('delta_min', 250) self.deltaMax = self.config.get('delta_max', -250)
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(1, self.config.get('interval', 0))) self.font = [x for x in ProportionalFont(MICRO_LETTERS, 2)] self.font[ord('\t')] = [0x00] self.time = MiniClock(0, 0) self.time.x = (self.width - self.time.width) // 2
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.upper_temp = self.config['upper_temp'] self.lower_temp = self.config['lower_temp'] self.upper_hum = self.config['upper_hum'] self.lower_hum = self.config['lower_hum'] self.upper_press = self.config['upper_press'] self.lower_press = self.config['lower_press'] self.timer = SafeTimer(self.on_timer, max(1, self.config.get('interval', 0)))
class SimpleClock(ClockFace): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.clock_y = 0 self.clock_height = 7 self.direction = 1 self.timer = SafeTimer(self.on_timer, max(0.1, self.config.get('interval', 0))) self.font = [[0]] * (ord(':') + 1) for ch in range(ord('0'), ord('9') + 1): self.font[ch] = BIG_DIGITS[ch] self.font[ord('\t')] = [0x00, 0x00, 0x00, 0x00, 0x00] self.font[ord(':')] = [0x00, 0x22, 0x00, 0x00, 0x00] def enter(self): self.timer.start(True) def exit(self): self.timer.stop() def on_timer(self): now = datetime.datetime.now() if now.microsecond > 500000: time_string = now.strftime("%H:%M") else: time_string = now.strftime("%H\t%M") x = (self.width - textsize(time_string, self.font)[0] + 1) / 2 image = Image.new('1', (self.width, self.height)) canvas = ImageDraw.Draw(image) text(canvas, (x, self.clock_y), time_string, 255, self.font) del canvas self.manager.draw_activity(self, image) self.clock_y += self.direction if self.clock_y == 0 or self.clock_y + self.clock_height == self.height: self.direction = -self.direction
class TetrisApp(ClockApp): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(0.1, self.config.get('interval', 0))) self.x = self.width / 2 self.y = self.height / 2 def enter(self): self.timer.start(True) def exit(self): self.timer.stop() def on_timer(self): image = Image.new('1', (self.width, self.height)) canvas = ImageDraw.Draw(image) canvas.point((self.x, self.y), 255) del canvas self.manager.draw_activity(self, image) def input(self, btn): if btn == InputButtons.BTN_LEFT: self.x -= 1 if btn == InputButtons.BTN_RIGHT: self.x += 1 if btn == InputButtons.BTN_UP: self.y -= 1 if btn == InputButtons.BTN_DOWN: self.y += 1 if self.x < 0: self.x = self.width - 1 if self.x >= self.width: self.x = 0 if self.y < 0: self.y = self.height - 1 if self.y >= self.height: self.y = 0
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.clock_y = 0 self.clock_height = 7 self.direction = 1 self.timer = SafeTimer(self.on_timer, max(0.1, self.config.get('interval', 0))) self.font = [[0]] * (ord(':') + 1) for ch in range(ord('0'), ord('9') + 1): self.font[ch] = BIG_DIGITS[ch] self.font[ord('\t')] = [0x00, 0x00, 0x00, 0x00, 0x00] self.font[ord(':')] = [0x00, 0x22, 0x00, 0x00, 0x00]
def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(0.1, self.config.get('interval', 0))) self.font = proportional(LCD_FONT) self.size = min(self.width, self.height) if self.size % 2 == 0: self.size -= 1 self.second_len = config.get('second_len', self.size / 2 - 2) self.minute_len = config.get('minute_len', self.size / 2 - 3) self.hour_len = config.get('hour_len', self.size / 2 - 5) self.background = None
def __init__(self, config, services_config, faces_config, apps_config): self.logger = logging.getLogger(__class__.__name__) self.config = config transition_interval = self.config['transition']['interval'] self.transition_step = self.config['transition']['step'] self.transition_timer = SafeTimer(self.on_transition_timer, transition_interval, 'transition') self.screen = ClockScreen(self.config['screen']) self.input = ClockInput(self.config['input']) self.storage = ClockStorage(self.config['storage']) self.input.on_input += self.on_input self.services = [] self.faces = [] self.apps = [] self.current_activity = None self.primary_image = None self.secondary_image = None self.transition_direction = None self.primary_x = 0 self.primary_y = 0 self.logger.info("Loading services") self.services = self.load_plugins( services_config, "services", lambda create, name, conf: create(conf, self)) self.logger.info("Loading faces") self.faces = self.load_plugins( faces_config, "faces", lambda create, name, conf: create( conf, self, self.screen.width, self.screen.height)) self.logger.info("Loading apps") self.apps = self.load_plugins( apps_config, "apps", lambda create, name, conf: create( conf, self, self.screen.width, self.screen.height)) self.current_face_index = 0
class Emulator(ClockService): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.upper_temp = self.config['upper_temp'] self.lower_temp = self.config['lower_temp'] self.upper_hum = self.config['upper_hum'] self.lower_hum = self.config['lower_hum'] self.upper_press = self.config['upper_press'] self.lower_press = self.config['lower_press'] self.timer = SafeTimer(self.on_timer, max(1, self.config.get('interval', 0))) def start(self): self.logger.info("Starting") self.timer.start(True) self.logger.info("Started") def stop(self): self.logger.info("Stopping") self.timer.stop() self.logger.info("Stopped") def on_timer(self): temperature = random.randint(self.lower_temp, self.upper_temp) humidity = random.randint(self.lower_hum, self.upper_hum) pressure = random.randint(self.lower_press, self.upper_press) self.logger.debug( "Temperature: {0}, Humidity: {1}, Pressure: {2}".format( temperature, humidity, pressure)) self.manager.set_info(self, 'temperature', temperature) self.manager.set_info(self, 'humidity', humidity) self.manager.set_info(self, 'pressure', pressure)
class Weather(ClockFace): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(1, self.config.get('interval', 0))) self.font = [x for x in ProportionalFont(MICRO_LETTERS, 2)] self.font[ord('\t')] = [0x00] self.time = MiniClock(0, 0) self.time.x = (self.width - self.time.width) // 2 def enter(self): self.timer.start(True) def exit(self): self.timer.stop() def on_timer(self): temperature = self.manager.get_info(self, 'temperature') humidity = self.manager.get_info(self, 'humidity') pressure = self.manager.get_info(self, 'pressure') image = Image.new('1', (self.width, self.height)) canvas = ImageDraw.Draw(image) self.time.draw(canvas) text(canvas, (0, 7), "T: %d" % int(temperature), 255, self.font) text(canvas, (0, 13), "H: %d" % int(humidity), 255, self.font) text(canvas, (0, 19), "P: %d" % int(pressure), 255, self.font) del canvas self.manager.draw_activity(self, image)
class FlameTestApp(ClockApp): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(0.05, self.config.get('interval', 0))) self.minHotspots = self.config.get('min_hotspots', 2) self.maxHotspots = self.config.get('max_hotspots', 16) self.hotspotStep = self.config.get('hotspot_step', 2) self.hotspots = self.config.get('hotspots', 6) self.minValue = self.config.get('min_value', 20) self.maxValue = self.config.get('max_value', 200) self.valueStep = self.config.get('value_step', 2) self.value = self.config.get('value', 40) self.barDelay = self.config.get('bar_delay', 1.0) self.main_frame = [[0 for x in range(self.height + 2)] for y in range(self.width + 2)] self.back_frame = [[0 for x in range(self.height + 2)] for y in range(self.width + 2)] self.hotspotBar = ProgressBar(ProgressBar.HORIZONTAL, self.minHotspots, self.maxHotspots, self.hotspots, 4, (self.height - 8) / 2, self.width - 8, 8) self.valueBar = ProgressBar(ProgressBar.VERTICAL, self.minValue, self.maxValue, self.value, (self.width - 8) / 2, 2, 8, self.height - 4) self.visibleBar = None self.visibleBarTimestamp = None def place_spots(self): for n in range(self.hotspots): x = random.randrange(1, self.width + 1) self.main_frame[x][self.height] = self.value def move_frame(self): for x in range(1, self.width + 1): for y in range(1, self.height + 1): self.back_frame[x][y - 1] = ( self.main_frame[x - 1][y - 1] + self.main_frame[x - 1][y] + self.main_frame[x - 1][y + 1] + self.main_frame[x][y - 1] + self.main_frame[x][y] + self.main_frame[x][y + 1] + self.main_frame[x + 1][y - 1] + self.main_frame[x + 1][y] + self.main_frame[x + 1][y + 1]) // 9 for x in range(1, self.width + 1): self.back_frame[x][self.height] = 0 tmp = self.main_frame self.main_frame = self.back_frame self.back_frame = tmp def enter(self): self.timer.start(True) def exit(self): self.timer.stop() def draw(self): image = Image.new('1', (self.width, self.height)) canvas = ImageDraw.Draw(image) for x in range(self.width): for y in range(self.height): canvas.point((x, y), 255 if self.main_frame[x + 1][y] > 0 else 0) if (self.visibleBar is not None and self.visibleBarTimestamp is not None and (datetime.datetime.now() - self.visibleBarTimestamp).total_seconds() <= self.barDelay): self.visibleBar.draw(canvas) del canvas self.manager.draw_activity(self, image) def on_timer(self): self.place_spots() self.move_frame() self.draw() def input(self, btn): now = datetime.datetime.now() if btn == InputButtons.BTN_RIGHT: self.hotspots += self.hotspotStep self.visibleBar = self.hotspotBar self.visibleBarTimestamp = now if btn == InputButtons.BTN_LEFT: self.hotspots -= self.hotspotStep self.visibleBar = self.hotspotBar self.visibleBarTimestamp = now if btn == InputButtons.BTN_UP: self.value += self.valueStep self.visibleBar = self.valueBar self.visibleBarTimestamp = now if btn == InputButtons.BTN_DOWN: self.value -= self.valueStep self.visibleBar = self.valueBar self.visibleBarTimestamp = now self.value = min(self.value, self.maxValue) self.value = max(self.value, self.minValue) self.hotspots = min(self.hotspots, self.maxHotspots) self.hotspots = max(self.hotspots, self.minHotspots) self.valueBar.value = self.value self.hotspotBar.value = self.hotspots
class LifeApp(ClockApp): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.minInterval = self.config.get('min_interval', 0.1) self.maxInterval = self.config.get('max_interval', 1.0) self.intervalStep = self.config.get('interval_step', 0.1) self.intervalBarDelay = self.config.get('interval_bar_delay', 1.0) self.interval = self.config.get('interval', 0.3) self.interval = min(self.interval, self.maxInterval) self.interval = max(self.interval, self.minInterval) self.lastIntervalChange = None self.timer = SafeTimer(self.on_timer, self.interval) self.cells = None self.new_cells = None self.intervalBar = ProgressBar(ProgressBar.HORIZONTAL, -self.maxInterval, -self.minInterval, -self.interval, 4, (self.height - 8) / 2, self.width - 8, 8) def start(self): self.init_cells() def init_cells(self): self.cells = [[random.choice([0, 255]) for x in range(self.height)] for y in range(self.width)] self.new_cells = [[0 for x in range(self.height)] for y in range(self.width)] def enter(self): self.timer.start(True) def exit(self): self.timer.stop() def near(self, x, y, system=None): if system is None: system = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]] count = 0 for i in system: if self.cells[(x + i[0]) % self.width][(y + i[1]) % self.height]: count += 1 return count def draw(self): image = Image.new('1', (self.width, self.height)) canvas = ImageDraw.Draw(image) for x in range(self.width): for y in range(self.height): canvas.point((x, y), self.cells[x][y]) if (self.lastIntervalChange is not None and (datetime.datetime.now() - self.lastIntervalChange ).total_seconds() <= self.intervalBarDelay): self.intervalBar.draw(canvas) del canvas self.manager.draw_activity(self, image) def on_timer(self): anybody_alive = False self.draw() for x in range(self.width): for y in range(self.height): if self.cells[x][y]: if self.near(x, y) not in (2, 3): self.new_cells[x][y] = 0 else: self.new_cells[x][y] = 255 anybody_alive = True elif self.near(x, y) == 3: self.new_cells[x][y] = 255 anybody_alive = True else: self.new_cells[x][y] = 0 tmp = self.cells self.cells = self.new_cells self.new_cells = tmp if not anybody_alive: self.init_cells() def input(self, btn): if btn == InputButtons.BTN_OK: self.init_cells() interval_changed = False if btn == InputButtons.BTN_UP or btn == InputButtons.BTN_RIGHT: self.interval -= self.intervalStep interval_changed = True if btn == InputButtons.BTN_DOWN or btn == InputButtons.BTN_LEFT: self.interval += self.intervalStep interval_changed = True if interval_changed: self.interval = min(self.interval, self.maxInterval) self.interval = max(self.interval, self.minInterval) self.timer.interval = self.interval self.intervalBar.value = -self.interval self.lastIntervalChange = datetime.datetime.now() self.draw()
class WeatherPredictor(ClockService): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(600, self.config.get('interval', 0))) self.approxSize = self.config.get('approx_size', 6) self.historySize = self.config.get('history_size', 144) self.deltaMin = self.config.get('delta_min', 250) self.deltaMax = self.config.get('delta_max', -250) def start(self): self.logger.info("Starting") self.timer.start(True) self.logger.info("Started") def stop(self): self.logger.info("Stopping") self.timer.stop() self.logger.info("Stopped") def get_rain_probability(self, pressure_points): sum_x = 0.0 sum_y = 0.0 sum_x2 = 0.0 sum_xy = 0.0 approx_size = len(pressure_points) for i in range(approx_size): sum_x += i sum_y += pressure_points[i] sum_x2 += i * i sum_xy += i * pressure_points[i] a = (approx_size * sum_xy - sum_x * sum_y) / ( approx_size * sum_x2 - sum_x * sum_x) * approx_size rain = (a - self.deltaMin) * 2 / (self.deltaMax - self.deltaMin) - 1 if rain < -1.0: rain = -1.0 elif rain > 1.0: rain = 1.0 return rain def on_timer(self): pressure = self.manager.get_info(self, 'pressure') pressure_history = self.manager.get_info(self, 'pressure_history') if not pressure_history: pressure_history = [] pressure_history.append(pressure) while len(pressure_history) > self.historySize: pressure_history = pressure_history[1:] self.manager.set_info(self, 'pressure_history', pressure_history, True) approx_points = pressure_history[-self.approxSize:] while len(approx_points) < self.approxSize: approx_points.insert(0, approx_points[0]) rain_probability = self.get_rain_probability(approx_points) self.manager.set_info(self, 'rain_probability', rain_probability)
class SnakeApp(ClockApp): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.minInterval = self.config.get('min_interval', 0.1) self.maxInterval = self.config.get('max_interval', 1.0) self.intervalStep = (self.maxInterval - self.minInterval) / 9 self.level = 5 self.timer = SafeTimer(self.on_timer, self.maxInterval - self.intervalStep * self.level) self.snake = None self.dx = 0 self.dy = 0 self.apple = None self.score = 0 self.gameOver = False self.btn = None self.gameWidth = self.width self.gameHeight = self.height - 6 self.main_font = [x for x in ProportionalFont(MICRO_LETTERS, 2)] self.main_font[ord('\t')] = [0x00] self.clock = MiniClock(0, 0) self.clock.x = self.width - self.clock.width def start(self): self.init_game() def gen_apple_pos(self): while True: x, y = random.randrange(self.gameWidth), random.randrange(self.gameHeight) if (x, y) not in self.snake: return x, y def init_game(self): self.snake = [ (int(self.gameWidth / 2) - 1, int(self.gameHeight / 2)), (int(self.gameWidth / 2), int(self.gameHeight / 2)), (int(self.gameWidth / 2) + 1, int(self.gameHeight / 2)) ] self.score = 0 self.dx = 1 self.dy = 0 self.apple = self.gen_apple_pos() self.gameOver = False self.btn = None def get_next_pos(self): x, y = self.snake[-1] x += self.dx y += self.dy if x >= self.gameWidth: x = 0 if x < 0: x = self.gameWidth - 1 if y >= self.gameHeight: y = 0 if y < 0: y = self.gameHeight - 1 return x, y def enter(self): self.timer.start(True) def exit(self): self.timer.stop() def draw(self): image = Image.new('1', (self.width, self.height)) canvas = ImageDraw.Draw(image) self.clock.draw(canvas) text(canvas, (0, 0), str(self.score), 255, self.main_font) canvas.point((self.apple[0], self.apple[1] + 6), 255) for x, y in self.snake: canvas.point((x, y + 6), 255) if self.gameOver: canvas.rectangle((0, 13, self.width, 19), 0, 0) text(canvas, (0, 14), "GAME\tOVER", 255, self.main_font) del canvas self.manager.draw_activity(self, image) def on_timer(self): if self.gameOver: self.draw() return if self.btn == InputButtons.BTN_UP and self.dx != 0: self.dx = 0 self.dy = -1 if self.btn == InputButtons.BTN_DOWN and self.dx != 0: self.dx = 0 self.dy = 1 if self.btn == InputButtons.BTN_LEFT and self.dy != 0: self.dx = -1 self.dy = 0 if self.btn == InputButtons.BTN_RIGHT and self.dy != 0: self.dx = 1 self.dy = 0 next_pos = self.get_next_pos() if next_pos in self.snake: self.gameOver = True else: self.snake.append(next_pos) if next_pos != self.apple: self.snake = self.snake[1:] else: self.score += self.level + 1 self.apple = self.gen_apple_pos() self.draw() def input(self, btn): if btn == InputButtons.BTN_OK: self.init_game() return if btn == InputButtons.BTN_0: return index = InputUtils.get_numeric_button_index(btn) if index is not None: self.level = index self.timer.interval = self.maxInterval - self.intervalStep * self.level return self.btn = btn
class AnalogClock(ClockFace): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.timer = SafeTimer(self.on_timer, max(0.1, self.config.get('interval', 0))) self.font = proportional(LCD_FONT) self.size = min(self.width, self.height) if self.size % 2 == 0: self.size -= 1 self.second_len = config.get('second_len', self.size / 2 - 2) self.minute_len = config.get('minute_len', self.size / 2 - 3) self.hour_len = config.get('hour_len', self.size / 2 - 5) self.background = None def start(self): self.background = Image.new('1', (self.size, self.size)) canvas = ImageDraw.Draw(self.background) center = int(self.size / 2) for h in range(0, 12): x = center + int(math.sin(h * math.pi / 6) * self.size / 2) y = center - int(math.cos(h * math.pi / 6) * self.size / 2) canvas.point((x, y), 255) canvas.point((self.size / 2, 1), 255) canvas.point((self.size / 2, self.size - 2), 255) canvas.point((1, self.size / 2), 255) canvas.point((self.size - 2, self.size / 2), 255) del canvas def stop(self): self.background.close() self.background = None def enter(self): self.timer.start(True) def exit(self): self.timer.stop() def on_timer(self): now = datetime.datetime.now() seconds = now.second minutes = now.minute + seconds / 60.0 hours = now.hour + minutes / 60.0 if hours > 12: hours -= 12 image = Image.new('1', (self.width, self.height)) bg_x = int((self.width - self.background.width) / 2) bg_y = int((self.height - self.background.height) / 2) image.paste(self.background, (bg_x, bg_y)) center_x = int(bg_x + self.background.width / 2) center_y = int(bg_y + self.background.height / 2) canvas = ImageDraw.Draw(image) arrow_len = self.background.width / 2 hour_x = center_x + int(math.sin(hours * math.pi / 6) * self.hour_len) hour_y = center_y - int(math.cos(hours * math.pi / 6) * self.hour_len) minute_x = center_x + int( math.sin(minutes * math.pi / 30) * self.minute_len) minute_y = center_y - int( math.cos(minutes * math.pi / 30) * self.minute_len) second_x = center_x + int( math.sin(seconds * math.pi / 30) * self.second_len) second_y = center_y - int( math.cos(seconds * math.pi / 30) * self.second_len) canvas.line([center_x, center_y, hour_x, hour_y], 255) canvas.line([center_x, center_y, minute_x, minute_y], 255) if image.getpixel((second_x, second_y)): canvas.point([second_x, second_y], 0) else: canvas.point([second_x, second_y], 255) canvas.ellipse( [center_x - 1, center_y - 1, center_x + 1, center_y + 1], 0) canvas.point([center_x, center_y], 255) del canvas self.manager.draw_activity(self, image)
class ClockCore: def __init__(self, config, services_config, faces_config, apps_config): self.logger = logging.getLogger(__class__.__name__) self.config = config transition_interval = self.config['transition']['interval'] self.transition_step = self.config['transition']['step'] self.transition_timer = SafeTimer(self.on_transition_timer, transition_interval, 'transition') self.screen = ClockScreen(self.config['screen']) self.input = ClockInput(self.config['input']) self.storage = ClockStorage(self.config['storage']) self.input.on_input += self.on_input self.services = [] self.faces = [] self.apps = [] self.current_activity = None self.primary_image = None self.secondary_image = None self.transition_direction = None self.primary_x = 0 self.primary_y = 0 self.logger.info("Loading services") self.services = self.load_plugins( services_config, "services", lambda create, name, conf: create(conf, self)) self.logger.info("Loading faces") self.faces = self.load_plugins( faces_config, "faces", lambda create, name, conf: create( conf, self, self.screen.width, self.screen.height)) self.logger.info("Loading apps") self.apps = self.load_plugins( apps_config, "apps", lambda create, name, conf: create( conf, self, self.screen.width, self.screen.height)) self.current_face_index = 0 def get_info(self, activity, key): return self.storage.get_info(activity, key) def set_info(self, activity, key, value, store=False): self.storage.set_info(activity, key, value, store) def draw_activity(self, activity, image): if activity != self.current_activity: return self.primary_image = image if self.transition_direction is None: self.screen.display_image(image) def load_plugins(self, plugins, plugin_folder, factory): result = [] for (name, config) in plugins.items(): if not config.get("enabled", True): continue self.logger.debug("Loading {0}".format(name)) module = importlib.import_module("%s.%s" % (plugin_folder, name)) result.append(factory(module.create, name, config)) return result def on_input(self, btn): self.logger.debug("Got input: %s" % btn) if btn == InputButtons.BTN_SHARP: self.restart_screen() if self.current_activity.receives_input(): if not self.current_activity.overrides_exit( ) and btn == InputButtons.BTN_STAR: self.close_app(self.current_activity) else: self.current_activity.input(btn) return app = None try: app_index = InputUtils.NumericButtonsSequence.index(btn) app = self.apps[app_index] except IndexError: pass except ValueError: pass if app is not None: self.open_app(app) return transition_direction = None if btn == InputButtons.BTN_LEFT: self.current_face_index -= 1 if self.current_face_index < 0: self.current_face_index = len(self.faces) - 1 transition_direction = TransitionDirections.RIGHT if btn == InputButtons.BTN_RIGHT: self.current_face_index += 1 if self.current_face_index >= len(self.faces): self.current_face_index = 0 transition_direction = TransitionDirections.LEFT if btn == InputButtons.BTN_UP: self.current_face_index -= 1 if self.current_face_index < 0: self.current_face_index = len(self.faces) - 1 transition_direction = TransitionDirections.DOWN if btn == InputButtons.BTN_DOWN: self.current_face_index += 1 if self.current_face_index >= len(self.faces): self.current_face_index = 0 transition_direction = TransitionDirections.UP self.change_activity(self.faces[self.current_face_index], transition_direction) def restart_screen(self): self.logger.info("Restarting screen") activity = self.current_activity self.current_activity.exit() self.current_activity = None self.transition_direction = None self.transition_timer.stop() self.screen.stop() self.screen.start() self.current_activity = activity self.current_activity.enter() def start(self): self.logger.info("Starting") self.screen.start() self.input.start() self.storage.start() for plugin in self.services: plugin.start() for plugin in self.faces: plugin.start() for plugin in self.apps: plugin.start() self.current_activity = self.faces[self.current_face_index] self.current_activity.enter() self.logger.info("Started") def stop(self): self.logger.info("Stopping") self.current_activity.exit() for plugin in self.apps: plugin.stop() for plugin in self.faces: plugin.stop() for plugin in self.services: plugin.stop() self.storage.stop() self.input.stop() self.screen.stop() self.logger.info("Stopped") def open_app(self, app): self.change_activity(app, TransitionDirections.LEFT) def close_app(self, app): if app != self.current_activity: return self.change_activity(self.faces[self.current_face_index], TransitionDirections.RIGHT) def change_activity(self, activity, transition_direction): self.current_activity.exit() self.transition_direction = transition_direction current_image = self.primary_image self.current_activity = activity self.current_activity.enter() if transition_direction is None: return self.secondary_image = current_image self.primary_x = 0 self.primary_y = 0 if transition_direction == TransitionDirections.UP: self.primary_y = self.screen.height if transition_direction == TransitionDirections.DOWN: self.primary_y = -self.screen.height if transition_direction == TransitionDirections.LEFT: self.primary_x = self.screen.width if transition_direction == TransitionDirections.RIGHT: self.primary_x = -self.screen.width self.transition_timer.start() def on_transition_timer(self): if self.transition_direction is None: return if self.transition_direction == TransitionDirections.UP: self.primary_y -= self.transition_step if self.primary_y < 0: self.primary_y = 0 if self.transition_direction == TransitionDirections.DOWN: self.primary_y += self.transition_step if self.primary_y > 0: self.primary_y = 0 if self.transition_direction == TransitionDirections.LEFT: self.primary_x -= self.transition_step if self.primary_x < 0: self.primary_x = 0 if self.transition_direction == TransitionDirections.RIGHT: self.primary_x += self.transition_step if self.primary_x > 0: self.primary_x = 0 image = Image.new('1', (self.screen.width, self.screen.height)) secondary_x = self.primary_x secondary_y = self.primary_y if secondary_x > 0: secondary_x -= self.screen.width elif secondary_x < 0: secondary_x += self.screen.width if secondary_y > 0: secondary_y -= self.screen.height elif secondary_y < 0: secondary_y += self.screen.height image.paste(self.secondary_image, (secondary_x, secondary_y)) image.paste(self.primary_image, (self.primary_x, self.primary_y)) self.screen.display_image(image) if self.primary_x == 0 and self.primary_y == 0: self.transition_timer.stop() self.secondary_image = None self.transition_direction = None
class Physical(ClockService): def __init__(self, config, *args, **kwargs): super().__init__(config, *args, **kwargs) self.logger = logging.getLogger(__class__.__name__) self.busNumber = config.get('smbus', 0) self.timer = SafeTimer(self.on_timer, max(1, self.config.get('interval', 0))) self.measureCycles = config.get('measure_cycles', 10) self.measureDelay = config.get('measure_delay', 0.01) self.smbus = None def start(self): self.si7021 = None self.bme208 = None def start(self): self.logger.info("Starting") self.smbus = SMBus(self.busNumber) self.si7021 = Si7021(self.smbus) self.si7021.reset() self.bme208 = Bme280(self.smbus) self.bme208.setup() self.timer.start(True) self.logger.info("Started") def stop(self): self.logger.info("Stopping") self.timer.stop() self.smbus.close() self.smbus = None self.logger.info("Stopped") def measure(self): hum1, temp1 = self.si7021.read() hum2, temp2, pres2 = self.bme208.read() temperature = (temp1 + temp2) / 2 pressure = pres2 humidity = hum1 return temperature, pressure, humidity def on_timer(self): t, p, h = self.measure() temperature = t pressure = p humidity = h for n in range(1,self.measureCycles): time.sleep(self.measureDelay) t, p, h = self.measure() temperature += t pressure += p humidity += h temperature /= self.measureCycles pressure /= self.measureCycles humidity /= self.measureCycles self.logger.debug("Temperature: {0}, Humidity: {1}, Pressure: {2}".format(temperature, humidity, pressure)) self.manager.set_info(self, 'temperature', temperature) self.manager.set_info(self, 'humidity', humidity) self.manager.set_info(self, 'pressure', pressure)