Exemplo n.º 1
0
def ddxRecheck(rule, device, current_time, ddx_delay, ddx_sensor):
    for x in range(ddx_delay):
        if current_time != dxState[ddx_sensor[1]][ddx_sensor[2]][ddx_sensor[3]][ddx_sensor[4]]:
            logging.info("ddx rule " + rule + " canceled after " + str(x) + " seconds")
            return # rule not valid anymore because sensor state changed while waiting for ddx delay
        sleep(1)
    current_time = datetime.now()
    rule_state = checkRuleConditions(rule, device, current_time, True)
    if rule_state[0]: #if all conditions are meet again
        logging.info("delayed rule " + rule + " is triggered")
        bridge_config["rules"][rule]["lasttriggered"] = current_time.strftime("%Y-%m-%dT%H:%M:%S")
        bridge_config["rules"][rule]["timestriggered"] += 1
        for action in bridge_config["rules"][rule]["actions"]:
            sendRequest("/api/" + bridge_config["rules"][rule]["owner"] + action["address"], action["method"], json.dumps(action["body"]))
Exemplo n.º 2
0
def rulesProcessor(device, current_time):
    bridge_config["config"]["localtime"] = current_time.strftime("%Y-%m-%dT%H:%M:%S") #required for operator dx to address /config/localtime
    actionsToExecute = []
    for rule in bridge_config["rules"].keys():
        if bridge_config["rules"][rule]["status"] == "enabled":
            rule_result = checkRuleConditions(rule, device, current_time)
            if rule_result[0]:
                if rule_result[1] == 0: #is not ddx rule
                    logging.info("rule " + rule + " is triggered")
                    bridge_config["rules"][rule]["lasttriggered"] = current_time.strftime("%Y-%m-%dT%H:%M:%S")
                    bridge_config["rules"][rule]["timestriggered"] += 1
                    for action in bridge_config["rules"][rule]["actions"]:
                        actionsToExecute.append(action)
                else: #if ddx rule
                    logging.info("ddx rule " + rule + " will be re validated after " + str(rule_result[1]) + " seconds")
                    Thread(target=ddxRecheck, args=[rule, device, current_time, rule_result[1], rule_result[2]]).start()
    for action in actionsToExecute:
        sendRequest("/api/" +    list(bridge_config["config"]["whitelist"])[0] + action["address"], action["method"], json.dumps(action["body"]))
