示例#1
0
 def get_loc_elev(event=None):
     """Get HA Location object & elevation."""
     try:
         loc, elev = get_astral_location(hass)
     except TypeError:
         loc = get_astral_location(hass)
         elev = None
     hass.data["illuminance"] = loc, elev
示例#2
0
    async def setup_auto_fetch(self):
        try:
            _LOGGER.debug(
                "registering API auto fetching hourly between sun up and sun set"
            )
            location, elevation = get_astral_location(self._hass)
            next_setting = get_location_astral_event_next(
                location, elevation, SUN_EVENT_SUNSET,
                dt_util.utcnow()) + timedelta(hours=1)

            self._finishhour = next_setting.astimezone(
            ).hour  # already one hour ahead
            self._debugData["auto_fetch_end_hour"] = self._finishhour

            self._auto_fetch_tracker = async_track_utc_time_change(
                self._hass,
                self.update_forecast,
                minute=0,
                second=0,
                local=True)
            self._debugData["auto_fetch_timer_object"] = (
                self._auto_fetch_tracker is not None)

            _LOGGER.debug("created auto forecast fetch hourly timer")
            _LOGGER.debug(
                "Remember that even though its every hour, the api will only connect between the hours %s and %s and at midnight",
                self._starthour, self._finishhour)

        except Exception:
            _LOGGER.error("setup_auto_fetch: %s", traceback.format_exc())
示例#3
0
        def sunrise_call_action(now=None):
            """Call action with right context."""
            next_setting = get_location_astral_event_next(
                get_astral_location(self._hass), SUN_EVENT_SUNSET,
                dt_util.utcnow()) + timedelta(hours=1)
            _LOGGER.info(
                f"Good Morning! Time to prepare the day until the sun will set at {next_setting - timedelta(hours=1)}"
            )

            remaining_api_calls = self.get_remaining_API_count()
            delay = (next_setting - dt_util.utcnow()) / (remaining_api_calls -
                                                         1)
            _LOGGER.info(
                f"During the day, there will be {remaining_api_calls} updates delayed by {delay} each"
            )

            # Schedule updates over the day (starting on 0 to process early morning update)
            for i in range(0, remaining_api_calls):
                exec_delay = delay.total_seconds() * i
                exec_time = dt_util.utcnow() + timedelta(seconds=exec_delay)

                _LOGGER.info(
                    f"History update scheduled update at {exec_time.isoformat()}"
                )
                async_call_later(self._hass, exec_delay, self.update_history)
 def update_location(_event):
     location, elevation = get_astral_location(self.hass)
     if location == self.location:
         return
     self.location = location
     self.elevation = elevation
     self.update_events()
示例#5
0
    def async_update(self):
        """Fetch new state data for the sensor.

        This is the only method that should fetch new data for Home Assistant.
        """
        use_transition = self._use_transition
        transition_elevation = self._transition_elevation
        location = get_astral_location(self.hass)

        # Using local states for async method. Must sync before return.
        state = PHASE_UNKNOWN

        elevation = location.solar_elevation()
        _LOGGER.debug("Current elevation: %r" % elevation)

        attributes = self._attributes or {}
        attributes[ATTR_ELEVATION] = elevation

        state = get_astral_phase(location,
                                 use_transition=use_transition,
                                 transition_elevation=transition_elevation)

        self._state = state
        self._icon = PHASE_ICONS[state]
        self._attributes = attributes
        _LOGGER.debug("Updated astral_phase: %s, %f" % (state, elevation))
