Esempio n. 1
0
 async def _async_update_interval(now):
     try:
         await async_update(now)
     finally:
         if not opp.is_stopping:
             async_track_point_in_utc_time(opp, _async_update_interval,
                                           util.dt.utcnow() + interval)
Esempio n. 2
0
    async def async_update_user_data(now):
        """Update user data from eight in USER_SCAN_INTERVAL."""
        await eight.update_user_data()
        async_dispatcher_send(opp, SIGNAL_UPDATE_USER)

        async_track_point_in_utc_time(opp, async_update_user_data,
                                      utcnow() + USER_SCAN_INTERVAL)
Esempio n. 3
0
    async def async_update_heat_data(now):
        """Update heat data from eight in HEAT_SCAN_INTERVAL."""
        await eight.update_device_data()
        async_dispatcher_send(opp, SIGNAL_UPDATE_HEAT)

        async_track_point_in_utc_time(opp, async_update_heat_data,
                                      utcnow() + HEAT_SCAN_INTERVAL)
Esempio n. 4
0
    def update_sun_position(self, now=None):
        """Calculate the position of the sun."""
        # Grab current time in case system clock changed since last time we ran.
        utc_point_in_time = dt_util.utcnow()
        self.solar_azimuth = round(
            self.location.solar_azimuth(utc_point_in_time, self.elevation), 2)
        self.solar_elevation = round(
            self.location.solar_elevation(utc_point_in_time, self.elevation),
            2)

        _LOGGER.debug(
            "sun position_update@%s: elevation=%s azimuth=%s",
            utc_point_in_time.isoformat(),
            self.solar_elevation,
            self.solar_azimuth,
        )
        self.async_write_op_state()

        # Next update as per the current phase
        delta = _PHASE_UPDATES[self.phase]
        # if the next update is within 1.25 of the next
        # position update just drop it
        if utc_point_in_time + delta * 1.25 > self._next_change:
            return
        event.async_track_point_in_utc_time(self.opp, self.update_sun_position,
                                            utc_point_in_time + delta)
Esempio n. 5
0
    async def async_handle_start_charge(service):
        """Handle service to start charging."""
        # It would be better if this was changed to use nickname, or
        # an entity name rather than a vin.
        vin = service.data[ATTR_VIN]

        if vin in opp.data[DATA_LEAF]:
            data_store = opp.data[DATA_LEAF][vin]

            # Send the command to request charging is started to Nissan
            # servers. If that completes OK then trigger a fresh update to
            # pull the charging status from the car after waiting a minute
            # for the charging request to reach the car.
            result = await opp.async_add_executor_job(
                data_store.leaf.start_charging)
            if result:
                _LOGGER.debug(
                    "Start charging sent, request updated data in 1 minute")
                check_charge_at = utcnow() + timedelta(minutes=1)
                data_store.next_update = check_charge_at
                async_track_point_in_utc_time(opp,
                                              data_store.async_update_data,
                                              check_charge_at)

        else:
            _LOGGER.debug("Vin %s not recognised for update", vin)
Esempio n. 6
0
    async def scan_devices(now):
        """Scan for devices."""
        try:
            results = await opp.async_add_job(_discover, netdisco)

            for result in results:
                opp.async_create_task(new_service_found(*result))
        except OSError:
            logger.error("Network is unreachable")

        async_track_point_in_utc_time(
            opp, scan_devices, dt_util.utcnow() + SCAN_INTERVAL
        )
Esempio n. 7
0
        def message_received(msg):
            """Handle new MQTT messages."""
            payload = msg.payload
            # auto-expire enabled?
            expire_after = self._config.get(CONF_EXPIRE_AFTER)
            if expire_after is not None and expire_after > 0:
                # When expire_after is set, and we receive a message, assume device is not expired since it has to be to receive the message
                self._expired = False

                # Reset old trigger
                if self._expiration_trigger:
                    self._expiration_trigger()
                    self._expiration_trigger = None

                # Set new trigger
                expiration_at = dt_util.utcnow() + timedelta(
                    seconds=expire_after)

                self._expiration_trigger = async_track_point_in_utc_time(
                    self.opp, self._value_is_expired, expiration_at)

            template = self._config.get(CONF_VALUE_TEMPLATE)
            if template is not None:
                variables = {"entity_id": self.entity_id}
                payload = template.async_render_with_possible_json_value(
                    payload,
                    self._state,
                    variables=variables,
                )
            self._state = payload
            self.async_write_op_state()
