Beispiel #1
0
 def datetime(self, aware=False):
     if aware is True:
         return (utils.run_coroutine_threadsafe(
             self, self.AD.sched.get_now()).astimezone(self.AD.tz))
     else:
         return utils.run_coroutine_threadsafe(
             self, self.AD.sched.get_now_naive())
Beispiel #2
0
    def listen_event(self, cb, event=None, **kwargs):
        """
        This is the primary way of listening for changes within the MQTT plugin.

        Unlike other plugins, MQTT does not keep state. All MQTT messages will have an event which is set to ``MQTT_MESSAGE`` by default. This can be changed to whatever that is required in the plugin configuration.

        :param cb: Function to be invoked when the requested state change occurs. It must conform to the standard Event Callback format documented `Here <APPGUIDE.html#about-event-callbacks>`__.
        :param event: Name of the event to subscribe to. Can be the declared ``event_name`` parameter as specified in the plugin configuration. If no event is specified, ``listen_event()`` will subscribe to all MQTT events within the app's functional namespace.
        :param \*\*kwargs: Additional keyword arguments:

            **namespace** (optional):  Namespace to use for the call - see the section on namespaces for a detailed description. In most cases it is safe to ignore this parameter. The value ``global`` for namespace has special significance, and means that the callback will lsiten to state updates from any plugin.

        :return: A handle that can be used to cancel the callback.
        """

        namespace = self._get_namespace(**kwargs)

        if 'wildcard' in kwargs:
            wildcard = kwargs['wildcard']
            if wildcard[-2:] == '/#' and len(wildcard.split('/')[0]) >= 1:
                plugin = utils.run_coroutine_threadsafe(
                    self, self.AD.plugins.get_plugin_object(namespace))
                utils.run_coroutine_threadsafe(
                    self, plugin.process_mqtt_wildcard(kwargs['wildcard']))
            else:
                self.logger.warning(
                    "Using %s as MQTT Wildcard for Event is not valid, use another. Listen Event will not be registered",
                    wildcard)
                return

        return super(Mqtt, self).listen_event(cb, event, **kwargs)
Beispiel #3
0
    def fire_event(self, event, **kwargs):
        namespace = self._get_namespace(**kwargs)

        if "namespace" in kwargs:
            del kwargs["namespace"]

        utils.run_coroutine_threadsafe(
            self, self.AD.events.fire_event(namespace, event, **kwargs))
Beispiel #4
0
 def func_wrapper(*args, **kwargs):
     self = args[0]
     ns = self._get_namespace(**kwargs)
     plugin = utils.run_coroutine_threadsafe(self, self.AD.plugins.get_plugin_object(ns))
     if plugin is None:
         self.logger.warning("non_existent namespace (%s) specified in call to %s", ns, func.__name__)
         return lambda *args: None
     if not utils.run_coroutine_threadsafe(self, plugin.am_reading_messages()):
         self.logger.warning("Attempt to call Home Assistant while disconnected: %s", func.__name__)
         return lambda *args: None
     else:
         return func(*args, **kwargs)
Beispiel #5
0
 def get_plugin_api(self, plugin_name):
     return utils.run_coroutine_threadsafe(
         self,
         self.AD.plugins.get_plugin_api(plugin_name, self.name,
                                        self._logging, self.args,
                                        self.config, self.app_config,
                                        self.global_vars))
Beispiel #6
0
    def run_daily(self, callback, start, **kwargs):
        info = None
        when = None
        if type(start) == datetime.time:
            when = start
        elif type(start) == str:
            info = utils.run_coroutine_threadsafe(
                self, self.AD.sched._parse_time(start, self.name))
        else:
            raise ValueError("Invalid type for start")

        if info is None or info["sun"] is None:
            if when is None:
                when = info["datetime"].time()
            aware_now = self.get_now()
            now = self.AD.sched.make_naive(aware_now)
            today = now.date()
            event = datetime.datetime.combine(today, when)
            if event < now:
                event = event + datetime.timedelta(days=1)
            handle = self.run_every(callback, event, 24 * 60 * 60, **kwargs)
        elif info["sun"] == "sunrise":
            kwargs["offset"] = info["offset"]
            handle = self.run_at_sunrise(callback, **kwargs)
        else:
            kwargs["offset"] = info["offset"]
            handle = self.run_at_sunset(callback, **kwargs)
        return handle
