예제 #1
0
 def newfunc(*args, **kwargs):
     start_time = time.time()
     result = func(*args, **kwargs)
     elapsed_time = time.time() - start_time
     ha.log(
         conf.dash, "INFO",
         'function [{}] finished in {} ms'.format(func.__name__,
                                                  int(elapsed_time * 1000)))
     return result
예제 #2
0
파일: appapi.py 프로젝트: trnila/appdaemon
 def func_wrapper(*args, **kwargs):
     if not reading_messages:
         ha.log(
             conf.logger, "WARNING",
             "Attempt to call Home Assistant while disconnected: {}".format(
                 func))
         return (lambda *args: None)
     else:
         return (func(*args, **kwargs))
예제 #3
0
파일: appapi.py 프로젝트: trnila/appdaemon
 def cancel_listen_state(self, handle):
     name = self.name
     ha.log(conf.logger, "DEBUG",
            "Canceling listen_state for {}".format(name))
     with conf.callbacks_lock:
         if name in conf.callbacks and handle in conf.callbacks[name]:
             del conf.callbacks[name][handle]
         if name in conf.callbacks and conf.callbacks[name] == {}:
             del conf.callbacks[name]
예제 #4
0
 def run_at_sunset(self, callback, **kwargs):
     name = self.name
     ha.log(
         conf.logger, "DEBUG",
         "Registering run_at_sunset with kwargs = {} for {}".format(
             kwargs, name
         )
     )
     handle = self._schedule_sun(name, "next_setting", callback, **kwargs)
     return handle
예제 #5
0
def process_sun(action):
  ha.log(conf.logger, "DEBUG", "Process sun: {}, next sunrise: {}, next sunset: {}".format(action, conf.sun["next_rising"], conf.sun["next_setting"]))
  for name in conf.schedule.keys():
    for entry in sorted(conf.schedule[name].keys(), key=lambda uuid: conf.schedule[name][uuid]["timestamp"]):
      schedule = conf.schedule[name][entry]
      if schedule["type"] == action and "inactive" in schedule:
        del schedule["inactive"]
        c_offset = ha.get_offset(schedule)
        schedule["timestamp"] = ha.calc_sun(action) + c_offset
        schedule["offset"] = c_offset
예제 #6
0
 def info_listen_event(self, handle):
     name = self.name
     ha.log(conf.logger, "DEBUG",
            "Calling info_listen_event for {}".format(name))
     with conf.callbacks_lock:
         if name in conf.callbacks and handle in conf.callbacks[name]:
             callback = conf.callbacks[name][handle]
             return callback["event"], callback["kwargs"].copy()
         else:
             raise ValueError("Invalid handle: {}".format(handle))
예제 #7
0
 def info_timer(self, handle):
     name = self.name
     ha.log(conf.logger, "DEBUG", "Calling info_timer for {}".format(name))
     if name in conf.schedule and handle in conf.schedule[name]:
         callback = conf.schedule[name][handle]
         return (datetime.datetime.fromtimestamp(callback["timestamp"]),
                 callback["interval"],
                 ha.sanitize_timer_kwargs(callback["kwargs"]))
     else:
         raise ValueError("Invalid handle: {}".format(handle))