Exemplo n.º 3
0
def sendLightRequest(light, data, lights, addresses):
    payload = {}
    if light in addresses:
        protocol_name = addresses[light]["protocol"]
        for protocol in protocols:
            if "protocols." + protocol_name == protocol.__name__:
                try:
                    light_state = protocol.set_light(addresses[light], lights[light], data)
                except Exception as e:
                    lights[light]["state"]["reachable"] = False
                    logging.warning(lights[light]["name"] + " light not reachable: %s", e)
                return

        if addresses[light]["protocol"] == "native": #ESP8266 light or strip
            url = "http://" + addresses[light]["ip"] + "/set?light=" + str(addresses[light]["light_nr"])
            method = 'GET'
            for key, value in data.items():
                if key == "xy":
                    url += "&x=" + str(value[0]) + "&y=" + str(value[1])
                else:
                    url += "&" + key + "=" + str(value)
        elif addresses[light]["protocol"] in ["hue","deconz"]: #Original Hue light or Deconz light
            url = "http://" + addresses[light]["ip"] + "/api/" + addresses[light]["username"] + "/lights/" + addresses[light]["light_id"] + "/state"
            method = 'PUT'
            payload.update(data)

        elif addresses[light]["protocol"] == "domoticz": #Domoticz protocol
            url = "http://" + addresses[light]["ip"] + "/json.htm?type=command&idx=" + addresses[light]["light_id"]
            method = 'GET'
            if "on" in data and not "bri" in data and not "ct" in data and not "xy" in data:
                for key, value in data.items():
                    url += "&param=switchlight"
                    if key == "on":
                        if value:
                            url += "&switchcmd=On"
                        else:
                            url += "&switchcmd=Off"
            else:
                url += "&param=setcolbrightnessvalue"
                color_data = {}

                old_light_state = lights[light]["state"]
                colormode = old_light_state["colormode"]
                ct = old_light_state["ct"]
                bri = old_light_state["bri"]
                xy = old_light_state["xy"]

                if "bri" in data:
                    bri = data["bri"]
                if "ct" in data:
                    ct = data["ct"]
                if "xy" in data:
                    xy = data["xy"]
                bri = int(bri)

                color_data["m"] = 1 #0: invalid, 1: white, 2: color temp, 3: rgb, 4: custom
                if colormode == "ct":
                    color_data["m"] = 2
                    ct01 = (ct - 153) / (500 - 153) #map color temperature from 153-500 to 0-1
                    ct255 = ct01 * 255 #map color temperature from 0-1 to 0-255
                    color_data["t"] = ct255
                elif colormode == "xy":
                    color_data["m"] = 3
                    (color_data["r"], color_data["g"], color_data["b"]) = convert_xy(xy[0], xy[1], 255)
                url += "&color="+json.dumps(color_data)
                url += "&brightness=" + str(round(float(bri)/255*100))

            urlObj = {}
            urlObj["url"] = url

        elif addresses[light]["protocol"] == "jeedom": #Jeedom protocol
            url = "http://" + addresses[light]["ip"] + "/core/api/jeeApi.php?apikey=" + addresses[light]["light_api"] + "&type=cmd&id="
            method = 'GET'
            for key, value in data.items():
                if key == "on":
                    if value:
                        url += addresses[light]["light_on"]
                    else:
                        url += addresses[light]["light_off"]
                elif key == "bri":
                    url += addresses[light]["light_slider"] + "&slider=" + str(round(float(value)/255*100)) # jeedom range from 0 to 100 (for zwave devices) instead of 0-255 of bridge

        elif addresses[light]["protocol"] == "milight": #MiLight bulb
            url = "http://" + addresses[light]["ip"] + "/gateways/" + addresses[light]["device_id"] + "/" + addresses[light]["mode"] + "/" + str(addresses[light]["group"])
            method = 'PUT'
            for key, value in data.items():
                if key == "on":
                    payload["status"] = value
                elif key == "bri":
                    payload["brightness"] = value
                elif key == "ct":
                    payload["color_temp"] = int(value / 1.6 + 153)
                elif key == "hue":
                    payload["hue"] = value / 180
                elif key == "sat":
                    payload["saturation"] = value * 100 / 255
                elif key == "xy":
                    payload["color"] = {}
                    (payload["color"]["r"], payload["color"]["g"], payload["color"]["b"]) = convert_xy(value[0], value[1], lights[light]["state"]["bri"])
            logging.info(json.dumps(payload))

        elif addresses[light]["protocol"] == "ikea_tradfri": #IKEA Tradfri bulb
            url = "coaps://" + addresses[light]["ip"] + ":5684/15001/" + str(addresses[light]["device_id"])
            for key, value in data.items():
                if key == "on":
                    payload["5850"] = int(value)
                elif key == "transitiontime":
                    payload["5712"] = value
                elif key == "bri":
                    payload["5851"] = value
                elif key == "ct":
                    if value < 270:
                        payload["5706"] = "f5faf6"
                    elif value < 385:
                        payload["5706"] = "f1e0b5"
                    else:
                        payload["5706"] = "efd275"
                elif key == "xy":
                    payload["5709"] = int(value[0] * 65535)
                    payload["5710"] = int(value[1] * 65535)
            if "hue" in data or "sat" in data:
                if("hue" in data):
                    hue = data["hue"]
                else:
                    hue = lights[light]["state"]["hue"]
                if("sat" in data):
                    sat = data["sat"]
                else:
                    sat = lights[light]["state"]["sat"]
                if("bri" in data):
                    bri = data["bri"]
                else:
                    bri = lights[light]["state"]["bri"]
                rgbValue = hsv_to_rgb(hue, sat, bri)
                xyValue = convert_rgb_xy(rgbValue[0], rgbValue[1], rgbValue[2])
                payload["5709"] = int(xyValue[0] * 65535)
                payload["5710"] = int(xyValue[1] * 65535)
            if "5850" in payload and payload["5850"] == 0:
                payload.clear() #setting brightnes will turn on the ligh even if there was a request to power off
                payload["5850"] = 0
            elif "5850" in payload and "5851" in payload: #when setting brightness don't send also power on command
                del payload["5850"]
        elif addresses[light]["protocol"] == "flex":
            msg = bytearray()
            if "on" in data:
                if data["on"]:
                    msg = bytearray([0x71, 0x23, 0x8a, 0x0f])
                else:
                    msg = bytearray([0x71, 0x24, 0x8a, 0x0f])
                checksum = sum(msg) & 0xFF
                msg.append(checksum)
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
                sock.sendto(msg, (addresses[light]["ip"], 48899))
            if ("bri" in data and lights[light]["state"]["colormode"] == "xy") or "xy" in data:
                logging.info(pretty_json(data))
                bri = data["bri"] if "bri" in data else lights[light]["state"]["bri"]
                xy = data["xy"] if "xy" in data else lights[light]["state"]["xy"]
                rgb = convert_xy(xy[0], xy[1], bri)
                msg = bytearray([0x41, rgb[0], rgb[1], rgb[2], 0x00, 0xf0, 0x0f])
                checksum = sum(msg) & 0xFF
                msg.append(checksum)
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
                sock.sendto(msg, (addresses[light]["ip"], 48899))
            elif ("bri" in data and lights[light]["state"]["colormode"] == "ct") or "ct" in data:
                bri = data["bri"] if "bri" in data else lights[light]["state"]["bri"]
                msg = bytearray([0x41, 0x00, 0x00, 0x00, bri, 0x0f, 0x0f])
                checksum = sum(msg) & 0xFF
                msg.append(checksum)
                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
                sock.sendto(msg, (addresses[light]["ip"], 48899))

        try:
            if addresses[light]["protocol"] == "ikea_tradfri":
                if "5712" not in payload:
                    payload["5712"] = 4 #If no transition add one, might also add check to prevent large transitiontimes
                check_output("./coap-client-linux -m put -u \"" + addresses[light]["identity"] + "\" -k \"" + addresses[light]["preshared_key"] + "\" -e '{ \"3311\": [" + json.dumps(payload) + "] }' \"" + url + "\"", shell=True)
            elif addresses[light]["protocol"] in ["hue", "deconz"]:
                color = {}
                if "xy" in payload:
                    color["xy"] = payload["xy"]
                    del(payload["xy"])
                elif "ct" in payload:
                    color["ct"] = payload["ct"]
                    del(payload["ct"])
                elif "hue" in payload:
                    color["hue"] = payload["hue"]
                    del(payload["hue"])
                elif "sat" in payload:
                    color["sat"] = payload["sat"]
                    del(payload["sat"])
                if len(payload) != 0:
                    sendRequest(url, method, json.dumps(payload))
                    if addresses[light]["protocol"] == "deconz":
                        sleep(0.7)
                if len(color) != 0:
                    sendRequest(url, method, json.dumps(color))
            else:
                sendRequest(url, method, json.dumps(payload))
        except:
            lights[light]["state"]["reachable"] = False
            logging.info("request error")
        else:
            lights[light]["state"]["reachable"] = True
            logging.info("LightRequest: " + url)
