mirror of
https://github.com/Crocmagnon/plant-badger.git
synced 2024-11-22 09:28:03 +01:00
Display status with details
This commit is contained in:
parent
ced8d3683a
commit
8f736bc647
1 changed files with 130 additions and 58 deletions
|
@ -1,15 +1,21 @@
|
||||||
import badger2040w as badger2040
|
from badger2040w import WIDTH, Badger2040W
|
||||||
from badger2040w import WIDTH
|
|
||||||
import urequests
|
import urequests
|
||||||
|
|
||||||
|
import secrets
|
||||||
from secrets import HA_BASE_URL, HA_ACCESS_TOKEN
|
from secrets import HA_BASE_URL, HA_ACCESS_TOKEN
|
||||||
|
|
||||||
|
|
||||||
display = badger2040.Badger2040W()
|
display = Badger2040W()
|
||||||
display.led(128)
|
display.led(128)
|
||||||
display.set_update_speed(2)
|
display.set_update_speed(2)
|
||||||
|
BLACK = 0
|
||||||
|
WHITE = 15
|
||||||
|
|
||||||
display.connect()
|
display.connect()
|
||||||
|
|
||||||
|
LINE_START_OFFSET = 3
|
||||||
|
STATUS_VALUE_OFFSET = 25
|
||||||
|
|
||||||
|
|
||||||
class HAError(Exception):
|
class HAError(Exception):
|
||||||
pass
|
pass
|
||||||
|
@ -19,66 +25,132 @@ class HAFetchStateError(HAError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class HAPlant:
|
def fetch_state(entity: str) -> dict:
|
||||||
def __init__(self, entity_id):
|
headers = {
|
||||||
self.entity_id = entity_id
|
"Authorization": f"Bearer {HA_ACCESS_TOKEN}",
|
||||||
self.state = None
|
"content-type": "application/json",
|
||||||
self._last_fetched = None
|
}
|
||||||
|
url = f"{HA_BASE_URL}/states/{entity}"
|
||||||
|
print("Fetching state from", url)
|
||||||
|
res = urequests.get(url, headers=headers)
|
||||||
|
if res.status_code != 200:
|
||||||
|
msg = f"Error fetching state for {entity}: {res.text}"
|
||||||
|
raise HAFetchStateError(msg)
|
||||||
|
data = res.json()
|
||||||
|
res.close()
|
||||||
|
del data["context"]
|
||||||
|
print(data)
|
||||||
|
return data
|
||||||
|
|
||||||
def fetch_state(self) -> None:
|
|
||||||
"""Fetch state and store in self.state."""
|
class HAPlant:
|
||||||
headers = {
|
def __init__(self):
|
||||||
"Authorization": f"Bearer {HA_ACCESS_TOKEN}",
|
self._last_fetched = None
|
||||||
"content-type": "application/json",
|
self.plant_state = None
|
||||||
}
|
# Example state
|
||||||
url = f"{HA_BASE_URL}/states/{self.entity_id}"
|
# {
|
||||||
print("Fetching state from", url)
|
# "entity_id": "plant.aloe_vera",
|
||||||
res = urequests.get(url, headers=headers)
|
# "state": "problem",
|
||||||
if res.status_code != 200:
|
# "attributes": {
|
||||||
msg = f"Error fetching state for {self.entity_id}: {res.text}"
|
# "species": "Aloe vera",
|
||||||
raise HAFetchStateError(msg)
|
# "moisture_status": "ok",
|
||||||
data = res.json()
|
# "temperature_status": "ok",
|
||||||
self.state = data
|
# "conductivity_status": "Low",
|
||||||
res.close()
|
# "illuminance_status": "ok",
|
||||||
|
# "humidity_status": null,
|
||||||
|
# "dli_status": "Low",
|
||||||
|
# "species_original": "aloe vera",
|
||||||
|
# "device_class": "plant",
|
||||||
|
# "entity_picture": "https://opb-img.plantbook.io/aloe%20vera.jpg",
|
||||||
|
# "friendly_name": "Aloe vera"
|
||||||
|
# },
|
||||||
|
# "last_changed": "2023-03-10T12:51:29.103630+00:00",
|
||||||
|
# "last_updated": "2023-03-10T12:52:47.188669+00:00",
|
||||||
|
# }
|
||||||
|
self.details = {}
|
||||||
|
# Example illuminance state
|
||||||
|
# {
|
||||||
|
# "entity_id": "sensor.aloe_vera_illuminance",
|
||||||
|
# "state": "245",
|
||||||
|
# "attributes": {
|
||||||
|
# "state_class": "measurement",
|
||||||
|
# "unit_of_measurement": "lx",
|
||||||
|
# "device_class": "illuminance",
|
||||||
|
# "friendly_name": "Aloe vera Illuminance"
|
||||||
|
# },
|
||||||
|
# "last_changed": "2023-03-10T13:58:08.838316+00:00",
|
||||||
|
# "last_updated": "2023-03-10T13:58:08.838316+00:00",
|
||||||
|
# }
|
||||||
|
|
||||||
|
def get_plant_attribute(self, attribute):
|
||||||
|
return self.plant_state.get("attributes", {}).get(attribute, None)
|
||||||
|
|
||||||
|
def get_detailed_state(self, attribute):
|
||||||
|
return self.details.get(attribute, {}).get("state", None)
|
||||||
|
|
||||||
|
def get_detailed_attribute(self, attribute, attribute_name):
|
||||||
|
return (
|
||||||
|
self.details.get(attribute, {})
|
||||||
|
.get("attributes", {})
|
||||||
|
.get(attribute_name, None)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_plant_status(self, attribute):
|
||||||
|
status = self.get_plant_attribute(f"{attribute}_status")
|
||||||
|
if status is None:
|
||||||
|
return "N/A"
|
||||||
|
status = status.upper()
|
||||||
|
if status == "OK":
|
||||||
|
return "OK"
|
||||||
|
detailed_state = self.get_detailed_state(
|
||||||
|
attribute
|
||||||
|
) + self.get_detailed_attribute(attribute, "unit_of_measurement")
|
||||||
|
if status == "LOW":
|
||||||
|
return f"Bas ({detailed_state})"
|
||||||
|
if status == "HIGH":
|
||||||
|
return f"Haut ({detailed_state})"
|
||||||
|
return status
|
||||||
|
|
||||||
|
def fetch_states(self) -> None:
|
||||||
|
self.plant_state = fetch_state(secrets.HA_PLANT_ID)
|
||||||
|
self.details["moisture"] = fetch_state(secrets.HA_PLANT_MOISTURE_SENSOR)
|
||||||
|
self.details["illuminance"] = fetch_state(secrets.HA_PLANT_ILLUMINANCE_SENSOR)
|
||||||
|
self.details["temperature"] = fetch_state(secrets.HA_PLANT_TEMPERATURE_SENSOR)
|
||||||
|
self.details["conductivity"] = fetch_state(secrets.HA_PLANT_CONDUCTIVITY_SENSOR)
|
||||||
|
print(self.details)
|
||||||
|
|
||||||
def display_state(self):
|
def display_state(self):
|
||||||
print(self.state)
|
# Clear the display
|
||||||
|
display.set_pen(WHITE)
|
||||||
|
display.clear()
|
||||||
|
|
||||||
|
# Draw the page header
|
||||||
|
display.set_pen(BLACK)
|
||||||
|
display.rectangle(0, 0, WIDTH, 20)
|
||||||
|
|
||||||
|
# Write text in header
|
||||||
|
display.set_font("bitmap6")
|
||||||
|
display.set_pen(WHITE)
|
||||||
|
display.text(self.get_plant_attribute("friendly_name"), 3, 4)
|
||||||
|
|
||||||
|
display.set_pen(BLACK)
|
||||||
|
display.text("H", LINE_START_OFFSET, 30)
|
||||||
|
display.text("T", LINE_START_OFFSET, 55)
|
||||||
|
display.text("C", LINE_START_OFFSET, 80)
|
||||||
|
display.text("L", LINE_START_OFFSET, 105)
|
||||||
|
|
||||||
|
display.set_font("bitmap8")
|
||||||
|
display.text(self.get_plant_status("moisture"), STATUS_VALUE_OFFSET, 30)
|
||||||
|
display.text(self.get_plant_status("temperature"), STATUS_VALUE_OFFSET, 55)
|
||||||
|
display.text(self.get_plant_status("conductivity"), STATUS_VALUE_OFFSET, 80)
|
||||||
|
display.text(self.get_plant_status("illuminance"), STATUS_VALUE_OFFSET, 105)
|
||||||
|
|
||||||
|
display.update()
|
||||||
|
|
||||||
|
|
||||||
def draw_page(plant):
|
plant = HAPlant()
|
||||||
print("Drawing page...")
|
plant.fetch_states()
|
||||||
# Clear the display
|
plant.display_state()
|
||||||
display.set_pen(15)
|
|
||||||
display.clear()
|
|
||||||
display.set_pen(0)
|
|
||||||
|
|
||||||
# Draw the page header
|
|
||||||
display.set_font("bitmap6")
|
|
||||||
display.set_pen(0)
|
|
||||||
display.rectangle(0, 0, WIDTH, 20)
|
|
||||||
display.set_pen(15)
|
|
||||||
display.text("Weather", 3, 4)
|
|
||||||
display.set_pen(0)
|
|
||||||
|
|
||||||
display.set_font("bitmap8")
|
|
||||||
display.set_pen(0)
|
|
||||||
display.rectangle(0, 60, WIDTH, 25)
|
|
||||||
display.set_pen(15)
|
|
||||||
display.text(
|
|
||||||
"Found state, check logs",
|
|
||||||
5,
|
|
||||||
65,
|
|
||||||
WIDTH,
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
|
|
||||||
display.update()
|
|
||||||
plant.display_state()
|
|
||||||
|
|
||||||
|
|
||||||
plant = HAPlant("plant.aloe_vera")
|
|
||||||
plant.fetch_state()
|
|
||||||
draw_page(plant)
|
|
||||||
|
|
||||||
# Call halt in a loop, on battery this switches off power.
|
# Call halt in a loop, on battery this switches off power.
|
||||||
# On USB, the app will exit when A+C is pressed because the launcher picks that up.
|
# On USB, the app will exit when A+C is pressed because the launcher picks that up.
|
||||||
|
|
Loading…
Reference in a new issue