示例#6
0
    def _get_sun_events(self, date):
        def _replace_time(date, key):
            other_date = getattr(self, f"_{key}_time")
            return date.replace(
                hour=other_date.hour,
                minute=other_date.minute,
                second=other_date.second,
                microsecond=other_date.microsecond,
            )

        location = get_astral_location(self.hass)
        sunrise = (
            location.sunrise(date, local=False)
            if self._sunrise_time is None
            else _replace_time(date, "sunrise")
        ) + self._sunrise_offset
        sunset = (
            location.sunset(date, local=False)
            if self._sunset_time is None
            else _replace_time(date, "sunset")
        ) + self._sunset_offset

        if self._sunrise_time is None and self._sunset_time is None:
            solar_noon = location.solar_noon(date, local=False)
            solar_midnight = location.solar_midnight(date, local=False)
        else:
            solar_noon = sunrise + (sunset - sunrise) / 2
            solar_midnight = sunset + ((sunrise + timedelta(days=1)) - sunset) / 2

        return {
            SUN_EVENT_SUNRISE: sunrise.timestamp(),
            SUN_EVENT_SUNSET: sunset.timestamp(),
            SUN_EVENT_NOON: solar_noon.timestamp(),
            SUN_EVENT_MIDNIGHT: solar_midnight.timestamp(),
        }
示例#7
0
def async_init_astral_loc(hass):
    """Initialize astral Location."""
    global _LOC, _HASS
    if not _LOC:
        _HASS = hass
        _LOC = get_astral_location(hass)
        hass.bus.async_listen(EVENT_CORE_CONFIG_UPDATE, _update_location)
示例#8
0
async def async_setup(hass, config):
    """Track the state of the sun."""
    if config.get(CONF_ELEVATION) is not None:
        _LOGGER.warning(
            "Elevation is now configured in home assistant core. "
            "See https://home-assistant.io/docs/configuration/basic/")
    Sun(hass, get_astral_location(hass))
    return True
示例#9
0
 def update_location(_event):
     location, elevation = get_astral_location(self.hass)
     if location == self.location:
         return
     self.location = location
     self.elevation = elevation
     if self._update_events_listener:
         self._update_events_listener()
     self.update_events()
示例#10
0
    def _get_sun_events(self, date):
        if self._manual_sunrise is not None and self._manual_sunset is not None:
            sunrise = self._replace_time(date, "sunrise")
            sunset = self._replace_time(date, "sunset")
            solar_noon = sunrise + (sunset - sunrise) / 2
            solar_midnight = sunset + (
                (sunrise + timedelta(days=1)) - sunset) / 2
        else:
            _loc = get_astral_location(self.hass)
            if isinstance(_loc, tuple):
                # Astral v2.2
                location, _ = _loc
            else:
                # Astral v1
                location = _loc
            location.name = "name"
            location.region = "region"
            location.latitude = self._latitude
            location.longitude = self._longitude
            location.elevation = self._elevation

            if self._manual_sunrise is not None:
                sunrise = self._replace_time(date, "sunrise")
            else:
                sunrise = location.sunrise(date)

            if self._manual_sunset is not None:
                sunset = self._replace_time(date, "sunset")
            else:
                sunset = location.sunset(date)

            try:
                solar_noon = location.noon(date)
            except AttributeError:
                solar_noon = location.solar_noon(date)
            try:
                solar_midnight = location.midnight(date)
            except AttributeError:
                solar_midnight = location.solar_midnight(date)

        if self._sunrise_offset is not None:
            sunrise = sunrise + self._sunrise_offset
        if self._sunset_offset is not None:
            sunset = sunset + self._sunset_offset

        datetimes = {
            SUN_EVENT_SUNRISE: sunrise,
            SUN_EVENT_SUNSET: sunset,
            SUN_EVENT_NOON: solar_noon,
            SUN_EVENT_MIDNIGHT: solar_midnight,
        }

        return {
            k: dt.astimezone(dt_util.UTC).timestamp()
            for k, dt in datetimes.items()
        }
示例#11
0
def async_setup(hass, config):
    """Track the state of the sun."""
    if config.get(CONF_ELEVATION) is not None:
        _LOGGER.warning(
            "Elevation is now configured in home assistant core. "
            "See https://home-assistant.io/docs/configuration/basic/")

    sun = Sun(hass, get_astral_location(hass), config[DOMAIN])
    sun.point_in_time_listener(dt_util.utcnow())

    return True
