예제 #1
0
 def update_text(self):
     x, y = self.position
     time = self.main.status.get('builds_time', timedelta(0))
     time -= timedelta(microseconds=time.microseconds)
     ping = datetime.utcnow() - self.main.last_message
     ping -= timedelta(microseconds=ping.microseconds)
     text = {
         0:
         'Last Ping: {}s'.format(int(ping.total_seconds())),
         1:
         'Disk Free: {}%'.format(100 *
                                 self.main.status.get('disk_free', 0) //
                                 self.main.status.get('disk_size', 1)),
         2:
         'Queue Size: {}'.format(self.main.status.get('builds_pending', 0)),
         3:
         'Builds/Hour: {}'.format(
             self.main.status.get('builds_last_hour', 0)),
         4:
         'Build Time: {}'.format(time),
         5:
         'Build Size: {}'.format(
             format_size(self.main.status.get('builds_size', 0))),
     }[x]
     self.text = array(
         draw_text(text, foreground=Color('gray'), padding=(8, 0, 8, 1)))
     # Ensure the text doesn't "skip" while we're rendering it by starting
     # the offset cycle at the current position of the offset cycle (unless
     # it's out of range)
     last = next(self.offset)
     if last >= self.text.shape[1] - 8:
         last = 0
     self.offset = iter(
         cycle(chain(range(last, self.text.shape[1] - 8), range(last))))
예제 #2
0
def switcher(events, readings, database='environ.rrd'):
    create_database(database)
    screens = {
        (thermometer, 'right'): hygrometer,
        (hygrometer, 'left'): thermometer,
        (hygrometer, 'right'): barometer,
        (barometer, 'left'): hygrometer,
    }
    screen = thermometer
    last_update = None
    for event, offset, reading in zip(events, bounce(range(8)), readings):
        anim = 'draw'
        if event is not None and event.pressed:
            try:
                screen = screens[screen, event.direction]
                anim = event.direction
            except KeyError:
                yield array(Color('black')), 'fade'
                break
        now = time()
        if last_update is None or now - last_update > 5:
            # Only update the database every 5 seconds
            last_update = now
            update_database(database, reading)
        yield screen(offset, reading), anim
        sleep(0.2)
예제 #3
0
 def update_back(self):
     x, y = self.position
     if x == 0:
         ping = 64 * max(timedelta(0), min(timedelta(seconds=30),
             datetime.utcnow() - self.main.last_message)).total_seconds() / 30
         self.back = array([
             c if i <= ping else Color('black')
             for i in range(64)
             for c in (self.ping_grad[min(63, int(ping))],)
         ])
         self.back = np.flipud(self.back)
     elif x == 1:
         disk = (
             64 * self.main.status.get('disk_free', 0) /
             self.main.status.get('disk_size', 1))
         self.back = array([
             c if i < int(disk) else
             c * Lightness(disk - int(disk)) if i < disk else
             Color('black')
             for i in range(64)
             for c in (self.disk_grad[min(63, int(disk))],)
         ])
         self.back = np.flipud(self.back)
     elif x == 2:
         pkgs = min(
             64, self.main.status.get('builds_pending', 0))
         self.back = array([
             Color('blue') if i < pkgs else
             Color('black')
             for i in range(64)
         ])
         self.back = np.flipud(self.back)
     elif x == 3:
         bph = (
             64 * self.main.status.get('builds_last_hour', 0) /
             1000)
         self.back = array([
             Color('blue') if i < int(bph) else
             Color('blue') * Lightness(bph - int(bph)) if i < bph else
             Color('black')
             for i in range(64)
         ])
         self.back = np.flipud(self.back)
     else:
         self.back = array(Color('black'))
예제 #4
0
    def __iter__(self):
        waiting = array(
            draw_text('Waiting for connection', padding=(8, 0, 8, 1)))
        for offset in cycle(range(waiting.shape[1] - 8)):
            if self.connected:
                break
            yield waiting[:, offset:offset + 8]

        buf = array(Color('black'))
        pulse = iter(bounce(range(10)))
        while True:
            x, y = self.position
            with self.watch_selection():
                self.slaves.prune()
            buf[:] = Color('black')
            self._render_stats(buf)
            self._render_slaves(buf, next(pulse))
            yield buf
예제 #5
0
 def update_text(self):
     x, y = self.position
     text = {
         0: 'Quit?',
         1: 'Reboot?',
         2: 'Off?',
     }[x]
     self.text = array(
         draw_text(text, foreground=Color('red'), padding=(8, 0, 8, 1)))
     self.offset = iter(cycle(range(self.text.shape[1] - 8)))
