Files
epaper-bathroom/epaper.py

185 lines
6.6 KiB
Python
Raw Normal View History

#!/usr/bin/python
2022-01-14 21:21:03 +01:00
import datetime
import json
import logging
import os
import requests
import time
class DisplaySegment:
""" validity - time in seconds how long the data is useful """
last_refresh = 0
validity = 1
def update(self):
pass
def get_data_text(self):
""" returns text formatted data """
now = time.time()
if self.last_refresh + self.validity < now:
logging.debug(f"{type(self)}: Data from {self.last_refresh} older than {self.validity} seconds, refreshing")
self.update()
self.last_refresh = now
return self._get_data_text()
def _get_data_text(self):
""" real function to return true text formatted data """
pass
class ClockSegment(DisplaySegment):
2022-01-14 21:21:03 +01:00
""" between 0600 and 0700 returns true time, then approximation """
time_display = ""
2022-01-14 21:21:03 +01:00
def _get_data_text(self):
return f"Czas: {self.time_display}"
2022-01-14 21:21:03 +01:00
def update(self):
2022-01-14 21:21:03 +01:00
now = datetime.datetime.now()
if now.hour >= 6 and now.hour < 7:
self.validity = 60
self.time_display = f"{now.hour}:{now.minute}"
2022-01-14 21:21:03 +01:00
self.validity = 5*60
if now.minute >= 45:
self.time_display = f"przed {now.hour+1}"
2022-01-14 21:21:03 +01:00
elif now.minute >= 15:
self.time_display = f"wpół do {now.hour+1}"
2022-01-14 21:21:03 +01:00
else:
self.time_display = f"po {now.hour}"
class TrafficSegment(DisplaySegment):
pass
class WeatherSegment(DisplaySegment):
2022-01-15 15:07:10 +01:00
def mps2kph(self, m_per_s):
return m_per_s * 3600 / 1000
def update(self):
lat = os.getenv("LATITUDE")
long = os.getenv("LONGITUDE")
self.validity = 6*60*60
req = requests.get(f'https://api.openweathermap.org/data/2.5/onecall?lat={lat}&lon={long}&appid={os.getenv("OPENWEATHERMAP_API_KEY")}&units=metric&exclude=minutely,hourly,alerts&lang=pl')
if not req.ok:
logging.info(f"{type(self)}: OpenWeatherMap API call failed {req.status_code}")
else:
response = req.json()
# current weather
self.cur_cloud_percent = response["current"]["clouds"]
# airly probably have better data - from the sensors in the area
self.cur_temperature = response["current"]["temp"]
self.cur_temperature_feel = response["current"]["feels_like"]
self.cur_wind = self.mps2kph(response["current"]["wind_speed"])
#self.cur_wind_gust = self.mps2kph(response["current"]["wind_gust"])
self.cur_description = response["current"]["weather"][0]["description"]
self.cur_description_short = response["current"]["weather"][0]["main"]
# also "icon" and "id" may be useful
# forecast for next day
now = datetime.datetime.now()
for daily in response["daily"]:
forecast_date = datetime.datetime.fromtimestamp(daily["dt"])
tomorrow_date = now + datetime.timedelta(days=1)
if forecast_date.day == tomorrow_date.day:
self.tomorrow_cloud_percent = daily["clouds"]
self.tomorrow_temperature = daily["temp"]["day"]
self.tomorrow_temperature_feel = daily["feels_like"]["day"]
self.tomorrow_wind = self.mps2kph(daily["wind_speed"])
self.tomorrow_wind_gust = self.mps2kph(daily["wind_gust"])
self.tomorrow_description = daily["weather"][0]["description"]
self.tomorrow_description_short = daily["weather"][0]["main"]
2022-01-15 15:07:10 +01:00
def _get_data_text(self):
now = datetime.datetime.now()
if now.hour < 20:
# current weather
ret = f"{self.cur_description_short} ({self.cur_description}) \n"
ret+= f"Wiatr {self.cur_wind:.0f} km/h \n"
ret+= f"{self.cur_temperature:.0f}°C, odczuwalna {self.cur_temperature_feel:.0f}°C"
return ret
else:
# forecast
ret = f"Jutro: {self.tomorrow_description_short} ({self.tomorrow_description}) \n"
ret+= f"Wiatr {self.tomorrow_wind:.0f} km/h, w porywach {self.tomorrow_wind_gust:.0f} km/h \n"
ret+= f"{self.tomorrow_temperature:.0f}°C, odczuwalna {self.tomorrow_temperature_feel:.0f}°C"
return ret
class AirSegment(DisplaySegment):
2022-01-15 10:55:39 +01:00
def text_gauge(self, value, start=0, end=200, length=20):
if length < 3:
return "[]"
per_character = (end - start) / (length - 2)
middle = (end - start) / 2
fill_char = "+"
gauge = "["
for i in range(0, length - 2):
gauge += fill_char
if i * per_character > value:
fill_char = " "
elif i * per_character >= middle:
fill_char = "!"
gauge += "]"
return gauge
def _get_data_text(self):
2022-01-15 10:55:39 +01:00
ret = f"{self.text_gauge(value=self.percent_pm25)} PM2,5: {self.percent_pm25}% ; "
ret+= f"{self.text_gauge(value=self.percent_pm10)} PM10: {self.percent_pm10}% \n "
ret+= f"{self.description} / {self.advice}"
return ret
def update(self):
lat = os.getenv("LATITUDE")
long = os.getenv("LONGITUDE")
self.validity = 30*60
headers = {
"Accept": "application/json",
"Accept-Language": "pl",
"apikey": os.getenv("AIRLY_API_KEY")
}
req = requests.get(f"https://airapi.airly.eu/v2/measurements/point?lat={lat}&lng={long}&l=pl",
headers=headers)
logging.debug(f'{type(self)}: API calls left for today: {req.headers["X-RateLimit-Remaining-day"]}')
if not req.ok:
logging.info(f"{type(self)}: AIRLY API call failed {req.status_code}")
else:
response = req.json()
self.description = response["current"]["indexes"][0]["description"]
self.advice = response["current"]["indexes"][0]["advice"]
for pollutants in response["current"]["standards"]:
if pollutants["pollutant"] == "PM25":
self.percent_pm25 = pollutants["percent"]
elif pollutants["pollutant"] == "PM10":
self.percent_pm10 = pollutants["percent"]
for measurement in response["current"]["values"]:
if measurement["name"] == "TEMPERATURE":
self.temperature = measurement["value"]
if __name__ == "__main__":
2022-01-14 21:21:03 +01:00
logging.basicConfig(level=logging.DEBUG)
segments = [
ClockSegment(),
2022-01-15 15:07:10 +01:00
WeatherSegment(),
AirSegment()
2022-01-14 21:21:03 +01:00
]
for segment in segments:
print(segment.get_data_text())
2022-01-15 10:55:39 +01:00
print("---")