Handle missing network on start/refactor code

This commit is contained in:
Mike Cifelli 2023-01-14 14:48:36 -05:00
parent fd1ea198fa
commit 0a212e5752
13 changed files with 83 additions and 63 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.vscode/
__pycache__/
*.swp
chutney.cfg

3
chutney/exceptions.py Normal file
View File

@ -0,0 +1,3 @@
class HaltException(Exception):
pass

View File

@ -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

View File

@ -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,

View File

@ -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()

View File

@ -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):

View File

@ -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

View File

@ -1 +1 @@
from .time_display import TimeDisplay
from .timedisplayer import TimeDisplayer

View File

@ -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
)

View File

@ -1,2 +1,2 @@
from .weather_display import WeatherDisplay
from .weather_updater import WeatherUpdater
from .weatherdisplayer import WeatherDisplayer
from .weatherupdater import WeatherUpdater

View File

@ -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