Exemple #1
0
 def __init__(self, i, o, *args, **kwargs):
     super(ClockApp, self).__init__(i, o)
     self.menu_name = "Clock"
     self.refresher = Refresher(self.on_refresh, i, o)
     default_config = '{}'
     config_filename = "config.json"
     self.config = read_or_create_config(local_path(config_filename), default_config, self.menu_name+" app")
Exemple #2
0
class StopwatchApp(ZeroApp):
    def __init__(self, i, o):
        super(StopwatchApp, self).__init__(i, o)
        self.menu_name = "Stopwatch"
        self.counter = Chronometer()
        self.refresher = None
        self.__instructions = [
            "", "UP/ENTER to start/pause", "RIGHT : restart", "DOWN : reset"
        ]

    def on_start(self):
        self.refresher = Refresher(
            self.refresh_function, self.i, self.o, .1, {
                "KEY_UP": self.counter.toggle,
                "KEY_RIGHT": self.counter.start,
                "KEY_ENTER": self.counter.toggle,
                "KEY_DOWN": self.counter.stop
            })
        self.refresher.activate()

    def refresh_function(self):
        self.counter.update()
        text_rows = [
            "{} {}".format(self.get_char(), round(self.counter.elapsed,
                                                  2)).center(self.o.cols)
        ]
        text_rows.extend([
            instruction.center(self.o.cols)
            for instruction in self.__instructions
        ])
        return text_rows

    def get_char(self):
        return "|>" if self.counter.active else "||"
Exemple #3
0
class ClockApp(ZeroApp, Refresher, CenteredTextRenderer):

    def __init__(self, i, o, *args, **kwargs):
        super(ClockApp, self).__init__(i, o)
        self.menu_name = "Clock"
        self.refresher = Refresher(self.on_refresh, i, o)
        default_config = '{}'
        config_filename = "config.json"
        self.config = read_or_create_config(local_path(config_filename), default_config, self.menu_name+" app")

    def draw_analog_clock(self, draw, time, radius="min(*self.o.device.size) / 3", clock_x = "center_x+32", clock_y = "center_y+5", h_len = "radius / 2", m_len = "radius - 5", s_len = "radius - 3", **kwargs):
        """Draws the analog clock, with parameters configurable through config.txt."""
        center_x, center_y = self.get_center(self.o.device.size)
        clock_x = eval(clock_x)
        clock_y = eval(clock_y)
        radius = eval(radius)
        draw.ellipse((clock_x - radius, clock_y - radius, clock_x + radius, clock_y + radius), fill=False, outline="white")
        self.draw_needle(draw, 60 - time.second / 60, eval(s_len), clock_x, clock_y, 1)
        self.draw_needle(draw, 60 - time.minute / 60, eval(m_len), clock_x, clock_y, 1)
        self.draw_needle(draw, 24 - time.hour / 24, eval(h_len), clock_x, clock_y, 1)

    def draw_text(self, draw, time, text_x="10", text_y="center_y-5", time_format = "%H:%M:%S", **kwargs):
        """Draws the digital clock, with parameters configurable through config.txt."""
        time_str = time.strftime(time_format)
        center_x, center_y = self.get_center(self.o.device.size)
        bounds = self.get_centered_text_bounds(draw, time_str, self.o.device.size)
        x = eval(text_x)
        y = eval(text_y)
        draw.text((x, y), time_str, fill="white")

    def on_refresh(self):
        current_time = datetime.now()
        return self.render_clock(current_time, **self.config)

    def render_clock(self, time, **kwargs):
        c = canvas(self.o.device)
        c.__enter__()
        width, height = c.device.size
        draw = c.draw
        self.draw_text(draw, time, **kwargs)
        self.draw_analog_clock(draw, time, **kwargs)
        return c.image

    def draw_needle(self, draw, progress, radius, x, y, width):
        # type: (ImageDraw, float, float, float, float, int) -> None
        hour_angle = math.pi * 2 * progress + math.pi
        draw.line(
            (
                x,
                y,
                x + radius * math.sin(hour_angle),
                y + radius * math.cos(hour_angle)
            ),
            width=width,
            fill=True
        )

    def on_start(self):
        super(ClockApp, self).on_start()
        self.refresher.activate()
Exemple #4
0
def callback():
    keymap = {
        "KEY_ENTER": pomodoro_options_menu,
        "KEY_KPENTER": pomodoro_options_menu
    }
    refresher = Refresher(status_refresher_data, i, o, 1, keymap,
                          "Pomodoro monitor")
    refresher.activate()