示例#12
0
async def async_setup(hass, config):
    """Track the state of the sun."""
    if config.get(CONF_ELEVATION) is not None:
        _LOGGER.warning(
            "Elevation is now configured in home assistant core. "
            "See https://home-assistant.io/docs/configuration/basic/")

    sun = Sun(hass, get_astral_location(hass))
    sun.point_in_time_listener(dt_util.utcnow())

    return True
示例#13
0
 def update_location(event):
     self.location = get_astral_location(self.hass)
     self.update_events(dt_util.utcnow())
示例#14
0
    def parse_date_time(cls, date_time_str, day_offset, now):
        """Parse a date time string, returning datetime."""
        year = now.year
        month = now.month
        day = now.day

        dt_str = date_time_str.strip().lower()
        #
        # parse the date
        #
        skip = True
        match0 = re.split(r"^0*(\d+)[-/]0*(\d+)(?:[-/]0*(\d+))?", dt_str)
        match1 = re.split(r"^(\w+).*", dt_str)
        if len(match0) == 5:
            if match0[3] is None:
                month, day = int(match0[1]), int(match0[2])
            else:
                year, month, day = int(match0[1]), int(match0[2]), int(match0[3])
            day_offset = 0  # explicit date means no offset
        elif len(match1) == 3:
            if match1[1] in cls.dow2int:
                dow = cls.dow2int[match1[1]]
                if dow >= (now.isoweekday() % 7):
                    day_offset = dow - (now.isoweekday() % 7)
                else:
                    day_offset = 7 + dow - (now.isoweekday() % 7)
            elif match1[1] == "today":
                day_offset = 0
            elif match1[1] == "tomorrow":
                day_offset = 1
            else:
                skip = False
        else:
            skip = False
        if day_offset != 0:
            now = dt.datetime(year, month, day) + dt.timedelta(days=day_offset)
            year = now.year
            month = now.month
            day = now.day
        else:
            now = dt.datetime(year, month, day)
        if skip:
            i = dt_str.find(" ")
            if i >= 0:
                dt_str = dt_str[i + 1 :].strip()
            else:
                return now

        #
        # parse the time
        #
        skip = True
        match0 = re.split(r"0*(\d+):0*(\d+)(?::0*(\d*\.?\d+(?:[eE][-+]?\d+)?))?", dt_str)
        if len(match0) == 5:
            if match0[3] is not None:
                hour, mins, sec = int(match0[1]), int(match0[2]), float(match0[3])
            else:
                hour, mins, sec = int(match0[1]), int(match0[2]), 0
        elif dt_str.startswith("sunrise") or dt_str.startswith("sunset"):
            location = sun.get_astral_location(cls.hass)
            try:
                if dt_str.startswith("sunrise"):
                    time_sun = location.sunrise(dt.date(year, month, day))
                else:
                    time_sun = location.sunset(dt.date(year, month, day))
            except Exception:
                _LOGGER.warning("'%s' not defined at this latitude", dt_str)
                # return something in the past so it is ignored
                return now - dt.timedelta(days=100)
            now += time_sun.date() - now.date()
            hour, mins, sec = time_sun.hour, time_sun.minute, time_sun.second
        elif dt_str.startswith("noon"):
            hour, mins, sec = 12, 0, 0
        elif dt_str.startswith("midnight"):
            hour, mins, sec = 0, 0, 0
        else:
            hour, mins, sec = 0, 0, 0
            skip = False
        now += dt.timedelta(seconds=sec + 60 * (mins + 60 * hour))
        if skip:
            i = dt_str.find(" ")
            if i >= 0:
                dt_str = dt_str[i + 1 :].strip()
            else:
                return now
        #
        # parse the offset
        #
        if len(dt_str) > 0 and (dt_str[0] == "+" or dt_str[0] == "-"):
            now = now + dt.timedelta(seconds=parse_time_offset(dt_str))
        return now