예제 #6
0
 def update_text(self):
     x, y = self.position
     text = {
         0: 'Quit?',
         1: 'Terminate?',
     }[x]
     self.text = array(
         draw_text(text, foreground=Color('red'), padding=(8, 0, 8, 1)))
     self.offset = iter(
         cycle(chain(range(8, self.text.shape[1] - 8), range(8))))
예제 #7
0
 def __iter__(self):
     buf = array(Color('black'))
     grad = list(Color('darkblue').gradient(Color('white'), steps=15))
     pulse = iter(bounce(range(len(grad))))
     while True:
         offset = next(self.offset)
         buf[:, :] = self.text[:, offset:offset + 8]
         buf[:3, :] = Color('darkblue')
         x, y = self.position
         buf[:3, x] = grad[next(pulse)]
         yield buf
예제 #8
0
 def _update_graph(self):
     self.graph = array(shape=(5, 8))
     for x, stat in zip(reversed(range(8)), self.selected.history()):
         if stat is None:
             continue
         # Scale the value to the vertical size
         value = stat.value * self.graph.shape[0]
         for y in range(5):
             self.graph[4 - y,
                        x] = (stat.color if y < int(value) else stat.color *
                              Lightness(value - int(value))
                              if y < value else Color('black'))
예제 #9
0
    def __call__(self, args=None):
        parser = terminal.configure_parser(__doc__, log_params=False)
        parser.add_argument(
            '--status-queue',
            metavar='ADDR',
            default=const.STATUS_QUEUE,
            help="The address of the queue used to report status to monitors "
            "(default: %(default)s)")
        parser.add_argument(
            '--control-queue',
            metavar='ADDR',
            default=const.CONTROL_QUEUE,
            dest='master_queue',
            help="The address of the queue a monitor can use to control the "
            "master (default: %(default)s)")
        parser.add_argument(
            '-r',
            '--rotate',
            metavar='DEGREES',
            default=0,
            type=int,
            help="The rotation of the HAT in degrees; must be 0 (the default) "
            "90, 180, or 270")
        try:
            config = parser.parse_args(args)
            config.control_queue = 'inproc://quit'
        except:  # pylint: disable=bare-except
            return terminal.error_handler(*sys.exc_info())

        with SenseHAT() as hat:
            hat.rotation = config.rotate
            ctx = transport.Context()
            quit_queue = ctx.socket(transport.PULL,
                                    protocol=protocols.task_control)
            quit_queue.bind(config.control_queue)
            try:
                stick = StickTask(config, hat)
                stick.start()
                screen = ScreenTask(config, hat)
                screen.start()
                msg, data = quit_queue.recv_msg()
                assert msg == 'QUIT'
                #signal.sigwait({signal.SIGINT, signal.SIGTERM})
            except KeyboardInterrupt:
                pass
            finally:
                screen.quit()
                screen.join()
                stick.quit()
                stick.join()
                ctx.close()
                hat.screen.fade_to(array(Color('black')))
예제 #10
0
def arrays(moves):
    a = array(Color('black'))  # blank screen
    x = y = 3
    a[y, x] = Color('white')
    yield a  # initial position
    for dx, dy in moves:
        a[y, x] = Color('black')
        x = max(0, min(7, x + dx))
        y = max(0, min(7, y + dy))
        a[y, x] = Color('white')
        yield a
    a[y, x] = Color('black')
    yield a  # end with a blank display
예제 #11
0
 def __iter__(self):
     buf = array(Color('black'))
     pulse = iter(bounce(range(10)))
     render_mode = {
         'text': self._render_text,
         'graph': self._render_graph,
     }
     while True:
         x, y = self.position
         buf[:] = Color('black')
         self._update_stats()
         self._render_stats(buf, next(pulse))
         render_mode[self.mode](buf)
         yield buf.clip(0, 1)
예제 #12
0
def thermometer(offset, reading):
    t = max(0, min(50, reading.temperature)) / 50 * 64
    screen = array([
        Color('red') if i < int(t) else
        Color('red') * Red(t - int(t)) if i < t else
        Color('black')
        for i in range(64)
    ])
    screen = np.flipud(screen)
    text = image_to_rgb(draw_text(int(round(reading.temperature)),
                                  'small.pil', foreground=Color('gray'),
                                  padding=(0, 0, 0, 3)))
    screen[:text.shape[0], :text.shape[1]] += text
    return screen.clip(0, 1)
예제 #13
0
def barometer(offset, reading):
    p = (max(950, min(1050, reading.pressure)) - 950) / 100 * 64
    screen = array([
        Color('green') if i < int(p) else
        Color('green') * Green(p - int(p)) if i < p else
        Color('black')
        for i in range(64)
    ])
    screen = np.flipud(screen)
    text = image_to_rgb(draw_text(int(round(reading.pressure)),
                                  'small.pil', foreground=Color('gray'),
                                  padding=(0, 0, 8, 3)))
    screen[:text.shape[0], :] += text[:, offset:offset + 8]
    return screen.clip(0, 1)
