def set_property(attribute, value, default=None, ttl=None): """Set an attribute inside the context to the given value.""" path = attribute.split(".") data = CONTEXT current_path = "" new_path = False for step in path: if step: if current_path: current_path += "." current_path += step if step not in data: LOGGER.debug("Creating field %s", current_path) new_path = True data[step] = {"_": None, "_ttl": None} data = data[step] LOGGER.debug("Saving '%s'.", attribute) data["_"] = value data["_default"] = default data["_ttl"] = ttl if new_path: eventbuilder.eEvent(sender_id=__name__, keyword="context.new_path.{}".format(attribute), data={"attribute": attribute, "value": value, "default": default, "ttl": ttl}) eventbuilder.eEvent(sender_id=__name__, keyword="context.change.{}".format(attribute), data={"attribute": attribute, "value": value, "default": default, "ttl": ttl})
def test1(key, data): """Test various events.""" for i in range(50): eventbuilder.eEvent(sender_id=PLUGIN.name, keyword="wait").trigger() LOGGER.warn("Test1 successful!\n%s - %s", key, data) return "Test1 successful!\n%s - %s".format(key, data)
def test2(key, data): """Test the 'test.2' event.""" for i in range(50): eventbuilder.eEvent(sender_id=PLUGIN.name, keyword="test.3").trigger() time.sleep(2) LOGGER.warn("Test2 successful!\n%s - %s", key, data) return "Test2 successful!\n%s - %s".format(key, data)
def _status_update(device): status = "online" if int(device["status"]) else "offline" LOGGER.debug("Updating device %s", device["mac"]) eventbuilder.eEvent( sender_id=PLUGIN.name, keyword="network.fritzbox.availability.{}.{}".format( status, device["name"]), data=device).trigger() context.set_property("network.devices.{}".format(device["mac"]), device)
def new_cast_status(self, status): """React to the "new_cast_status" event.""" if status.display_name: # Skip the event if the displayed name is None. That happens # sometimes for a short moment if a new app connects. if not status.display_name == self.display_name: self.display_name = status.display_name LOGGER.debug("New app connected: %s", self.display_name) eventbuilder.eEvent(sender_id=self.name, keyword="chromecast.connection_change", data=status.__dict__).trigger()
def new_media_status(self, status): """React to the "new_media_status" event.""" if not status.player_state == self.player_state: self.player_state = status.player_state LOGGER.debug("New state: %s", self.player_state) eventbuilder.eEvent(sender_id=self.name, keyword="chromecast.playstate_change", data=status.__dict__).trigger() if not status.content_type == self.content_type: self.content_type = status.content_type LOGGER.debug("New content_type: %s", self.content_type) eventbuilder.eEvent(sender_id=self.name, keyword="chromecast.contenttype_change", data=status.__dict__).trigger()
def _trigger(keyword, data): if "10s" in keyword: ttl = 8 elif "10s" in keyword: ttl = 55 elif "10s" in keyword: ttl = 3300 else: ttl = 0 eventbuilder.eEvent(sender_id=name, keyword=keyword, data=data, ttl=ttl).trigger()
def check_weather(key, data): """Check the weather.""" LOGGER.debug("Checking the Weather..") url = "http://api.openweathermap.org/data/2.5/weather" req = None tries = 0 errors = [] while tries <= 3 and req is None: if tries > 0: LOGGER.debug("Retrying in 15 seconds.") time.sleep(15) try: tries += 1 req = requests.get(url, params=SECRETS, timeout=15) if req.status_code == 200: new_data = req.json() eventbuilder.eEvent(sender_id=PLUGIN.name, keyword="weather.update", data=new_data).trigger() for category in new_data: eventbuilder.eEvent(sender_id=PLUGIN.name, keyword="weather.{}.update".format( category), data=new_data[category]).trigger() return "Weather updated successfully." else: LOGGER.warn("The request returned the wrong status code: %s", req.status_code) req = None except (requests.exceptions.ConnectionError, requests.exceptions.SSLError, requests.exceptions.Timeout), e: LOGGER.warn("Connecting to OWM failed on attempt %d. Error: %s", tries, e) errors.append(e.__repr__()) except ValueError, e: LOGGER.warn("The requested data could not be processed " "successfully. Error: %s", e) errors.append(e.__repr__())
def update(key, data): global CC_CONTENT_TYPE, CC_DISPLAY_NAME, CC_PLAYER_STATE updated = False invalid = True if "content_type" in data and data["content_type"]: # playstate_change invalid = False if not data["content_type"] == CC_CONTENT_TYPE: CC_CONTENT_TYPE = data["content_type"] updated = True LOGGER.debug("Updated CC_CONTENT_TYPE to '%s'.", CC_CONTENT_TYPE) if "player_state" in data and data["player_state"]: invalid = False if not data["player_state"] == CC_PLAYER_STATE: CC_PLAYER_STATE = data["player_state"] or "" updated = True LOGGER.debug("Updated CC_PLAYER_STATE to '%s'.", CC_PLAYER_STATE) if "display_name" in data and data["display_name"]: invalid = False if not data["display_name"] == CC_DISPLAY_NAME: CC_DISPLAY_NAME = data["display_name"] or "" updated = True LOGGER.debug("Updated CC_DISPLAY_NAME to '%s'.", CC_DISPLAY_NAME) if invalid: return ("Error: Invalid Data. 'content_type', 'player_state' and " "'display_name' were all missing or empty.") if updated: if context.get_value("time.time_of_day") == "night": if CC_CONTENT_TYPE and "audio" not in CC_CONTENT_TYPE: # Ignore the updates while Audio is playing. This is only # supposed to dim the lights while videos are playing. if (CC_PLAYER_STATE in ["PLAYING", "BUFFERING"] and CC_DISPLAY_NAME not in [None, "Backdrop"]): # An app is playing video. eventbuilder.eEvent( # Turn on ambient light sender_id=PLUGIN.name, keyword="turn.on.ambient.light").trigger() return "Ambient light turned on." else: # No app connected or video is paused eventbuilder.eEvent( # Turn off ambient light sender_id=PLUGIN.name, keyword="turn.off.ambient.light").trigger() return "Ambient light turned off." else: return "No video is playing. Not changing the light." else: eventbuilder.eEvent( # Turn off all light sender_id=PLUGIN.name, keyword="turn.off.light").trigger() return "It's daytime. The light is supposed to stay off." else: return "No relevant information was updated. Not changing the light."
def _check_daytime(datetime_obj, timelist): if (SUNSET < SUNRISE < datetime_obj or SUNRISE < datetime_obj < SUNSET or datetime_obj < SUNSET < SUNRISE): # The sun has risen. time_of_day = "day" else: # The sun hasn't risen yet. time_of_day = "night" if time_of_day == context.get_value("time.time_of_day", None): logger.debug("It's still %stime.", time_of_day) else: logger.debug("It's now %stime.", time_of_day) context.set_property("time.time_of_day", time_of_day) keyword = "time.time_of_day.{}".format(time_of_day) eventbuilder.eEvent(sender_id=name, keyword=keyword, data=timelist).trigger() # calculate time between now and sunrise if SUNRISE < datetime_obj: # the sunrise is in the past sunrise_pre_post = "post" diff_sunrise = datetime_obj - SUNRISE else: # the sunrise is in the future sunrise_pre_post = "pre" diff_sunrise = SUNRISE - datetime_obj if 0 < diff_sunrise.seconds % 300 < 59: # the difference between now and the sunrise is a multiple of 5 # minutes (this check is executed every minute, thus I'm checking # this in a way that the condition becomes true every 5th minute. keyword_sunrise = "time.sunrise.{}.{}".format( sunrise_pre_post, diff_sunrise.seconds / 60) LOGGER.warn("Triggering event '%s'!", keyword_sunrise) eventbuilder.eEvent(sender_id=name, keyword=keyword_sunrise, data=timelist).trigger() # calculate time between now and sunset if SUNSET < datetime_obj: # the sunset is in the past sunset_pre_post = "post" diff_sunset = datetime_obj - SUNSET else: # the sunset is in the future sunset_pre_post = "pre" diff_sunset = SUNSET - datetime_obj if 0 < diff_sunset.seconds % 300 < 59: # the difference between now and the sunset is a multiple of 5 # minutes (this check is executed every minute, thus I'm checking # this in a way that the condition becomes true every 5th minute. keyword_sunset = "time.sunset.{}.{}".format( sunset_pre_post, diff_sunset.seconds / 60) LOGGER.warn("Triggering event '%s'!", keyword_sunset) eventbuilder.eEvent(sender_id=name, keyword=keyword_sunset, data=timelist).trigger() logger.debug("SUNRISE: %s, SUNSET: %s, NOW: %s", SUNRISE, SUNSET, datetime_obj)
poke["text"] = m.group("name") + m.group("text") poke["name"] = m.group("name") m = re.search((r'<i class="img profpic"[\s\S]*?url\("' r'(?P<imgurl>[\s\S]*?)"\)'), match) poke["imgurl"] = UNESCAPE(m.group("imgurl")) m = re.search((r'<a class="_56bz _54k8 _56bs _56bu" href="' r'(?P<pokeurl>[\s\S]*?)"'), match) poke["pokeurl"] = "https://m.facebook.com" + UNESCAPE( m.group("pokeurl")) if poke["name"] not in CACHE: LOGGER.debug(poke["text"]) eEvent(sender_id=PLUGIN.name, keyword="facebook.poked", data=poke).trigger() new_count += 1 else: LOGGER.warn("This poke by %s is an old one.", poke["name"]) cache.append(poke["name"]) else: LOGGER.warn("No new pokes!") CACHE = cache return "Found {} poke{}, {} of them new. (Cache: {})".format( len(CACHE), "s" if len(CACHE) is not 1 else "", new_count, CACHE)
for item in data: # Get the account name (unique!) for the current item channelname = item["channel"]["name"] \ .encode("utf-8").decode("utf-8") current_game = item["channel"]["game"] \ .encode("utf-8").decode("utf-8") # save the stream's data in a new list new_streamlist[channelname] = item if (channelname not in STREAM_LIST or STREAM_LIST[channelname] is None): # The stream came online since the last check LOGGER.debug(u"'%s' is now online. Playing '%s'", channelname, current_game) eventbuilder.eEvent( sender_id=PLUGIN.name, keyword="media.twitch.availability.online.{}".format( channelname), data=item).trigger() context.set_property( "media.twitch.{}".format(channelname), item) if channelname in STREAM_LIST: # remove the channel from STREAM_LIST so that it can be # refilled with the new data del STREAM_LIST[channelname] else: # The channel was already online at the last check if current_game == STREAM_LIST[channelname]["channel"]["game"]: # The game hasn't changed LOGGER.debug("'%s' is still playing '%s'.", channelname, current_game) else:
def update_devices(key, data): """Check for updated device-info.""" if key == "time.schedule.10s" and data[5] % 20 is not 10: return "Skipping this check since I'm only refreshing every 20 Sec." ignored_macs = ["00:80:77:F2:71:23", None] # this list holds the mac-addresses of ignored devices. They won't be able # to trigger events such as coming on/offline or registering. The 1st # listed address is for example my printer which dis- and reconnects every # few minutes and only spams my logs. # LOGGER.debug("The INDEX holds %d devices.", len(DEVICES_DICT)) # Update data from the FritzBox devices_list = _get_hosts_info() devices_list = sorted(devices_list, key=lambda item: item["name"].lower()) count = 0 ignored = 0 new = 0 updated = 0 for device in devices_list: count += 1 if device["mac"] in ignored_macs: ignored += 1 LOGGER.debug("Ignoring '%s' as requested by the user.", device["name"]) else: c_device = context.get_value( "network.devices.{}".format(device["mac"]), None) if c_device is None: new += 1 LOGGER.debug("%s is a new device.", device["mac"]) eventbuilder.eEvent( sender_id=PLUGIN.name, keyword="network.fritzbox.newdevice.{}".format( device["name"]), data=device).trigger() _status_update(device) else: # LOGGER.debug("%s is a known device.", device["mac"]) if (int(device["status"]) is int(DEVICES_DICT[device["mac"]]["status"]) is not int(c_device["status"])): updated += 1 LOGGER.debug("Device: %d %s, Cache: %d %s, Context: %d %s", int(device["status"]), device["status"], int(DEVICES_DICT[device["mac"]]["status"]), DEVICES_DICT[device["mac"]]["status"], int(c_device["status"]), c_device["status"]) _status_update(device) # else: # status = "online" if int(device["status"]) else "offline" # LOGGER.debug("%s is still %s ('%s').", # device["mac"], status, device["status"]) DEVICES_DICT[device["mac"]] = device return("Processed {} devices in total, {} of them new. Ignored {} and " "updated {}.".format(count, new, ignored, updated))