diff --git a/.gitignore b/.gitignore index 19bfbb7..409ef35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.vscode/ __pycache__/ *.swp chutney.cfg diff --git a/chutney/exceptions.py b/chutney/exceptions.py new file mode 100644 index 0000000..6196ff0 --- /dev/null +++ b/chutney/exceptions.py @@ -0,0 +1,3 @@ + +class HaltException(Exception): + pass diff --git a/chutney/garage/__init__.py b/chutney/garage/__init__.py index fc2456e..b8321f4 100644 --- a/chutney/garage/__init__.py +++ b/chutney/garage/__init__.py @@ -1,2 +1,3 @@ -from .garage_display import GarageDisplay -from .garage_updater import GarageUpdater +from .garagedisplayer import GarageDisplayer +from .garagelistener import GarageListener +from .garageupdater import GarageUpdater diff --git a/chutney/garage/garage_display.py b/chutney/garage/garagedisplayer.py similarity index 83% rename from chutney/garage/garage_display.py rename to chutney/garage/garagedisplayer.py index efd7a98..d9e5d72 100644 --- a/chutney/garage/garage_display.py +++ b/chutney/garage/garagedisplayer.py @@ -2,9 +2,9 @@ import chutney.colors as colors import json -class GarageDisplay: - def __init__(self, symbolDisplay, topRow): - self.symbolDisplay = symbolDisplay +class GarageDisplayer: + def __init__(self, symbolDisplayer, topRow): + self.symbolDisplayer = symbolDisplayer self.topRow = topRow self.westDoorStartColumn = 1 self.eastDoorStartColumn = 12 @@ -15,7 +15,7 @@ class GarageDisplay: self.openFillColor = colors.WHITE self.garageFile = 'data/garage.json' - self.symbolDisplay.clearRow(self.topRow, rowHeight=4) + self.symbolDisplayer.clearRow(self.topRow, rowHeight=4) def showGarageState(self): state = self.getGarageState() @@ -26,7 +26,7 @@ class GarageDisplay: if self.isGarageStateValid(state): self.showState(state) else: - self.symbolDisplay.clearRow(self.topRow, rowHeight=4) + self.symbolDisplayer.clearRow(self.topRow, rowHeight=4) def getGarageState(self): try: @@ -51,7 +51,7 @@ class GarageDisplay: self.showOpenDoor(self.eastDoorStartColumn) def showOpenDoor(self, column): - self.symbolDisplay.displaySquare( + self.symbolDisplayer.displaySquare( x=column, y=self.topRow, outlineColor=self.openOutlineColor, @@ -59,7 +59,7 @@ class GarageDisplay: ) def showClosedDoor(self, column): - self.symbolDisplay.displaySquare( + self.symbolDisplayer.displaySquare( x=column, y=self.topRow, outlineColor=self.closedOutlineColor, diff --git a/chutney/garage/garagelistener.py b/chutney/garage/garagelistener.py new file mode 100644 index 0000000..939e1f7 --- /dev/null +++ b/chutney/garage/garagelistener.py @@ -0,0 +1,28 @@ +import json +import requests + +from configparser import ConfigParser + + +class GarageListener: + def __init__(self, configFile): + config = ConfigParser() + config.read(configFile) + + ntfy = config['garage'].get('ntfy') + topic = config['garage'].get('topic') + + self.ntfyUri = f'https://{ntfy}/{topic}/json' + + def listenForNotifications(self, queue): + resp = requests.get(self.ntfyUri, stream=True) + + try: + for line in resp.iter_lines(): + if line: + data = json.loads(line.decode('utf-8')) + + if (data['event'] == 'message'): + queue.put('update') + finally: + resp.close() diff --git a/chutney/garage/garage_updater.py b/chutney/garage/garageupdater.py similarity index 100% rename from chutney/garage/garage_updater.py rename to chutney/garage/garageupdater.py diff --git a/chutney/runner.py b/chutney/runner.py index 151c613..0f486ef 100644 --- a/chutney/runner.py +++ b/chutney/runner.py @@ -1,14 +1,13 @@ -import json -import requests import sys -from .symbol_display import SymbolDisplay -from .garage import GarageDisplay +from .exceptions import HaltException +from .garage import GarageDisplayer +from .garage import GarageListener from .garage import GarageUpdater -from .time import TimeDisplay -from .weather import WeatherDisplay +from .symboldisplayer import SymbolDisplayer +from .time import TimeDisplayer +from .weather import WeatherDisplayer from .weather import WeatherUpdater -from configparser import ConfigParser from multiprocessing import Event from multiprocessing import Process from multiprocessing import Queue @@ -27,14 +26,11 @@ except ImportError: WEATHER_UPDATE_INTERVAL_IN_SECONDS = 60 GARAGE_UPDATE_INTERVAL_IN_SECONDS = 30 +GARAGE_LISTENER_RETRY_INTERVAL_IN_SECONDS = 120 DISPLAY_UPDATE_INTERVAL_IN_SECONDS = 0.5 CONFIG_FILE = 'chutney.cfg' -class HaltException(Exception): - pass - - def main(): queue = Queue() haltEvent = Event() @@ -44,15 +40,15 @@ def main(): unicorn.brightness(0.3) - symbolDisplay = SymbolDisplay(unicorn) - timeDisplay = TimeDisplay(symbolDisplay, topRow=15) - weatherDisplay = WeatherDisplay(symbolDisplay, topRow=9) - garageDisplay = GarageDisplay(symbolDisplay, topRow=3) + symbolDisplayer = SymbolDisplayer(unicorn) + timeDisplayer = TimeDisplayer(symbolDisplayer, topRow=15) + weatherDisplayer = WeatherDisplayer(symbolDisplayer, topRow=9) + garageDisplayer = GarageDisplayer(symbolDisplayer, topRow=3) while True: - timeDisplay.showTime() - weatherDisplay.showWeather() - garageDisplay.showGarageState() + timeDisplayer.showTime() + weatherDisplayer.showWeather() + garageDisplayer.showGarageState() sleep(DISPLAY_UPDATE_INTERVAL_IN_SECONDS) @@ -88,27 +84,18 @@ def garageLoop(queue): def garageNotifyLoop(queue): signal(SIGTERM, raiseHaltException()) - config = ConfigParser() - config.read(CONFIG_FILE) - ntfy = config['garage'].get('ntfy') - topic = config['garage'].get('topic') + garageListener = GarageListener(configFile=CONFIG_FILE) + isRunning = True - try: - resp = requests.get(f'https://{ntfy}/{topic}/json', stream=True) - - for line in resp.iter_lines(): - if line: - data = json.loads(line.decode('utf-8')) - - if (data['event'] == 'message'): - queue.put('update') - except HaltException: - pass - except Exception as e: - print(e, flush=True) - finally: - resp.close() + while isRunning: + try: + garageListener.listenForNotifications(queue) + except HaltException: + isRunning = False + except Exception as e: + print(e, flush=True) + sleep(GARAGE_LISTENER_RETRY_INTERVAL_IN_SECONDS) def cleanExit(unicorn, haltEvent, queue): diff --git a/chutney/symbol_display.py b/chutney/symboldisplayer.py similarity index 99% rename from chutney/symbol_display.py rename to chutney/symboldisplayer.py index f8124ac..3590e0a 100644 --- a/chutney/symbol_display.py +++ b/chutney/symboldisplayer.py @@ -1,7 +1,7 @@ import chutney.colors as colors -class SymbolDisplay: +class SymbolDisplayer: def __init__(self, unicorn, minX=0, maxX=15, minY=0, maxY=15): self.unicorn = unicorn diff --git a/chutney/time/__init__.py b/chutney/time/__init__.py index 8804a97..a34a969 100644 --- a/chutney/time/__init__.py +++ b/chutney/time/__init__.py @@ -1 +1 @@ -from .time_display import TimeDisplay +from .timedisplayer import TimeDisplayer diff --git a/chutney/time/time_display.py b/chutney/time/timedisplayer.py similarity index 88% rename from chutney/time/time_display.py rename to chutney/time/timedisplayer.py index 2796f57..a924643 100644 --- a/chutney/time/time_display.py +++ b/chutney/time/timedisplayer.py @@ -3,10 +3,10 @@ import chutney.colors as colors from datetime import datetime -class TimeDisplay: +class TimeDisplayer: - def __init__(self, symbolDisplay, topRow): - self.symbolDisplay = symbolDisplay + def __init__(self, symbolDisplayer, topRow): + self.symbolDisplayer = symbolDisplayer self.topRow = topRow self.currentHour = [-1, -1] self.currentMinute = [-1, -1] @@ -37,7 +37,7 @@ class TimeDisplay: def showTimeDots(self): if self.color != self.currentColor: - self.symbolDisplay.displayTimeDots( + self.symbolDisplayer.displayTimeDots( x=self.timeDotsColumn, y=self.topRow, color=self.color @@ -53,7 +53,7 @@ class TimeDisplay: self.showDigit(self.minuteStartColumn + 4, minute[1]) def showDigit(self, x, digit): - self.symbolDisplay.displayDigit( + self.symbolDisplayer.displayDigit( x=x, y=self.topRow, digit=digit, @@ -61,7 +61,7 @@ class TimeDisplay: ) def hideDigit(self, x): - self.symbolDisplay.clearDigit( + self.symbolDisplayer.clearDigit( x=x, y=self.topRow ) diff --git a/chutney/weather/__init__.py b/chutney/weather/__init__.py index ef5fa67..9ba00c3 100644 --- a/chutney/weather/__init__.py +++ b/chutney/weather/__init__.py @@ -1,2 +1,2 @@ -from .weather_display import WeatherDisplay -from .weather_updater import WeatherUpdater +from .weatherdisplayer import WeatherDisplayer +from .weatherupdater import WeatherUpdater diff --git a/chutney/weather/weather_display.py b/chutney/weather/weatherdisplayer.py similarity index 88% rename from chutney/weather/weather_display.py rename to chutney/weather/weatherdisplayer.py index c65d953..24276e8 100644 --- a/chutney/weather/weather_display.py +++ b/chutney/weather/weatherdisplayer.py @@ -1,9 +1,9 @@ import chutney.colors as colors -class WeatherDisplay: - def __init__(self, symbolDisplay, topRow): - self.symbolDisplay = symbolDisplay +class WeatherDisplayer: + def __init__(self, symbolDisplayer, topRow): + self.symbolDisplayer = symbolDisplayer self.topRow = topRow self.twoDigitStartColumn = 5 self.oneDigitStartColumn = 7 @@ -17,7 +17,7 @@ class WeatherDisplay: if temperature != self.currentTemperature: self.currentTemperature = temperature - self.symbolDisplay.clearRow(self.topRow) + self.symbolDisplayer.clearRow(self.topRow) if self.isTemperatureValid(temperature): self.updateColor(temperature) @@ -68,14 +68,14 @@ class WeatherDisplay: return abs(int(temperature))//10 == 0 def showNegative(self, column): - self.symbolDisplay.displayNegative( + self.symbolDisplayer.displayNegative( x=column, y=self.topRow, color=self.color ) def showDigit(self, column, digit): - self.symbolDisplay.displayDigit( + self.symbolDisplayer.displayDigit( x=column, y=self.topRow, digit=digit, @@ -83,7 +83,7 @@ class WeatherDisplay: ) def showDegree(self, column): - self.symbolDisplay.displayDegree( + self.symbolDisplayer.displayDegree( x=column, y=self.topRow, color=self.color diff --git a/chutney/weather/weather_updater.py b/chutney/weather/weatherupdater.py similarity index 100% rename from chutney/weather/weather_updater.py rename to chutney/weather/weatherupdater.py