class LocationManager(Singleton): def __init__(self): try: if self.doneloading: pass except: self.name = "Wunderground" self.doneloading = True self.settings_c = Settings() self.logging = Logging() try: self.apikey = self.settings_c.get_setting("wunderground", "apikey") self.updateperiod = int(self.settings_c.get_setting("wunderground", "updateperiod")) self.language = self.settings_c.get_setting("wunderground", "language") except Exception as e: self.logging.error("Check your wunderground settings: " + str(e), location="wunderground") self.locations = {} def GetLocation(self, location, update = False): if not update: period = self.updateperiod else: period = update if location in self.locations.keys(): return self.locations[location] else: self.locations[location] = ForecastData(self.apikey, location, update = period, language = self.language) return self.locations[location]
def receive_forever(self): """ Puts the receiver in receiving mode forever. In this mode the receiver blocks until new data is received from the sender. Every time a new chunk of data is received it calls the registered handlers' on_new_data() method. """ while True: # allow reconnecting on error try: Logging.debug("Trying to connect to %s:%s..." % (self._sender_address[0], self._sender_address[1])) with sock.create_connection(self._sender_address, timeout=30) as connection: for handler in self._connection_handlers: handler.on_new_connection(self, connection, self._sender_address) Logging.debug("Connected successfully") while True: try: Logging.info("Waiting for data...") data = self.receive(connection) Logging.info("Received data") for handler in self._data_handlers: handler.on_new_data(data) except InvalidFormatException as error: # data was not correct Logging.warning("Received data with invalid format:" " %s" % str(error)) except ConnectionAbortedError: Logging.warning("connection aborted by the sender") except sock.timeout: Logging.warning("connection timed out") except (sock.herror, sock.gaierror): Logging.error("the address of the sender is not valid") break # leave the function except ConnectionRefusedError: Logging.warning("can not reach the sender") # retry in connecting in 10 seconds Logging.debug( "connection failed: will try to connect in 10 seconds") sleep(10)
class Loader(): def __init__(self, sym, s_date, e_date, path=None): self.symbol = sym self.d_data = {} self.log = Logging() if not path: s = Symbol(sym, s_date, e_date) self.d_data[s.name] = s def get_data(self, name=None): if not name: return self.d_data elif name in self.d_data: return self.d_data[name] else: self.log.error("{} not found in loader list".format(name)) def to_csv(self, path=""): return 0 def to_pandas(self, symbol): df_s = pd.DataFrame(symbol.data) return df_s def run_all_methods(self, symbol): return 0 def data_to_csv(self, symbol): symdata = self.get_data(symbol) df_data = self.to_pandas(symdata) df_data['Date'] = pd.to_datetime(df_data['Date']) #df_data['Adj_Close'] = df_data.apply(pd.to_numeric) try: df_data = df_data.set_index('Date').sort_index() return df_data except: self.log.error("unable to format {} to csv".format(symbol))
class pf_openhab(Singleton): def __init__(self): try: if self.loadingdone: pass except: self.loadingdone = True self.logging = Logging() settings_c = Settings() self.openhab_server = settings_c.get_setting("main", "openhab_ip") self.openhab_port = settings_c.get_setting("main", "openhab_port") self.host = settings_c.get_setting("main", "hostname") self.port = settings_c.get_setting("main", "port") self.sitemap_name = settings_c.get_setting("main", "sitemap") self.sitemap_name = "main" if self.sitemap_name == None else self.sitemap_name self.resize_icons = settings_c.get_setting("main", "resize_icons") self.iconh = 64 self.iconw = 64 self.name = "pf_openhab" self.http = urllib3.PoolManager() def get_pages(self, filter): if type(filter) != list: filter = [filter] self.load_sitemap() data = [] n = 0 for i in range(len(self.sitemap["homepage"]["widgets"][0]["widgets"])): key = self.sitemap["homepage"]["widgets"][0]["widgets"][i] found = False for filt in filter: if key["label"][0:len(filt)] == filt and not found: icon_url = "/item/icon/" + key["icon"] + ".png" data.append({ "label": key["label"], "icon": icon_url, "id": n }) found = True n += 1 return data def get_page(self, name): for i in range(len(self.sitemap["homepage"]["widgets"][0]["widgets"])): key = self.sitemap["homepage"]["widgets"][0]["widgets"][i] if key["label"] == name: return key def get_items(self, pagename, subpage="none", subsubpage=0): self.load_sitemap() page = self.get_page(pagename) data = [] n_subp = 1 n = 0 page_type = [page["label"], page["icon"]] for key in page["linkedPage"]["widgets"]: n += 1 item = self.convert_item_data(key) item["id"] = item["name"] + "__" + pagename + "__" + str( subpage) + "__" + str(n) if subpage == "none" or str(subpage) == "0": if item["type"] == "Frame": item["page"] = pagename item["subpage"] = item["label"] data.append(item) elif item["type"] == "Frame" and item["label"] == subpage: page_type[0] = page_type[0] + " / " + key["label"] sub_n = 0 for k in key["widgets"]: sub_n += 1 item = self.convert_item_data(k) item["id"] = item["name"] + "__" + pagename + "__" + str( subpage) + "__" + str(sub_n) if item["type"] == "Frame": item["type"] = "Text" data.append(item) return [data, page_type] def load_sitemap(self): if self.host == None or self.openhab_server == None: #if self.openhab_server == None: data = self.load_error_sitemap(False) else: try: url = "http://" + self.openhab_server + ":" + self.openhab_port + "/rest/sitemaps/" + self.sitemap_name #print(url) content = self.http.request('GET', url) data = content.data.decode("utf-8") except: self.logging.error( "Error connecting to openHAB server, please check settings", location=self.name) data = self.load_error_sitemap(True) data = data.replace("true", "True").replace("false", "False") data = eval(data) self.sitemap = data def load_error_sitemap(self, exception): PATH = os.path.dirname(os.path.abspath(__file__)) errorfile = PATH + "/files/error_sitemap.txt" with open(errorfile, 'r') as f: data = f.read() if exception: data = data.replace("{{HOST_CONFIG_ERROR}}", "No error detected") data = data.replace("{{OPENHAB_CONFIG_ERROR}}", "Error connecting to server, check settings") else: data = data.replace("{{HOST_CONFIG_ERROR}}", "Check settings") data = data.replace("{{OPENHAB_CONFIG_ERROR}}", "Check settings") data = data.replace("{{IP}}", str(self.openhab_server)) data = data.replace("{{PORT}}", str(self.openhab_port)) data = data.replace("{{SITEMAP}}", str(self.sitemap_name)) data = data.replace("{{RESIZE}}", str(self.resize_icons)) data = data.replace("{{HOST_IP}}", str(self.host)) data = data.replace("{{HOST_PORT}}", str(self.port)) return data def get_item(self, item_name): name, pagename, subpage, n = self.split_item_name(item_name) #print(name, pagename, subpage, n) item = self.get_item_data(name, pagename, subpage, n) self.logging.debug("Item from get_item: " + str(item), location=self.name) return item def get_item_data(self, item_name, pagename, subpage, n): #search for the item self.load_sitemap() #print("Name: " + item_name) o = 1 subpage_o = 1 for i in range(len(self.sitemap["homepage"]["widgets"][0]["widgets"])): if self.sitemap["homepage"]["widgets"][0]["widgets"][i][ "label"] == pagename: for key in self.sitemap["homepage"]["widgets"][0]["widgets"][ i]["linkedPage"]["widgets"]: if key["label"].find("[") != -1: comp_label = key["label"][0:key["label"].find("[")] while comp_label[-1:] == " ": comp_label = comp_label[0:-1] else: comp_label = key["label"] try: if key["type"] == "Frame" and ( str(subpage_o) == subpage or comp_label == subpage): #print(subpage) sub_o = 0 for k in key["widgets"]: sub_o += 1 try: if k["item"][ "name"] == item_name and sub_o == n: item = self.convert_item_data(k) item["id"] = item[ "name"] + "__" + pagename + "__" + str( subpage) + "__" + str(n) item["page"] = pagename item["subpage"] = str(subpage) self.logging.debug("Item found, id: " + item["id"], location=self.name) return item except Exception as e: self.logging.warn( "Invalid item found in sitemap 2 %s" % (str(e)), location=self.name) elif "item" in key and key["item"][ "name"] == item_name and o == n: item = self.convert_item_data(key) item["id"] = item[ "name"] + "__" + pagename + "__" + str( subpage) + "__" + str(n) item["page"] = pagename item["subpage"] = str(subpage) self.logging.debug("Item found, id: " + item["id"], location=self.name) return item elif str(subpage) == "0" or subpage == "none": o += 1 elif key["type"] == "Frame": subpage_o += 1 o += 1 except Exception as e: self.logging.warn( "Invalid item found in sitemap 1: %s, %s" % (str(key), str(e)), location=self.name) def convert_item_data(self, key): #print(key) item_data = { "icon": key["icon"], "type": key["type"], "name": key["label"], "state": "" } if "item" in key: item_data.update({ "state": key["item"]["state"], "link": key["item"]["link"], "name": key["item"]["name"] }) if key["item"]["state"] != "" and key["item"]["state"].find( " ") == -1: item_data["icon"] = key["icon"] + "-" + key["item"]["state"] if "transformedState" in key["item"]: transformedState = key["item"]["transformedState"] if len(str(transformedState)) < 15: item_data.update( {"icon": key["icon"] + "-" + transformedState}) if "mappings" in key: item_data.update({"mappings": key["mappings"]}) if "label" in key: item_data.update({"label": key["label"]}) #### correct icon for state try: state = float(item_data["state"]) if state < 0.0: item_data["icon"] = key["icon"] + "-" + str(-1 * state + 100) except: if item_data["state"] == "NULL": item_data["state"] = "OFF" item_data["icon"] = key["icon"] + "-off" elif len(str(item_data["state"])) > 15: item_data["icon"] = key["icon"] #### transform state name if item_data["label"].find("[") != -1: label = item_data["label"][0:item_data["label"].find("[")] while label[-1:] == " ": label = label[0:-1] state = item_data["label"][item_data["label"].find("[") + 1:item_data["label"].find("]")] item_data.update({"state": state, "label": label}) if key["type"] == "Colorpicker": if item_data["state"].lower() != "off": item_data["state"] = self.convert_color_to_rgb( item_data["state"]) item_data["icon"] = key["icon"] + "-on" if len(item_data["state"].split(",")) > 2: if item_data["state"].split(",")[2] == "0" or item_data[ "state"].split(",")[2] == "0.0": item_data.update({ "state": "off", "icon": key["icon"] + "-off" }) elif key["type"] == "Selection": item_state = "" if len(key["mappings"]) == 1: item_data["type"] = "Switch_single" item_state = key["mappings"][0]["label"] for mapp in key["mappings"]: if mapp["command"].lower() == item_data["state"].lower(): ## mappings are like [ displayed state, actual state ] item_state = mapp["label"] elif mapp["label"].lower() == item_data["state"].lower(): item_state = mapp[ 'label'] ##sometimes a state is 0 ==> OFF, which is not mapped correctly with Off or 0 try: ##why is this????? #print(item_state) int(item_state) item_data.update({"item_state": item_data["label"]}) item_data.update({"label": "_"}) except: item_data.update({"state": item_state}) elif key["type"] == "Setpoint": try: step = round(float(key["step"]), 1) if int(step) == step: step = int(step) item_data.update({ "setpoint": [int(key["minValue"]), int(key["maxValue"]), step] }) except: pass elif key["type"] == "Slider": item_data.update({"setpoint": [0, 100, 10]}) ##update the icon to the right url: if self.resize_icons == "1": item_data["icon"] = "/item/icon/" + item_data["icon"] + ".png" else: item_data[ "icon"] = "http://" + self.openhab_server + ":" + self.openhab_port + "/icon/" + item_data[ "icon"] + ".png" return item_data def set_state(self, item_name, state): item, pagename, subpage, n = self.split_item_name(item_name) if state[0:5] == "Color": state = self.convert_color_to_hsv(state[5:]) #cmd = "curl --header \"Content-Type: text/plain\" --request POST --data \"" + state+ "\" " + self.openhab_server + ":" + self.openhab_port + "/rest/items/" + item url = "http://" + self.openhab_server + ":" + self.openhab_port + "/rest/items/" + item headers = {'Content-Type': 'text/plain'} requests.post(url, data=state, headers=headers) self.logging.info("Put state openhab: " + url + " " + str(state), location="openhab") #os.system(cmd) #print(cmd) self.load_sitemap() return self.get_item(item_name) def get_mappings(self, item_name, occurrence=1): ##self.load_sitemap() item = self.get_item(item_name) mappings = [] for mapping in item["mappings"]: mappings.append([mapping["label"], mapping["command"]]) return mappings def convert_color_to_rgb(self, color): if color == "": color = "0.0,0.0,0" color = color.split(",") color = colorsys.hsv_to_rgb( float(color[0]) / 360, float(color[1]) / 100, float(color[2]) / 100) red = hex(int(color[0] * 255))[2:] if len(red) < 2: red = "0" + red blue = hex(int(color[1] * 255))[2:] if len(blue) < 2: blue = "0" + blue green = hex(int(color[2] * 255))[2:] if len(green) < 2: green = "0" + green return "#" + red + blue + green def convert_color_to_hsv(self, color): color = colorsys.rgb_to_hsv( float(int("0x" + color[0:2], 0)) / 255.0, float(int("0x" + color[2:4], 0)) / 255.0, float(int("0x" + color[4:6], 0)) / 255.0) return str(color[0] * 360) + "," + str(color[1] * 100) + "," + str( color[2] * 100) def get_icon(self, name): URL = "http://" + self.openhab_server + ":" + self.openhab_port + "/icon/" + name response = requests.get(URL) with Image.open(BytesIO(response.content)) as image: imgByteArr = BytesIO() cover = Image.Image.resize(image, [self.iconh, self.iconw]) cover.save(imgByteArr, image.format) return imgByteArr.getvalue() def get_chart_data(self, item, period): try: p = int(period[0:len(period) - 1]) except: p = 1 if period[-1:] == "D": dt = datetime.datetime.now() - datetime.timedelta(days=p) elif period[-1:] == "H": p += 1 dt = datetime.datetime.now() - datetime.timedelta(hours=p) elif period[-1:] == "W": dt = datetime.datetime.now() - datetime.timedelta(weeks=p) elif period[-1:] == "M": dt = datetime.datetime.now() - relativedelta(months=p) start = dt.strftime("%Y-%m-%dT%H:%M:%S.000+01:00") self.logging.info("Starting date for data: " + start, location="openhab") start = start.replace("+", "%2B").replace(":", "%3A") name, pagename, subpage, n = self.split_item_name(item) URL = "http://" + self.openhab_server + ":" + self.openhab_port + "/rest/persistence/items/" + name + "?serviceId=rrd4j&starttime=" + start response = requests.get(URL) ## get item info i = self.get_item(item) if i == None: return None else: if i["icon"].lower().find("temp") != -1: typ = "temp" elif i["icon"].lower().find("humi") != -1: typ = "humi" elif i["icon"].lower().find("press") != -1: typ = "pres" elif i["icon"].lower().find("energy") != -1: typ = "watt" else: typ = "value" return {"data": response.content, "type": typ} def split_item_name(self, item_name): a = item_name.split("__") if len(a) > 1: name = a[0] pagename = a[1] subpage = a[2] n = int(a[3]) else: return item_name return name, pagename, subpage, n
class ForecastData: data = None args = None verbose = False def __init__(self, api_key, location, update=15, language="EN", fetch=False): args = {} args["apikey"] = api_key args["location"] = location args["language"] = language args["fetch"] = -1 args["sub"] = "fetch" self.args = args self.data_update = 0 self.update_time = update * 60 self.logging = Logging() self.name = "Wunderground" if fetch: self.fetch_data() def check_update(self): if time.time() - self.update_time > self.data_update: self.fetch_data() def fetch_data(self): # Grab data from Weather Underground API req = ( "http://api.wunderground.com/api/%s/conditions/alerts/forecast10day/lang:%s/q/%s.json" % (self.args["apikey"], self.args["language"], quote(self.args["location"]))) self.link = req self.logging.info("Fetching weather data from location: " + str(self.args["location"]), location=self.name) try: response = urlopen(req) except URLError as e: if hasattr(e, 'reason'): self.logging.error(e.reason, location=self.name) elif hasattr(e, 'code'): self.logging.error("Status returned: " + str(e.code), location=self.name) json_data = response.read().decode('utf-8', 'replace') data = json.loads(json_data) try: self.logging.error(data['response']['error']['description'], location=self.name) self.logging.error("Error fetching data, check settings", location=self.name) except KeyError: self.logging.info("Data fetched successfully", location=self.name) self.data = data self.data_update = time.time() def read_current(self): self.check_update() # Assign current conditions to a dictionary try: current = self.data['current_observation'] except KeyError: self.fetch_error() # Collect and merge wind data wind_dir = current['wind_dir'] wind_mph = current['wind_mph'] wind_kph = current['wind_kph'] wind_gust_mph = current['wind_gust_mph'] wind_gust_kph = current['wind_gust_kph'] wind_string_mph = (wind_dir + " " + str(float(wind_mph)) + "mph gusting to " + str(float(wind_gust_mph)) + "mph") wind_string_kph = (wind_dir + " " + str(float(wind_kph)) + "km/h gusting to " + str(float(wind_gust_kph)) + "km/h") wind = wind_dir + " " + str(float(wind_kph)) + "km/h" neerslag = current["precip_today_string"] neerslag = neerslag[neerslag.find("(") + 1:neerslag.find(")")].replace( " ", "") current_dict = { "location": current["display_location"]["full"], "city": current["display_location"]["city"], "condition": current['weather'], "n_condition": self.get_numbered_state(self.convert_icon(current['icon'], True), True), "temp_f": int(round(float(current['temp_f']))), "temp_c": "%.1f" % (float(current['temp_c'])), "humidity": current['relative_humidity'].replace("%", ""), "icon": self.convert_icon(current['icon'], True), "icon_url": current['icon_url'], "wind": wind, "wind_dir": wind_dir, "wind_mph": wind_mph, "wind_kph": wind_kph, "wind_gust_mph": wind_gust_mph, "wind_gust_kph": wind_gust_kph, "wind_string_mph": wind_string_mph, "wind_string_kph": wind_string_kph, "pressure_mb": current['pressure_mb'], "pressure_in": current['pressure_in'], "pressure_trend": current['pressure_trend'], "dewpoint_c": current['dewpoint_c'], "dewpoint_f": current['dewpoint_f'], "heat_index_c": current['heat_index_c'], "heat_index_f": current['heat_index_f'], "windchill_c": current['windchill_c'], "windchill_f": current['windchill_f'], "feelslike_c": current['feelslike_c'], "feelslike_f": current['feelslike_f'], "visibility_mi": current['visibility_mi'], "visibility_km": current['visibility_km'], "prec_hour_in": current['precip_1hr_in'], "prec_hour_cm": current['precip_1hr_metric'], "prec_day_mm": neerslag, "prec_day_cm": current['precip_today_metric'], "timezone": current['local_tz_long'], "sunset": self.get_next_sunset( current['local_tz_long'], current["display_location"]).strftime('%H:%M'), "sunrise": self.get_next_sunrise( current['local_tz_long'], current["display_location"]).strftime('%H:%M'), } return current_dict def read_forecast(self): self.check_update() # Assign forecast to a dictionary forecast_dict = [] try: forecast = self.data['forecast']['simpleforecast']['forecastday'] except KeyError: self.fetch_error() count = 1 for index, node in enumerate(forecast): d = node['date'] if str(node['qpf_allday']['mm']) == "None": node['qpf_allday']['mm'] = "-" conditions = { "day": d['weekday'], "shortdate": str(d['month']) + "/" + str(d['day']) + "/" + str(d['year']), "longdate": d['monthname'] + " " + str(d['day']) + ", " + str(d['year']), "low_f": node['low']['fahrenheit'], "low_c": node['low']['celsius'], "high_f": node['high']['fahrenheit'], "high_c": node['high']['celsius'], "avg_c": "%.0f" % ((float(node['low']['celsius']) + float(node['high']['celsius'])) / 2.0), "avg_f": "%.0f" % ((float(node['low']['fahrenheit']) + float(node['high']['fahrenheit'])) / 2.0), "icon": self.convert_icon(node['icon']), "icon_url": node['icon_url'], "condition": node['conditions'], "n_condition": self.get_numbered_state(self.convert_icon(node['icon'])), "rain_in": node['qpf_allday']['in'], "rain_mm": str(node['qpf_allday']['mm']) + "mm", "snow_in": node['snow_allday']['in'], "snow_cm": str(node['snow_allday']['cm']) + "cm", } forecast_dict.append(conditions) count += 1 return forecast_dict def read_info(self): self.check_update() try: info = self.data['current_observation'] except KeyError: self.fetch_error() info_dict = { "city": info['display_location']['city'], "postal": info['display_location']['zip'], "datetime": info['observation_time'], "location": info['display_location']['full'], "country": info['display_location']['country'], "latitude": info['display_location']['latitude'], "longitude": info['display_location']['longitude'], "elevation": info['display_location']['elevation'], "observation": info['observation_location']['full'], } return info_dict def read_alerts(self): self.check_update() alerts_dict = [] try: alerts = self.data['alerts'] except KeyError: self.fetch_error() for index, node in enumerate(alerts): a = { "start": node['date'], "expires": node['expires'], "description": node['description'], "message": node['message'], } alerts_dict.append(a) return alerts_dict def convert_icon(self, icon, current=False): self.check_update() pattern = re.compile(r'[A-Za-z]+ \d+ (.+):\d+:\d+') time_string = self.data['current_observation']['local_time_rfc822'] hour = int(pattern.search(time_string).group(1)) day_icon_dict = self.get_icons_db() night_icon_dict = self.get_icons_db(day=False) try: if (hour > 20 or hour < 6) and current is True: new_icon = night_icon_dict[icon] else: new_icon = day_icon_dict[icon] except KeyError: self.logging.error( "Icon type doesn't exist. Please report this. [%s]" % str(icon), location=self.name) new_icon = "" return new_icon def get_numbered_state(self, icon, current=False): day_icon_dict = self.get_icons_db() numbered_dict = self.get_icons_db(numbered=True) pattern = re.compile(r'[A-Za-z]+ \d+ (.+):\d+:\d+') time_string = self.data['current_observation']['local_time_rfc822'] hour = int(pattern.search(time_string).group(1)) if (hour > 20 or hour < 6) and current is True: add = 31 else: add = 1 for i in range(len(numbered_dict)): name = numbered_dict[i] if day_icon_dict[name][-1:] == icon[-1:]: return i + add return 20 + add def get_icons_db(self, day=True, numbered=False): if numbered: return [ "chancerain", "sunny", "mostlysunny", "partlycloudy", "mostlycloudy", "rain", "chancesnow", "cloudy", "tstorms", "chancetstorms", "sleet", "snow", "fog", "smoke", "hazy", "flurries", "chanceflurries", "chancesleet", "clear", "partlysunny", "unknown" ] elif day: return { "chancerain": "weather_g", "sunny": "weather_h", "mostlysunny": "weather_b", "partlycloudy": "weather_c", "mostlycloudy": "weather_d", "rain": "weather_i", "chancesnow": "weather_u", "cloudy": "weather_e", "tstorms": "weather_m", "chancetstorms": "weather_k", "sleet": "weather_j", "snow": "weather_q", "fog": "weather_f", "smoke": "weather_n", "hazy": "weather_t", "flurries": "weather_p", "chanceflurries": "weather_s", "chancesleet": "weather_o", "clear": "weather_r", "partlysunny": "weather_l", "unknown": "weather_u" } else: return { "chancerain": "weather_nt_g", "sunny": "weather_nt_a", "mostlysunny": "weather_nt_b", "partlycloudy": "weather_nt_c", "mostlycloudy": "weather_nt_d", "rain": "weather_nt_i", "chancesnow": "weather_nt_u", "cloudy": "weather_nt_e", "tstorms": "weather_nt_m", "chancetstorms": "weather_nt_k", "sleet": "weather_nt_j", "snow": "weather_nt_q", "fog": "weather_nt_f", "smoke": "weather_nt_n", "hazy": "weather_nt_t", "flurries": "weather_nt_p", "chanceflurries": "weather_nt_s", "chancesleet": "weather_nt_o", "clear": "weather_nt_r", "partlysunny": "weather_nt_l", "unknown": "weather_nt_u" } def getCondNames(self, language="EN"): if language == "EN": return [ "chancerain", "sunny", "mostlysunny", "partlycloudy", "mostlycloudy", "rain", "chancesnow", "cloudy", "tstorms", "chancetstorms", "sleet", "snow", "fog", "smoke", "hazy", "flurries", "chanceflurries", "chancesleet", "clear", "partlysunny", "unknown" ] def fetch_error(self): pass def output_data(self, parser): if self.args.sub == "current": current_dict = self.read_current() print(current_dict[self.args.current], file=sys.stdout) elif self.args.sub == "forecast": forecast_dict = self.read_forecast() self.logging.info(forecast_dict[int( self.args.day)][self.args.forecast], location=self.name) elif self.args.sub == "info": info_dict = self.read_info() print(info_dict[self.args.information], file=sys.stdout) elif self.args.sub == "alert": alerts_dict = self.read_alerts() if len(alerts_dict) < 1: print('No alerts to display') sys.exit(10) if self.args.num > len(alerts_dict): self.logging.error('Invalid alert number. Available: %s' % len(alerts_dict), location=self.name) print(alerts_dict[int(self.args.num - 1)][self.args.alert], file=sys.stdout) elif self.args.sub != "fetch": parser.print_usage() def get_next_sunrise(self, timezone, location): tz = pytz.timezone(timezone) obs = self.create_observer(location) sunrise = obs.next_rising(ephem.Sun()).datetime() return pytz.utc.localize(sunrise).astimezone(tz) def get_next_sunset(self, timezone, location): tz = pytz.timezone(timezone) obs = self.create_observer(location) sunset = obs.next_setting(ephem.Sun()).datetime() return pytz.utc.localize(sunset).astimezone(tz) def create_observer(self, loc): user = ephem.Observer() #print(loc) user.lat = loc["latitude"] user.lon = loc["longitude"] user.elevation = float(loc["elevation"]) return user
class Symbol(object): def __init__(self, symbol, s_date=None, e_date=None): self.log=Logging() self.name=symbol self.created=datetime.datetime.utcnow() self.log.info("created {}".format(self.name)) try: self.share=Share(symbol) except: self.log.error("platform is offline or not connecting") if s_date and e_date: self.begin=s_date self.end=e_date try: self.share=Share(symbol) self.data=self.share.get_historical(self.begin, self.end) self.log.refresh("{} data collected".format(self.name)) except: self.log.error("platform is offline or not connecting") def refresh_data(self, s_date=None, e_date=None): if s_date and e_date: try: share=Share(self.name) self.begin=s_date self.end=e_date share.get_historical(s_date, e_date) self.log.refresh("{} data collected".format(self.name)) except: self.log.error("platform is offline or not connecting") def market_cap(self): try: self.market_cap = self.share.get_market_cap() self.log.info("{} market cap refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting") def earnings_per_share(self): try: self.eps = self.share.get_earnings_share() self.log.info("{} eps refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting") def moving_average_50(self): try: self.moving_average_50 = self.share.get_50day_moving_average() self.log.info("{} 50 day moving ave refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting") #implement TODO def nday_moving_average(self, n): try: self.moving_average_n = None self.log.info("{} {} day moving ave refreshed".format(self.name, n)) except: self.log.error("platform is offline or not connecting") def price_earnings_ratio(self): try: self.price_to_earnings = self.share.get_price_earnings_ratio() self.log.info("{} price to earnings refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting") def book_value(self): try: self.book = self.share.get_price_book() self.log.info("{} book value refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting") def year_high(self): try: self.year_high = self.share.get_change_from_year_high() self.log.info("{} year high change refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting") def year_low(self): try: self.year_low = self.share.get_change_from_year_low() self.log.info("{} year low change refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting") def target_price(self): try: self.year_target = self.share.get_change_from_year_high() self.log.info("{} year target change refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting") def year_range(self): try: self.year_range = self.share.get_change_from_year_high() self.log.info("{} year range change refreshed".format(self.name)) except: self.log.error("platform is offline or not connecting")
class setting_handler(Singleton): def __init__(self): try: if self.loadingdone: pass except: self.loadingdone = True self.name = "setting_handler" self.database = main_database() self.logging = Logging() self.http = urllib3.PoolManager() self.settings = {} #self.settings["main_page"] = ["Front page", ["OpenHAB", "Weather"]] self.settings["screen_timeout"] = [ "Screen timeout (min)", [1, 3, 5, 10, 15, 30, "off"] ] self.settings["album_timeout"] = [ "Album timeout (hr)", [1, 3, 5, 10, 15, 30] ] self.settings["message_timeout"] = [ "Message timeout (s)", [10, 30, 60, 120, 300] ] self.settings["toast_timeout"] = [ "Info timeout (s)", [7, 10, 15, 20, 30] ] self.settings["mouse"] = ["Mouse button", ["on", "off"]] self.settings["items_per_page"] = [ "Number of items per page", [6, 8, 9, 12] ] self.settings["sensors_per_page"] = [ "Number of sensor items per page", [6, 8, 9, 12] ] self.settings["screen"] = ["Screen", ["on", "off"]] self.settings["frame"] = ["Photo / Clock", ["photoframe", "clock"]] self.settings["frame_info"] = [ "Frame Info", ["none", "load", "album", "both"] ] self.settings["frame_td"] = [ "Frame Time/Date", ["none", "clock", "date", "both"] ] self.settings["frame_display_time"] = [ "Photo display time", ["short", "medium", "long", "extra long"] ] self.settings["clock_type"] = ["Clock type", ["digital", "analog"]] self.settings["chart_period"] = [ "Default chart period", ["auto", "4 hours", "12 hours", "1 day", "3 days", "1 week"] ] for key, item in self.settings.items(): value = self.database.data["settings"][key] self.settings[key].append(int(value)) settings_c = Settings() self.enable_screen_control = settings_c.get_setting( "main", "enable_screen_control") try: topics = settings_c.get_setting( "main", "mqtt_control_topic").split(",") self.mqtt = mqtt() for topic in topics: self.mqtt.add_listener(topic, self, "received_mqtt_message") except: self.logging.warn("Mqtt not configured for handling settings", location="settings_handler") if self.enable_screen_control in ["pi", "black"]: pass elif self.enable_screen_control == "url": try: self.screen_control_on_url = settings_c.get_setting( "main", "screen_on_url") self.screen_control_off_url = settings_c.get_setting( "main", "screen_off_url") self.settings["screen_control_on_url"] = [ 0, 0, self.screen_control_on_url ] self.settings["screen_control_off_url"] = [ 0, 0, self.screen_control_off_url ] except: self.logging.error( "Add settings 'screen_on_url' and 'screen_off_url' for external url screen control", location="settings_handler") self.enable_screen_control = "black" elif self.enable_screen_control == "cmd": try: self.screen_control_on_cmd = settings_c.get_setting( "main", "screen_on_cmd") self.screen_control_off_cmd = settings_c.get_setting( "main", "screen_off_cmd") self.settings["screen_control_on_cmd"] = [ 0, 0, self.screen_control_on_cmd ] self.settings["screen_control_off_cmd"] = [ 0, 0, self.screen_control_off_cmd ] except: self.logging.error( "Add settings 'screen_on_cmd' and 'screen_off_cmd' for external command screen control", location="settings_handler") self.enable_screen_control = "black" elif self.enable_screen_control != "off": self.logging.error( "Incorrect screen control enable settings, screen control is off", location="settings_handler") self.enable_screen_control = "off" self.settings["main_enable_clock"] = [ 0, 0, settings_c.get_setting("main", "enable_clock") ] self.settings["main_enable_album"] = [ 0, 0, settings_c.get_setting("main", "enable_album") ] if settings_c.get_setting("main", "enable_album") == "0": self.logging.warn("Album not enabled, setting frame to clock", location="settings_handler") self.__set_setting("frame", "clock") elif settings_c.get_setting("main", "enable_clock") == "0": self.logging.warn( "clock not enabled, setting frame to photoframe", location="settings_handler") self.__set_setting("frame", "photoframe") if settings_c.get_setting( "main", "enable_clock") == "0" and settings_c.get_setting( "main", "enable_album") == "0": self.logging.warn( "Album and clock not enabled, turning off screen setting", location="settings_handler") self.__set_setting( "screen", "off" ) ##in this case only the screensaver determines if the screen is turned on or off self.settings["main_screen_control"] = [ 0, 0, self.enable_screen_control ] def get_name(self): return self.name def setting_request(self, request): if request[0] == "setsetting": setting = request[1] if setting == "screen" and self.get_setting( "main_enable_album") == "0" and self.get_setting( "main_enable_clock") == "0": return [ "Enable album or clock to be able to control this setting" ] if setting == "frame" and ( self.get_setting("main_enable_album") == "0" or self.get_setting("main_enable_clock") == "0"): return [ "Enable album and clock to be able to control this setting" ] cur_value = self.settings[setting][2] if cur_value + 1 < len(self.settings[setting][1]): self.settings[setting][2] = cur_value + 1 else: self.settings[setting][2] = 0 self.save_settings() self.logging.write( self.settings[setting][0] + ": " + str(self.settings[setting][1][self.settings[setting][2]]), level=2) return [ self.settings[setting][0] + ": " + str(self.settings[setting][1][self.settings[setting][2]]) ] elif request[0] == "getsetting": return [str(self.get_setting(request[1]))] def set_setting(self, setting, value): if setting == "screen" and self.get_setting( "main_enable_album") == "0" and self.get_setting( "main_enable_clock") == "0": return ["Enable album or clock to be able to control this setting"] if setting == "frame" and (self.get_setting("main_enable_album") == "0" or self.get_setting("main_enable_clock") == "0"): return [ "Enable album and clock to be able to control this setting" ] self.__set_setting(setting, value) def __set_setting(self, setting, value): values = self.settings[setting][1] self.screen_timeout_start = time.time() for i in range(len(values)): if values[i] == value: self.settings[setting][2] = i self.save_settings() def get_settings(self): settings = [] for key, item in self.settings.items(): if (key == "clock_type" ) and self.get_setting("main_enable_clock") == "0": pass elif (key == "album_timeout" or key == "frame_info" or key == "frame_td" or key == "frame_display_time" ) and self.get_setting("main_enable_album") == "0": pass elif key == "frame" and ( self.get_setting("main_enable_album") == "0" or self.get_setting("main_enable_clock") == "0"): pass elif key == "screen" and self.get_setting( "main_enable_album") == "0" and self.get_setting( "main_enable_clock") == "0": pass elif key == "screen" and self.enable_screen_control == "off": pass elif item[0] != 0: settings.append([key, item[0], item[1][item[2]]]) return settings def save_settings(self): for key, item in self.settings.items(): self.database.data["settings"][key] = item[2] self.database.save_datafile() def get_setting(self, setting): value = self.settings[setting][2] if self.settings[setting][0] != 0: return self.translate_setting(setting, self.settings[setting][1][value]) else: return value def translate_setting(self, setting, value): if setting == "frame_display_time": timing = { "short": 5000, "medium": 13000, "long": 20000, "extra long": 60000 } if value == 0: return "short" return timing[value] elif setting == "chart_period": period = { "auto": "auto", "4 hours": "4H", "12 hours": "12H", "1 day": "1D", "3 days": "3D", "1 week": "1W" } if value == 0: return "auto" return period[value] return value def received_mqtt_message(self, topic, payload): try: payload_setting = payload['setting'] for setting in self.settings: if setting == payload_setting: if "cmd" in topic.lower(): self.set_setting(setting, payload[setting]) self.logging.info( "Set setting via mqtt message: %s, %s" % (setting, payload[setting]), location="settings_handler") elif "state" in topic.lower(): val = self.get_setting(setting) topic = topic[0:topic.rfind("/") + 1] + "status" self.mqtt.publish( topic, str({ 'setting': setting, 'value': val })) if payload_setting == "all": topic = topic[0:topic.rfind("/") + 1] + "status" self.mqtt.publish(topic, str(list(self.settings.keys()))) except Exception as e: raise Exception(e)
class widgets_handler: def __init__(self): self.openhab = pf_openhab() self.logging = Logging() self.name = "widget_handler" PATH = os.path.dirname(os.path.abspath(__file__)) self.template_dir = PATH + "/../templates/" self.imported_widget_classes = {} def render_widget(self, page, lowerpage): w_info = self.get_widget_info(lowerpage, main_page=page) data = self.openhab.get_items(page, lowerpage) item_data = self.render_item_data_for_widget(data[0]) try: item_data = self.get_widget_data(w_info, item_data) if "error" in item_data: return render_template("error.html", data=item_data) except Exception as e: self.logging.error("Error creating widget %s" % str(e), location=self.name) er = self.render_widget_error(e, lowerpage) return render_template("error.html", data={"error": str(er)}) item_data["gen_name"] = w_info["name"] item_data["pagename"] = page try: self.logging.debug("Rendering widget: %s" % w_info["template"], location=self.name) return render_template("widgets/%s.html" % w_info["template"].lower(), data=item_data) except Exception as e: self.logging.error("Error creating widget %s" % str(e), location=self.name) er = self.render_widget_error(e, lowerpage) return render_template("error.html", data={"error": str(er)}) def create_mainpage_popup(self, page, subpage, menuwidget=False): if page == "none": ##in case the widget is on the main page data = self.openhab.get_items(subpage, page) else: data = self.openhab.get_items(page, subpage) item_data = self.render_item_data_for_widget(data[0]) if len(item_data) == 0: #return "widget not in sitemap" self.logging.error("Widget is not in sitemap", location=self.name) er = self.render_widget_error("widget not in sitemap", subpage) return render_template("popups/error.html", data={"error": str(er)}) info = self.get_widget_info(subpage, main_page=page) try: item_data = self.get_widget_data(info, item_data) if "error" in item_data: return render_template("popups/error.html", data=item_data) except Exception as e: self.logging.error("Error creating widget %s" % str(e), location=self.name) er = self.render_widget_error(e, subpage) if menuwidget: return render_template("popups/error.html", data={"error": str(er)}), "Error" else: return render_template("popups/error.html", data={"error": str(er)}) item_data["page_name"] = page item_data["widget_name"] = subpage item_data["menuwidget"] = menuwidget if info == None: return render_template( "popups/error.html", data={ "error": "Popup widget template for %s does not exist" % subpage.lower() }) elif info["template"] == "generic_button_page": return info["template"] else: try: self.logging.debug("Rendering popup widget: %s" % info["template"], location=self.name) data = render_template("popup_widgets/" + info["template"] + ".html", data=item_data) if menuwidget: title = self.find_var(data, "Title") if title == None: title = "" return data, title else: return data except Exception as e: self.logging.error("Error creating popup widget %s" % str(e), location=self.name) er = self.render_widget_error(e, subpage) if menuwidget: return render_template("popups/error.html", data={"error": str(er)}), "Error" else: return render_template("popups/error.html", data={"error": str(er)}) def get_widget_data(self, w_info, item_data): if w_info["name"] not in self.imported_widget_classes: try: a = __import__(w_info["name"] + "_widget") self.imported_widget_classes[w_info["name"]] = getattr( a, w_info["name"] + "_widget")() except Exception as e: self.logging.warn("Could not create widget %s" % str(e), location=self.name) self.logging.warn("Could not create widget %s" % str(w_info["name"]), location=self.name) self.logging.warn("Importing normal widget", location=self.name) a = __import__("widget") self.imported_widget_classes[w_info["name"]] = a.widget() cl = self.imported_widget_classes[w_info["name"]] item_data = cl.get_data(item_data) return item_data def check_widget_type(self, name): if name[0:2] == "m_": return "menu_button" if name[0:2] in ["a_"]: return "menu_popup" if name[0:2] in ["b_"]: return "widget_popup" if name[0:2] in ["c_"]: return "widget_subpage" if name[0:2] == "s_": info = self.get_widget_info(name) return "widget_" + str(info["rows"]) else: return name def get_widget_label(self, name): for n in ["b_"]: if name.find(n) != -1: return name[name.find(n) + 2:] if name.find("[") != -1 and name.find("]") != -1: name = name[name.find("[") + 1:name.find("]")] return name for n in ["m_", "a_", "b_", "c_", "d_"]: if name.find("/ " + n) != -1: return name[name.find("/ " + n) + 4:] if name.find(n) != -1: return name[name.find(n) + 2:] i = self.get_widget_info(name) if i == None: return name else: return i["name"] def get_widget_info(self, name, main_page="none"): ## s_ frontpage widget with possible popup widget ## a_ generic button page (with large button on frontpage ## b_ bottom page ## c_ popup widget with button ## d_ popup widget with button ## m_ generic button linking to a page instead of popup widget_data = {} widget_data["a_"] = { "type": "popup_widget", "name": name[2:], "template": "generic_button_page" } if name[0:2] in widget_data: return widget_data[name[0:2]] else: ##try to find the info from the widget template data = "_" name_lower = name[2:].lower() if name[0:2] == "s_": ##widget f_name = self.template_dir + "widgets/" + name_lower + ".html" if Path(f_name).is_file(): with open(f_name, 'r') as myfile: data = myfile.read().replace('\n', '') n = self.find_var(data, "Name") rows = self.find_var(data, "Rows") title = self.find_var(data, "Title") if rows != None and n != None: return { "title": title, "name": n, "rows": int(rows), "template": name_lower, "type": "frontpage_widget", "pagename": main_page } else: ##popup f_name = self.template_dir + "popup_widgets/" + name_lower + ".html" if Path(f_name).is_file(): with open(f_name, 'r') as myfile: data = myfile.read().replace('\n', '') n = self.find_var(data, "Name") if n != None: return { "name": n, "template": name_lower, "type": "popup_widget", "pagename": main_page } return None def find_var(self, data, var): if data.find(var + "=") != -1: pos = data.find(var + "=") pos2 = data[pos + len(var) + 1:].find("/") return data[pos + len(var) + 1:pos + len(var) + 1 + pos2] else: return None def render_item_data_for_widget(self, data): d = {} for dat in data: dat["state_length"] = len(dat["state"]) d[dat["label"].lower()] = dat return d def render_widget_error(self, e, w): e = str(e) if e.find("attribute") != -1: pos = e.find("attribute") n = e[pos + 10:] return "Please add an item labeled %s to the widget named %s" % ( n, str(w)) else: return "Widget: " + str(w) + " " + str(e)
class mqtt(Singleton): def __init__(self): try: if self.loadingdone: pass except: self.loadingdone = True self.started = True self.logging = Logging() self.name = "mqtt" self.settings_c = Settings() try: self.server = self.settings_c.get_setting("mqtt", "server") self.port = int(self.settings_c.get_setting("mqtt", "port")) self.timeout = int( self.settings_c.get_setting("mqtt", "timeout")) except Exception as e: self.logging.error("Configuration not correct, check settings", location=self.name) self.listeners = [] self.client = mqtt_cl.Client() self.client.on_connect = self.on_connect self.client.on_message = self.on_message self.client.connect(self.server, self.port, self.timeout) self.client.loop_start() self.logging.info("Connected to mqtt broker at: " + self.server, location=self.name) def on_connect(self, client, userdata, flags, rc): self.logging.info("Resubscribing for all listeners at " + self.server, location=self.name) for listen in self.listeners: self.client.subscribe(listen[0]) def on_message(self, client, userdata, msg): self.logging.info("Received message: " + msg.topic + " " + str(msg.payload), location=self.name) if self.started: for listen in self.listeners: topic = listen[0][0:-1] if msg.topic.find(topic) != -1: self.logging.debug("Topic match for %s at %s" % (listen[1].get_name(), listen[0]), location=self.name) try: data = ast.literal_eval(msg.payload.decode("utf-8")) except: data = msg.payload.decode("utf-8") try: p = getattr(listen[1], listen[2]) p(msg.topic, data) except Exception as e: self.logging.error("Error executing: " + str(e), location=self.name) def add_listener(self, topic, class_item, functionname): self.listeners.append([topic, class_item, functionname]) self.client.subscribe(topic) try: name = class_item.get_name() except: name = "unknown" self.logging.info("Added listener for %s at %s" % (name, topic), location=self.name) def publish(self, topic, payload): self.logging.info("Publish %s, %s " % (topic, str(payload)), location=self.name) self.client.publish(topic, payload)
from logger import Logging from symbol import Symbol from loader import Loader print "***** logging test *****" l = Logging() l.error("missing symbol") l.info("missing symbol") l.refresh("missing symbol") l.buy("missing symbol") l.profit("missing symbol") l.terminate("missing symbol") print "***** symbol test *****" s = Symbol('AMD') s.market_cap() print s.market_cap s.earnings_per_share() print s.eps print "***** loader test *****" load = Loader('AMD', '2016-11-01', '2016-11-21') amd = load.get_data('AMD') amd.book_value() print amd.book print load.data_to_csv('AMD')
class message_handler(Singleton): def __init__(self): try: if self.loadingdone: pass except: self.loadingdone = True self.database = main_database() self.popupflag = False self.popupactive = False self.logging = Logging() self.setting_handler = setting_handler() self.setting_popup_timeout = self.setting_handler.get_setting( "message_timeout") self.page_handler = page_handler.page_handler() self.toast_flag = False self.toast_db = [] self.toast_message = "none" self.toast_sender = "none" self.toast_received = 0 self.mqtt = mqtt() settings_c = Settings() self.mqtt_topics = settings_c.get_setting("messaging", "mqtt_topics").split(",") for topic in self.mqtt_topics: self.mqtt.add_listener(topic, self, "received_mqtt_message") ##send information messages on first run if not self.database.data["settings"]["first_run_messages_flag"]: self.database.data["settings"][ "first_run_messages_flag"] = True message = "On a black screen, clock or photoframe, click on the bottom left corner to return to the main screen. " self.database.data["messages"].append([ time.time(), "HABframe", "Return from screensaver", message, False ]) message = "Thank you for using HABframe!" self.database.data["messages"].append([ time.time(), "HABframe", "welcome message", message, False ]) self.database.save_datafile() self.del_popup_flag() def get_name(self): return "message_handler" def message_request(self, request, data_get): if request[0] == "new": try: if "message" in data_get: message = data_get["message"].replace("@20", "/").replace( "%3B", ":") else: message = request[2].replace("@20", "/").replace("%3B", ":") if "sender" in data_get: sender = data_get["sender"] else: sender = request[1] if "subject" in data_get: subject = data_get["subject"] else: subject = "-" self.new_message(sender, subject, message) return ["Message received"] except Exception as e: self.logging.error("Error in message: " + str(e), location="messages") return ["Invalid new message"] elif request[0] == "message_popup": i = 0 found = False while i < len(self.database.data["messages"]) and not found: message = self.database.data["messages"][i] if not message[-1]: show_message = [i] + message #we want the last unread message #found = True i += 1 n_unread = self.check_amount_unread() times = datetime.datetime.fromtimestamp(float( show_message[1])).strftime('%a %d-%m, %H:%M') return self.page_handler.create_popup("message", { "id": show_message[0], "from": show_message[2], "time": times, "message": show_message[4], "subject": show_message[3], "n_unread": n_unread }, renew_screensaver=False) elif request[0] == "markread_popup": message_id = int(request[1]) self.logging.info("Marking message as read " + str(message_id), location="messages") self.database.data["messages"][message_id][-1] = True self.database.save_datafile() self.popupactive = False self.del_popup_flag() return ["Marked as read"] elif request[0] == "markallread_popup": message_id = int(request[1]) self.logging.info("Marking all messages as read ", location="messages") for i in range(len(self.database.data["messages"])): self.database.data["messages"][i][-1] = True self.database.save_datafile() self.popupactive = False self.del_popup_flag() return ["Marked as read"] elif request[0] == "message_timeout": timeout = self.setting_handler.get_setting("message_timeout") return [str(timeout)] elif request[0] == "toast_timeout": timeout = self.setting_handler.get_setting("toast_timeout") return [str(timeout)] elif request[0] == "delete_popup": message_id = int(request[1]) del (self.database.data["messages"][message_id]) self.logging.info("Deleting message: " + str(message_id), location="messages") if len(self.database.data["messages"]) == 0: self.database.data["messages"] = [] #self.database.data["messages"].append([time.time(), "none", "message database is empty", True]) self.database.save_datafile() self.popupactive = False self.del_popup_flag() return ["Message deleted"] elif request[0] == "deactivate_popup": self.popupactive = False return ["popup deactive"] elif request[0] == "showmessage": message_id = int(request[1]) return self.format_message(message_id=message_id) elif request[0] == "deletemessage": if request[1] == "all": self.database.data["messages"] = [] #self.database.data["messages"].append([time.time(), "none", "message database is empty", True]) else: message_id = int(request[1]) del (self.database.data["messages"][message_id]) self.logging.info("Deleting message: " + str(message_id), location="messages") if len(self.database.data["messages"]) == 0: self.database.data["messages"] = [] #self.database.data["messages"].append([time.time(), "none", "message database is empty", True]) self.database.save_datafile() return self.format_message_list(start=0) elif request[0] == "showmessagepage": message_id = int(request[1]) return self.format_message_list(start=message_id) elif request[0] == "toast": if "message" in data_get: self.toast_message = data_get["message"].replace( "@20", "/").replace("%3B", ":") else: self.toast_message = request[2].replace("@20", "/").replace( "%3B", ":") if "sender" in data_get: self.toast_sender = data_get["sender"].replace("@20", "/").replace( "%3B", ":") else: self.toast_sender = request[1].replace("@20", "/").replace( "%3B", ":") self.logging.debug("Received new toast message from http", location="messages") self.new_toast() return ["Toast received"] elif request[0] == "get_toast": return self.create_toast(len_max=31) def new_message(self, sender, subject, message): self.database.data["messages"].append( [time.time(), sender, subject, message, False]) self.database.save_datafile() self.del_popup_flag() ##popup flag when a popup was activated self.logging.write("Received new message from " + sender + ": " + message, level="info", location="messages") def new_toast(self): self.toast_received = time.time() self.toast_db.append( [self.toast_sender, self.toast_message, time.time(), False, 0]) self.logging.info("Received new toast message: " + self.toast_message, location="messages") def create_toast(self, len_max): toast = self.get_toast_message() data = { "text": toast[0], "from": toast[1], "len": len(toast[0]), "max": len_max } return self.page_handler.create_popup("toast", data=data, renew_screensaver=False) def get_messages(self): messages = [] for i in reversed(range(len(self.database.data["messages"]))): m = self.database.data["messages"][i] messages.append({ "id": i, "date": m[0], "from": m[1], "subject": m[2], "message": m[3] }) return messages def check_amount_unread(self): unread = 0 for message in self.database.data["messages"]: if not message[-1]: unread += 1 return unread def check_unread(self): unread = False for message in self.database.data["messages"]: if not message[-1]: unread = True return unread def get_popup_flag( self ): ##The popup flag is set when a new message has generated a popup return self.popupflag def set_popup_flag(self): self.logging.write("Setting popup flag", level="warn", location="messages") self.popupflag = True def del_popup_flag(self): ##Only a new message can delete a popup if self.popupflag: self.logging.write("Removing popup flag", level="warn", location="messages") self.popupflag = False def get_popup_active(self): if time.time( ) > self.popup_time_activated + self.setting_popup_timeout + 1: ##seconds return False else: return True def set_popup_active(self, state): self.popup_time_activated = time.time() def check_toast(self): #print("=========================, checking toast") timeout = self.setting_handler.get_setting("toast_timeout") new_toast = False last_toast_send = 0 for i in range(len(self.toast_db)): if self.toast_db[i][3]: last_toast_send = self.toast_db[i][4] if self.toast_db[i][2] < time.time() - 600: self.toast_db[i][3] = True if not self.toast_db[i][3]: new_toast = True if len(self.toast_db) > 50: del self.toast_db[0:25] if self.toast_received > time.time( ) - 600 and new_toast and last_toast_send < time.time() - timeout - 3: return True else: return False def get_toast_message(self): ##return the first unread toast message for i in range(len(self.toast_db)): if not self.toast_db[i][3]: ##toast is unread self.toast_db[i][3] = True self.toast_db[i][4] = time.time() self.logging.write("Sending toast message: " + self.toast_db[i][0] + " / " + self.toast_db[i][1], level=2, location="messages") return [self.toast_db[i][1], self.toast_db[i][0]] self.logging.write("No unread toast message, sending last one: " + self.toast_message + " / " + self.toast_sender, level="warning", location="messages") return [self.toast_message, self.toast_sender] def format_message_list(self, start=0): messages = self.get_messages() page_data = {"next_page": False, "prev_page": False, "messages": []} try: start_page = int(start) except: start_page = 0 if start_page == 0: start_message = 0 stop_message = 6 else: page_data["prev_page"] = start_page start_message = start_page * 5 + 1 stop_message = start_page * 5 + 6 n_messages = len(messages) if stop_message >= n_messages: stop_message = n_messages else: page_data["next_page"] = start_page + 1 for i in range(start_message, stop_message): messages[i]["date"] = datetime.datetime.fromtimestamp( messages[i]["date"]).strftime('%a %d-%m, %H:%M') page_data["messages"].append(messages[i]) return render_template("message_list.html", data=page_data) def format_message(self, message_id=0): messages = self.get_messages() if message_id == -1: message_id = len(messages) - 1 if len(messages) > 0: for m in messages: if m["id"] == message_id: message = m message["date"] = datetime.datetime.fromtimestamp( message["date"]).strftime('%a %d-%m, %H:%M') else: message = {"date": "", "message": "No messages", "from": ""} if len(messages) > 0 and message["subject"] == "-": message["subject"] = message["date"] return render_template("message.html", data=message) def received_mqtt_message(self, topic, payload): try: message = payload['message'] if "message" in topic.lower(): t = "message" elif "toast" in topic.lower(): t = "toast" else: try: t = payload['type'] except: t = 'message' try: sender = payload['sender'] except: sender = "unknown" if t == "message": subject = payload['subject'] self.new_message(sender, subject, message) else: self.toast_sender = sender self.toast_message = message self.new_toast() except Exception as e: raise Exception(e)
class state_handler(Singleton): def __init__(self): try: if self.loadingdone: pass except: self.loadingdone = True self.openhab = pf_openhab() self.name = "state_handler" self.database = main_database() self.setting_handler = setting_handler() self.message_handler = message_handler() self.logging = Logging() settings_c = Settings() self.host = settings_c.get_setting("main", "hostname") self.port = settings_c.get_setting("main", "port") self.http = urllib3.PoolManager() self.timeouts = {} self.update_timeout("screensaver", 60) self.update_timeout("message", -1) self.screentrigger = 0 self.screen_state = True try: self.im_size = settings_c.get_setting("album", "image_size") self.album_url = settings_c.get_setting("album", "random_picture_url") except Exception as e: self.logging.error("Invalid album settings: " + str(e), location=self.name) self.album_url = "none" try: self.album_info_url = settings_c.get_setting("album", "picture_info_url") if self.album_info_url == None: raise Exception("No data") except: self.logging.warn("No album info url", location=self.name) self.album_info_url = "none" def state_request(self, request): action = request[0] if len(request) > 1: item = request[1] ##handle a button press per type of item: #print(item) if action == "photoframe": if item == "frame": ans = self.setting_handler.set_setting("frame", request[2]) if ans != None: return ans[0] return "Setting saved" elif item == "screen": ans = self.setting_handler.set_setting("screen", request[2]) if ans != None: return ans[0] return "Setting saved" elif item == "trigger": self.screentrigger = time.time() self.refresh_screensaver() self.logging.info("Triggered frame on externally", location=self.name) return "Screen triggered" else: return "none_none" elif action == "icon": icon = self.openhab.get_icon(item) return ["jpg", icon] elif action == "picture": try: if item == "new" and self.album_url != "none": response = requests.get(self.album_url) with Image.open(BytesIO(response.content)) as image: imgByteArr = BytesIO() cover = Image.Image.resize(image, [int(self.im_size.split("x")[0]), int(self.im_size.split("x")[1])]) cover.save(imgByteArr, image.format) return ["jpg", imgByteArr.getvalue()] elif item == "info" and self.album_info_url != "none" and self.album_info_url != "": content = self.http.request('GET', self.album_info_url) return content.data.decode("utf-8") elif item == "info": return "no album info" except Exception as e: self.logging.error("Error occured in processing picture for album %s" %e, location=self.name) return "error" def state_check(self, request): page = [] main_page = request[0] subpage = "none" if len(request) > 1: subpage = request[1] ## get used settings setting_album_timeout = self.setting_handler.get_setting("album_timeout") ##not used setting_popup_timeout = self.setting_handler.get_setting("message_timeout") setting_screen_user = self.setting_handler.get_setting("screen") ##screen on or off main_setting_screen_control = self.setting_handler.get_setting("main_screen_control") current_screen_state = self.get_screen_state() screensaver_page = self.get_screensaver_page() desired_screen_state = "off" desired_page = "unchanged" ##reset old screen trigger if self.screentrigger != 0 and time.time() > self.screentrigger + 5*60: self.screentrigger = 0 ##calculate desired screen state (on / off) ##switching is done depending on configuration if main_page in ["main", "settings", "messages"]: if self.check_timeout("screensaver") and setting_screen_user == "off": desired_screen_state = "off" else: desired_screen_state = "on" elif main_page in ["photoframe", "clock", "black"]: desired_screen_state = setting_screen_user ## check desired screen state for messages self.logging.debug("Unread messages: %s" %(str(self.message_handler.check_unread())), location=self.name) self.logging.debug("Popup flag: %s" %(str(self.message_handler.get_popup_flag())), location=self.name) if self.message_handler.check_unread() and not self.message_handler.get_popup_flag(): self.message_handler.set_popup_active(True) self.message_handler.set_popup_flag() self.logging.info("responding new message", location=self.name) desired_screen_state = "on" new_message = True ###turn on screen and make popup elif not self.check_timeout("message"): desired_screen_state = "on" ##keep screen on for message new_message = False else: new_message = False ##calculate desired page (main, black, album or clock) ##switching is done depending on configuration if main_page in ["main", "settings", "messages"]: if self.check_timeout("screensaver") and setting_screen_user == "on" and screensaver_page != "main": desired_page = screensaver_page elif main_page == "photoframe" and screensaver_page != "album": desired_page = screensaver_page elif main_page == "clock" and screensaver_page != "clock": desired_page = screensaver_page elif main_page == "black" and setting_screen_user == "on": desired_page = screensaver_page self.logging.debug("Show new messages: %s" %(str(new_message)), location=self.name) self.logging.debug("Screensaver page: %s" %(screensaver_page), location=self.name) self.logging.debug("Desired page: %s, desired_screen_state: %s" %(desired_page, desired_screen_state), location=self.name) self.logging.debug("Message timeout: %s, Subpage timeout: %s" %(self.check_timeout("message"), self.check_timeout("screensaver_subpage")), location=self.name) ## switch screen off is desired state is off if desired_screen_state == "off" and main_setting_screen_control != "off" and current_screen_state: ##=="on" return self.switch_off_screen(main_setting_screen_control) elif desired_screen_state == "off" and current_screen_state: ##=="on" link = self.get_desired_page_link("clock") return [link] elif self.screentrigger != 0: self.toggle_screen(state = True) self.screentrigger = 0 self.refresh_screensaver() self.logging.info("turn on screen for trigger", location=self.name) return ["close_return_main"] ##actions when we want the screen on elif new_message: if not current_screen_state: self.toggle_screen(state = "on") ##no need for a page change self.update_timeout("message", self.setting_handler.get_setting("message_timeout") + 2) ##in seconds return ["new_message"] elif self.message_handler.check_toast(): ##even if the screen is off self.logging.write("responding new toast message", level=2, location="item_handle") return ["new_toast"] elif desired_screen_state == "on" and desired_page != "unchanged" and self.check_timeout("message"): ##except when there is a message popup self.toggle_screen(state = setting_screen_user) link = self.get_desired_page_link(desired_page) return [link] elif self.check_timeout("screensaver_subpage") and self.check_timeout("message") and main_page not in ["photoframe", "clock"]: ##except when there is a message popup self.delete_timeout("screensaver_subpage") return ["close_return_main"] elif self.check_timeout("screensaver_subpage") and self.check_timeout("message"): self.delete_timeout("screensaver_subpage") ##if for some reason it end here; return ["no_actionHERE"] def switch_off_screen(self, main_setting_screen_control): self.toggle_screen(state = "off") if main_setting_screen_control == "black": link = self.get_desired_page_link("black") return [link] else: link = self.get_desired_page_link("main") return [link] def get_screensaver_page(self): enable_clock = self.setting_handler.get_setting("main_enable_clock") enable_album = self.setting_handler.get_setting("main_enable_album") setting_album_clock = self.setting_handler.get_setting("frame") ##photoframe or clock when screen is on if enable_album == "1" and setting_album_clock == "photoframe": return "album" elif enable_clock == "1" and setting_album_clock == "clock": return "clock" else: return "main" def get_desired_page_link(self, page): if page == "album": self.logging.info("http://"+self.host+":"+self.port+"/page/photoframe", location=self.name) return "http://"+self.host+":"+self.port+"/page/photoframe" elif page == "clock": type_clock = self.setting_handler.get_setting("clock_type") self.logging.info("http://"+self.host+":"+self.port+"/page/clock/"+type_clock, location=self.name) return "http://"+self.host+":"+self.port+"/page/clock/"+type_clock elif page == "main": main_setting_screen_control = self.setting_handler.enable_screen_control self.logging.info("External screen control: %s, no action, stay on main page" %main_setting_screen_control, location=self.name) return "http://"+self.host+":"+self.port+"/page/maindiv/screensaver" elif page == "black": self.logging.write("http://"+self.host+":"+self.port+"/black", level=2) return "http://"+self.host+":"+self.port+"/page/black" def update_timeout(self, name, delta): ##delta in seconds self.timeouts[name] = time.time() + delta def check_timeout(self, name): if name in self.timeouts: self.logging.debug(("Timeout %s: "%name).ljust(30) + str(time.ctime(int(self.timeouts[name]))), location=self.name) if self.timeouts[name] < time.time(): return True else: return False else: return False def delete_timeout(self, name): if name in self.timeouts: del self.timeouts[name] else: self.logging.debug("Timeout %s not deleted, not existing" %name, location=self.name) def refresh_screensaver(self): to = self.setting_handler.get_setting("screen_timeout") if to == "off": to = 24*60*300 self.logging.info("refreshing screensaver", location=self.name) self.update_timeout("screensaver", int(to)*60) self.delete_timeout("screensaver_subpage") def refresh_screensaver_subpage(self): self.refresh_screensaver() self.logging.info("refreshing screensaver for popup", location=self.name) self.update_timeout("screensaver_subpage", 25) def toggle_screen(self, state = True): screen_control = self.setting_handler.get_setting("main_screen_control") switch = False if str(self.screen_state) != str(state): self.logging.info("Switching screen state: %s, %s" %(str(self.screen_state), str(state)), location=self.name) else: self.logging.debug("Switching screen state: %s, %s" %(str(self.screen_state), str(state)), location=self.name) if (state == "off" or state == "0" or state == False) and self.get_screen_state() == True: state = False self.screen_state = False switch = True elif (state == "on" or state == "1" or state == True) and self.get_screen_state() == False: state = True self.screen_state = True switch = True if screen_control == "pi": if not state: self.logging.write("Turn off screen", level=2) cmd = "echo 1 > /sys/class/backlight/rpi_backlight/bl_power" os.system(cmd) else: self.logging.write("Turn on screen", level=2) cmd = "echo 0 > /sys/class/backlight/rpi_backlight/bl_power" os.system(cmd) elif screen_control == "url" and switch: if not state: self.logging.info("Turn off screen via url", location=self.name) url = self.setting_handler.get_setting("screen_control_off_url") else: self.logging.info("Turn on screen via url", location=self.name) url = self.setting_handler.get_setting("screen_control_on_url") self.logging.debug("Screensaver url: %s" %url, location=self.name) self.http.request('GET', url) elif screen_control == "cmd" and switch: if not state: self.logging.info("Turn off screen via cmd", location=self.name) cmd = self.setting_handler.get_setting("screen_control_off_cmd") else: self.logging.info("Turn on screen via cmd", location=self.name) cmd = self.setting_handler.get_setting("screen_control_on_cmd") self.logging.debug("Screensaver cmd: %s" %cmd, location=self.name) os.system(cmd) def get_screen_state(self): return self.screen_state