Exemple #5
0
 def on_start(self):
     self.refresher = Refresher(
         self.refresh_function, self.i, self.o, .1, {
             "KEY_UP": self.counter.toggle,
             "KEY_RIGHT": self.counter.start,
             "KEY_ENTER": self.counter.toggle,
             "KEY_DOWN": self.counter.stop
         })
     self.refresher.activate()
Exemple #6
0
def status_monitor():
    keymap = {
        "KEY_ENTER": wireless_status,
        "KEY_RIGHT": lambda: scan(False),
        "KEY_UP": lambda: reconnect()
    }
    refresher = Refresher(status_refresher_data, i, o, 0.5, keymap,
                          "Wireless monitor")
    refresher.activate()
Exemple #7
0
def callback():
    global refresher, keys_called
    keys_called = []
    i.set_streaming(process_key)
    refresher = Refresher(get_keys, i, o, 1, name="Key monitor")
    refresher.keymap.pop(
        "KEY_LEFT")  #Removing deactivate callback to show KEY_LEFT
    PrettyPrinter("To exit this app, press the same key 3 times", i, o)
    refresher.activate()
    i.remove_streaming()
Exemple #8
0
 def detect_loop(self):
     """
     The detect loop. Will exit on RefresherExitException (raised by
     ``show_chip_status`` or on KEY_LEFT from the user.
     """
     r = Refresher(self.get_current_status_data,
                   self.i,
                   self.o,
                   name="Avrdude chip detect loop")
     r.activate()
Exemple #9
0
 def __init__(self, *args, **kwargs):
     ZeroApp.__init__(self, *args, **kwargs)
     self.active = Event()
     self.pop_on_event = Event()
     self.pop_on_event.set()
     self.c = Canvas(self.o)
     device_manager.register_monitor_callback(self.process_dm_event)
     self.i.set_streaming(self.deactivate)
     self.state = None
     self.status_image = "No image"
     self.r = Refresher(self.get_status_image, self.i, self.o, name="Keyboard fallback status refresher")
Exemple #10
0
def init_app(input, output):
    global callback, i, o
    i = input
    o = output  #Getting references to output and input device objects and saving them as globals
    time_refresher = Refresher(show_time, i, o, 1, name="Timer")
    counter_refresher = Refresher(
        count,
        i,
        o,
        1,
        keymap={"KEY_KPENTER": time_refresher.activate},
        name="Counter")
    callback = counter_refresher.activate
Exemple #11
0
 def test_exit_label_leakage(self):
     """tests whether the keymaps (and keymap entries) of different Refresher leak one into another"""
     i = get_mock_input()
     o = get_mock_output()
     r1 = Refresher(lambda: "Hello", i, o, name=r_name + "1", keymap={"KEY_LEFT":lambda: True})
     r2 = Refresher(lambda: "Hello", i, o, name=r_name + "2", keymap={"KEY_LEFT":lambda: False})
     r3 = Refresher(lambda: "Hello", i, o, name=r_name + "3")
     assert (r1.keymap != r2.keymap)
     assert (r1.keymap["KEY_LEFT"] != r2.keymap["KEY_LEFT"])
     assert (r2.keymap != r3.keymap)
     assert (r2.keymap["KEY_LEFT"] != r3.keymap["KEY_LEFT"])
     assert (r1.keymap != r3.keymap)
     assert (r1.keymap["KEY_LEFT"] != r3.keymap["KEY_LEFT"])
Exemple #12
0
class LectureHelper(object):
    refresher = None
    position = 0
    started_at = None

    def __init__(self, file, interval):
        self.filename = file
        with open(self.filename, 'r') as f:
            self.contents = [
                line.rstrip('\n') for line in f.readlines()
                if line.rstrip('\n')
            ]
        self.contents.append("STOP")
        self.interval = interval  #In minutes

    def move_left(self):
        if self.position == 0:
            self.refresher.deactivate()
            return
        self.position -= 1

    def move_right(self):
        if self.position == len(self.contents) - 1:
            return
        self.position += 1

    def get_keymap(self):
        keymap = {"KEY_LEFT": self.move_left, "KEY_RIGHT": self.move_right}
        return keymap

    def get_displayed_data(self):
        data = []
        data_rows = o.rows - 1
        current_data = self.contents[self.position]
        for i in range(data_rows):
            data.append(current_data[o.cols * i:][:o.cols * (i + 1)])
        total_seconds_since_start = (datetime.now() -
                                     self.started).total_seconds()
        total_seconds_till_end = self.interval * 60 - total_seconds_since_start
        minutes_till_end, seconds_till_end = map(
            int, (total_seconds_till_end / 60, total_seconds_till_end % 60))
        time_str = "{}:{}".format(minutes_till_end,
                                  seconds_till_end).center(o.cols)
        data.append(time_str)
        return data

    def start(self):
        self.started = datetime.now()
        self.refresher = Refresher(self.get_displayed_data, i, o, 1,
                                   self.get_keymap())
        self.refresher.activate()
