from dataclasses import dataclass from datetime import datetime, timedelta from appdaemon.entity import Entity from appdaemon.plugins.hass.hassapi import Hass from daylight_adjuster import DaylightAdjuster from pvlib.location import Location from rich import print import pandas as pd from astral.sun import elevation, time_at_elevation from astral import SunDirection import astral HOME_TZ = datetime.now().astimezone().tzinfo @dataclass(init=False) class Continuous(Hass): entity: Entity latitude: float longitude: float def initialize(self): # self.log(f'Brightness Range: {self.brightness_rng}, {self.current_adjuster.get_brightness()}') # self.run_daily(self.refresh_daylight_times, '00:00:00') # self.run_every(self.create_img, 'now', int(timedelta(minutes=5).total_seconds())) self.run_every(self.adjust, 'now', int(timedelta(seconds=30).total_seconds())) @property def entity(self) -> Entity: return self.get_entity(self.args['entity']) @property def light_state(self) -> bool: return self.entity.is_state('on') @light_state.setter def light_state(self, new): if isinstance(new, bool): if new: self.entity.turn_on() else: self.entity.turn_off() elif isinstance(new, dict): self.entity.turn_on(**new) else: raise TypeError(f'Wrong type for light state: {new}') @property def brightness(self) -> int: return self.entity.get_state('brightness') @brightness.setter def brightness(self, val: int): self.log(f'Setting brightness of {self.friendly_name(self.args["entity"])} to {val}') self.entity.turn_on(brightness=val) @property def latitude(self) -> float: return float(self.args['latitude']) @property def longitude(self) -> float: return float(self.args['longitude']) @property def location(self) -> Location: return Location(latitude=self.latitude, longitude=self.longitude) @property def period_df(self): return pd.DataFrame(self.periods).set_index('time') # @property # def full_df(self): # return pd.concat([df, sub_df], axis=1).sort_index().interpolate().bfill().ffill() @property def brightness_rng(self): for time, brightness_rng in self.periods[::-1]: if time <= self.time(): return brightness_rng else: period_start, brightness = self.periods[-1] return brightness @property def adjuster(self): return DaylightAdjuster(self.latitude, self.longitude, self.args['periods']) @property def sleeping_active(self) -> bool: if 'sleep_var' in self.args: return self.get_state(self.args['sleep_var']) == 'on' else: return False def adjust(self, kwargs): self.log(f'Adjusting...') self.log(self.adjuster.current_settings) if self.light_state and not self.sleeping_active: self.light_state = self.adjuster.current_settings def create_img(self, kwargs): self.log(f'Creating daylight curve img...') try: # self.current_adjuster.elevation_fig().savefig('/mnt/ha_config/www/daylight_curve.png') self.adjuster.elevation_fig().savefig('/conf/daylight_curve.png') except: raise else: self.log(f'Done')