from datetime import timedelta from pathlib import Path import aiohttp import yaml from appdaemon.plugins.hass.hassapi import Hass def convert_vals_dict(vals): weather_codes = { 0: 'Unknown', 1000: 'Clear', 1001: 'Cloudy', 1100: 'Mostly Clear', 1101: 'Partly Cloudy', 1102: 'Mostly Cloudy', 2000: 'Fog', 2100: 'Light Fog', 3000: 'Light Wind', 3001: 'Wind', 3002: 'Strong Wind', 4000: 'Drizzle', 4001: 'Rain', 4200: 'Light Rain', 4201: 'Heavy Rain', 5000: 'Snow', 5001: 'Flurries', 5100: 'Light Snow', 5101: 'Heavy Snow', 6000: 'Freezing Drizzle', 6001: 'Freezing Rain', 6200: 'Light Freezing Rain', 6201: 'Heavy Freezing Rain', 7000: 'Ice Pellets', 7101: 'Heavy Ice Pellets', 7102: 'Light Ice Pellets', 8000: 'Thunderstorm', } return { 'cloud_coverage': int(round(vals['cloudCover'], 0)), 'condition': weather_codes[vals['weatherCode']], 'humidity': vals['humidity'], 'native_apparent_temperature': vals['temperatureApparent'], 'native_dew_point': vals['dewPoint'], 'native_precipitation_unit': 'in.', 'native_pressure': vals['pressureSurfaceLevel'], 'native_pressure_unit': 'inHg', 'native_temperature': vals['temperature'], 'native_temperature_unit': 'F', 'native_wind_gust_speed': vals['windGust'], 'native_wind_speed': vals['windSpeed'], 'native_wind_speed_unit': 'mph', 'uv_index': vals['uvIndex'], 'wind_bearing': vals['windDirection'], } class Weather(Hass): def initialize(self): with (Path(self.AD.config_dir) / 'secrets.yaml').open('r') as f: apikey = yaml.safe_load(f)['tomorrow.io'] self.log('API key loaded') lat = self.AD.sched.location.latitude long = self.AD.sched.location.longitude self.request_kwargs = { 'url': 'https://api.tomorrow.io/v4/weather/forecast', 'params': { 'apikey': apikey, 'location': f'{lat},{long}', 'timesteps': '1h', 'units': 'imperial', }, } if loc := self.args.get('location'): self.request_kwargs['params']['location'] = loc self.log(f'Updated location to {loc}', level='DEBUG') interval = timedelta(minutes=5) self.run_every(self.get_weather_async, 'now', interval.total_seconds()) self.log(f'Getting weather every {interval}') async def get_weather_async(self, **kwargs): async with aiohttp.ClientSession() as session: async with session.get(**self.request_kwargs) as resp: if resp.status == 200: self.log('Got weather async', level='DEBUG') json_data = await resp.json() await self.publish_temp(json_data) elif resp.status == 429: self.log('Rate limited when getting weather', level='WARNING') else: self.log(f'Error getting weather async: {resp.status}', level='ERROR') async def publish_temp(self, json_data): vals = convert_vals_dict(json_data['timelines']['hourly'][0]['values']) await self.set_state('weather.tomorrowio', state=vals['condition'], **vals)