Exemple #13
0
    def test_set_interval(self):
        """
        Tests whether the refresh_interval of Refresher is set correctly
        when using set_refresh_interval.
        """
        i = get_mock_input()
        o = get_mock_output()
        r = Refresher(lambda: "Hello", i, o, name=r_name, refresh_interval=1)

        assert(r.refresh_interval == 1)
        assert(r.sleep_time == 0.1)
        assert(r.iterations_before_refresh == 10)
        # Refresh intervals up until 0.1 don't change the sleep time
        r.set_refresh_interval(0.1)
        assert(r.refresh_interval == 0.1)
        assert(r.sleep_time == 0.1)
        assert(r.iterations_before_refresh == 1)
        # Refresh intervals less than 0.1 change sleep_time to match refresh interval
        r.set_refresh_interval(0.01)
        assert(r.refresh_interval == 0.01)
        assert(r.sleep_time == 0.01)
        assert(r.iterations_before_refresh == 1)
        # Now setting refresh_interval to a high value
        r.set_refresh_interval(10)
        assert(r.refresh_interval == 10)
        assert(r.sleep_time == 0.1) # Back to normal
        assert(r.iterations_before_refresh == 100)
Exemple #14
0
 def __init__(self, i, o, *args, **kwargs):
     super(ClockApp, self).__init__(i, o)
     self.menu_name = "Clock"
     self.countdown = None
     self.refresher = Refresher(
         self.on_refresh,
         i,
         o,
         keymap={"KEY_RIGHT": self.countdown_settings})
     default_config = '{}'
     config_filename = "config.json"
     self.config = read_or_create_config(local_path(config_filename),
                                         default_config,
                                         self.menu_name + " app")
Exemple #15
0
    def test_refresher_exit_exception(self):
        """
        Tests whether the Refresher deactivates when it receives an exit exception.
        """
        i = get_mock_input()
        o = get_mock_output()
        def get_data():
            raise RefresherExitException
        r = Refresher(get_data, i, o, name=r_name, refresh_interval=0.1)

        #Doing what an activate() would do, but without a loop
        r.to_foreground()
        #Should've caught the exception and exited, since to_foreground() calls refresh()
        assert r.in_foreground == False
Exemple #16
0
def init_app(input, output):
    global refresher, callback, i, o
    i = input
    o = output
    i.set_streaming(process_key)
    refresher = Refresher(get_keys, i, o, 1, name="Key monitor")
    callback = refresher.activate
Exemple #17
0
 def test_constructor(self):
     """Tests constructor"""
     r = Refresher(lambda: "Hello",
                   get_mock_input(),
                   get_mock_output(),
                   name=r_name)
     self.assertIsNotNone(r)
Exemple #18
0
 def test_string_keymap(self):
     """Tests the keymap entries"""
     k = {"KEY_LEFT":'refresh', "KEY_RIGHT":'deactivate'}
     r = Refresher(lambda: "Hello", get_mock_input(), get_mock_output(), keymap=k, name=r_name)
     for key_name, callback in r.keymap.iteritems():
         self.assertIsNotNone(callback)
     assert (r.keymap["KEY_LEFT"] == r.refresh)
     assert (r.keymap["KEY_RIGHT"] == r.deactivate)
Exemple #19
0
 def test_keymap(self):
     """Tests the keymap entries"""
     r = Refresher(lambda: "Hello",
                   get_mock_input(),
                   get_mock_output(),
                   name=r_name)
     self.assertIsNotNone(r.keymap)
     for key_name, callback in r.keymap.iteritems():
         self.assertIsNotNone(callback)
Exemple #20
0
    def test_shows_data_on_screen(self):
        """Tests whether the Refresher outputs data on screen when it's ran"""
        i = get_mock_input()
        o = get_mock_output()
        r = Refresher(lambda: "Hello", i, o, name=r_name)

        def scenario():
            r.refresh()
            r.deactivate()

        with patch.object(r, 'idle_loop', side_effect=scenario) as p:
            r.activate()
            #The scenario should only be called once
            assert r.idle_loop.called
            assert r.idle_loop.call_count == 1

        assert o.display_data.called
        assert o.display_data.call_count == 2 #One in to_foreground, and one in patched idle_loop
        assert o.display_data.call_args_list[0][0] == ("Hello", )
        assert o.display_data.call_args_list[1][0] == ("Hello", )
