示例#1
0
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
示例#2
0
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"
示例#3
0
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