def run_8d_readout(hat, curr_x): """Displays a text readout of the forecast for the next 8 days and gives the respective dates""" global program_state readout_8d = [] readout_string = "" #Send another request for data owm = OWM(API_KEY) #Retrieve daily forecast for 8 days (includes today) fc = owm.daily_forecast_at_id(SomeCity, limit=8) f = fc.get_forecast() i = 0 for weather in f: readout_8d.append(weather) if (i == 8): break i += 1 for weather in readout_8d: readout_string = readout_string + " For " + str( utc_to_eastern(weather.get_reference_time('date')))[0:10] readout_string = readout_string + " " + weather.get_detailed_status( ) + " - " hat.show_message(readout_string, scroll_speed=0.035, text_colour=nwhite) #Goes here after break program_state = 0 #Main menu return_to_main_menu(hat, curr_x) #--------------------------- SOME NEW READOUT OR LOOP ------------------------# """
class OpenWeatherMapModel: def __init__(self, api_key: str, city_id: int): self.owm = OWM(api_key) self._city_id = city_id self._unit = 'celsius' @property def city_id(self): return self._city_id @city_id.setter def city_id(self, city_id: int): self._city_id = city_id @property def temperature_unit(self): return self._unit @temperature_unit.setter def temperature_unit(self, unit: str): assert unit == 'fahrenheit' or unit == 'celsius' self._unit = unit def _parse_weather(self, weather): temperature = weather.get_temperature(unit=self.temperature_unit) humidity = weather.get_humidity() weather_code = weather.get_weather_code() return (weather_code, temperature.get('temp_min', temperature.get('min')), temperature.get('temp_max', temperature.get('max')), humidity) def get_current_weather(self): """ Get the current weather data :return: Tuple of weather code, temperature range, and humidity """ try: obs = self.owm.weather_at_id(self.city_id) weather = obs.get_weather() return self._parse_weather(weather) except pyowm.exceptions.api_call_error.APICallTimeoutError: return 0, 0, 0, 0 def get_daily_forecast(self, limit=14, include_today=False): """ Get a list of forecasts :param limit: The max number of forecasts to get :param include_today: whether include today in the forecast :return: list of tuples of weather code, temperature range and humidity """ forecaster = self.owm.daily_forecast_at_id(self.city_id, limit=limit) weathers = forecaster.get_forecast().get_weathers() today = datetime.datetime.now().date() if not include_today: weathers = filter( lambda weather: not (weather.get_reference_time( timeformat='date') == today), weathers) return list(map(lambda weather: self._parse_weather(weather), weathers))
def run_outdoor_hud_loop(hat, curr_x): """Run the program loop for this mini program""" global program_state #How often do you want to request the forecast data? REFRESH_RATE = 600 #Every 10 min (600 seconds) #Clear the screen hat.clear() #We are initializing this screen now init = True #Capture the start time for refresh rate calculations start_time = time.time() #Run the sub program loop while (True): #Check to see if user wants to return to main menu return_requested = check_stick_events_2(hat) if (return_requested): break #Exit while to return to main menu counter = time.time() - start_time #If it's been < 10 min since the first, or most recent data download... if (counter > REFRESH_RATE or init): #Send another request for data owm = OWM(API_KEY) """FOR 8-DAY FORECAST (ROW 1 & ROW 2)""" #Retrieve daily forecast for 8 days (includes today) fc = owm.daily_forecast_at_id(SomeCity, limit=8) f = fc.get_forecast() i = 0 for weather in f: #FOR DEBUGGING #print("At " , str(utc_to_eastern(weather.get_reference_time('date'))),weather.get_weather_code()) if (i == 8): break # Where W_CODES[weather.get_weather_code()][0] is giving the # [weather.get_weather_code()] as a KEY to get the data object # that holds the color at index [0] and description string # (unused here) at index [1] #Top row hat.set_pixel(i, 0, W_CODES[weather.get_weather_code()][0]) #Second row down from top hat.set_pixel(i, 1, W_CODES[weather.get_weather_code()][0]) i += 1 """FOR 3 HOUR FORECAST (ROW 3 & ROW 4)""" #Current conditions w = get_observation(SomeCity, owm) #Set leftmost pixels to show current status #Row 3 hat.set_pixel(0, 2, W_CODES[w.get_weather_code()][0]) #Row 4 hat.set_pixel(0, 3, W_CODES[w.get_weather_code()][0]) #Get current temperature temp_now = w.get_temperature('fahrenheit')["temp"] #Restrict temp_now readings to bound for display purposes if (temp_now > 100.00): temp_now = 100.00 elif (temp_now < 0.00): temp_now = 0.00 #Get current humidity humi_now = w.get_humidity() #Get current pressure pres_now = w.get_pressure()["press"] #Set current temperature color here for leftmost pixels curr_temp_color = cold_ok_or_hot(temp_now) """ROW 5 Code -- 3HR temperature forecast""" #Set leftmost pixel for ROW 5 hat.set_pixel(0, 4, curr_temp_color) #Get the 3hr forecast for the next 7 days fc = owm.three_hours_forecast_at_id(SomeCity) #A list of weather objects f = fc.get_forecast() i = 1 #Fill in the rest of the row after first pixels for rows 3,4,5 for weather in f: if (i == 8): break #Row 3 hat.set_pixel(i, 2, W_CODES[weather.get_weather_code()][0]) #Row 4 hat.set_pixel(i, 3, W_CODES[weather.get_weather_code()][0]) #Get the temp for the 3hr interval temp_then = weather.get_temperature('fahrenheit')["temp"] #Also set the temperature indicator row color to show if # the temp is high, low, or tolerable at # ROW 5 hat.set_pixel(i, 4, cold_ok_or_hot(temp_then)) i += 1 """TEMPERATURE (ROW 6)""" #Where 8/100 = 12.5, so every pixel is 12.5 degrees F of temp. num_pixels = int(temp_now / 12.5) #Temperature displays on row y == 5(6th row) from 0 # to 100 degrees where each pixel represents 12.5 degrees F for i in range(num_pixels): hat.set_pixel(i, 5, curr_temp_color) for i in range(8 - num_pixels): hat.set_pixel(i + num_pixels, 5, nwhite) """HUMIDITY (ROW 7)""" curr_humi_color = dry_humid_or_ok(humi_now) num_pixels = int(humi_now / 12.5) #Humidity displays on row y == 6 (7th row) #as a relative percent for i in range(num_pixels): hat.set_pixel(i, 6, curr_humi_color) for i in range(8 - num_pixels): hat.set_pixel(i + num_pixels, 6, nwhite) """AIR PRESSURE (ROW 8)""" #Air pressure (in millibars) displays on # the last row as one of three colors indicating # if the air pressure is high, low, or reasonable # for normal conditions curr_pres_color = pres_lo_hi_or_ok(pres_now) for i in range(8): hat.set_pixel(i, 7, curr_pres_color) #Reset counter for refreshing start_time = time.time() init = False #Goes here after "break" program_state = 0 #Main menu return_to_main_menu(hat, curr_x)
class OpenWeatherMapModel: def __init__(self, api_key: str, city_id: int) -> None: self.owm = OWM(api_key) self._city_id = city_id self._unit = 'celsius' self._current_weather = (0, 0.0, 0.0, 0.0, 0.0) self._forecast = [] # type:List[Tuple[int, float, float, float, float]] @property def city_id(self) -> int: return self._city_id @city_id.setter def city_id(self, city_id: int) -> None: self._city_id = city_id @property def temperature_unit(self) -> str: return self._unit @temperature_unit.setter def temperature_unit(self, unit: str) -> None: assert unit == 'fahrenheit' or unit == 'celsius' self._unit = unit def _parse_weather(self, weather: Weather) -> Tuple[int, float, float, float, float]: temperature = weather.get_temperature(unit=self.temperature_unit) humidity = weather.get_humidity() weather_code = weather.get_weather_code() return (weather_code, temperature.get('temp_min', temperature.get('min')), temperature.get('temp_max', temperature.get('max')), temperature.get('temp'), humidity) def get_current_weather(self) -> Tuple[int, float, float, float, float]: """ Get the current weather data :return: Tuple of weather code, temperature range, current temperature and humidity """ try: obs = self.owm.weather_at_id(self.city_id) weather = obs.get_weather() self._current_weather = self._parse_weather(weather) except Exception as exception: print(exception) return self._current_weather def get_daily_forecast(self, limit: int = 14, include_today: bool = False) -> List[Tuple[int, float, float, float, float]]: """ Get a list of forecasts :param limit: The max number of forecasts to get :param include_today: whether include today in the forecast :return: list of tuples of weather code, temperature range, temperature and humidity """ try: forecaster = self.owm.daily_forecast_at_id(self.city_id, limit=limit) weathers = forecaster.get_forecast().get_weathers() today = datetime.datetime.now().date() if not include_today: weathers = filter( lambda weather: not (weather.get_reference_time( timeformat='date').date() == today), weathers) self._forecast = list( map(lambda weather: self._parse_weather(weather), weathers)) except Exception as exception: print(exception) return self._forecast
class WeatherPoller(object): API_key = '9ef86a5c847ad6a5c67d09dd9b72e9a6' API_fetch_interval = timedelta(days=1) map_city_id = {'kitchener': 5992996} temperature_change_threshold = 5.0 def __init__(self, city='kitchener'): if city in WeatherPoller.map_city_id: self.city_id = WeatherPoller.map_city_id[city] else: logging.error(' '.join([self.__class__.__name__, ": city:", city, "not found in map_city_id dict."])) raise Exception("city:", city, " not found in map_city_id dict.") self.owm = None self.last_api_fetch_time = None def poll_data(self): if self.owm is None or self.last_api_fetch_time is None \ or self.forecast is None or \ (datetime.utcnow() - self.last_api_fetch_time > WeatherPoller.API_fetch_interval): self.owm = OWM(WeatherPoller.API_key) self.forecast = self.owm.daily_forecast_at_id(self.city_id) self.last_api_fetch_time = datetime.utcnow() logging.info(' '.join( [self.__class__.__name__, ": poll_data() fetched new data at:", self.last_api_fetch_time.isoformat()])) else: logging.info(' '.join([self.__class__.__name__, ( ": poll_data() called within fetch " "interval threshold, use previous " "fetched data at:"), self.last_api_fetch_time.isoformat()])) def trigger_notification(self, message): print message def check_temperature_change(self): weather_lst = self.forecast.get_forecast().get_weathers() today = datetime.utcnow() tomorrow = today + timedelta(days=1) today_temp = weather_lst[0].get_temperature(unit='celsius') tomorrow_temp = self.forecast.get_weather_at(tomorrow).get_temperature( unit='celsius') logging.debug(' '.join( [self.__class__.__name__, ": check_temperature_change", "\ntoday:", str(today_temp), "\ntomorrow", str(tomorrow_temp)])) alert_lst = [] for item in today_temp: if abs(today_temp[item] - tomorrow_temp[ item]) >= WeatherPoller.temperature_change_threshold: alert_lst.append( "Temperature change alert:" "item: {key}, today:{today}, tomorrow:{tomorrow}".format( key=item, today=today_temp[item], tomorrow=tomorrow_temp[item])) return alert_lst