Exemple #21
0
    def test_left_key_exits(self):
        r = Refresher(lambda: "Hello", get_mock_input(), get_mock_output(), name=r_name)
        r.refresh = lambda *args, **kwargs: None

        # This test doesn't actually test whether the Refresher exits
        # It only tests whether the in_foreground attribute is set
        # Any ideas? Maybe use some kind of "timeout" library?
        def scenario():
            r.keymap["KEY_LEFT"]()
            assert not r.in_foreground
            # If the test fails, either the assert will trigger a test failure,
            # or the idle loop will just run indefinitely
            # The exception thrown should protect from the latter
            raise KeyboardInterrupt

        with patch.object(r, 'idle_loop', side_effect=scenario) as p:
            try:
                r.activate()
            except KeyboardInterrupt:
                pass #Test succeeded
Exemple #22
0
def show_pinouts(i, o):
    zp_pinout = zp_pinouts_page(o).get_image()
    ua_pinout = uap_pinouts_page(o).get_image()
    isp_pinout = isp_pinouts_page(o).get_image()
    pk2_pinout = pk2_pinouts_page(o).get_image()
    show_pinout = lambda x: Refresher(
        lambda: x, i, o, name="Pinout display refresher").activate()
    contents = [["ZeroPhone side header", lambda: show_pinout(zp_pinout)],
                ["USB ASP", lambda: show_pinout(ua_pinout)],
                ["AVR ISP", lambda: show_pinout(isp_pinout)],
                ["PICkit2", lambda: show_pinout(pk2_pinout)]]
    Menu(contents, i, o, name="Pinout gallery page").activate()
Exemple #23
0
 def test_keymap_restore_on_resume(self):
     """Tests whether the Refresher re-sets the keymap upon resume."""
     i = get_mock_input()
     o = get_mock_output()
     r = Refresher(lambda: "Hello", i, o, name=r_name, refresh_interval=0.1)
     r.refresh = lambda *args, **kwargs: None
     
     r.to_foreground()
     assert i.set_keymap.called
     assert i.set_keymap.call_count == 1
     assert i.set_keymap.call_args[0][0] == r.keymap
     r.pause()
     assert i.set_keymap.call_count == 1 #paused, so count shouldn't change
     i.set_keymap(None)
     assert i.set_keymap.call_args[0][0] != r.keymap
     r.resume()
     assert i.set_keymap.call_count == 3 #one explicitly done in the test right beforehand
     assert i.set_keymap.call_args[0][0] == r.keymap
Exemple #24
0
    def learn_about_5_buttons(self):
        c = Canvas(self.o)
        c.centered_text(
            "Let's go through\nthe main buttons\nand their meanings")
        GraphicsPrinter(c.get_image(), self.i, self.o, 5, invert=False)
        c.clear()
        c.centered_text("Press the buttons\nto test\nThen ENTER\nto continue")
        GraphicsPrinter(c.get_image(), self.i, self.o, 5, invert=False)
        c.clear()
        # First, show the left/right/up/down buttons
        # TODO: different behaviour for ZP and emulator?
        c.text("Enter", (48, 22))
        c.text("Continue", (39, 30))
        c.text("Left", (2, 18))
        c.text("Back", (2, 26))
        c.text("Cancel", (2, 34))
        c.text("Right", (92, 22))
        c.text("Option", (90, 30))
        c.text("Up", (56, 5))
        c.text("Down", (52, "-18"))
        image = c.get_image()

        def process_key(key, state):
            # invert/deinvert areas on the canvas when buttons are pressed/released
            # on drivers that don't support key states, will toggle inversion on every press
            # on drivers that support key states, will "highlight" the buttons pressed
            print(key, state)
            if state != KEY_HELD:
                if key == "KEY_UP":
                    c.invert_rect((64 - 20, 2, 64 + 20, 22))
                elif key == "KEY_DOWN":
                    c.invert_rect((64 - 20, "-2", 64 + 20, "-22"))
                elif key == "KEY_LEFT":
                    c.invert_rect((2, 32 - 15, 38, 32 + 15))
                elif key == "KEY_RIGHT":
                    c.invert_rect(("-2", 32 - 10, "-40", 32 + 10))

        keys = ["KEY_UP", "KEY_DOWN", "KEY_LEFT", "KEY_RIGHT"]
        keymap = {"KEY_ENTER": "deactivate"}
        for key in keys:
            cb = cb_needs_key_state(lambda st, x=key: process_key(x, st))
            keymap[key] = cb
        Refresher(c.get_image,
                  self.i,
                  self.o,
                  override_left=False,
                  keymap=keymap).activate()
        return True
