WIP adjuster
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
import logging
|
import logging
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from dataclasses import InitVar, dataclass, field
|
from dataclasses import InitVar, dataclass, field
|
||||||
from datetime import datetime, timedelta, tzinfo, date, time
|
from datetime import date, datetime, time, timedelta, tzinfo
|
||||||
from typing import Dict, Iterable
|
from typing import Dict, Iterable
|
||||||
|
|
||||||
import astral
|
import astral
|
||||||
import matplotlib.dates as mdates
|
import matplotlib.dates as mdates
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from astral import Observer, SunDirection
|
from astral import Observer, SunDirection
|
||||||
from astral.sun import elevation, sun, time_at_elevation
|
from astral.sun import elevation, sun, time_at_elevation
|
||||||
@@ -36,7 +37,7 @@ def get_today_series():
|
|||||||
return days.values
|
return days.values
|
||||||
|
|
||||||
|
|
||||||
def times_at_elevation(observer: Observer, elevation, direction, days = None):
|
def times_at_elevation(observer: Observer, elevation, direction, days=None):
|
||||||
kwargs = dict(
|
kwargs = dict(
|
||||||
observer=observer,
|
observer=observer,
|
||||||
elevation=elevation,
|
elevation=elevation,
|
||||||
@@ -56,53 +57,16 @@ def times_at_elevation(observer: Observer, elevation, direction, days = None):
|
|||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
def get_next_time_at_elevation(*args, **kwargs):
|
|
||||||
time = time_at_elevation(*args, **kwargs)
|
|
||||||
if time < (now := datetime.now(HOME_TZ)):
|
|
||||||
time = time_at_elevation(
|
|
||||||
*args,
|
|
||||||
date=(now + timedelta(days=1)).date(),
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
return time
|
|
||||||
|
|
||||||
|
|
||||||
def get_next_sun_time(named_time: str, observer: Observer):
|
|
||||||
sun_times_dict = sun(observer, datetime.today().date())
|
|
||||||
try:
|
|
||||||
time = sun_times_dict[named_time].astimezone()
|
|
||||||
except KeyError:
|
|
||||||
time = datetime.combine(
|
|
||||||
datetime.today().date(),
|
|
||||||
datetime.strptime(named_time, '%I:%M:%S%p').time()
|
|
||||||
).astimezone()
|
|
||||||
|
|
||||||
if time < (now := datetime.now(HOME_TZ)):
|
|
||||||
tomorrow = (now + timedelta(days=1)).date()
|
|
||||||
sun_times_dict = sun(observer, tomorrow)
|
|
||||||
try:
|
|
||||||
time = sun_times_dict[named_time].astimezone()
|
|
||||||
except KeyError:
|
|
||||||
time = datetime.combine(
|
|
||||||
tomorrow,
|
|
||||||
datetime.strptime(named_time, '%I:%M:%S%p').time()
|
|
||||||
).astimezone()
|
|
||||||
|
|
||||||
return time
|
|
||||||
|
|
||||||
|
|
||||||
def parse_periods(observer: Observer, periods: Dict, date: date):
|
def parse_periods(observer: Observer, periods: Dict, date: date):
|
||||||
now = datetime.now(HOME_TZ)
|
|
||||||
|
|
||||||
for period in periods:
|
for period in periods:
|
||||||
if 'time' in period:
|
if 'time' in period:
|
||||||
try:
|
try:
|
||||||
time = datetime.strptime(period['time'], '%I:%M:%S%p')
|
time = datetime.strptime(period['time'], '%I:%M:%S%p').time()
|
||||||
except:
|
except:
|
||||||
sun_dict = sun(observer=observer, date=date, tzinfo=HOME_TZ)
|
sun_dict = sun(observer=observer, date=date, tzinfo=HOME_TZ)
|
||||||
dt = sun_dict[period['time']]
|
dt = sun_dict[period['time']]
|
||||||
else:
|
else:
|
||||||
dt = datetime.combine(date, time)
|
dt = datetime.combine(date, time, tzinfo=HOME_TZ)
|
||||||
|
|
||||||
elif 'elevation' in period:
|
elif 'elevation' in period:
|
||||||
if period['direction'] == 'rising':
|
if period['direction'] == 'rising':
|
||||||
@@ -126,6 +90,14 @@ def parse_periods(observer: Observer, periods: Dict, date: date):
|
|||||||
yield res
|
yield res
|
||||||
|
|
||||||
|
|
||||||
|
def elevation_series(observer: Observer, date, **kwargs):
|
||||||
|
times = pd.date_range(start=date, end=(date + timedelta(days=1)), **kwargs)
|
||||||
|
elevations = pd.Series(
|
||||||
|
[elevation(observer, timestamp) for timestamp in times],
|
||||||
|
index=times, name='elevation')
|
||||||
|
return elevations
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DaylightAdjuster:
|
class DaylightAdjuster:
|
||||||
latitude: float
|
latitude: float
|
||||||
@@ -136,40 +108,37 @@ class DaylightAdjuster:
|
|||||||
|
|
||||||
def __post_init__(self, periods: Dict, resolution: int):
|
def __post_init__(self, periods: Dict, resolution: int):
|
||||||
self.logger: logging.Logger = logging.getLogger(type(self).__name__)
|
self.logger: logging.Logger = logging.getLogger(type(self).__name__)
|
||||||
now = datetime.now().astimezone()
|
|
||||||
times = pd.date_range(
|
self.period_df: pd.DataFrame = pd.DataFrame([
|
||||||
start=now, end=now + timedelta(days=1),
|
p
|
||||||
periods=resolution,
|
for date in get_today_series()
|
||||||
tz=HOME_TZ
|
for p in parse_periods(self.observer, periods, date)
|
||||||
|
]).set_index('time').interpolate(method='index').round(0).astype(int)
|
||||||
|
|
||||||
|
self.df = self.period_df.join(pd.concat([
|
||||||
|
elevation_series(self.observer, date, periods=1000, tz=HOME_TZ)
|
||||||
|
for date in get_today_series()
|
||||||
|
]), how='outer')
|
||||||
|
|
||||||
|
self.df = (
|
||||||
|
self.df
|
||||||
|
.sort_index()
|
||||||
|
.interpolate(method='index')
|
||||||
|
.bfill().ffill()
|
||||||
|
# .round(0).astype(int)
|
||||||
|
# .drop_duplicates()
|
||||||
)
|
)
|
||||||
self.logger.debug(times)
|
self.df.index = self.df.index.to_series().dt.tz_localize(None)
|
||||||
|
|
||||||
pytimes = [dt.to_pydatetime() for dt in times]
|
|
||||||
|
|
||||||
el = pd.Series(
|
|
||||||
(elevation(self.observer, dt) for dt in pytimes),
|
|
||||||
index=times, name='elevation'
|
|
||||||
)
|
|
||||||
self.logger.debug(el)
|
|
||||||
|
|
||||||
# el.index = el.index.tz_convert(HOME_TZ)
|
|
||||||
# el.index = el.index.tz_convert(None)
|
|
||||||
|
|
||||||
self.periods = parse_periods(self.observer, periods)
|
|
||||||
|
|
||||||
# self.df = pd.DataFrame(el)
|
|
||||||
self.df = pd.concat([pd.DataFrame(self.periods).set_index('time'), el], axis=1)
|
|
||||||
self.df = self.df.sort_index().interpolate().bfill().ffill()
|
|
||||||
|
|
||||||
# self.df.index = self.df.index.to_series().dt.tz_localize(None)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def observer(self) -> astral.Observer:
|
def observer(self) -> astral.Observer:
|
||||||
return astral.Observer(self.latitude, self.longitude)
|
return astral.Observer(self.latitude, self.longitude)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_settings(self) -> pd.Series:
|
def current_settings(self) -> Dict:
|
||||||
return self.df[:datetime.now().astimezone()].iloc[-1].drop('elevation').astype(int).to_dict()
|
now = datetime.now(HOME_TZ)
|
||||||
|
self.period_df.loc[now] = np.nan
|
||||||
|
return self.period_df.interpolate(method='index').round(0).astype(int).loc[now].to_dict()
|
||||||
|
|
||||||
def elevation_fig(self):
|
def elevation_fig(self):
|
||||||
fig, ax = plt.subplots(figsize=(10, 7))
|
fig, ax = plt.subplots(figsize=(10, 7))
|
||||||
@@ -191,9 +160,9 @@ class DaylightAdjuster:
|
|||||||
ax2.set_ylabel('Brightness')
|
ax2.set_ylabel('Brightness')
|
||||||
ax2.set_ylim(0, 100)
|
ax2.set_ylim(0, 100)
|
||||||
|
|
||||||
# handles.append(ax.axvline(datetime.now().astimezone(),
|
handles.append(ax.axvline(datetime.now().astimezone(),
|
||||||
# linestyle='--',
|
linestyle='--',
|
||||||
# color='g'))
|
color='g'))
|
||||||
|
|
||||||
# handles.append(ax2.axhline(self.get_brightness(),
|
# handles.append(ax2.axhline(self.get_brightness(),
|
||||||
# linestyle='--',
|
# linestyle='--',
|
||||||
|
|||||||
Reference in New Issue
Block a user