示例#15
0
 def async_update_location(event=None):
     self._location = get_astral_location(self.hass)
     self.async_schedule_update_ha_state(True)
示例#16
0
    def __init__(
        self,
        hass,
        config_entry: ConfigEntry,
        turn_on_off_listener: TurnOnOffListener,
        sleep_mode_switch: AdaptiveSleepModeSwitch,
    ):
        """Initialize the Adaptive Lighting switch."""
        self.hass = hass
        self.turn_on_off_listener = turn_on_off_listener
        self.sleep_mode_switch = sleep_mode_switch

        data = validate(config_entry)
        self._name = data[CONF_NAME]
        self._lights = data[CONF_LIGHTS]

        self._adapt_brightness = data[CONF_ADAPT_BRIGHTNESS]
        self._adapt_color_temp = data[CONF_ADAPT_COLOR_TEMP]
        self._adapt_rgb_color = data[CONF_ADAPT_RGB_COLOR]
        self._detect_non_ha_changes = data[CONF_DETECT_NON_HA_CHANGES]
        self._initial_transition = data[CONF_INITIAL_TRANSITION]
        self._interval = data[CONF_INTERVAL]
        self._only_once = data[CONF_ONLY_ONCE]
        self._prefer_rgb_color = data[CONF_PREFER_RGB_COLOR]
        self._take_over_control = data[CONF_TAKE_OVER_CONTROL]
        self._transition = min(data[CONF_TRANSITION],
                               self._interval.total_seconds() // 2)

        self._sun_light_settings = SunLightSettings(
            name=self._name,
            astral_location=get_astral_location(self.hass),
            max_brightness=data[CONF_MAX_BRIGHTNESS],
            max_color_temp=data[CONF_MAX_COLOR_TEMP],
            min_brightness=data[CONF_MIN_BRIGHTNESS],
            min_color_temp=data[CONF_MIN_COLOR_TEMP],
            sleep_brightness=data[CONF_SLEEP_BRIGHTNESS],
            sleep_color_temp=data[CONF_SLEEP_COLOR_TEMP],
            sunrise_offset=data[CONF_SUNRISE_OFFSET],
            sunrise_time=data[CONF_SUNRISE_TIME],
            sunset_offset=data[CONF_SUNSET_OFFSET],
            sunset_time=data[CONF_SUNSET_TIME],
            time_zone=self.hass.config.time_zone,
        )

        # Set other attributes
        self._icon = ICON
        self._state = None

        # Tracks 'off' → 'on' state changes
        self._on_to_off_event: Dict[str, Event] = {}
        # Tracks 'on' → 'off' state changes
        self._off_to_on_event: Dict[str, Event] = {}
        # Locks that prevent light adjusting when waiting for a light to 'turn_off'
        self._locks: Dict[str, asyncio.Lock] = {}
        # To count the number of `Context` instances
        self._context_cnt: int = 0

        # Set in self._update_attrs_and_maybe_adapt_lights
        self._settings: Dict[str, Any] = {}

        # Set and unset tracker in async_turn_on and async_turn_off
        self.remove_listeners = []
        _LOGGER.debug(
            "%s: Setting up with '%s',"
            " config_entry.data: '%s',"
            " config_entry.options: '%s', converted to '%s'.",
            self._name,
            self._lights,
            config_entry.data,
            config_entry.options,
            data,
        )
示例#17
0
文件: __init__.py 项目: 1e1/core-1
 def update_location(_event):
     location = get_astral_location(self.hass)
     if location == self.location:
         return
     self.location = location
     self.update_events(dt_util.utcnow())
示例#18
0
def _update_location(event):
    global _LOC
    _LOC = get_astral_location(_HASS)
    dispatcher_send(_HASS, SIG_LOC_UPDATED)