Esempio n. 8
0
    async def _async_delay(self, action, variables, context):
        """Handle delay."""
        # Call ourselves in the future to continue work
        unsub = None

        @callback
        def async_script_delay(now):
            """Handle delay."""
            with suppress(ValueError):
                self._async_listener.remove(unsub)

            self.opp.async_create_task(self.async_run(variables, context))

        delay = action[CONF_DELAY]

        try:
            if isinstance(delay, template.Template):
                delay = vol.All(cv.time_period, cv.positive_timedelta)(
                    delay.async_render(variables))
            elif isinstance(delay, dict):
                delay_data = {}
                delay_data.update(template.render_complex(delay, variables))
                delay = cv.time_period(delay_data)
        except (exceptions.TemplateError, vol.Invalid) as ex:
            _LOGGER.error("Error rendering '%s' delay template: %s", self.name,
                          ex)
            raise _StopScript

        self.last_action = action.get(CONF_ALIAS, f"delay {delay}")
        self._log("Executing step %s" % self.last_action)

        unsub = async_track_point_in_utc_time(self.opp, async_script_delay,
                                              date_util.utcnow() + delay)
        self._async_listener.append(unsub)
        raise _SuspendScript
Esempio n. 9
0
    async def update(now):
        """Update status from the online service."""
        try:
            if not await connection.update(journal=True):
                _LOGGER.warning("Could not query server")
                return False

            for vehicle in connection.vehicles:
                if vehicle.vin not in data.vehicles:
                    discover_vehicle(vehicle)

            async_dispatcher_send(opp, SIGNAL_STATE_UPDATED)

            return True
        finally:
            async_track_point_in_utc_time(opp, update, utcnow() + interval)
Esempio n. 10
0
 def point_in_time_listener(self, time_date):
     """Get the latest data and update state."""
     self._update_internal_state(time_date)
     self.async_write_op_state()
     self.unsub = async_track_point_in_utc_time(
         self.opp, self.point_in_time_listener, self.get_next_interval()
     )
Esempio n. 11
0
    def _restart_timer(self):
        """Restart the 25 hour timer."""
        try:
            self._heartbeat_timer()
            self._heartbeat_timer = None
        except TypeError:
            # No heartbeat timer is active
            pass

        @callback
        def timer_elapsed(now) -> None:
            """Heartbeat missed; set state to ON to indicate dead battery."""
            self._computed_state = True
            self._heartbeat_timer = None
            self.async_write_op_state()

        point_in_time = dt_util.utcnow() + timedelta(hours=25)
        _LOGGER.debug(
            "Heartbeat timer starting. Now: %s Then: %s",
            dt_util.utcnow(),
            point_in_time,
        )

        self._heartbeat_timer = async_track_point_in_utc_time(
            self.opp, timer_elapsed, point_in_time)
Esempio n. 12
0
    def _point_in_time_listener(self, now):
        """Run when the state of the sensor should be updated."""
        self._calculate_next_update()
        self.async_write_op_state()

        self._unsub_update = event.async_track_point_in_utc_time(
            self.opp, self._point_in_time_listener, self._next_update)
Esempio n. 13
0
    def schedule_light_turn_on(now):
        """Turn on all the lights at the moment sun sets.

        We will schedule to have each light start after one another
        and slowly transition in.
        """
        start_point = calc_time_for_light_when_sunset()
        if not start_point:
            return

        for index, light_id in enumerate(light_ids):
            async_track_point_in_utc_time(
                opp,
                async_turn_on_factory(light_id),
                start_point + index * LIGHT_TRANSITION_TIME,
            )
Esempio n. 14
0
    async def update_image(self, image, filename):
        """Update the camera image."""
        if self._state == STATE_IDLE:
            self._state = STATE_RECORDING
            self._last_trip = dt_util.utcnow()
            self.queue.clear()

        self._filename = filename
        self.queue.appendleft(image)

        @callback
        def reset_state(now):
            """Set state to idle after no new images for a period of time."""
            self._state = STATE_IDLE
            self._expired_listener = None
            _LOGGER.debug("Reset state")
            self.async_write_op_state()

        if self._expired_listener:
            self._expired_listener()

        self._expired_listener = async_track_point_in_utc_time(
            self.opp, reset_state, dt_util.utcnow() + self._timeout
        )

        self.async_write_op_state()
