class CalendarUpdateThread(Thread): def __init__(self, parent, cal_feeds, cal_update_period_secs): Thread.__init__(self) self.the_parent = parent self.cal_feeds = cal_feeds self.cal_update_period_secs = cal_update_period_secs self.continue_running = True self.httpHandler = HttpHandler("requests") def stop(self): self.continue_running = False def run(self): while self.continue_running: calendars = [] for calFeed in self.cal_feeds: ics_str = self.httpHandler.getTextResponse(calFeed["icsUrl"]) if len(ics_str) <= 0: continue print ("Cal len = ", len(ics_str)) cal_parser = ICalParser.ICalParser() cal_parser.from_string(ics_str) dt_now = datetime.now() dt_end = dt_now + timedelta(days=7) dates = cal_parser.get_event_instances(dt_now.strftime("%Y%m%d"),dt_end.strftime("%Y%m%d")) calendars.append(dates) self.the_parent.setNewCalendarEntries(calendars) time.sleep(self.cal_update_period_secs)
class AutomationServer: def __init__(self, automation_server_info, update_secs): self.list_update_thread = None self.data_lock = Lock() self.data_updated = False self.cur_actions = {} self.automation_server_info = automation_server_info self.update_secs = update_secs self.httpHandler = HttpHandler("requests") def start(self): self.list_update_thread = AutomationServerUpdateThread(self, self.automation_server_info, self.update_secs, self.setNewActionEntries) self.list_update_thread.start() def stop(self): if self.list_update_thread is not None: self.list_update_thread.stop() def setNewActionEntries(self, actions, serverType): with self.data_lock: self.cur_actions[serverType] = actions self.data_updated = True print (str(len(actions)) + " new actions from server type " + serverType) def getActionsDataJson(self): print ("Tablet requesting actions") cal_str = json.dumps(self.cur_actions) return cal_str def execCommand(self, cmdParam): reg = r'_(.*?)_' grp = re.match(reg, cmdParam) if grp is None or grp.lastindex is None: return "FAIL" remain = cmdParam[len(grp.group(0)):] for serv_info in self.automation_server_info: if serv_info["serverType"] == grp.group(1): cmdUrl = serv_info["baseUrl"] + serv_info["cmdPrefix"] + remain + serv_info["cmdSuffix"] self.sendHttpCommand(cmdUrl) break return "OK" def sendHttpCommand(self, cmdUrl): resp_str = self.httpHandler.getTextResponse(cmdUrl) return "OK"
class DoorControllerKeepAliveThread(Thread): def __init__(self, parent, door_controller_url, keepalive_period_secs): Thread.__init__(self) self.the_parent = parent self.door_controller_url = door_controller_url self.keepalive_period_secs = keepalive_period_secs self.continue_running = True self.httpHandler = HttpHandler("requests") def stop(self): self.continue_running = False def run(self): while self.continue_running: statusStr = self.httpHandler.getTextResponse(self.door_controller_url) if len(statusStr) > 0: print("Front Door Watchdog reset") else: print("FAILED TO RESET Front Door Watchdog") time.sleep(self.keepalive_period_secs)
class AutomationServerUpdateThread(Thread): the_parent = None continue_running = True automation_server_urls = [] def __init__(self, parent, automation_server_info, update_period_secs, data_ready_callback): Thread.__init__(self) self.the_parent = parent self.automation_server_info = automation_server_info self.update_period_secs = update_period_secs self.data_ready_callback = data_ready_callback self.rooms = {} self.actions = [] self.httpHandler = HttpHandler("requests") # Add in actions for statically defined automation servers now for server_info in self.automation_server_info: if server_info["reqStr"] == "": self.data_ready_callback(server_info["cmdList"], server_info["serverType"]) def stop(self): self.continue_running = False def run(self): while self.continue_running: for server_info in self.automation_server_info: if server_info["reqStr"] != "": # Check for separate room info needed room_str = "" if "roomReqStr" in server_info and server_info["roomReqStr"] != "": roomUrl = server_info["baseUrl"] + server_info["roomReqStr"] room_str = self.httpHandler.getTextResponse(roomUrl) reqUrl = server_info["baseUrl"] + server_info["reqStr"] resp_str = self.httpHandler.getTextResponse(reqUrl) if len(resp_str) <= 0: continue # print ("Automation Manager Actions Received len = {0}".format(len(resp_str))) self.rooms = self.getRooms(room_str if room_str != "" else resp_str, server_info) self.actions = self.getActions(resp_str, self.rooms, server_info) # self.actions.sort() self.data_ready_callback(self.actions, server_info["serverType"]) time.sleep(self.update_period_secs) def getRooms(self, resp_str, server_info): rooms = {} if server_info["serverType"] == "fibaro": try: roomsIntern = json.loads(resp_str) for roomInf in roomsIntern: rooms[roomInf["id"]] = roomInf["name"] except: print("Failed to interpret fibaro rooms info") else: match_room = r".*?(<room\b.*?>)" matches = re.split(match_room, resp_str) for match in matches: if match[:6] == "<room ": self.addRoom(rooms, match) return rooms def getAttrib(self, tagBody, tagId): reg = r'' + tagId + r'="(.*?)"' grp = re.search(reg, tagBody) if grp is None or grp.lastindex is None: return "" return grp.group(1) def getValue(self, tagBody): reg = r'>(.*?)<' grp = re.search(reg, tagBody) if grp is None or grp.lastindex is None: return "" return grp.group(1) def addRoom(self, rooms, tagBody): name = self.getAttrib(tagBody, "name") id = self.getAttrib(tagBody, "id") if id != "": rooms[id] = name def getActions(self, resp_str, rooms, server_info): actions = [] if server_info["serverType"] == "fibaro": try: scenesIntern = json.loads(resp_str) for sceneInf in scenesIntern: self.addFibaroAction(actions, sceneInf, rooms, server_info) except: print("Failed to interpret fibaro rooms info") else: # Try Vera first match_scene = r".*?(<scene\b.*?>)" matches = re.split(match_scene, resp_str) if len(matches) > 1: # Vera for match in matches: if match[:7] == "<scene ": self.addVeraAction(actions, match, rooms, server_info) else: # Indigo match_action = r".*?(<action\b.*?>.*?</action>)" matches = re.split(match_action, resp_str) for match in matches: if match[:8] == "<action ": self.addIndigoAction(actions, match, rooms, server_info) return actions def addVeraAction(self, actions, tagBody, rooms, server_info): serverUrlPrefix = "automation/api/v1.0/exec" name = self.getAttrib(tagBody, "name") iconName = "" id = self.getAttrib(tagBody, "id") roomId = self.getAttrib(tagBody, "room") roomName = "" if roomId in rooms: roomName = rooms[roomId] if id != "": cmdParam = serverUrlPrefix + "/_vera_" + id actions.append( { "actionNum" : id, "actionName" : name, "groupName" : roomName, "actionUrl" : cmdParam, "iconName": iconName, "urlPrefix": serverUrlPrefix } ) def addIndigoAction(self, actions, tagBody, rooms, server_info): serverUrlPrefix = "automation/api/v1.0/exec" cmdParam = self.getAttrib(tagBody, "href") name = self.getValue(tagBody) iconName = "" cmdParam = serverUrlPrefix + "/_indigo_" + cmdParam if name != "": actions.append( { "actionNum" : "", "actionName" : name, "groupName" : "", "actionUrl" : cmdParam, "iconName": iconName, "urlPrefix": serverUrlPrefix } ) def addFibaroAction(self, actions, sceneInf, rooms, server_info): serverUrlPrefix = "automation/api/v1.0/exec" id = sceneInf["id"] name = sceneInf["name"] roomId = sceneInf["roomID"] roomName = "" if roomId in rooms: roomName = rooms[roomId] iconName = "bulb-on" iconId = sceneInf["iconID"] if iconId == 1: iconName = "bulb-on" if iconId == 2: iconName = "bulb-on" if iconId == 3: iconName = "bulb-off" if id is not None: if server_info["controlPath"] != "sendDirect": cmdParam = serverUrlPrefix + "/_fibaro_" + str(id) else: # Tried to get this to work on Fibaro Home Center 2 but auth using username:password@url doesn't seem to work through jquery # Need to see if I can get Fibaro server to support any other kind of auth - have tried basic auth using base64 key but not succeeded so far cmdParam = server_info["baseUrl"] + server_info["cmdPrefix"] + str(id) + server_info["cmdSuffix"] actions.append( { "actionNum" : id, "actionName" : name, "groupName" : roomName, "actionUrl" : cmdParam, "iconName": iconName, "urlPrefix": serverUrlPrefix } )