Exemplo n.º 4
0
def syncWithLights(lights, addresses, users, groups, off_if_unreachable): #update Hue Bridge lights states
    while True:
        logging.info("sync with lights")
        for light in addresses:
            try:
                protocol_name = addresses[light]["protocol"]
                for protocol in protocols:
                    if "protocols." + protocol_name == protocol.__name__:
                        try:
                            light_state = protocol.get_light_state(addresses[light], lights[light])
                            lights[light]["state"].update(light_state)
                            lights[light]["state"]["reachable"] = True
                        except Exception as e:
                            lights[light]["state"]["reachable"] = False
                            lights[light]["state"]["on"] = False
                            logging.warning(lights[light]["name"] + " is unreachable: %s", e)

                if addresses[light]["protocol"] == "native":
                    light_data = json.loads(sendRequest("http://" + addresses[light]["ip"] + "/get?light=" + str(addresses[light]["light_nr"]), "GET", "{}"))
                    lights[light]["state"].update(light_data)
                    lights[light]["state"]["reachable"] = True
                elif addresses[light]["protocol"] == "hue":
                    light_data = json.loads(sendRequest("http://" + addresses[light]["ip"] + "/api/" + addresses[light]["username"] + "/lights/" + addresses[light]["light_id"], "GET", "{}"))
                    lights[light]["state"].update(light_data["state"])
                elif addresses[light]["protocol"] == "ikea_tradfri":
                    light_data = json.loads(check_output("./coap-client-linux -m get -u \"" + addresses[light]["identity"] + "\" -k \"" + addresses[light]["preshared_key"] + "\" \"coaps://" + addresses[light]["ip"] + ":5684/15001/" + str(addresses[light]["device_id"]) +"\"", shell=True).decode('utf-8').rstrip('\n').split("\n")[-1])
                    lights[light]["state"]["on"] = bool(light_data["3311"][0]["5850"])
                    lights[light]["state"]["bri"] = light_data["3311"][0]["5851"]
                    if "5706" in light_data["3311"][0]:
                        if light_data["3311"][0]["5706"] == "f5faf6":
                            lights[light]["state"]["ct"] = 170
                        elif light_data["3311"][0]["5706"] == "f1e0b5":
                            lights[light]["state"]["ct"] = 320
                        elif light_data["3311"][0]["5706"] == "efd275":
                            lights[light]["state"]["ct"] = 470
                    else:
                        lights[light]["state"]["ct"] = 470
                    lights[light]["state"]["reachable"] = True
                elif addresses[light]["protocol"] == "milight":
                    light_data = json.loads(sendRequest("http://" + addresses[light]["ip"] + "/gateways/" + addresses[light]["device_id"] + "/" + addresses[light]["mode"] + "/" + str(addresses[light]["group"]), "GET", "{}"))
                    if light_data["state"] == "ON":
                        lights[light]["state"]["on"] = True
                    else:
                        lights[light]["state"]["on"] = False
                    if "brightness" in light_data:
                        lights[light]["state"]["bri"] = light_data["brightness"]
                    if "color_temp" in light_data:
                        lights[light]["state"]["colormode"] = "ct"
                        lights[light]["state"]["ct"] = int(light_data["color_temp"] * 1.6)
                    elif "bulb_mode" in light_data and light_data["bulb_mode"] == "color":
                        lights[light]["state"]["colormode"] = "hs"
                        lights[light]["state"]["hue"] = light_data["hue"] * 180
                        if (not "saturation" in light_data) and addresses[light]["mode"] == "rgbw":
                            lights[light]["state"]["sat"] = 255
                        else:
                            lights[light]["state"]["sat"] = int(light_data["saturation"] * 2.54)
                    lights[light]["state"]["reachable"] = True
                elif addresses[light]["protocol"] == "domoticz": #domoticz protocol
                    light_data = json.loads(sendRequest("http://" + addresses[light]["ip"] + "/json.htm?type=devices&rid=" + addresses[light]["light_id"], "GET", "{}"))
                    if light_data["result"][0]["Status"] == "Off":
                         lights[light]["state"]["on"] = False
                    else:
                         lights[light]["state"]["on"] = True
                    lights[light]["state"]["bri"] = str(round(float(light_data["result"][0]["Level"])/100*255))
                    lights[light]["state"]["reachable"] = True
                elif addresses[light]["protocol"] == "jeedom": #jeedom protocol
                    light_data = json.loads(sendRequest("http://" + addresses[light]["ip"] + "/core/api/jeeApi.php?apikey=" + addresses[light]["light_api"] + "&type=cmd&id=" + addresses[light]["light_id"], "GET", "{}"))
                    if light_data == 0:
                         lights[light]["state"]["on"] = False
                    else:
                         lights[light]["state"]["on"] = True
                    lights[light]["state"]["bri"] = str(round(float(light_data)/100*255))
                    lights[light]["state"]["reachable"] = True

                if off_if_unreachable:
                    if lights[light]["state"]["reachable"] == False:
                        lights[light]["state"]["on"] = False
                updateGroupStats(light, lights, groups)
            except Exception as e:
                lights[light]["state"]["reachable"] = False
                lights[light]["state"]["on"] = False
                logging.warning(lights[light]["name"] + " is unreachable: %s", e)
        sleep(10) #wait at last 10 seconds before next sync
        i = 0
        while i < 300: #sync with lights every 300 seconds or instant if one user is connected
            for user in users.keys():
                if users[user]["last use date"] == datetime.now().strftime("%Y-%m-%dT%H:%M:%S"):
                    i = 300
                    break
            i += 1
            sleep(1)