예제 #14
0
 def update_text(self):
     x, y = self.position
     text, fg, bg = {
         0: (self.slave.label, 'white', None),
         1: ('ABI:' + self.slave.abi, 'white', None),
         2: (self.slave.status, 'white', None),
         3: ('Kill?', 'red', 'black'),
     }[x]
     self.text = array(
         draw_text(text,
                   foreground=Color(fg),
                   background=self.slave.color if bg is None else Color(bg),
                   padding=(8, 0, 8, 1)))
     self.offset = iter(
         cycle(chain(range(8, self.text.shape[1] - 8), range(8))))
예제 #15
0
def display(screen, states):
    try:
        for anim, data in states:
            if anim == 'fade':
                screen.fade_to(data)
            elif anim == 'zoom':
                screen.zoom_to(data)
            elif anim == 'show':
                screen.array = data
            elif anim == 'scroll':
                screen.scroll_text(data, background=Color('red'))
            else:
                assert False
    finally:
        screen.fade_to(ps.array(Color('black')))
예제 #16
0
def hygrometer(offset, reading):
    h = reading.humidity / 100 * 64
    screen = array([
        Color('#008') if i < int(h) else
        Color('#008') * Blue(h - int(h)) if i < h else
        Color('black')
        for i in range(64)
    ])
    screen = np.flipud(screen)
    text = image_to_rgb(draw_text('^^' if reading.humidity > 99 else
                                  int(round(reading.humidity)),
                                  'small.pil', foreground=Color('gray'),
                                  padding=(0, 0, 0, 3)))
    screen[:text.shape[0], :text.shape[1]] += text
    return screen.clip(0, 1)
예제 #17
0
 def _update_text(self, *, restart=True):
     self.text = array(
         draw_text(self.selected.label,
                   font='small.pil',
                   padding=(8, 3, 8, 0)))
     if restart or self.offset is None:
         last = 0
     else:
         # Ensure the text doesn't "skip" while we're rendering it by
         # starting the offset cycle at the current position of the offset
         # cycle (unless it's out of range)
         last = next(self.offset)
         if last >= self.text.shape[1] - 8:
             last = 0
     self.offset = iter(
         cycle(chain(range(last, self.text.shape[1] - 8), range(last))))
예제 #18
0
 def __iter__(self):
     buf = array(Color('black'))
     pulse = iter(bounce(range(15)))
     methods = (
         self._render_ping,
         self._render_disk,
         self._render_queue,
         self._render_slaves,
     )
     while True:
         buf[:] = Color('black')
         p = next(pulse)
         self.slaves.prune()
         for method in methods:
             method(buf, p)
         yield buf
예제 #19
0
    def __call__(self, args=None):
        parser = terminal.configure_parser(__doc__, log_params=False)
        parser.add_argument(
            '--status-queue',
            metavar='ADDR',
            default=const.STATUS_QUEUE,
            help="The address of the queue used to report status to monitors "
            "(default: %(default)s)")
        parser.add_argument(
            '--control-queue',
            metavar='ADDR',
            default=const.CONTROL_QUEUE,
            help="The address of the queue a monitor can use to control the "
            "master (default: %(default)s)")
        parser.add_argument(
            '-r',
            '--rotate',
            metavar='DEGREES',
            default=0,
            type=int,
            help="The rotation of the HAT in degrees; must be 0 (the default) "
            "90, 180, or 270")
        try:
            config = parser.parse_args(args)
        except:  # pylint: disable=bare-except
            return terminal.error_handler(*sys.exc_info())

        with SenseHAT() as hat:
            hat.rotation = config.rotate
            ctx = zmq.Context()
            try:
                stick = StickTask(config, hat)
                stick.start()
                screen = ScreenTask(config, hat)
                screen.start()
                signal.sigwait({signal.SIGINT, signal.SIGTERM})
            except KeyboardInterrupt:
                pass
            finally:
                screen.quit()
                screen.join()
                stick.quit()
                stick.join()
                ctx.destroy(linger=1000)
                ctx.term()
                hat.screen.fade_to(array(Color('black')))
예제 #20
0
def generate_maze(width, height, colors):
    walls = generate_walls(width, height)
    maze = ps.array(shape=(2 * height + 1, 2 * width + 1))
    maze[...] = colors['unvisited']
    maze[::2, ::2] = colors['wall']
    for a, b in walls:
        ay, ax = a
        by, bx = b
        y = 2 * by + 1
        x = 2 * bx + 1
        if ay == by:
            maze[y, x - 1] = colors['wall']
        else:
            maze[y - 1, x] = colors['wall']
    maze[0, :] = maze[:, 0] = colors['wall']
    maze[-1, :] = maze[:, -1] = colors['wall']
    maze[-2, -2] = colors['goal']
    return maze
