commit 2e2f3748d46cbb7a9ebcbc64c1a4326f976fe12e Author: david Date: Tue Apr 18 22:49:47 2017 -0400 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..99e2751 --- /dev/null +++ b/.gitignore @@ -0,0 +1,151 @@ +# Created by .ignore support plugin (hsz.mobi) +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject +.idea/ +bells.py +clock.json +countdown.py +events.txt +panel.py +panel_script.py +requirements.txt +res/ +weatherclock.py +wxget.py diff --git a/bells.py b/bells.py new file mode 100755 index 0000000..6e25be7 --- /dev/null +++ b/bells.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +from subprocess import Popen + +from pydub import AudioSegment + +bell1path = "res/wav/bellhit1.wav" +bell2path = "res/wav/bellhit2.wav" +bell3path = "res/wav/bellhit3.wav" +bell4path = "res/wav/bellhit4.wav" +bell5path = bell4path + +g = AudioSegment.from_file(bell1path) +e = AudioSegment.from_file(bell2path) +f = AudioSegment.from_file(bell3path) +b = AudioSegment.from_file(bell4path) +e3 = AudioSegment.from_file(bell5path) + +try: + horn = AudioSegment.from_file("/home/pi/sound/traphorn.wav") +except FileNotFoundError: + horn = AudioSegment.empty() + +phrase1 = [(g, .25), (f, .25), (e, .25), (b, .50)] +phrase2 = [(e, .25), (g, .25), (f, .25), (b, .50)] +phrase3 = [(e, .25), (f, .25), (g, .25), (e, .50)] +phrase4 = [(g, .25), (e, .25), (f, .25), (b, .50)] +phrase5 = [(b, .25), (f, .25), (g, .25), (e, .50)] +rest = [(AudioSegment.empty(), .50)] +strike = [(e3, .75)] +trap_horn = [(horn, 0)] + +whole_time = 3000 + + +def chime_length(chime): + return sum(c[1] for c in chime) * whole_time + len(chime[-1][0]) + + +def play(audio): + audio.export('/tmp/clock_chime.wav', 'wav') + Popen(['aplay', '/tmp/clock_chime.wav', '-q']) + + +def play_phrase(phrase): + audio = AudioSegment.silent(chime_length(phrase)) + time = 0 + + for a, t in phrase: + audio = audio.overlay(a, int(time)) + time += t * whole_time + + play(audio) + + +last_chime = None + + +def play_chime(hour, minute): + global last_chime + this_chime = hour, minute + if last_chime == this_chime: + return + last_chime = this_chime + + chime = [] + + if hour == 16 and minute == 20: + chime = trap_horn + + if minute == 15: + chime = phrase1 + if minute == 30: + chime = phrase2 + phrase3 + if minute == 45: + chime = phrase4 + phrase5 + phrase1 + if minute == 0: + if hour > 12: + hour -= 12 + if hour == 0: + hour = 12 + chime = phrase2 + phrase3 + phrase4 + phrase5 + rest + strike * hour + + if not chime: + return + + play_phrase(chime) + + +if __name__ == '__main__': + play_chime(2, 00) diff --git a/clock.json b/clock.json new file mode 100644 index 0000000..069c625 --- /dev/null +++ b/clock.json @@ -0,0 +1,39 @@ +[ + { + "surf": "panel_script::time", + "anchor": "0.5,0.5" + }, + { + "surf": "500 500", + "anchor": "0.5,0.5", + "position": "0 250", + "children": [ + { + "surf": "panel_script::date", + "position": "0 -60", + "anchor": ".5 .5" + }, + { + "surf": "panel_script::icon", + "position": "0 80", + "anchor": ".5 .5", + "pivot": "1 .5" + }, + { + "surf": "panel_script::temperature", + "position": "0 80", + "anchor": ".5 .5", + "pivot": "0 .5" + } + ] + }, + { + "surf": "1280 100", + "children": [ + { + "surf": "panel_script::header", + "anchor": ".5 .5" + } + ] + } +] \ No newline at end of file diff --git a/countdown.py b/countdown.py new file mode 100755 index 0000000..41da099 --- /dev/null +++ b/countdown.py @@ -0,0 +1,55 @@ +#!/usr/bin/python3 + +import datetime +import os + +import timestring + + +class Event(object): + def __init__(self, date, label): + self.label = label + self.date = date + + @property + def time(self): + r = timestring.Date(self.date).date - timestring.now().date # type: datetime.timedelta + s = int(r.seconds) + m, s = s // 60, s % 60 + h, m = m // 60, m % 60 + d, h = r.days, h % 25 + return {'days': d, 'hours': h, 'minutes': m, 'seconds': s, 'label': self.label} + + def __format__(self, format_spec): + return format_spec.format(**self.time) + + def __str__(self): + return format(self, '{days}d {hours}h {minutes}m {seconds}s to {label}') + + +__events = [] +__event_load = 0 + + +def update_events(force=False): + global __events, __event_load + + event_time = os.stat('events.txt').st_mtime_ns + if force or __event_load != event_time: + with open('events.txt') as f: + etext = [tuple(i.strip() for i in l.split('|')) for l in f.readlines() if + l.strip() and not l.startswith('#')] + __events = [Event(date, lbl) for lbl, date in etext] + __event_load = event_time + + +def get_events(force_update=False): + update_events(force_update) + + return __events + + +if __name__ == '__main__': + print(timestring.now()) + for e in get_events(): + print(e) diff --git a/events.txt b/events.txt new file mode 100755 index 0000000..fe279cb --- /dev/null +++ b/events.txt @@ -0,0 +1,8 @@ +# datetime | event name +# space before and after | omitted + +Solar Eclipse | 8/21/2017 2:46:22PM +Untrump | 1/20/2021 9:00AM +Move-out | 5/12/2017 noon + +# Dinner Tomorrow | Tomorrow 6:30pm diff --git a/panel.py b/panel.py new file mode 100644 index 0000000..d8e1fca --- /dev/null +++ b/panel.py @@ -0,0 +1,141 @@ +import importlib +import json +import re + +import pygame + + +class Panel(object): + def __init__(self, surf, position=None, anchor=None, pivot=None, children=None): + if isinstance(surf, tuple) or not surf: + self.__surf = pygame.Surface(surf or (0, 0), flags=pygame.SRCALPHA) + else: + self.__surf = surf + + self.position = position or (0, 0) + self.anchor = anchor or (0, 0) + self.pivot = pivot or self.anchor + self.children = children or [] + + @property + def size(self): + surf = self.__surf + + if callable(surf): + surf = surf() + if isinstance(surf, Panel): + return surf.size + + return surf.get_width(), surf.get_height() + + @property + def surf(self): + surf = self.__surf + + if callable(surf): + surf = surf() + elif isinstance(surf, Panel): + surf = surf.surf + else: + surf = surf.copy() + + for child in self.children: + c_surf = child + position = (0, 0) + + if isinstance(child, Panel): + c_surf = child.surf + + position = tuple(int(a * s - v * c + p) for a, v, s, c, p in + zip(child.anchor, child.pivot, self.size, child.size, child.position)) + + if callable(c_surf): + c_surf = c_surf() + if isinstance(c_surf, Panel): + c_surf=c_surf.surf + + surf.blit(c_surf, position) + + return surf + + +old_modules = {} + + +def load(file): + loaded_modules = {} + + def ordered_pair(s, dtype=float): + if not s: + return None + + try: + op = tuple(dtype(c) for c in (re.split(r'\s*[,x\s]\s*', s))) + except ValueError: + return None + + if len(op) != 2: + return None + + return op + + def script(s): + if not s: + return None + + pair = re.split(r'::', s) + + if len(pair) != 2: + return None + + mod, func = pair + + if mod not in loaded_modules: + if mod in old_modules: + importlib.reload(old_modules[mod]) + + try: + loaded_modules[mod] = importlib.import_module(mod) + except ModuleNotFoundError: + return None + + mod = loaded_modules[mod] + + try: + func = getattr(mod, func) + except AttributeError: + return None + + return func + + def from_dict(d: dict): + surf = d.get('surf', None) + position = d.get('position', None) + anchor = d.get('anchor', None) + pivot = d.get('pivot', None) + children = d.get('children', []) + + surf = ordered_pair(surf, int) or script(surf) + position = ordered_pair(position, int) + anchor = ordered_pair(anchor) + pivot = ordered_pair(pivot) + children = [from_dict(d) for d in children] + + return Panel(surf, position, anchor, pivot, children) + + with open(file) as f: + j = json.load(f) + if isinstance(j, list): + ls = [from_dict(d) for d in j] + else: + ls = [from_dict(j)] + + old_modules.clear() + for k, v in loaded_modules.items(): + old_modules[k] = v + + return ls + + +if __name__ == '__main__': + print(load('clock.json')) diff --git a/panel_script.py b/panel_script.py new file mode 100644 index 0000000..23fa50b --- /dev/null +++ b/panel_script.py @@ -0,0 +1,59 @@ +from datetime import datetime + +import pygame + +from countdown import get_events +from panel import Panel +from wxget import get_weather + +pygame.font.init() + +WHITE = (255, 255, 255) +GRAY = (175, 175, 175) +BLACK = (0, 0, 0) + +font = { + 'RobotoSlab': { + 30: pygame.font.Font("res/RobotoSlab-Regular.ttf", 30), + 45: pygame.font.Font("res/RobotoSlab-Regular.ttf", 45), + 60: pygame.font.Font("res/RobotoSlab-Regular.ttf", 60), + 90: pygame.font.Font("res/RobotoSlab-Regular.ttf", 90), + 360: pygame.font.Font("res/RobotoSlab-Regular.ttf", 360), + } +} + + +def time(): + return font['RobotoSlab'][360].render(format(datetime.now(), '%I:%H').lstrip('0'), True, WHITE) + + +def date(): + return font['RobotoSlab'][60].render(format(datetime.now(), '%A, %B %d'), True, GRAY) + + +def temperature(): + f = font['RobotoSlab'][90] + return f.render('{0[current_conditions][temperature]}\u00b0'.format(get_weather()), True, WHITE) + + +def icon(): + return pygame.image.load('res/png/12.png') + + +def header(): + es = get_events() + + def item(i): + f = font['RobotoSlab'][30] + e = es[i] + l = e.label + t = '{days}d {hours}h {minutes}m'.format(**e.time) + + return Panel((1280 // len(es), 70), anchor=((i + 1) / (len(es) + 1), .5), children=[ + Panel(f.render(l, True, WHITE), anchor=(.5, .5), pivot=(.5, .9)), + Panel(f.render(t, True, GRAY), anchor=(.5, .5), pivot=(.5, .1)), + ]) + + return Panel((1280, 70), anchor=(.5, .5), children=[ + item(i) for i in range(len(get_events())) + ]).surf diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5b6165f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +pygame +pydub +timestring +https://launchpad.net/python-weather-api/trunk/0.3.8/+download/pywapi-0.3.8.tar.gz diff --git a/res/RobotoSlab-Regular.ttf b/res/RobotoSlab-Regular.ttf new file mode 100755 index 0000000..eb52a79 Binary files /dev/null and b/res/RobotoSlab-Regular.ttf differ diff --git a/res/png/0.png b/res/png/0.png new file mode 100755 index 0000000..3585984 Binary files /dev/null and b/res/png/0.png differ diff --git a/res/png/1.png b/res/png/1.png new file mode 100755 index 0000000..e3386b4 Binary files /dev/null and b/res/png/1.png differ diff --git a/res/png/10.png b/res/png/10.png new file mode 100755 index 0000000..1c8d919 Binary files /dev/null and b/res/png/10.png differ diff --git a/res/png/11.png b/res/png/11.png new file mode 100755 index 0000000..37268b8 Binary files /dev/null and b/res/png/11.png differ diff --git a/res/png/12.png b/res/png/12.png new file mode 100755 index 0000000..ba97398 Binary files /dev/null and b/res/png/12.png differ diff --git a/res/png/13.png b/res/png/13.png new file mode 100755 index 0000000..9730710 Binary files /dev/null and b/res/png/13.png differ diff --git a/res/png/14.png b/res/png/14.png new file mode 100755 index 0000000..1295344 Binary files /dev/null and b/res/png/14.png differ diff --git a/res/png/15.png b/res/png/15.png new file mode 100755 index 0000000..6f0b63e Binary files /dev/null and b/res/png/15.png differ diff --git a/res/png/16.png b/res/png/16.png new file mode 100755 index 0000000..5e2d537 Binary files /dev/null and b/res/png/16.png differ diff --git a/res/png/17.png b/res/png/17.png new file mode 100755 index 0000000..3585984 Binary files /dev/null and b/res/png/17.png differ diff --git a/res/png/18.png b/res/png/18.png new file mode 100755 index 0000000..1908e79 Binary files /dev/null and b/res/png/18.png differ diff --git a/res/png/19.png b/res/png/19.png new file mode 100755 index 0000000..6b5dcd1 Binary files /dev/null and b/res/png/19.png differ diff --git a/res/png/2.png b/res/png/2.png new file mode 100755 index 0000000..e3386b4 Binary files /dev/null and b/res/png/2.png differ diff --git a/res/png/20.png b/res/png/20.png new file mode 100755 index 0000000..6a7b001 Binary files /dev/null and b/res/png/20.png differ diff --git a/res/png/21.png b/res/png/21.png new file mode 100755 index 0000000..637966d Binary files /dev/null and b/res/png/21.png differ diff --git a/res/png/22.png b/res/png/22.png new file mode 100755 index 0000000..6b5dcd1 Binary files /dev/null and b/res/png/22.png differ diff --git a/res/png/23.png b/res/png/23.png new file mode 100755 index 0000000..54c0802 Binary files /dev/null and b/res/png/23.png differ diff --git a/res/png/24.png b/res/png/24.png new file mode 100755 index 0000000..54c0802 Binary files /dev/null and b/res/png/24.png differ diff --git a/res/png/25.png b/res/png/25.png new file mode 100755 index 0000000..81684e9 Binary files /dev/null and b/res/png/25.png differ diff --git a/res/png/26.png b/res/png/26.png new file mode 100755 index 0000000..05110c2 Binary files /dev/null and b/res/png/26.png differ diff --git a/res/png/27.png b/res/png/27.png new file mode 100755 index 0000000..75e3002 Binary files /dev/null and b/res/png/27.png differ diff --git a/res/png/28.png b/res/png/28.png new file mode 100755 index 0000000..fe023bb Binary files /dev/null and b/res/png/28.png differ diff --git a/res/png/29.png b/res/png/29.png new file mode 100755 index 0000000..65a840f Binary files /dev/null and b/res/png/29.png differ diff --git a/res/png/3.png b/res/png/3.png new file mode 100755 index 0000000..3585984 Binary files /dev/null and b/res/png/3.png differ diff --git a/res/png/30.png b/res/png/30.png new file mode 100755 index 0000000..ac43303 Binary files /dev/null and b/res/png/30.png differ diff --git a/res/png/31.png b/res/png/31.png new file mode 100755 index 0000000..b934a2f Binary files /dev/null and b/res/png/31.png differ diff --git a/res/png/32.png b/res/png/32.png new file mode 100755 index 0000000..1b15abd Binary files /dev/null and b/res/png/32.png differ diff --git a/res/png/33.png b/res/png/33.png new file mode 100755 index 0000000..824a9ac Binary files /dev/null and b/res/png/33.png differ diff --git a/res/png/34.png b/res/png/34.png new file mode 100755 index 0000000..1449356 Binary files /dev/null and b/res/png/34.png differ diff --git a/res/png/35.png b/res/png/35.png new file mode 100755 index 0000000..3585984 Binary files /dev/null and b/res/png/35.png differ diff --git a/res/png/36.png b/res/png/36.png new file mode 100755 index 0000000..00de41e Binary files /dev/null and b/res/png/36.png differ diff --git a/res/png/37.png b/res/png/37.png new file mode 100755 index 0000000..efb2121 Binary files /dev/null and b/res/png/37.png differ diff --git a/res/png/38.png b/res/png/38.png new file mode 100755 index 0000000..efb2121 Binary files /dev/null and b/res/png/38.png differ diff --git a/res/png/39.png b/res/png/39.png new file mode 100755 index 0000000..94fe49c Binary files /dev/null and b/res/png/39.png differ diff --git a/res/png/4.png b/res/png/4.png new file mode 100755 index 0000000..3585984 Binary files /dev/null and b/res/png/4.png differ diff --git a/res/png/40.png b/res/png/40.png new file mode 100755 index 0000000..ba97398 Binary files /dev/null and b/res/png/40.png differ diff --git a/res/png/41.png b/res/png/41.png new file mode 100755 index 0000000..be817df Binary files /dev/null and b/res/png/41.png differ diff --git a/res/png/42.png b/res/png/42.png new file mode 100755 index 0000000..1268764 Binary files /dev/null and b/res/png/42.png differ diff --git a/res/png/43.png b/res/png/43.png new file mode 100755 index 0000000..6f0b63e Binary files /dev/null and b/res/png/43.png differ diff --git a/res/png/44.png b/res/png/44.png new file mode 100755 index 0000000..81684e9 Binary files /dev/null and b/res/png/44.png differ diff --git a/res/png/45.png b/res/png/45.png new file mode 100755 index 0000000..a57aca7 Binary files /dev/null and b/res/png/45.png differ diff --git a/res/png/46.png b/res/png/46.png new file mode 100755 index 0000000..7b13a91 Binary files /dev/null and b/res/png/46.png differ diff --git a/res/png/47.png b/res/png/47.png new file mode 100755 index 0000000..297ec10 Binary files /dev/null and b/res/png/47.png differ diff --git a/res/png/5.png b/res/png/5.png new file mode 100755 index 0000000..8a123b4 Binary files /dev/null and b/res/png/5.png differ diff --git a/res/png/6.png b/res/png/6.png new file mode 100755 index 0000000..6e8a61b Binary files /dev/null and b/res/png/6.png differ diff --git a/res/png/7.png b/res/png/7.png new file mode 100755 index 0000000..fa5756b Binary files /dev/null and b/res/png/7.png differ diff --git a/res/png/8.png b/res/png/8.png new file mode 100755 index 0000000..e8bcccc Binary files /dev/null and b/res/png/8.png differ diff --git a/res/png/9.png b/res/png/9.png new file mode 100755 index 0000000..37268b8 Binary files /dev/null and b/res/png/9.png differ diff --git a/res/png/na.png b/res/png/na.png new file mode 100755 index 0000000..81684e9 Binary files /dev/null and b/res/png/na.png differ diff --git a/res/wav/bellhit1.wav b/res/wav/bellhit1.wav new file mode 100755 index 0000000..c4a61ae Binary files /dev/null and b/res/wav/bellhit1.wav differ diff --git a/res/wav/bellhit2.wav b/res/wav/bellhit2.wav new file mode 100755 index 0000000..8862920 Binary files /dev/null and b/res/wav/bellhit2.wav differ diff --git a/res/wav/bellhit3.wav b/res/wav/bellhit3.wav new file mode 100755 index 0000000..b999d10 Binary files /dev/null and b/res/wav/bellhit3.wav differ diff --git a/res/wav/bellhit4.wav b/res/wav/bellhit4.wav new file mode 100755 index 0000000..2b19dfd Binary files /dev/null and b/res/wav/bellhit4.wav differ diff --git a/weatherclock.py b/weatherclock.py new file mode 100755 index 0000000..9d6dfc9 --- /dev/null +++ b/weatherclock.py @@ -0,0 +1,98 @@ +#!/usr/bin/python3 +import os + +import pygame + +import countdown +import panel +import wxget + +CONFIG_PATH = 'clock.json' + +pygame.init() + +pygame.mouse.set_visible(False) + +SIZE = (1280, 1024) +mode = pygame.display.set_mode(SIZE, 1) +pygame.display.set_caption("weather clock") +clock = pygame.time.Clock() + + +def game_loop(): + panel_load = None + parent = None + + while True: + for event in pygame.event.get(): + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_q: + pygame.quit() + quit() + if event.key == pygame.K_r: + wxget.update_weather(True) + countdown.update_events(True) + if event.type == pygame.QUIT: + pygame.quit() + quit() + + panel_time = os.stat(CONFIG_PATH).st_mtime_ns + if panel_time != panel_load: + parent = panel.Panel(SIZE, children=panel.load(CONFIG_PATH)) + panel_load = panel_time + + wxget.update_weather() + mode.fill((0, 0, 0)) + mode.blit(parent.surf, (0, 0)) + pygame.display.update() + + clock.tick(8) + + # weather = wxget.__weather + # + # if iconName != weather['current_conditions']['icon']: + # iconName = str(int(weather['current_conditions']['icon'])) + # icon = pygame.image.load('res/png/' + iconName + '.png') + # + # temp = '{0[current_conditions][temperature]}\u00b0{0[units][temperature]}'.format(wxget.get_weather()) + # temp = font60.render(temp, True, WHITE) + # feels_like = 'Feels like ' + weather['current_conditions']['feels_like'] + # feels_like = font45.render(feels_like, True, GRAY) + # lastupdate = Date(weather['current_conditions']['last_updated']).format('Last updated %I:%M') + # lastupdate = font30.render(lastupdate, True, GRAY) + # + # status = join_horizontal(icon, join_vertical(temp, feels_like, 10, TOP_LEFT, BOTTOM_LEFT), 0) + # status = join_vertical(status, lastupdate, 10) + # + # draw_surf(status, (0, -30), BOTTOM_CENTER, BOTTOM_CENTER) + # + # now = datetime.now() + # time = now.strftime('%I:%M') + # time = font360.render(time, True, WHITE) + # date = now.strftime('%A, %B %d') + # date = font60.render(date, True, GRAY) + # + # time = join_vertical(time, date, -100) + # + # draw_surf(time, ZERO, CENTER, (0.5, 0.4)) + # + # event_surfs = [] + # events = countdown.events + # + # for e in events: + # elbl = font45.render(e.label, True, WHITE) + # etime = font30.render(format(e, '{days}d {hours}h {minutes}m'), True, GRAY) + # event = join_vertical(elbl, etime, 5) + # event_surfs.append(event) + # + # timer = pygame.Surface((0, 0)) + # max_w = max((e.get_width() for e in event_surfs)) + # for es in event_surfs: + # timer = join_horizontal(timer, join_vertical(es, pygame.Surface((max_w, 1)), -1), 15) + # + # draw_surf(timer, ZERO, TOP_CENTER, TOP_CENTER) + # + # bells.play_chime(now.hour, now.minute) + + +game_loop() diff --git a/wxget.py b/wxget.py new file mode 100755 index 0000000..9426683 --- /dev/null +++ b/wxget.py @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +from datetime import datetime + +import pywapi +import timestring + +LOCATION = '28223' +UNITS = 'imperial' + +UPDATE_INTERVAL = 60 * 20 + +__weather = {} + + +def update_weather(force=False): + global __weather + now = datetime.now() + last_check = timestring.Date(__weather.get('current_conditions', {}).get('last_checked', now)).date + + interval = (now - last_check).total_seconds() + + if force or interval <= 0 or interval > UPDATE_INTERVAL: + __weather = pywapi.get_weather_from_weather_com(LOCATION, UNITS) + __weather.setdefault('current_conditions', {}).setdefault('last_checked', str(now)) + print('updated weather at', now) + + +def get_weather(force_update=False): + update_weather(force_update) + + return __weather + + +if __name__ == '__main__': + while True: + print('{0[current_conditions][temperature]}\u00b0{0[units][temperature]}'.format(get_weather()))