Beispiel #7
0
 def listen_log(self, cb, level="INFO", **kwargs):
     namespace = self._get_namespace(**kwargs)
     if "namespace" in kwargs:
         del kwargs["namespace"]
     return utils.run_coroutine_threadsafe(
         self,
         self.AD.logging.add_log_callback(namespace, self.name, cb, level,
                                          **kwargs))
Beispiel #8
0
 def _check_entity(self, namespace, entity):
     if "." not in entity:
         raise ValueError("{}: Invalid entity ID: {}".format(
             self.name, entity))
     if not utils.run_coroutine_threadsafe(
             self, self.AD.state.entity_exists(namespace, entity)):
         self.logger.warning("%s: Entity %s not found in namespace %s",
                             self.name, entity, namespace)
Beispiel #9
0
    def get_state(self, entity_id=None, attribute=None, **kwargs):
        namespace = self._get_namespace(**kwargs)
        if "namespace" in kwargs:
            del kwargs["namespace"]

        return utils.run_coroutine_threadsafe(
            self,
            self.AD.state.get_state(self.name, namespace, entity_id, attribute,
                                    **kwargs))
Beispiel #10
0
    def set_state(self, entity_id, **kwargs):
        self.logger.debug("set state: %s, %s", entity_id, kwargs)
        namespace = self._get_namespace(**kwargs)
        self._check_entity(namespace, entity_id)
        if "namespace" in kwargs:
            del kwargs["namespace"]

        return utils.run_coroutine_threadsafe(
            self,
            self.AD.state.set_state(self.name, namespace, entity_id, **kwargs))
Beispiel #11
0
 def run_at(self, callback, start, **kwargs):
     if type(start) == datetime.datetime:
         when = start
     elif type(start) == str:
         when = utils.run_coroutine_threadsafe(
             self, self.AD.sched._parse_time(start, self.name))["datetime"]
     else:
         raise ValueError("Invalid type for start")
     aware_when = self.AD.sched.convert_naive(when)
     name = self.name
     now = self.get_now()
     if aware_when < now:
         raise ValueError("{}: run_at() Start time must be "
                          "in the future".format(self.name))
     handle = utils.run_coroutine_threadsafe(
         self,
         self.AD.sched.insert_schedule(name, aware_when, callback, False,
                                       None, **kwargs))
     return handle
Beispiel #12
0
 def listen_state(self, cb, entity=None, **kwargs):
     namespace = self._get_namespace(**kwargs)
     if "namespace" in kwargs:
         del kwargs["namespace"]
     name = self.name
     if entity is not None and "." in entity:
         self._check_entity(namespace, entity)
     return utils.run_coroutine_threadsafe(
         self,
         self.AD.state.add_state_callback(name, namespace, entity, cb,
                                          kwargs))
Beispiel #13
0
    def call_service(self, service, **kwargs):
        self._check_service(service)
        d, s = service.split("/")
        self.logger.debug("call_service: %s/%s, %s", d, s, kwargs)

        namespace = self._get_namespace(**kwargs)
        if "namespace" in kwargs:
            del kwargs["namespace"]

        return utils.run_coroutine_threadsafe(
            self, self.AD.services.call_service(namespace, d, s, kwargs))
Beispiel #14
0
    def _schedule_sun(self, name, type_, callback, **kwargs):

        if type_ == "next_rising":
            event = self.AD.sched.next_sunrise()
        else:
            event = self.AD.sched.next_sunset()

        handle = utils.run_coroutine_threadsafe(
            self,
            self.AD.sched.insert_schedule(name, event, callback, True, type_,
                                          **kwargs))
        return handle
