class piOClock(daemon.Daemon): def __init__(self): path, filename = os.path.split(os.path.abspath(__file__)) pidfile = os.path.join("/var/run", "piOClock.pid") self.logfile = os.path.join("/var/log", "piOClock.log") logging.basicConfig( format='%(asctime)-23s - %(levelname)-7s - %(name)s - %(message)s', file=self.logfile) self.log = logging.getLogger("piOClock") self.log.setLevel(logging.INFO) locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8') daemon.Daemon.__init__(self, pidfile, stderr=self.logfile, stdout=self.logfile) def shutdown(self, signum=0, frame=None): self.log.info("Shutdown clock...") self.clk.clear() self.clk.oled.text_center("Exiting...", "blue", size=30) self.clk.display() self.clk.stop_all() self.clk.oled.fillScreen(0) os._exit(0) def run(self): # Wiringpi pin number, NOT RPI PIN! see here: http://wiringpi.com/pins/ # Maybe use RPi instead of wiringpi... RESET_PIN = 15 DC_PIN = 16 led = ssd1351.SSD1351(reset_pin=RESET_PIN, dc_pin=DC_PIN, rows=96) self.clk = Clock(led) # handle sigterm signal.signal(signal.SIGTERM, self.shutdown) now = datetime.datetime.now() led.clear() led.log.setLevel(logging.WARNING) hours = now.hour minutes = now.minute # time sync time.sleep(1 - datetime.datetime.now().microsecond / 1000.0 / 1000.0) REFRESH_RATE = 1 # Alarm (fixed for testing purpose) self.clk.alarm = "" # 07:00" try: while True: now = datetime.datetime.now() resync = 0 self.clk.clear() if self.clk.input_thread.has_input.is_set(): with self.clk.audio_thread.lock: wheel = self.clk.input_thread.wheel click = self.clk.input_thread.click self.clk.input_thread.has_input.clear() if wheel != 0 and not self.clk.in_menu: new_vol = self.clk.audio_thread.volume + self.clk.input_thread.wheel self.clk.d_volume(new_vol) elif click or wheel != 0: self.clk.d_menu(click, wheel) with self.clk.input_thread.lock: self.clk.input_thread.wheel = 0 self.clk.input_thread.click = False # elif clk.freeze > 0: # clk.freeze -= 1 # clk.d_menu() else: self.clk.in_menu = False self.clk.in_volume = False self.clk.freeze = 0 self.clk.d_clock() if not self.clk.in_menu: self.clk.d_mplayer() self.clk.d_signal() self.clk.d_temp() self.clk.d_audio() self.clk.d_alarm() self.clk.d_cpu() self.clk.display() if minutes != now.minute: # refresh minutes minutes = now.minute if (now.microsecond > 100000): resync = 0 - (now.microsecond / 1000.0 / 1000.0) # end here d = (datetime.datetime.now() - now).total_seconds() s = max(REFRESH_RATE - d + resync, 0) if s > 0: # time.sleep(s) self.clk.input_thread.has_input.wait(s + 1 * self.clk.freeze) if resync: self.log.info( "process: %.4f sleep: %.4f total: %.4f resync: %.2fms" % (d, s, d + s, resync * 1000)) elif d > 0.5: self.log.info( "process: %.4f sleep: %.4f total: %.4f overhead!" % (d, s, d + s)) except KeyboardInterrupt, e: self.shutdown() except Exception, e: self.clk.stop_all() self.clk.clear() self.clk.oled.text_center_y(0, "ERROR!", "red", size=36) error_lines = wrap("%s" % e, width=self.clk.oled.cols / 7) y = 40 for err_line in error_lines: self.clk.oled.draw_text(0, y, err_line, "white", size=12) y += 12 self.log.error(e) self.clk.display() raise
class ClockManager: def __init__(self): self.brightness = 0 self.mode = Mode.CLOCK self.sta_if = network.WLAN(network.STA_IF) self.credentials = Creds().load() self.settings = Settings().load() routes = { b"/": b"./index.html", b"/connect": self.connect, b"/action/color": self.set_color, b"/action/clock/display": self.display_clock, b"/action/brightness/more": self.brightness_more, b"/action/brightness/less": self.brightness_less, b"/action/scoreboard/display": self.display_scoreboard, b"/action/scoreboard/green/more": self.scoreboard_green_more, b"/action/scoreboard/green/less": self.scoreboard_green_less, b"/action/scoreboard/red/more": self.scoreboard_red_more, b"/action/scoreboard/red/less": self.scoreboard_red_less, b"/action/scoreboard/reset": self.scoreboard_reset, b"/settings/values": self.settings_values, b"/settings/net": self.settings_net, b"/settings/group": self.settings_group } self.poller = poll() self.http = HTTPServer(self.poller, CaptivePortal.AP_IP, routes) print("> HTTP server started") self.clock = Clock(self.settings.color) self.loop = get_event_loop() self.loop.create_task(self.check_wifi()) self.loop.create_task(self.poll_web_server()) async def check_wifi(self): while True: collect() threshold(mem_free() // 4 + mem_alloc()) print("> Free memory: {}".format(mem_free())) # self.clock.play_spinner(SPINNER_RATE, ORANGE) self.portal = CaptivePortal(PUBLIC_NAME + b"-%s" % self.settings.net_id) self.portal.start() while not self.sta_if.isconnected(): await sleep_ms(1000) ip = self.sta_if.ifconfig()[0] self.http.set_ip(ip) print("> Connected to {:s} ({:s})".format(self.credentials.essid, ip)) self.portal = None collect() print("> Free memory: {}".format(mem_free())) self.clock.stop_clock() self.clock.stop_effect_init = True self.clock.display() while self.sta_if.isconnected(): await sleep_ms(1000) async def poll_web_server(self): while True: for response in self.poller.ipoll(1000): sock, event, *others = response self.http.handle(sock, event, others) await sleep_ms(50) def settings_values(self, params): essid = self.credentials.essid if not essid: essid = "" result = b'{"ip": "' + self.http.local_ip + '", "netId": "' + self.settings.net_id + '", "group": "' + \ self.settings.group + '", "essid": "' + essid + '"}' return result, b"HTTP/1.1 200 OK\r\n" def connect(self, params): if self.portal: # Write out credentials self.credentials.essid = params.get(b"essid", None) self.credentials.password = params.get(b"password", None) self.credentials.write() self.loop.create_task(self.portal.connect_to_wifi()) return b"", b"HTTP/1.1 200 OK\r\n" def display_clock(self, params=None): if self.mode == Mode.SCOREBOARD: self.mode = Mode.CLOCK self.clock.display() return b"", b"HTTP/1.1 200 OK\r\n" def display_scoreboard(self, params=None): if self.mode == Mode.CLOCK: self.clock.stop_clock() self.mode = Mode.SCOREBOARD self.clock.display_scoreboard() return b"", b"HTTP/1.1 200 OK\r\n" def set_color(self, params): self.display_clock() color = params.get(b"hex", None) if color: self.clock.set_color(color) # Comment the following lines in order to NOT save the selected color for the next boot self.settings.color = color self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n" def scoreboard_green_more(self, params): return self.scoreboard_update(Player.GREEN, 1) def scoreboard_green_less(self, params): return self.scoreboard_update(Player.GREEN, -1) def scoreboard_red_more(self, params): return self.scoreboard_update(Player.RED, 1) def scoreboard_red_less(self, params): return self.scoreboard_update(Player.RED, -1) def scoreboard_update(self, player, increment): if player == Player.GREEN: self.clock.update_scoreboard_green(increment) else: self.clock.update_scoreboard_red(increment) return self.display_scoreboard() def brightness_more(self, params): self.display_clock() self.clock.set_brighter() self.settings.color = b"" + self.clock.hex self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n" def brightness_less(self, params): self.display_clock() self.clock.set_darker() self.settings.color = b"" + self.clock.hex self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n" def scoreboard_reset(self, params): self.display_scoreboard() self.clock.reset_scoreboard() return b"", b"HTTP/1.1 200 OK\r\n" def settings_net(self, params): id = params.get(b"id", None) if id: self.settings.net_id = id self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n" def settings_group(self, params): name = params.get(b"name", None) if name: self.settings.group = name self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n"
class piOClock(daemon.Daemon): def __init__(self): path, filename = os.path.split(os.path.abspath(__file__)) pidfile = os.path.join("/var/run", "piOClock.pid") self.logfile = os.path.join("/var/log", "piOClock.log") logging.basicConfig( format='%(asctime)-23s - %(levelname)-7s - %(name)s - %(message)s', file=self.logfile) self.log = logging.getLogger("piOClock") self.log.setLevel(logging.INFO) locale.setlocale(locale.LC_ALL, 'fr_FR.UTF-8') daemon.Daemon.__init__(self, pidfile, stderr=self.logfile, stdout=self.logfile) def shutdown(self, signum=0, frame=None): self.log.info("Shutdown clock...") self.clk.clear() self.clk.oled.text_center("Exiting...", "blue", size=30) self.clk.display() self.clk.stop_all() self.clk.oled.fillScreen(0) os._exit(0) def run(self): # Wiringpi pin number, NOT RPI PIN! see here: http://wiringpi.com/pins/ # Maybe use RPi instead of wiringpi... RESET_PIN = 15 DC_PIN = 16 led = ssd1351.SSD1351(reset_pin=RESET_PIN, dc_pin=DC_PIN, rows=96) self.clk = Clock(led) # handle sigterm signal.signal(signal.SIGTERM, self.shutdown) now = datetime.datetime.now() led.clear() led.log.setLevel(logging.WARNING) hours = now.hour minutes = now.minute # time sync time.sleep(1-datetime.datetime.now().microsecond/1000.0/1000.0) REFRESH_RATE = 1 # Alarm (fixed for testing purpose) self.clk.alarm = "" # 07:00" try: while True: now = datetime.datetime.now() resync = 0 self.clk.clear() if self.clk.input_thread.has_input.is_set(): with self.clk.audio_thread.lock: wheel = self.clk.input_thread.wheel click = self.clk.input_thread.click self.clk.input_thread.has_input.clear() if wheel != 0 and not self.clk.in_menu: new_vol = self.clk.audio_thread.volume + self.clk.input_thread.wheel self.clk.d_volume(new_vol) elif click or wheel != 0: self.clk.d_menu(click, wheel) with self.clk.input_thread.lock: self.clk.input_thread.wheel = 0 self.clk.input_thread.click = False # elif clk.freeze > 0: # clk.freeze -= 1 # clk.d_menu() else: self.clk.in_menu = False self.clk.in_volume = False self.clk.freeze = 0 self.clk.d_clock() if not self.clk.in_menu: self.clk.d_mplayer() self.clk.d_signal() self.clk.d_temp() self.clk.d_audio() self.clk.d_alarm() self.clk.d_cpu() self.clk.display() if minutes != now.minute: # refresh minutes minutes = now.minute if (now.microsecond > 100000): resync = 0 - (now.microsecond/1000.0/1000.0) # end here d = (datetime.datetime.now()-now).total_seconds() s = max(REFRESH_RATE - d + resync, 0) if s > 0: # time.sleep(s) self.clk.input_thread.has_input.wait(s + 1*self.clk.freeze) if resync: self.log.info("process: %.4f sleep: %.4f total: %.4f resync: %.2fms" % (d, s, d+s, resync*1000)) elif d > 0.5: self.log.info("process: %.4f sleep: %.4f total: %.4f overhead!" % (d, s, d+s)) except KeyboardInterrupt, e: self.shutdown() except Exception, e: self.clk.stop_all() self.clk.clear() self.clk.oled.text_center_y(0, "ERROR!", "red", size=36) error_lines = wrap("%s" % e, width=self.clk.oled.cols/7) y = 40 for err_line in error_lines: self.clk.oled.draw_text(0, y, err_line, "white", size=12) y += 12 self.log.error(e) self.clk.display() raise