Exemplo n.º 5
0
def scheduleProcessor():
    while True:
        for schedule in bridge_config["schedules"].keys():
            try:
                delay = 0
                if bridge_config["schedules"][schedule]["status"] == "enabled":
                    if bridge_config["schedules"][schedule]["localtime"][
                            -9:-8] == "A":
                        delay = random.randrange(
                            0,
                            int(bridge_config["schedules"][schedule]
                                ["localtime"][-8:-6]) * 3600 +
                            int(bridge_config["schedules"][schedule]
                                ["localtime"][-5:-3]) * 60 +
                            int(bridge_config["schedules"][schedule]
                                ["localtime"][-2:]))
                        schedule_time = bridge_config["schedules"][schedule][
                            "localtime"][:-9]
                    else:
                        schedule_time = bridge_config["schedules"][schedule][
                            "localtime"]
                    if schedule_time.startswith("W"):
                        pieces = schedule_time.split('/T')
                        if int(pieces[0][1:]) & (
                                1 << 6 - datetime.today().weekday()):
                            if pieces[1] <= datetime.now().strftime(
                                    "%H:%M:%S"):
                                logging.info("execute schedule: " + schedule +
                                             " withe delay " + str(delay))
                                sendRequest(
                                    bridge_config["schedules"][schedule]
                                    ["command"]["address"],
                                    bridge_config["schedules"][schedule]
                                    ["command"]["method"],
                                    json.dumps(bridge_config["schedules"]
                                               [schedule]["command"]["body"]),
                                    1, delay)
                    elif schedule_time.startswith("PT"):
                        timer = schedule_time[2:]
                        (h, m, s) = timer.split(':')
                        d = timedelta(hours=int(h),
                                      minutes=int(m),
                                      seconds=int(s))
                        if bridge_config["schedules"][schedule][
                                "starttime"] <= (
                                    datetime.utcnow() -
                                    d).replace(microsecond=0).isoformat():
                            logging.info("execute timer: " + schedule +
                                         " withe delay " + str(delay))
                            sendRequest(
                                bridge_config["schedules"][schedule]["command"]
                                ["address"], bridge_config["schedules"]
                                [schedule]["command"]["method"],
                                json.dumps(bridge_config["schedules"][schedule]
                                           ["command"]["body"]), 1, delay)
                            bridge_config["schedules"][schedule][
                                "status"] = "disabled"
                    elif schedule_time.startswith("R/PT"):
                        timer = schedule_time[4:]
                        (h, m, s) = timer.split(':')
                        d = timedelta(hours=int(h),
                                      minutes=int(m),
                                      seconds=int(s))
                        if bridge_config["schedules"][schedule][
                                "starttime"] <= (
                                    datetime.utcnow() -
                                    d).replace(microsecond=0).isoformat():
                            logging.info("execute timer: " + schedule +
                                         " withe delay " + str(delay))
                            bridge_config["schedules"][schedule][
                                "starttime"] = datetime.utcnow().replace(
                                    microsecond=0).isoformat()
                            sendRequest(
                                bridge_config["schedules"][schedule]["command"]
                                ["address"], bridge_config["schedules"]
                                [schedule]["command"]["method"],
                                json.dumps(bridge_config["schedules"][schedule]
                                           ["command"]["body"]), 1, delay)
                    else:
                        if schedule_time <= datetime.now().strftime(
                                "%Y-%m-%dT%H:%M:%S"):
                            logging.info("execute schedule: " + schedule +
                                         " withe delay " + str(delay))
                            sendRequest(
                                bridge_config["schedules"][schedule]["command"]
                                ["address"], bridge_config["schedules"]
                                [schedule]["command"]["method"],
                                json.dumps(bridge_config["schedules"][schedule]
                                           ["command"]["body"]), 1, delay)
                            if bridge_config["schedules"][schedule][
                                    "autodelete"]:
                                del bridge_config["schedules"][schedule]
            except Exception as e:
                logging.info("Exception while processing the schedule " +
                             schedule + " | " + str(e))

        if (datetime.now().strftime("%M:%S") == "00:10"
            ):  #auto save configuration every hour
            configManager.bridgeConfig.save_config()
            Thread(target=daylightSensor).start()
            if (datetime.now().strftime("%H") == "23"
                    and datetime.now().strftime("%A")
                    == "Sunday"):  #backup config every Sunday at 23:00:10
                configManager.bridgeConfig.save_config(True)
        sleep(1)
