Receive notifications for garage updates

This commit is contained in:
Mike Cifelli 2022-12-30 14:31:25 -05:00
parent 460be567c9
commit d1a8769e07
4 changed files with 67 additions and 27 deletions

View File

@ -1,17 +1,3 @@
# There are 4 different types of patterns used when generating a digit that is
# to be placed in a rectangle 3X5 pixels. Combinations of these are used to
# create a number pattern such as:
# * * *
# *
# * * *
# * *
# * * *
#
# 1) * * * Full Row
# 2) * * Both Sides
# 3) * Right Side
# 4) * Left Side
import colors import colors

View File

@ -1,10 +1,15 @@
import json
import requests
import sys import sys
from character_display import CharacterDisplay from character_display import CharacterDisplay
from configparser import ConfigParser
from garage_display import GarageDisplay from garage_display import GarageDisplay
from garage_updater import GarageUpdater from garage_updater import GarageUpdater
from multiprocessing import Event from multiprocessing import Event
from multiprocessing import Process from multiprocessing import Process
from multiprocessing import Queue
from queue import Empty
from signal import signal from signal import signal
from signal import SIGTERM from signal import SIGTERM
from time import sleep from time import sleep
@ -21,22 +26,24 @@ except ImportError:
WEATHER_UPDATE_INTERVAL_IN_SECONDS = 10 WEATHER_UPDATE_INTERVAL_IN_SECONDS = 10
GARAGE_UPDATE_INTERVAL_IN_SECONDS = 10 GARAGE_UPDATE_INTERVAL_IN_SECONDS = 30
DISPLAY_UPDATE_INTERVAL_IN_SECONDS = 0.5 DISPLAY_UPDATE_INTERVAL_IN_SECONDS = 0.5
CONFIG_FILE = 'chutney.cfg' CONFIG_FILE = 'chutney.cfg'
class HaltException(Exception):
pass
def main(): def main():
queue = Queue()
haltEvent = Event() haltEvent = Event()
signal(SIGTERM, cleanExit(unicorn, haltEvent)) Process(target=weatherLoop, args=[haltEvent]).start()
Process(target=garageLoop, args=[queue]).start()
signal(SIGTERM, cleanExit(unicorn, haltEvent, queue))
unicorn.brightness(0.3) unicorn.brightness(0.3)
weatherThread = Process(target=weatherLoop, args=[haltEvent])
weatherThread.start()
garageThread = Process(target=garageLoop, args=[haltEvent])
garageThread.start()
characterDisplay = CharacterDisplay(unicorn) characterDisplay = CharacterDisplay(unicorn)
timeDisplay = TimeDisplay(characterDisplay, topRow=15) timeDisplay = TimeDisplay(characterDisplay, topRow=15)
weatherDisplay = WeatherDisplay(characterDisplay, topRow=9) weatherDisplay = WeatherDisplay(characterDisplay, topRow=9)
@ -59,24 +66,68 @@ def weatherLoop(haltEvent):
weatherUpdater.clearWeather() weatherUpdater.clearWeather()
def garageLoop(haltEvent): def garageLoop(queue):
garageUpdater = GarageUpdater(configFile=CONFIG_FILE) garageNotify = Process(target=garageNotifyLoop, args=[queue])
garageNotify.start()
while not haltEvent.is_set(): garageUpdater = GarageUpdater(configFile=CONFIG_FILE)
isRunning = True
while isRunning:
garageUpdater.updateGarageState() garageUpdater.updateGarageState()
haltEvent.wait(timeout=GARAGE_UPDATE_INTERVAL_IN_SECONDS)
try:
item = queue.get(timeout=GARAGE_UPDATE_INTERVAL_IN_SECONDS)
isRunning = item != 'halt'
except Empty:
pass
garageUpdater.clearGarageState() garageUpdater.clearGarageState()
garageNotify.terminate()
def cleanExit(unicorn, haltEvent): def garageNotifyLoop(queue):
signal(SIGTERM, raiseHaltException())
config = ConfigParser()
config.read(CONFIG_FILE)
ntfy = config['garage'].get('ntfy')
topic = config['garage'].get('topic')
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()
def cleanExit(unicorn, haltEvent, queue):
def _exit_(signum, frame): def _exit_(signum, frame):
unicorn.off() unicorn.off()
haltEvent.set() haltEvent.set()
queue.put('halt')
queue.close()
sys.exit(0) sys.exit(0)
return _exit_ return _exit_
def raiseHaltException():
def _exit_(signum, frame):
raise HaltException()
return _exit_
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -7,3 +7,5 @@ lon=lon
[garage] [garage]
uri=uri uri=uri
ntfy=ntfy.sh
topic=topic

View File

@ -18,6 +18,7 @@ class GarageDisplay:
def showGarageState(self): def showGarageState(self):
state = self.getGarageState() state = self.getGarageState()
# TODO - only update the changed door so the other one doesn't flicker
if state != self.currentState: if state != self.currentState:
self.currentState = state self.currentState = state
self.characterDisplay.clearRow(self.topRow, rowHeight=4) self.characterDisplay.clearRow(self.topRow, rowHeight=4)