예제 #21
0
 def _update_text(self):
     label = [
         'Last Seen',
         'Builds Queue/Build Time',
         'Disk Used',
         'Swap Used',
         'Mem Used',
         'CPU Temperature',
         'Load Avg',
         'Builds Done/Clock Skew',
     ][self.position[0]]
     self.text = array(
         draw_text(label,
                   font='small.pil',
                   foreground=Color('white'),
                   background=Color('black'),
                   padding=(8, 3, 8, 0)))
     self.offset = iter(cycle(range(self.text.shape[1] - 8)))
예제 #22
0
def switcher(events, readings):
    screens = {
        (thermometer, 'right'): hygrometer,
        (hygrometer, 'left'): thermometer,
        (hygrometer, 'right'): barometer,
        (barometer, 'left'): hygrometer,
    }
    screen = thermometer
    for event, offset, reading in zip(events, bounce(range(8)), readings):
        anim = 'draw'
        if event is not None and event.pressed:
            try:
                screen = screens[screen, event.direction]
                anim = event.direction
            except KeyError:
                yield array(Color('black')), 'fade'
                break
        yield screen(offset, reading), anim
        sleep(0.2)
예제 #23
0
def game(maze, colors, moves):
    height, width = maze.shape
    y, x = (1, 1)
    maze[y, x] = colors['ball']
    left, right = clamp(x, width)
    top, bottom = clamp(y, height)
    yield 'fade', maze[top:bottom, left:right]
    for delta_y, delta_x in moves:
        if Color(*maze[y + delta_y, x + delta_x]) != colors['wall']:
            maze[y, x] = colors['visited']
            y += delta_y
            x += delta_x
            if Color(*maze[y, x]) == colors['goal']:
                yield from winners_cup()
                break
            else:
                maze[y, x] = colors['ball']
                left, right = clamp(x, width)
                top, bottom = clamp(y, height)
                yield 'show', maze[top:bottom, left:right]
    yield 'fade', ps.array(Color('black'))
예제 #24
0
from __future__ import division  # for py2.x compatibility
from pisense import SenseHAT, array
from colorzero import Color
from time import sleep

hat = SenseHAT()
offset = 0.0
while True:
    rainbow = array([
        Color(h=(x + y) / 14 + offset, s=1, v=1) for x in range(8)
        for y in range(8)
    ])
    hat.screen.array = rainbow
    offset += 0.05
    sleep(0.05)
예제 #25
0
def main():
    with SenseHAT() as hat:
        hat.stick.stream = True
        for a in switcher(hat.stick, hat.environ):
            hat.screen.array = a
        hat.screen.fade_to(array(Color('black')))
def winners_cup():
    r = Color('red')
    y = Color('yellow')
    W = Color('white')
    yield 'zoom', ps.array([
        r,
        r,
        W,
        y,
        y,
        y,
        r,
        r,
        r,
        r,
        W,
        y,
        y,
        y,
        r,
        r,
        r,
        r,
        W,
        y,
        y,
        y,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        r,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        r,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        r,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        y,
        y,
        r,
        r,
    ])
    sleep(2)
    stopwatch.stop()
    score = stopwatch.duration
    score = round(score, 1)
    yield 'fade', ps.array(r)
    yield 'scroll', 'You win!'
    yield 'scroll', (str(score))
예제 #27
0
def empty_screen_board():
    # return an empty board for PiSense
    return pisense.array([
        Color(h=0.0, s=0.0, v=((x + y + 1) % 2) * brightness) for x in range(8)
        for y in range(8)
    ])
예제 #28
0
def winners_cup():
    r = Color('red')
    y = Color('yellow')
    W = Color('white')
    yield 'zoom', ps.array([
        r,
        r,
        W,
        y,
        y,
        y,
        r,
        r,
        r,
        r,
        W,
        y,
        y,
        y,
        r,
        r,
        r,
        r,
        W,
        y,
        y,
        y,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        r,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        r,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        r,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        r,
        r,
        r,
        r,
        r,
        W,
        y,
        y,
        y,
        r,
        r,
    ])
    sleep(2)
    yield 'fade', ps.array(r)
    yield 'scroll', 'You win!'
예제 #29
0
 def __iter__(self):
     buf = array(Color('black'))
     while True:
         offset = next(self.offset)
         yield self.text[:, offset:offset + 8]
예제 #30
0
 def __iter__(self):
     buf = array(Color('black'))
     while True:
         offset = next(self.offset)
         buf[:self.text.shape[0], :] = self.text[:, offset:offset + 8]
         yield buf.clip(0, 1)