Exemplo n.º 6
0
def scanDeconz():
    deconz_ip = configManager.runtimeConfig.arg["DECONZ"]
    if not bridge_config["deconz"]["enabled"]:
        if "username" not in bridge_config["deconz"]:
            try:
                registration = json.loads(
                    sendRequest(
                        "http://" + deconz_ip + ":" +
                        str(bridge_config["deconz"]["port"]) + "/api", "POST",
                        "{\"username\": \"283145a4e198cc6535\", \"devicetype\":\"Hue Emulator\"}"
                    ))
            except:
                logging.info("registration fail, is the link button pressed?")
                return
            if "success" in registration[0]:
                bridge_config["deconz"]["username"] = registration[0][
                    "success"]["username"]
                bridge_config["deconz"]["enabled"] = True
    if "username" in bridge_config["deconz"]:
        deconz_config = json.loads(
            sendRequest(
                "http://" + deconz_ip + ":" +
                str(bridge_config["deconz"]["port"]) + "/api/" +
                bridge_config["deconz"]["username"] + "/config", "GET", "{}"))
        bridge_config["deconz"]["websocketport"] = deconz_config[
            "websocketport"]

        #lights
        deconz_lights = json.loads(
            sendRequest(
                "http://" + deconz_ip + ":" +
                str(bridge_config["deconz"]["port"]) + "/api/" +
                bridge_config["deconz"]["username"] + "/lights", "GET", "{}"))
        for light in deconz_lights:
            if light not in bridge_config["deconz"][
                    "lights"] and "modelid" in deconz_lights[light]:
                new_light_id = nextFreeId(bridge_config, "lights")
                logging.info("register new light " + new_light_id)
                bridge_config["lights"][new_light_id] = deconz_lights[light]
                bridge_config["lights_address"][new_light_id] = {
                    "username": bridge_config["deconz"]["username"],
                    "light_id": light,
                    "ip":
                    deconz_ip + ":" + str(bridge_config["deconz"]["port"]),
                    "protocol": "deconz"
                }
                bridge_config["deconz"]["lights"][light] = {
                    "bridgeid": new_light_id,
                    "modelid": deconz_lights[light]["modelid"],
                    "type": deconz_lights[light]["type"]
                }

        #sensors
        deconz_sensors = json.loads(
            sendRequest(
                "http://" + deconz_ip + ":" +
                str(bridge_config["deconz"]["port"]) + "/api/" +
                bridge_config["deconz"]["username"] + "/sensors", "GET", "{}"))
        for sensor in deconz_sensors:
            if sensor not in bridge_config["deconz"][
                    "sensors"] and "modelid" in deconz_sensors[sensor]:
                new_sensor_id = nextFreeId(bridge_config, "sensors")
                if deconz_sensors[sensor]["modelid"] in [
                        "TRADFRI remote control", "TRADFRI wireless dimmer"
                ]:
                    logging.info("register new " +
                                 deconz_sensors[sensor]["modelid"])
                    bridge_config["sensors"][new_sensor_id] = {
                        "config":
                        deconz_sensors[sensor]["config"],
                        "manufacturername":
                        deconz_sensors[sensor]["manufacturername"],
                        "modelid":
                        deconz_sensors[sensor]["modelid"],
                        "name":
                        deconz_sensors[sensor]["name"],
                        "state":
                        deconz_sensors[sensor]["state"],
                        "type":
                        deconz_sensors[sensor]["type"],
                        "uniqueid":
                        deconz_sensors[sensor]["uniqueid"]
                    }
                    if "swversion" in deconz_sensors[sensor]:
                        bridge_config["sensors"][new_sensor_id][
                            "swversion"] = deconz_sensors[sensor]["swversion"]
                    bridge_config["deconz"]["sensors"][sensor] = {
                        "bridgeid": new_sensor_id,
                        "modelid": deconz_sensors[sensor]["modelid"],
                        "type": deconz_sensors[sensor]["type"]
                    }
                elif deconz_sensors[sensor][
                        "modelid"] == "TRADFRI motion sensor":
                    logging.info(
                        "register TRADFRI motion sensor as Philips Motion Sensor"
                    )
                    newMotionSensorId = addHueMotionSensor(
                        "", deconz_sensors[sensor]["name"])
                    bridge_config["deconz"]["sensors"][sensor] = {
                        "bridgeid": newMotionSensorId,
                        "triggered": False,
                        "modelid": deconz_sensors[sensor]["modelid"],
                        "type": deconz_sensors[sensor]["type"],
                        "lightsensor": "internal"
                    }
                elif deconz_sensors[sensor]["modelid"] == "lumi.vibration.aq1":
                    logging.info(
                        "register Xiaomi Vibration sensor as Philips Motion Sensor"
                    )
                    newMotionSensorId = addHueMotionSensor(
                        "", deconz_sensors[sensor]["name"])
                    bridge_config["deconz"]["sensors"][sensor] = {
                        "bridgeid": newMotionSensorId,
                        "triggered": False,
                        "modelid": deconz_sensors[sensor]["modelid"],
                        "type": deconz_sensors[sensor]["type"],
                        "lightsensor": "astral"
                    }
                elif deconz_sensors[sensor][
                        "modelid"] == "lumi.sensor_motion.aq2":
                    if deconz_sensors[sensor]["type"] == "ZHALightLevel":
                        logging.info("register new Xiaomi light sensor")
                        bridge_config["sensors"][new_sensor_id] = {
                            "name":
                            "Hue ambient light sensor 1",
                            "uniqueid":
                            "00:17:88:01:02:" +
                            deconz_sensors[sensor]["uniqueid"][12:],
                            "type":
                            "ZLLLightLevel",
                            "swversion":
                            "6.1.0.18912",
                            "state": {
                                "dark": True,
                                "daylight": False,
                                "lightlevel": 6000,
                                "lastupdated": "none"
                            },
                            "manufacturername":
                            "Philips",
                            "config": {
                                "on": False,
                                "battery": 100,
                                "reachable": True,
                                "alert": "none",
                                "tholddark": 21597,
                                "tholdoffset": 7000,
                                "ledindication": False,
                                "usertest": False,
                                "pending": []
                            },
                            "modelid":
                            "SML001"
                        }
                        bridge_config["sensors"][nextFreeId(
                            bridge_config, "sensors")] = {
                                "name":
                                "Hue temperature sensor 1",
                                "uniqueid":
                                "00:17:88:01:02:" +
                                deconz_sensors[sensor]["uniqueid"][12:-1] +
                                "2",
                                "type":
                                "ZLLTemperature",
                                "swversion":
                                "6.1.0.18912",
                                "state": {
                                    "temperature": None,
                                    "lastupdated": "none"
                                },
                                "manufacturername":
                                "Philips",
                                "config": {
                                    "on": False,
                                    "battery": 100,
                                    "reachable": True,
                                    "alert": "none",
                                    "ledindication": False,
                                    "usertest": False,
                                    "pending": []
                                },
                                "modelid":
                                "SML001"
                            }
                        bridge_config["deconz"]["sensors"][sensor] = {
                            "bridgeid": new_sensor_id,
                            "modelid": deconz_sensors[sensor]["modelid"],
                            "type": deconz_sensors[sensor]["type"]
                        }
                    elif deconz_sensors[sensor]["type"] == "ZHAPresence":
                        logging.info("register new Xiaomi motion sensor")
                        bridge_config["sensors"][new_sensor_id] = {
                            "name":
                            deconz_sensors[sensor]["name"],
                            "uniqueid":
                            "00:17:88:01:02:" +
                            deconz_sensors[sensor]["uniqueid"][12:],
                            "type":
                            "ZLLPresence",
                            "swversion":
                            "6.1.0.18912",
                            "state": {
                                "lastupdated": "none",
                                "presence": None
                            },
                            "manufacturername":
                            "Philips",
                            "config": {
                                "on": False,
                                "battery": 100,
                                "reachable": True,
                                "alert": "lselect",
                                "ledindication": False,
                                "usertest": False,
                                "sensitivity": 2,
                                "sensitivitymax": 2,
                                "pending": []
                            },
                            "modelid":
                            "SML001"
                        }
                        bridge_config["deconz"]["sensors"][sensor] = {
                            "bridgeid": new_sensor_id,
                            "modelid": deconz_sensors[sensor]["modelid"],
                            "type": deconz_sensors[sensor]["type"]
                        }
                elif deconz_sensors[sensor]["modelid"] == "lumi.sensor_motion":
                    logging.info(
                        "register Xiaomi Motion sensor w/o light sensor")
                    newMotionSensorId = addHueMotionSensor(
                        "", deconz_sensors[sensor]["name"])
                    bridge_config["deconz"]["sensors"][sensor] = {
                        "bridgeid": newMotionSensorId,
                        "triggered": False,
                        "modelid": deconz_sensors[sensor]["modelid"],
                        "type": deconz_sensors[sensor]["type"]
                    }
                else:
                    bridge_config["sensors"][new_sensor_id] = deconz_sensors[
                        sensor]
                    bridge_config["deconz"]["sensors"][sensor] = {
                        "bridgeid": new_sensor_id,
                        "modelid": deconz_sensors[sensor]["modelid"],
                        "type": deconz_sensors[sensor]["type"]
                    }

            else:  #temporary patch for config compatibility with new release
                bridge_config["deconz"]["sensors"][sensor][
                    "modelid"] = deconz_sensors[sensor]["modelid"]
                bridge_config["deconz"]["sensors"][sensor][
                    "type"] = deconz_sensors[sensor]["type"]
        generateDxState()

        if "websocketport" in bridge_config["deconz"]:
            logging.info("Starting deconz websocket")
            Thread(target=websocketClient).start()