Exemple #25
0
    def test_update_keymap(self):
        """Tests whether the Refresher updates the keymap correctly."""
        i = get_mock_input()
        o = get_mock_output()
        r = Refresher(lambda: "Hello", i, o, name=r_name, refresh_interval=0.1)
        r.refresh = lambda *args, **kwargs: None

        # We need to patch "process_callback" because otherwise the keymap callbacks
        # are wrapped and we can't test equivalence
        with patch.object(r, 'process_callback', side_effect=lambda keymap:keymap) as p:
            keymap1 = {"KEY_LEFT": lambda:1}
            r.update_keymap(keymap1)
            assert(r.keymap == keymap1)
            keymap2 = {"KEY_RIGHT": lambda:2}
            r.update_keymap(keymap2)
            keymap2.update(keymap1)
            assert(r.keymap == keymap2)
Exemple #26
0
 def learn_about_help_icon(self):
     o = HelpOverlay("test")
     c = Canvas(self.o)
     c.text("See this icon?->", (1, 1))
     c.text("When it appears,", (3, 10))
     c.text("press F5 to get help", (3, 19))
     c.text("Try now, or", (3, 28))
     c.text("press ENTER to skip", (3, 37))
     if not is_emulator():
         c.text("F5:", (5, 51))
         c.paste(local_path("f5_button_location.png"), (30, 50),
                 invert=True)
     o.draw_icon(c)
     Refresher(c.get_image,
               self.i,
               self.o,
               keymap={
                   "KEY_ENTER": "deactivate",
                   "KEY_F5": self.on_help_button_press
               }).activate()
     return True
Exemple #27
0
 def learn_about_zeromenu(self):
     c = Canvas(self.o)
     if is_emulator():
         c.text("Press F11 to get", (1, 1))
     else:
         c.text("Press PROG2 to get", (1, 1))
     c.text("a shortcut menu -", (3, 10))
     c.text("ZeroMenu. You can", (3, 19))
     c.text("add apps to it", (3, 28))
     c.text("for quick launch", (3, 37))
     if not is_emulator():
         c.text("PROG2:", (5, 51))
         c.paste(local_path("prog2_button_location.png"), (40, 50),
                 invert=True)
     Refresher(c.get_image,
               self.i,
               self.o,
               keymap={
                   "KEY_ENTER": "deactivate",
                   "KEY_PROG2": self.on_zeromenu_button_press
               }).activate()
     return True
Exemple #28
0
def i2c_read_ui(address, reg=None):
    global last_values

    if reg == True:
        reg = UniversalInput(i, o, message="Register:",
                             charmap="hex").activate()
        if reg is None:  # User picked "cancel"
            return
    if isinstance(reg, basestring):
        reg = int(reg, 16)

    last_values = []
    values_on_screen = o.cols

    def read_value(
    ):  # A helper function to read a value and format it into a list
        global last_values
        try:
            if reg:
                answer = "{} {}".format(
                    hex(reg), hex(current_bus.read_byte_data(address, reg)))
            else:
                answer = hex(current_bus.read_byte(address))
        except IOError:
            answer = "{} error".format(reg) if reg else "error"
        last_values.append(answer)
        last_values = last_values[:values_on_screen]
        return list(reversed(last_values))

    r = Refresher(read_value, i, o)

    def change_interval(
    ):  # A helper function to adjust the Refresher's refresh interval while it's running
        new_interval = IntegerAdjustInput(
            r.refresh_interval, i, o, message="Refresh interval:").activate()
        if new_interval is not None:
            r.set_refresh_interval(new_interval)

    r.update_keymap({"KEY_RIGHT": change_interval})
    r.activate()
Exemple #29
0
def callback():
    Refresher(show_temp, i, o, 0.1, name="Temperature monitor").activate()
Exemple #30
0
 def start(self):
     self.started = datetime.now()
     self.refresher = Refresher(self.get_displayed_data, i, o, 1,
                                self.get_keymap())
     self.refresher.activate()
Exemple #31
0
def callback():
    keymap = {"KEY_ENTER":pomodoro_options_menu, "KEY_KPENTER":pomodoro_options_menu}
    refresher = Refresher(status_refresher_data, i, o, 1, keymap, "Pomodoro monitor")
    refresher.activate()
Exemple #32
0
def status_monitor():
    keymap = {"KEY_ENTER":wireless_status, "KEY_KPENTER":wireless_status}
    refresher = Refresher(status_refresher_data, i, o, 0.5, keymap, "Wireless monitor")
    refresher.activate()