Esempio n. 15
0
    async def async_start(self, duration):
        """Start a timer."""
        if self._listener:
            self._listener()
            self._listener = None
        newduration = None
        if duration:
            newduration = duration

        event = EVENT_TIMER_STARTED
        if self._state == STATUS_ACTIVE or self._state == STATUS_PAUSED:
            event = EVENT_TIMER_RESTARTED

        self._state = STATUS_ACTIVE
        start = dt_util.utcnow().replace(microsecond=0)
        if self._remaining and newduration is None:
            self._end = start + self._remaining
        else:
            if newduration:
                self._config[CONF_DURATION] = newduration
                self._remaining = newduration
            else:
                self._remaining = self._config[CONF_DURATION]
            self._end = start + self._config[CONF_DURATION]

        self.opp.bus.async_fire(event, {"entity_id": self.entity_id})

        self._listener = async_track_point_in_utc_time(self.opp,
                                                       self.async_finished,
                                                       self._end)
        self.async_write_op_state()
Esempio n. 16
0
async def async_setup_platform(opp,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Set up the Time and Date sensor."""
    if opp.config.time_zone is None:
        _LOGGER.error("Timezone is not set in Open Peer Power configuration")
        return False

    devices = []
    for variable in config[CONF_DISPLAY_OPTIONS]:
        device = TimeDateSensor(opp, variable)
        async_track_point_in_utc_time(opp, device.point_in_time_listener,
                                      device.get_next_interval())
        devices.append(device)

    async_add_entities(devices, True)
Esempio n. 17
0
    def _schedule_refresh(self) -> None:
        """Schedule a refresh."""
        if self._unsub_refresh:
            self._unsub_refresh()
            self._unsub_refresh = None

        self._unsub_refresh = async_track_point_in_utc_time(
            self.opp, self._handle_refresh_interval, utcnow() + self.update_interval
        )
Esempio n. 18
0
 def _async_track_unavailable(self):
     if self._remove_unavailability_tracker:
         self._remove_unavailability_tracker()
     self._remove_unavailability_tracker = async_track_point_in_utc_time(
         self.opp, self._async_set_unavailable,
         utcnow() + TIME_TILL_UNAVAILABLE)
     if not self._is_available:
         self._is_available = True
         return True
     return False
Esempio n. 19
0
 async def async_turn_on(self, **kwargs):
     """Power the relay."""
     if self._reset_sub is not None:
         self._reset_sub()
         self._reset_sub = None
     self._reset_sub = async_track_point_in_utc_time(
         self.opp, self._async_turn_off, dt_util.utcnow() + self._time
     )
     await self.opp.async_add_executor_job(self._turn_on)
     self.async_write_op_state()
Esempio n. 20
0
    def setup_leaf(car_config):
        """Set up a car."""
        _LOGGER.debug("Logging into You+Nissan")

        username = car_config[CONF_USERNAME]
        password = car_config[CONF_PASSWORD]
        region = car_config[CONF_REGION]
        leaf = None

        try:
            # This might need to be made async (somehow) causes
            # openpeerpower to be slow to start
            sess = Session(username, password, region)
            leaf = sess.get_leaf()
        except KeyError:
            _LOGGER.error(
                "Unable to fetch car details..."
                " do you actually have a Leaf connected to your account?")
            return False
        except CarwingsError:
            _LOGGER.error(
                "An unknown error occurred while connecting to Nissan: %s",
                sys.exc_info()[0],
            )
            return False

        _LOGGER.warning(
            "WARNING: This may poll your Leaf too often, and drain the 12V"
            " battery.  If you drain your cars 12V battery it WILL NOT START"
            " as the drive train battery won't connect."
            " Don't set the intervals too low")

        data_store = LeafDataStore(opp, leaf, car_config)
        opp.data[DATA_LEAF][leaf.vin] = data_store

        for platform in PLATFORMS:
            load_platform(opp, platform, DOMAIN, {}, car_config)

        async_track_point_in_utc_time(opp, data_store.async_update_data,
                                      utcnow() + INITIAL_UPDATE)
        def state_message_received(msg):
            """Handle a new received MQTT state message."""
            payload = msg.payload
            # auto-expire enabled?
            expire_after = self._config.get(CONF_EXPIRE_AFTER)

            if expire_after is not None and expire_after > 0:

                # When expire_after is set, and we receive a message, assume device is not expired since it has to be to receive the message
                self._expired = False

                # Reset old trigger
                if self._expiration_trigger:
                    self._expiration_trigger()
                    self._expiration_trigger = None

                # Set new trigger
                expiration_at = dt_util.utcnow() + timedelta(
                    seconds=expire_after)

                self._expiration_trigger = async_track_point_in_utc_time(
                    self.opp, self.value_is_expired, expiration_at)

            value_template = self._config.get(CONF_VALUE_TEMPLATE)
            if value_template is not None:
                payload = value_template.async_render_with_possible_json_value(
                    payload, variables={"entity_id": self.entity_id})
            if payload == self._config[CONF_PAYLOAD_ON]:
                self._state = True
            elif payload == self._config[CONF_PAYLOAD_OFF]:
                self._state = False
            else:  # Payload is not for this entity
                _LOGGER.warning(
                    "No matching payload found for entity: %s with state topic: %s. Payload: %s, with value template %s",
                    self._config[CONF_NAME],
                    self._config[CONF_STATE_TOPIC],
                    payload,
                    value_template,
                )
                return

            if self._delay_listener is not None:
                self._delay_listener()
                self._delay_listener = None

            off_delay = self._config.get(CONF_OFF_DELAY)
            if self._state and off_delay is not None:
                self._delay_listener = evt.async_call_later(
                    self.opp, off_delay, off_delay_listener)

            self.async_write_op_state()
Esempio n. 22
0
    def update_sun_position(self, utc_point_in_time):
        """Calculate the position of the sun."""
        self.solar_azimuth = round(
            self.location.solar_azimuth(utc_point_in_time), 2)
        self.solar_elevation = round(
            self.location.solar_elevation(utc_point_in_time), 2)

        _LOGGER.debug(
            "sun position_update@%s: elevation=%s azimuth=%s",
            utc_point_in_time.isoformat(),
            self.solar_elevation,
            self.solar_azimuth,
        )
        self.async_write_op_state()

        # Next update as per the current phase
        delta = _PHASE_UPDATES[self.phase]
        # if the next update is within 1.25 of the next
        # position update just drop it
        if utc_point_in_time + delta * 1.25 > self._next_change:
            return
        async_track_point_in_utc_time(self.opp, self.update_sun_position,
                                      utc_point_in_time + delta)
Esempio n. 23
0
    async def async_added_to_opp(self):
        """Call when entity about to be added to Open Peer Power."""
        self._calculate_boudary_time()
        self._calculate_next_update()

        @callback
        def _clean_up_listener():
            if self._unsub_update is not None:
                self._unsub_update()
                self._unsub_update = None

        self.async_on_remove(_clean_up_listener)

        self._unsub_update = event.async_track_point_in_utc_time(
            self.opp, self._point_in_time_listener, self._next_update)
Esempio n. 24
0
    async def update_during_transition(self, when):
        """Update state at the start and end of a transition."""
        if self.postponed_update:
            self.postponed_update()

        # Transition has started
        await self.update_opp()

        # Transition has ended
        if when > 0:
            self.postponed_update = async_track_point_in_utc_time(
                self.opp,
                self.update_opp,
                util.dt.utcnow() + timedelta(milliseconds=when),
            )
Esempio n. 25
0
    def _async_handle_update(self, *args, **kwargs) -> None:
        """Update the state using webhook data."""
        if self._cancel_update:
            self._cancel_update()
            self._cancel_update = None

        if args[0][0][KEY_SUBTYPE] == SUBTYPE_RAIN_DELAY_ON:
            endtime = parse_datetime(args[0][0][KEY_RAIN_DELAY_END])
            _LOGGER.debug("Rain delay expires at %s", endtime)
            self._state = True
            self._cancel_update = async_track_point_in_utc_time(
                self.opp, self._delay_expiration, endtime)
        elif args[0][0][KEY_SUBTYPE] == SUBTYPE_RAIN_DELAY_OFF:
            self._state = False

        self.async_write_op_state()
Esempio n. 26
0
    async def async_update_data(self, now):
        """Update data from nissan leaf."""
        # Prevent against a previously scheduled update and an ad-hoc update
        # started from an update from both being triggered.
        if self._remove_listener:
            self._remove_listener()
            self._remove_listener = None

        # Clear next update whilst this update is underway
        self.next_update = None

        await self.async_refresh_data(now)
        self.next_update = self.get_next_interval()
        _LOGGER.debug("Next update=%s", self.next_update)
        self._remove_listener = async_track_point_in_utc_time(
            self.opp, self.async_update_data, self.next_update)
Esempio n. 27
0
    def _schedule_refresh(self) -> None:
        """Schedule a refresh."""
        if self._unsub_refresh:
            self._unsub_refresh()
            self._unsub_refresh = None

        # We _floor_ utcnow to create a schedule on a rounded second,
        # minimizing the time between the point and the real activation.
        # That way we obtain a constant update frequency,
        # as long as the update process takes less than a second
        if self.last_update_success:
            update_interval = self.update_interval
            self.last_update_success_time = utcnow()
        else:
            update_interval = self.failed_update_interval
        self._unsub_refresh = async_track_point_in_utc_time(
            self.opp,
            self._handle_refresh_interval,
            utcnow().replace(microsecond=0) + update_interval,
        )
Esempio n. 28
0
    async def async_added_to_opp(self):
        """Subscribe to updates."""
        if KEY_RAIN_DELAY in self._controller.init_data:
            self._state = self._controller.init_data[
                KEY_RAIN_DELAY] / 1000 > as_timestamp(now())

        # If the controller was in a rain delay state during a reboot, this re-sets the timer
        if self._state is True:
            delay_end = utc_from_timestamp(
                self._controller.init_data[KEY_RAIN_DELAY] / 1000)
            _LOGGER.debug("Re-setting rain delay timer for %s", delay_end)
            self._cancel_update = async_track_point_in_utc_time(
                self.opp, self._delay_expiration, delay_end)

        self.async_on_remove(
            async_dispatcher_connect(
                self.opp,
                SIGNAL_RACHIO_RAIN_DELAY_UPDATE,
                self._async_handle_any_update,
            ))
Esempio n. 29
0
        def message_received(msg):
            """Handle new MQTT messages."""
            payload = msg.payload
            # auto-expire enabled?
            expire_after = self._config.get(CONF_EXPIRE_AFTER)
            if expire_after is not None and expire_after > 0:
                # Reset old trigger
                if self._expiration_trigger:
                    self._expiration_trigger()
                    self._expiration_trigger = None

                # Set new trigger
                expiration_at = dt_util.utcnow() + timedelta(seconds=expire_after)

                self._expiration_trigger = async_track_point_in_utc_time(
                    self.opp, self.value_is_expired, expiration_at
                )

            json_attributes = set(self._config[CONF_JSON_ATTRS])
            if json_attributes:
                self._attributes = {}
                try:
                    json_dict = json.loads(payload)
                    if isinstance(json_dict, dict):
                        attrs = {
                            k: json_dict[k] for k in json_attributes & json_dict.keys()
                        }
                        self._attributes = attrs
                    else:
                        _LOGGER.warning("JSON result was not a dictionary")
                except ValueError:
                    _LOGGER.warning("MQTT payload could not be parsed as JSON")
                    _LOGGER.debug("Erroneous JSON: %s", payload)

            if template is not None:
                payload = template.async_render_with_possible_json_value(
                    payload, self._state
                )
            self._state = payload
            self.async_write_op_state()
Esempio n. 30
0
    def _async_set_timeout(self, action, variables, context,
                           continue_on_timeout):
        """Schedule a timeout to abort or continue script."""
        timeout = action[CONF_TIMEOUT]
        unsub = None

        @callback
        def async_script_timeout(now):
            """Call after timeout is retrieve."""
            with suppress(ValueError):
                self._async_listener.remove(unsub)

            # Check if we want to continue to execute
            # the script after the timeout
            if continue_on_timeout:
                self.opp.async_create_task(self.async_run(variables, context))
            else:
                self._log("Timeout reached, abort script.")
                self.async_stop()

        unsub = async_track_point_in_utc_time(self.opp, async_script_timeout,
                                              date_util.utcnow() + timeout)
        self._async_listener.append(unsub)