Beispiel #15
0
    def listen_event(self, cb, event=None, **kwargs):
        namespace = self._get_namespace(**kwargs)

        if "namespace" in kwargs:
            del kwargs["namespace"]

        _name = self.name
        self.logger.debug("Calling listen_event for %s", self.name)
        return utils.run_coroutine_threadsafe(
            self,
            self.AD.events.add_event_callback(_name, namespace, cb, event,
                                              **kwargs))
Beispiel #16
0
 def run_in(self, callback, seconds, **kwargs):
     name = self.name
     self.logger.debug("Registering run_in in %s seconds for %s", seconds,
                       name)
     # convert seconds to an int if possible since a common pattern is to
     # pass this through from the config file which is a string
     exec_time = self.get_now() + timedelta(seconds=int(seconds))
     handle = utils.run_coroutine_threadsafe(
         self,
         self.AD.sched.insert_schedule(name, exec_time, callback, False,
                                       None, **kwargs))
     return handle
Beispiel #17
0
 def register_endpoint(self, cb, name=None):
     if name is None:
         ep = self.name
     else:
         ep = name
     if self.AD.http is not None:
         return utils.run_coroutine_threadsafe(
             self, self.AD.http.register_endpoint(cb, ep))
     else:
         self.logger.warning(
             "register_endpoint for %s filed - HTTP component is not configured",
             name)
Beispiel #18
0
 def run_once(self, callback, start, **kwargs):
     if type(start) == datetime.time:
         when = start
     elif type(start) == str:
         when = utils.run_coroutine_threadsafe(
             self, self.AD.sched._parse_time(start, self.name,
                                             True))["datetime"].time()
     else:
         raise ValueError("Invalid type for start")
     name = self.name
     now = self.get_now()
     today = now.date()
     event = datetime.datetime.combine(today, when)
     if event < now:
         one_day = datetime.timedelta(days=1)
         event = event + one_day
     exec_time = event.timestamp()
     handle = utils.run_coroutine_threadsafe(
         self,
         self.AD.sched.insert_schedule(name, exec_time, callback, False,
                                       None, **kwargs))
     return handle
Beispiel #19
0
    def run_every(self, callback, start, interval, **kwargs):
        name = self.name
        now = self.get_now()
        aware_start = self.AD.sched.convert_naive(start)
        if aware_start < now:
            raise ValueError("start cannot be in the past")

        self.logger.debug(
            "Registering run_every starting %s in %ss intervals for %s",
            aware_start, interval, name)

        handle = utils.run_coroutine_threadsafe(
            self,
            self.AD.sched.insert_schedule(name,
                                          aware_start,
                                          callback,
                                          True,
                                          None,
                                          interval=interval,
                                          **kwargs))
        return handle
Beispiel #20
0
 def get_callback_entries(self):
     return utils.run_coroutine_threadsafe(
         self, self.AD.callbacks.get_callback_entries())
Beispiel #21
0
 def get_scheduler_entries(self):
     return utils.run_coroutine_threadsafe(
         self, self.AD.sched.get_scheduler_entries())
Beispiel #22
0
 def get_thread_info(self):
     return utils.run_coroutine_threadsafe(
         self, self.AD.threading.get_thread_info())
Beispiel #23
0
 def parse_datetime(self, time_str, name=None, aware=False):
     return utils.run_coroutine_threadsafe(
         self, self.AD.sched.parse_datetime(time_str, name, aware))
Beispiel #24
0
 def sunset(self, aware=False):
     return utils.run_coroutine_threadsafe(self,
                                           self.AD.sched.sunset(aware))
Beispiel #25
0
 def now_is_between(self, start_time_str, end_time_str, name=None):
     return utils.run_coroutine_threadsafe(
         self,
         self.AD.sched.now_is_between(start_time_str, end_time_str, name))