Exemplo n.º 7
0
def runScheduler():
    while True:
        for schedule, obj in bridgeConfig["schedules"].items():
            try:
                delay = 0
                if obj.status == "enabled":
                    if obj.localtime[-9:-8] == "A":
                        delay = random.randrange(
                            0,
                            int(obj.localtime[-8:-6]) * 3600 +
                            int(obj.localtime[-5:-3]) * 60 +
                            int(obj.localtime[-2:]))
                        schedule_time = obj.localtime[:-9]
                    else:
                        schedule_time = obj.localtime
                    if schedule_time.startswith("W"):
                        pices = schedule_time.split('/T')
                        if int(pices[0][1:]) & (
                                1 << 6 - datetime.today().weekday()):
                            if pices[1] == datetime.now().strftime("%H:%M:%S"):
                                logging.info("execute schedule: " + schedule +
                                             " withe delay " + str(delay))
                                sendRequest(obj.command["address"],
                                            obj.command["method"],
                                            json.dumps(obj.command["body"]), 1,
                                            delay)
                    elif schedule_time.startswith("PT"):
                        timmer = schedule_time[2:]
                        (h, m, s) = timmer.split(':')
                        d = timedelta(hours=int(h),
                                      minutes=int(m),
                                      seconds=int(s))
                        if obj.starttime == (datetime.utcnow() - d).replace(
                                microsecond=0).isoformat():
                            logging.info("execute timmer: " + schedule +
                                         " withe delay " + str(delay))
                            sendRequest(obj.command["address"],
                                        obj.command["method"],
                                        json.dumps(obj.command["body"]), 1,
                                        delay)
                            obj.status = "disabled"
                    elif schedule_time.startswith("R/PT"):
                        timmer = schedule_time[4:]
                        (h, m, s) = timmer.split(':')
                        d = timedelta(hours=int(h),
                                      minutes=int(m),
                                      seconds=int(s))
                        if obj.starttime == (datetime.utcnow() - d).replace(
                                microsecond=0).isoformat():
                            logging.info("execute timmer: " + schedule +
                                         " withe delay " + str(delay))
                            obj.starttime = datetime.utcnow().replace(
                                microsecond=0).isoformat()
                            sendRequest(obj.command["address"],
                                        obj.command["method"],
                                        json.dumps(obj.command["body"]), 1,
                                        delay)
                    else:
                        if schedule_time == datetime.now().strftime(
                                "%Y-%m-%dT%H:%M:%S"):
                            logging.info("execute schedule: " + schedule +
                                         " withe delay " + str(delay))
                            sendRequest(obj.command["address"],
                                        obj.command["method"],
                                        json.dumps(obj.command["body"]), 1,
                                        delay)
                            if obj.autodelete:
                                del obj

            except Exception as e:
                logging.info("Exception while processing the schedule " +
                             schedule + " | " + str(e))

        for instance, obj in bridgeConfig["behavior_instance"].items():
            try:
                delay = 0
                if obj.enabled:
                    if "when" in obj.configuration:
                        if "recurrence_days" in obj.configuration["when"]:
                            if datetime.now().strftime(
                                    "%A").lower() not in obj.configuration[
                                        "when"]["recurrence_days"]:
                                continue
                        if "time_point" in obj.configuration[
                                "when"] and obj.configuration["when"][
                                    "time_point"]["type"] == "time":
                            triggerTime = obj.configuration["when"][
                                "time_point"]["time"]
                            time_object = datetime(
                                year=1,
                                month=1,
                                day=1,
                                hour=triggerTime["hour"],
                                minute=triggerTime["minute"],
                                second=triggerTime["second"]
                                if "second" in triggerTime else 0)
                            if "fade_in_duration" in obj.configuration:
                                fade_duration = obj.configuration[
                                    "fade_in_duration"]
                                delta = timedelta(
                                    hours=fade_duration["hours"]
                                    if "hours" in fade_duration else 0,
                                    minutes=fade_duration["minutes"]
                                    if "minutes" in fade_duration else 0,
                                    seconds=fade_duration["seconds"]
                                    if "seconds" in fade_duration else 0)
                                time_object = time_object - delta
                            if datetime.now(
                            ).second == time_object.second and datetime.now(
                            ).minute == time_object.minute and datetime.now(
                            ).hour == time_object.hour:
                                logging.info("execute timmer: " + obj.name)
                                Thread(target=triggerScript,
                                       args=[obj]).start()

                    elif "when_extended" in obj.configuration:
                        if "recurrence_days" in obj.configuration[
                                "when_extended"]:
                            if datetime.now().strftime(
                                    "%A").lower() not in obj.configuration[
                                        "when_extended"]["recurrence_days"]:
                                continue
                            if "start_at" in obj.configuration[
                                    "when_extended"] and "time_point" in obj.configuration[
                                        "when_extended"][
                                            "start_at"] and obj.configuration[
                                                "when_extended"]["start_at"][
                                                    "time_point"][
                                                        "type"] == "time":
                                triggerTime = obj.configuration[
                                    "when_extended"]["start_at"]["time_point"][
                                        "time"]
                                time_object = time(
                                    hour=triggerTime["hour"],
                                    minute=triggerTime["minute"],
                                    second=triggerTime["second"]
                                    if "second" in triggerTime else 0)
                                if datetime.now(
                                ).second == time_object.second and datetime.now(
                                ).minute == time_object.minute and datetime.now(
                                ).hour == time_object.hour:
                                    logging.info("execute timmer: " + obj.name)
                                    Thread(target=triggerScript,
                                           args=[obj]).start()

            except Exception as e:
                logging.info("Exception while processing the schedule " +
                             obj.name + " | " + str(e))

        if (datetime.now().strftime("%M:%S") == "00:10"
            ):  #auto save configuration every hour
            configManager.bridgeConfig.save_config()
            Thread(target=daylightSensor,
                   args=[
                       bridgeConfig["config"]["timezone"],
                       bridgeConfig["sensors"]["1"]
                   ]).start()
            if (datetime.now().strftime("%H") == "23"
                    and datetime.now().strftime("%A")
                    == "Sunday"):  #backup config every Sunday at 23:00:10
                configManager.bridgeConfig.save_config(backup=True)
        sleep(1)