예제 #8
0
 def run_in(self, callback, seconds, **kwargs):
     name = self.name
     ha.log(conf.logger, "DEBUG",
            "Registering run_in in {} seconds for {}".format(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 = ha.get_now_ts() + int(seconds)
     handle = ha.insert_schedule(name, exec_time, callback, False, None,
                                 **kwargs)
     return handle
예제 #9
0
 def _check_entity(self, entity):
     if "." not in entity:
         raise ValueError("{}: Invalid entity ID: {}".format(
             self.name, entity))
     with conf.ha_state_lock:
         if entity not in conf.ha_state:
             ha.log(
                 conf.logger, "WARNING",
                 "{}: Entity {} not found in Home Assistant".format(
                     self.name, entity))
예제 #10
0
 def set_app_state(self, entity_id, state):
     ha.log(conf.logger, "DEBUG", "set_app_state: {}".format(entity_id))
     if entity_id is not None and "." in entity_id:
         with conf.ha_state_lock:
             if entity_id in conf.ha_state:
                 old_state = conf.ha_state[entity_id]
             else:
                 old_state = None
             data = {"entity_id": entity_id, "new_state": state, "old_state": old_state}
             args = {"event_type": "state_changed", "data": data}
             conf.appq.put_nowait(args)
예제 #11
0
 def fire_event(self, event, **kwargs):
     ha.log(conf.logger, "DEBUG",
            "fire_event: {}, {}".format(event, kwargs))
     if conf.ha_key != "":
         headers = {'x-ha-access': conf.ha_key}
     else:
         headers = {}
     apiurl = "{}/api/events/{}".format(conf.ha_url, event)
     r = requests.post(apiurl, headers=headers, json=kwargs)
     r.raise_for_status()
     return r.json()
예제 #12
0
 def info_listen_state(self, handle):
     name = self.name
     ha.log(conf.logger, "DEBUG",
            "Calling info_listen_state for {}".format(name))
     if name in conf.callbacks and handle in conf.callbacks[name]:
         callback = conf.callbacks[name][handle]
         return (callback["entity"],
                 callback["kwargs"].get("attribute", None),
                 ha.sanitize_state_kwargs(callback["kwargs"]))
     else:
         raise ValueError("Invalid handle: {}".format(handle))
예제 #13
0
def dump_objects():
    ha.log(conf.logger, "INFO",
           "--------------------------------------------------")
    ha.log(conf.logger, "INFO", "Objects")
    ha.log(conf.logger, "INFO",
           "--------------------------------------------------")
    for object in conf.objects.keys():
        ha.log(conf.logger, "INFO", "{}: {}".format(object,
                                                    conf.objects[object]))
    ha.log(conf.logger, "INFO",
           "--------------------------------------------------")
예제 #14
0
 def set_state(self, entity_id, **kwargs):
     self._check_entity(entity_id)
     ha.log(conf.logger, "DEBUG",
            "set_state: {}, {}".format(entity_id, kwargs))
     if conf.ha_key != "":
         headers = {'x-ha-access': conf.ha_key}
     else:
         headers = {}
     apiurl = "{}/api/states/{}".format(conf.ha_url, entity_id)
     r = requests.post(apiurl, headers=headers, json=kwargs)
     r.raise_for_status()
     return r.json()
예제 #15
0
def process_state_change(data):

    entity_id = data['data']['entity_id']
    ha.log(conf.logger, "DEBUG", "Entity ID:{}:".format(entity_id))
    device, entity = entity_id.split(".")

    # First update our global state
    with conf.ha_state_lock:
        conf.ha_state[entity_id] = data['data']['new_state']

    # Process state callbacks

    with conf.callbacks_lock:
        for name in conf.callbacks.keys():
            for uuid in conf.callbacks[name]:
                callback = conf.callbacks[name][uuid]
                if callback["type"] == "state":
                    cdevice = None
                    centity = None
                    if callback["entity"] != None:
                        if "." not in callback["entity"]:
                            cdevice = callback["entity"]
                            centity = None
                        else:
                            cdevice, centity = callback["entity"].split(".")
                    if callback["kwargs"].get("attribute") == None:
                        cattribute = "state"
                    else:
                        cattribute = callback["kwargs"].get("attribute")

                    cold = callback["kwargs"].get("old")
                    cnew = callback["kwargs"].get("new")

                    if cdevice == None:
                        check_and_disapatch(name, callback["function"],
                                            entity_id, cattribute,
                                            data['data']['new_state'],
                                            data['data']['old_state'], cold,
                                            cnew, callback["kwargs"])
                    elif centity == None:
                        if device == cdevice:
                            check_and_disapatch(name, callback["function"],
                                                entity_id, cattribute,
                                                data['data']['new_state'],
                                                data['data']['old_state'],
                                                cold, cnew, callback["kwargs"])
                    elif device == cdevice and entity == centity:
                        check_and_disapatch(name, callback["function"],
                                            entity_id, cattribute,
                                            data['data']['new_state'],
                                            data['data']['old_state'], cold,
                                            cnew, callback["kwargs"])
예제 #16
0
 def call_service(self, service, **kwargs):
     self._check_service(service)
     d, s = service.split("/")
     ha.log(conf.logger, "DEBUG",
            "call_service: {}/{}, {}".format(d, s, kwargs))
     if conf.ha_key != "":
         headers = {'x-ha-access': conf.ha_key}
     else:
         headers = {}
     apiurl = "{}/api/services/{}/{}".format(conf.ha_url, d, s)
     r = requests.post(apiurl, headers=headers, json=kwargs)
     r.raise_for_status()
     return r.json()
예제 #17
0
def ws_update(jdata):
    ha.log(conf.dash,
           "DEBUG",
           "Sending data to {} dashes: {}".format(len(app['websockets']), jdata))

    data = json.dumps(jdata)

    for ws in app['websockets']:

        if "dashboard" in app['websockets'][ws]:
            ha.log(conf.dash,
                   "DEBUG",
                   "Found dashboard type {}".format(app['websockets'][ws]["dashboard"]))
            ws.send_str(data)
예제 #18
0
 def run_every(self, callback, start, interval, **kwargs):
     name = self.name
     now = ha.get_now()
     if start < now:
         raise ValueError("start cannot be in the past")
     ha.log(
         conf.logger, "DEBUG",
         "Registering run_every starting {} in {}s intervals for {}".format(
              start, interval, name
         )
     )
     exec_time = start.timestamp()
     handle = ha.insert_schedule(name, exec_time, callback, True, None,
                                 interval=interval, **kwargs)
     return handle
예제 #19
0
 def get_state(self, entity_id=None, attribute=None):
     ha.log(conf.logger, "DEBUG",
            "get_state: {}.{}".format(entity_id, attribute))
     device = None
     entity = None
     if entity_id is not None and "." in entity_id:
         if not self.entity_exists(entity_id):
             return None
     if entity_id is not None:
         if "." not in entity_id:
             if attribute is not None:
                 raise ValueError(
                     "{}: Invalid entity ID: {}".format(self.name, entity))
             device = entity_id
             entity = None
         else:
             device, entity = entity_id.split(".")
     with conf.ha_state_lock:
         if device is None:
             return conf.ha_state
         elif entity is None:
             devices = {}
             for entity_id in conf.ha_state.keys():
                 thisdevice, thisentity = entity_id.split(".")
                 if device == thisdevice:
                     devices[entity_id] = conf.ha_state[entity_id]
             return devices
         elif attribute is None:
             entity_id = "{}.{}".format(device, entity)
             if entity_id in conf.ha_state:
                 return conf.ha_state[entity_id]["state"]
             else:
                 return None
         else:
             entity_id = "{}.{}".format(device, entity)
             if attribute == "all":
                 if entity_id in conf.ha_state:
                     return conf.ha_state[entity_id]
                 else:
                     return None
             else:
                 if attribute in conf.ha_state[entity_id]:
                     return conf.ha_state[entity_id][attribute]
                 elif attribute in conf.ha_state[entity_id]["attributes"]:
                     return conf.ha_state[entity_id]["attributes"][
                         attribute]
                 else:
                     return None
예제 #20
0
def run_dash(loop):
    # noinspection PyBroadException
    try:
        set_paths()
        setup_routes()

        handler = app.make_handler()
        f = loop.create_server(handler, "0.0.0.0", int(conf.dash_port))
        conf.srv = loop.run_until_complete(f)
        conf.rss = loop.run_until_complete(update_rss(loop))
    except:
        ha.log(conf.dash, "WARNING", '-' * 60)
        ha.log(conf.dash, "WARNING", "Unexpected error in dashboard thread")
        ha.log(conf.dash, "WARNING", '-' * 60)
        ha.log(conf.dash, "WARNING", traceback.format_exc())
        ha.log(conf.dash, "WARNING", '-' * 60)
예제 #21
0
 def get_callback_entries(self):
     callbacks = {}
     for name in conf.callbacks.keys():
         callbacks[name] = {}
         ha.log(conf.logger, "INFO", "{}:".format(name))
         for uuid_ in conf.callbacks[name]:
             callbacks[name][uuid_] = {}
             if "entity" in callbacks[name][uuid_]:
                 callbacks[name][uuid_]["entity"] = conf.callbacks[name][uuid_]["entity"]
             else:
                 callbacks[name][uuid_]["entity"] = None
             callbacks[name][uuid_]["type"] = conf.callbacks[name][uuid_]["type"]
             callbacks[name][uuid_]["kwargs"] = conf.callbacks[name][uuid_]["kwargs"]
             callbacks[name][uuid_]["function"] = conf.callbacks[name][uuid_]["function"]
             callbacks[name][uuid_]["name"] = conf.callbacks[name][uuid_]["name"]
     return(callbacks)
예제 #22
0
def add_layout(value, layout, occupied, dash, page, includes, css_vars,
               global_parameters):
    if value is None:
        return
    widgetdimensions = re.compile("^(.+)\\((\d+)x(\d+)\\)$")
    value = ''.join(value.split())
    widgets = value.split(",")
    column = 1
    for wid in widgets:
        size = widgetdimensions.search(wid)
        if size:
            name = size.group(1)
            xsize = size.group(2)
            ysize = size.group(3)

        elif "widget_size" in dash:
            name = wid
            xsize = dash["widget_size"][0]
            ysize = dash["widget_size"][1]
        else:
            name = wid
            xsize = 1
            ysize = 1

        while "{}x{}".format(column, layout) in occupied:
            column += 1

        if name != "spacer":
            sanitized_name = name.replace(".", "-").replace("_", "-").lower()
            widget = {}
            widget["id"] = "{}-{}".format(page, sanitized_name)

            if widget_exists(dash["widgets"], widget["id"]):
                ha.log(conf.dash, "WARNING",
                       "Duplicate widget name '{}' - ignored".format(name))
            else:
                widget["position"] = [column, layout]
                widget["size"] = [xsize, ysize]
                widget["parameters"] = load_widget(dash, includes, name,
                                                   css_vars, global_parameters)
                dash["widgets"].append(widget)

        for x in range(column, column + int(xsize)):
            for y in range(layout, layout + int(ysize)):
                occupied["{}x{}".format(x, y)] = 1
        column += int(xsize)
예제 #23
0
def get_styles(style_str, name, field):
    #
    # Parse styles in order from a string and allow later entries to override earlier ones
    #
    result = {}
    styles = style_str.split(";")
    for style in styles:
        if style != "" and style is not None:
            pieces = style.split(":")
            if len(pieces) == 2:
                result[pieces[0].strip()] = pieces[1]
            else:
                ha.log(
                    conf.dash, "WARNING",
                    "malformed CSS: {} in widget '{}', field '{}' (could be a problem in the skin) - ignoring"
                    .format(style, name, field))

    return result
예제 #24
0
    def set_state(self, entity_id, **kwargs):
        with conf.ha_state_lock:
            self._check_entity(entity_id)
            ha.log(
                conf.logger, "DEBUG",
                "set_state: {}, {}".format(entity_id, kwargs)
            )
            if conf.ha_key != "":
                headers = {'x-ha-access': conf.ha_key}
            else:
                headers = {}
            apiurl = "{}/api/states/{}".format(conf.ha_url, entity_id)

            if entity_id not in conf.ha_state:
                # Its a new state entry
                conf.ha_state[entity_id] = {}
                conf.ha_state[entity_id]["attributes"] = {}

            args = {}

            if "state" in kwargs:
                args["state"] = kwargs["state"]
            else:
                if "state" in conf.ha_state[entity_id]:
                    args["state"] = conf.ha_state[entity_id]["state"]

            if "attributes" in conf.ha_state[entity_id]:
                args["attributes"] = conf.ha_state[entity_id]["attributes"]
                if "attributes" in kwargs:
                    args["attributes"].update(kwargs["attributes"])
            else:
                if "attributes" in kwargs:
                    args["attributes"] = kwargs["attributes"]

            r = requests.post(apiurl, headers=headers, json=args,
                              verify=conf.certpath)
            r.raise_for_status()
            # Update our local copy of state
            state = r.json()
            conf.ha_state[entity_id] = state

            return state
예제 #25
0
파일: api.py 프로젝트: philmottin/appdaemon
def run_api(loop, tasks):
    # noinspection PyBroadException
    try:
        setup_api()

        if conf.api_ssl_certificate is not None and conf.api_ssl_key is not None:
            context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
            context.load_cert_chain(conf.api_ssl_certificate, conf.api_ssl_key)
        else:
            context = None

        handler = app.make_handler()

        f = loop.create_server(handler, "0.0.0.0", int(conf.api_port), ssl = context)
        tasks.append(asyncio.async(f))
    except:
        ha.log(conf.dash, "WARNING", '-' * 60)
        ha.log(conf.dash, "WARNING", "Unexpected error in api thread")
        ha.log(conf.dash, "WARNING", '-' * 60)
        ha.log(conf.dash, "WARNING", traceback.format_exc())
        ha.log(conf.dash, "WARNING", '-' * 60)
예제 #26
0
def logon(request):
    data = yield from request.post()
    success = False
    password = data["password"]

    if password == conf.dash_password:
        ha.log(conf.dash, "INFO",
               "Succesful logon from {}".format(request.host))

        hashed = bcrypt.hashpw(str.encode(conf.dash_password),
                               bcrypt.gensalt())

        #ha.log(conf.dash, "INFO", hashed)

        response = yield from list_dash_no_secure(request)
        response.set_cookie("adcreds", hashed.decode("utf-8"))

    else:
        ha.log(conf.dash, "WARNING",
               "Unsuccesful logon from {}".format(request.host))
        response = yield from list_dash(request)

    return response
예제 #27
0
def init_object(name, class_name, module_name, args):
    ha.log(
        conf.logger, "INFO",
        "Loading Object {} using class {} from module {}".format(
            name, class_name, module_name))
    module = __import__(module_name)
    APPclass = getattr(module, class_name)
    conf.objects[name] = {
        "object": APPclass(name, conf.logger, conf.error, args,
                           conf.global_vars),
        "id": uuid.uuid4()
    }

    # Call it's initialize function

    with conf.threads_busy_lock:
        conf.threads_busy += 1
        q.put_nowait({
            "type": "initialize",
            "name": name,
            "id": conf.objects[name]["id"],
            "function": conf.objects[name]["object"].initialize
        })
예제 #28
0
def wshandler(request):
    ws = web.WebSocketResponse()
    yield from ws.prepare(request)

    request.app['websockets'][ws] = {}
    # noinspection PyBroadException
    try:
        while True:
            msg = yield from ws.receive()
            if msg.type == aiohttp.WSMsgType.TEXT:
                ha.log(conf.dash, "INFO",
                       "New dashboard connected: {}".format(msg.data))
                request.app['websockets'][ws]["dashboard"] = msg.data
            elif msg.type == aiohttp.WSMsgType.ERROR:
                ha.log(conf.dash, "INFO",
                       "ws connection closed with exception {}".format(ws.exception()))
    except:
        ha.log(conf.dash, "INFO", "Dashboard disconnected")
    finally:
        request.app['websockets'].pop(ws, None)

    return ws
예제 #29
0
 def error(self, msg, level="WARNING"):
     msg = self._sub_stack(msg)
     ha.log(self._error, level, msg, self.name)
예제 #30
0
 def log(self, msg, level="INFO"):
     msg = self._sub_stack(msg)
     ha.log(self._logger, level, msg, self.name)