Beispiel #26
0
 def get_now_ts(self):
     return utils.run_coroutine_threadsafe(self, self.AD.sched.get_now_ts())
Beispiel #27
0
 def date(self):
     return (utils.run_coroutine_threadsafe(
         self, self.AD.sched.get_now()).astimezone(self.AD.tz).date())
Beispiel #28
0
 def info_timer(self, handle):
     return utils.run_coroutine_threadsafe(
         self, self.AD.sched.info_timer(handle, self.name))
Beispiel #29
0
    def worker(self):  # noqa: C901
        thread_id = threading.current_thread().name
        q = self.get_q(thread_id)
        while True:
            args = q.get()
            _type = args["type"]
            funcref = args["function"]
            _id = args["id"]
            objectid = args["objectid"]
            name = args["name"]
            error_logger = logging.getLogger("Error.{}".format(name))
            args["kwargs"]["__thread_id"] = thread_id
            callback = "{}() in {}".format(funcref.__name__, name)
            silent = False
            if "__silent" in args["kwargs"]:
                silent = args["kwargs"]["__silent"]

            app = utils.run_coroutine_threadsafe(self, self.AD.app_management.get_app_instance(name, objectid))
            if app is not None:
                try:
                    if _type == "scheduler":
                        try:
                            utils.run_coroutine_threadsafe(
                                self, self.update_thread_info(thread_id, callback, name, _type, _id, silent),
                            )
                            funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
                        except TypeError:
                            self.report_callback_sig(name, "scheduler", funcref, args)

                    elif _type == "state":
                        try:
                            entity = args["entity"]
                            attr = args["attribute"]
                            old_state = args["old_state"]
                            new_state = args["new_state"]
                            utils.run_coroutine_threadsafe(
                                self, self.update_thread_info(thread_id, callback, name, _type, _id, silent),
                            )
                            funcref(
                                entity,
                                attr,
                                old_state,
                                new_state,
                                self.AD.state.sanitize_state_kwargs(app, args["kwargs"]),
                            )
                        except TypeError:
                            self.report_callback_sig(name, "state", funcref, args)

                    if _type == "log":
                        data = args["data"]
                        try:
                            utils.run_coroutine_threadsafe(
                                self, self.update_thread_info(thread_id, callback, name, _type, _id, silent),
                            )
                            funcref(
                                data["app_name"],
                                data["ts"],
                                data["level"],
                                data["log_type"],
                                data["message"],
                                self.AD.events.sanitize_event_kwargs(app, args["kwargs"]),
                            )
                        except TypeError:
                            self.report_callback_sig(name, "log_event", funcref, args)

                    elif _type == "event":
                        data = args["data"]
                        try:
                            utils.run_coroutine_threadsafe(
                                self, self.update_thread_info(thread_id, callback, name, _type, _id, silent),
                            )
                            funcref(args["event"], data, self.AD.events.sanitize_event_kwargs(app, args["kwargs"]))
                        except TypeError:
                            self.report_callback_sig(name, "event", funcref, args)

                except Exception:
                    error_logger.warning("-" * 60)
                    error_logger.warning("Unexpected error in worker for App %s:", name)
                    error_logger.warning("Worker Ags: %s", args)
                    error_logger.warning("-" * 60)
                    error_logger.warning(traceback.format_exc())
                    error_logger.warning("-" * 60)
                    if self.AD.logging.separate_error_log() is True:
                        self.logger.warning(
                            "Logged an error to %s", self.AD.logging.get_filename("error_log"),
                        )
                finally:
                    utils.run_coroutine_threadsafe(
                        self, self.update_thread_info(thread_id, "idle", name, _type, _id, silent),
                    )

            else:
                if not self.AD.stopping:
                    self.logger.warning("Found stale callback for %s - discarding", name)

            q.task_done()
Beispiel #30
0
 def cancel_timer(self, handle):
     name = self.name
     utils.run_coroutine_threadsafe(
         self, self.AD.sched.cancel_timer(name, handle))