diff --git a/api.py b/api.py index 5b432d1..718fa18 100644 --- a/api.py +++ b/api.py @@ -1,4 +1,4 @@ -from requests import get +from requests import get, post import gc import time @@ -17,6 +17,17 @@ class Api: print("Starting request for " + endpoint) response = get(url, headers=headers) return response.json() + + def __post(self, endpoint, d) -> bool: + gc.collect() + url = self.base_url + endpoint + headers = { + "Authorization": "Bearer " + self.access_token, + "content-type": "application/json" + } + print("Starting post request to " + endpoint) + response = post(url, headers=headers, json=d) + return response.status_code == 200 def getLightData(self, entity_id: str) -> dict: # TODO: error handling if can't access hass (e.g. no connection, invalid token) @@ -38,8 +49,6 @@ class Api: p = 0 if ("media_position_updated_at" in (dict)(response["attributes"])): dts = response["attributes"]["media_position_updated_at"] - # p += (datetime.now() - datetime.strptime(dts, "%Y-%m-%dT%H:%M:%S.%f%z")).total_seconds() - print(dts) t = time.mktime((int(dts[0:4]), int(dts[5:7]), int(dts[8:10]), int(dts[11:13]) + int(dts[27:29]), int(dts[14:16]) + int(dts[30:31]), int(dts[17:19]), 0, 0)) p += time.mktime(time.localtime()) - t return { @@ -54,4 +63,10 @@ class Api: "media_title": response["attributes"]["media_title"] if "media_title" in (dict)(response["attributes"]) else "Nothing playing", "media_artist": response["attributes"]["media_artist"] if "media_artist" in (dict)(response["attributes"]) else "", "media_album_name": response["attributes"]["media_album_name"] if "media_album_name" in (dict)(response["attributes"]) else "" - } \ No newline at end of file + } + + def changeVolume(self, entity_id: str, up: bool = True) -> None: + if (up): dir = "up" + else: dir = "down" + self.__post(f"/api/services/media_player/volume_{dir}", {"entity_id": entity_id}) + self.__post(f"/api/services/media_player/volume_{dir}", {"entity_id": entity_id}) diff --git a/app.py b/app.py index 3d22975..8c3c6bb 100644 --- a/app.py +++ b/app.py @@ -16,10 +16,10 @@ class App: def __init__(self) -> None: if (len(SCREENS) == 0): print("No screens configured. Check env.py.") - self.screen = -1 + self.screen = -1 + else: self.screen = 0 self.lcd = LCD() self.api = Api(HASS_URL, TOKEN) - self.screen = 0 self.scr_vals = {} # stored values from the current screen def __connect(self) -> int: @@ -49,8 +49,8 @@ class App: self.lcd.keyB["v"] = False self.lcd.keyX["v"] = False self.lcd.keyY["v"] = False - self.lcd.right["v"] = False self.lcd.left["v"] = False + self.lcd.right["v"] = False self.lcd.up["v"] = False self.lcd.down["v"] = False self.lcd.ctrl["v"] = False @@ -63,7 +63,8 @@ class App: if (self.lcd.keyY["p"].value() == 0): self.lcd.keyY["v"] = True if (self.lcd.right["p"].value() == 0): self.lcd.right["v"] = True if (self.lcd.left["p"].value() == 0): self.lcd.left["v"] = True - if (self.lcd.up["p"].value() == 0): self.lcd.up["v"] = True + if (self.lcd.up["p"].value() == 0): + self.lcd.up["v"] = True if (self.lcd.down["p"].value() == 0): self.lcd.down["v"] = True if (self.lcd.ctrl["p"].value() == 0): self.lcd.ctrl["v"] = True @@ -79,16 +80,16 @@ class App: self.screen = len(SCREENS) - 1 else: self.screen -= 1 - self.__resetButtonStatuses() change = self.screen != orig if (change): self.scr_vals = {} - + self.lcd.left["v"] = False + self.lcd.right["v"] = False + print(f"Screen change: {change}") return change def __displayLightEntity(self, i: int, w: int, h: int, xo: int, yo: int, n: str, d) -> None: self.scr_vals[i] = d - print("Checking if light is on") # if the light is turned on, display the filled-in lightbulb icon in the colour of the light, centrally in the light's grid square if (d["on"]): color = Utils.colour(d["rgb_color"][0], d["rgb_color"][1], d["rgb_color"][2]) @@ -108,9 +109,7 @@ class App: # otherwise display the outline lightbulb icon in grey, centrally in the light's grid square else: color = Utils.colour(80, 80, 80) - print("Opening file...") with open("images/lightbulb-off.bmp", "rb") as file_handle: - print("Opened file") reader = bmpr.BMPFileReader(file_handle) img_height = reader.get_height() x_offset = w//2 + xo - reader.get_width()//2 @@ -137,9 +136,7 @@ class App: # TODO: handle buttons def __updateMediaPositionBar(self, d): - print("Redrawing media progress bar") if (d["media_position"] != None and d["media_duration"] != None and d["media_duration"] != 0): - print(f"Progress is {(self.lcd.width * d["media_position"])//d["media_duration"]} for pos {d["media_position"]} and dur {d["media_duration"]}") for x in range (0, (self.lcd.width * d["media_position"])//d["media_duration"]): self.lcd.pixel(x, self.lcd.height - 2, self.lcd.white) self.lcd.pixel(x, self.lcd.height - 1, self.lcd.white) @@ -182,7 +179,11 @@ class App: if (d != self.scr_vals[i]): self.__displayLightEntity(i, self.lcd.width//2, self.lcd.height//2, self.lcd.width//2 * (i % 2), self.lcd.height//2 * (i//2), SCREENS[self.screen]["entities"][i]["name"], d[i]) # TODO: double button press to select a light, then up/down to change brightness? and single button click to turn on/off? - self.lcd.show() + self.lcd.show() + + def __handleLightsScreenButtons(self) -> bool: + # TODO: reset buttons used + return False def __updateMediaScreen(self) -> None: d = self.api.getMediaPlayerData(SCREENS[self.screen]["entity"]) @@ -194,25 +195,46 @@ class App: else: self.__displayMediaScreen(d) + def __handleMediaScreenButtons(self) -> bool: + up = self.lcd.up["v"] + down = self.lcd.down["v"] + self.lcd.up["v"] = False + self.lcd.down["v"] = False + a = False + if (up): + self.api.changeVolume(SCREENS[self.screen]["entity"]) + a = True + elif (down): + self.api.changeVolume(SCREENS[self.screen]["entity"], False) + a = True + return a + # if (a): self.__handleMediaScreenButtons() + def __manageScreen(self) -> None: started = False while (True): gc.collect() changed = not started or self.__changeScreen() - started = True + # TODO: make screen not change within given interval, as holding button too long changes it twice + if (not started): started = True # if the screen has changed, redraw the whole screen if (changed): if (SCREENS[self.screen]["type"] == 0): + self.__resetButtonStatuses() self.__displayLightsScreen() elif (SCREENS[self.screen]["type"] == 1): + self.__resetButtonStatuses() self.__displayMediaScreen() else: + self.__resetButtonStatuses() self.__displayUnknownScreen() # otherwise minimise the number of pixels being changed else: if (SCREENS[self.screen]["type"] == 0): + if (self.__handleLightsScreenButtons()): continue self.__updateLightsScreen() elif (SCREENS[self.screen]["type"] == 1): + if (self.__handleMediaScreenButtons()): continue self.__updateMediaScreen() def run(self) -> None: