Beispiel #1
0
class main_database(Singleton):
    def __init__(self):
        try:
            if self.loadingdone:
                pass
        except:
            self.loadingdone = True
            settings_c = settings.Settings()
            self.logging = Logging()
            self.data_location = settings_c.get_setting("data", "location")
            PATH = os.path.dirname(os.path.abspath(__file__))
            self.datafile = PATH + "/../" + self.data_location + "/main_db.pckl"
            my_file = Path(self.datafile)
            if not my_file.is_file():
                self.logging.write("Creating database", level=1)
                self.data = {
                    "last_saved": time.time(),
                    "settings": {},
                    "messages": []
                }
                self.data["settings"]["main_page"] = 0
                self.data["settings"]["items_per_page"] = 0
                self.data["settings"]["sensors_per_page"] = 0
                self.data["settings"]["screen_timeout"] = 1
                self.data["settings"]["album_timeout"] = 0
                self.data["settings"]["message_timeout"] = 0
                self.data["settings"]["mouse"] = 0
                self.data["settings"]["screen"] = 0
                self.data["settings"]["frame"] = 0
                self.data["settings"]["frame_info"] = 0
                self.data["settings"]["frame_td"] = 0
                self.data["settings"]["frame_display_time"] = 0
                self.data["settings"]["toast_timeout"] = 0
                self.data["settings"]["clock_type"] = 0
                self.data["settings"]["chart_period"] = 0
                self.data["settings"]["first_run_messages_flag"] = False
                self.data["messages"] = []
                self.save_datafile()
            self.data = self.load_datafile()

    def load_datafile(self):
        return pickle.load(open(self.datafile, "rb"))

    def save_datafile(self):
        self.data["last_saved"] = time.time()
        self.logging.write("Saving database", level=2)
        pickle.dump(self.data, open(self.datafile, "wb"))
Beispiel #2
0
class task_scheduler(Singleton):
    def __init__(self):
        try:
            if self.loadingdone:
                pass
        except:
            self.loadingdone = True
            self.logging = Logging()
            self.scheduled_tasks = []
            self.add_task(self.logging,
                          "log_rotate", (time.time() + 4 * 60 * 60),
                          period=24 * 60 * 60)

    def check_tasks(self):
        self.logging.write("Checking tasks, running scheduler",
                           level="TRACE",
                           location="tasks")
        cur_time = time.time()
        length = len(self.scheduled_tasks)
        for h in range(length):
            try:
                i = length - h - 1  ##reverse iteration
                task = self.scheduled_tasks[i]
                if cur_time > task[2]:  ##task[2] == next_time
                    class_name = task[0].get_name()
                    try:
                        item_name = task[0].get_item().get_name()
                        self.logging.write("Executing task: " + class_name +
                                           "." + task[1] + " for item: " +
                                           item_name,
                                           level='info',
                                           location="tasks")
                    except:
                        self.logging.write("Executing task: " + class_name +
                                           "." + task[1],
                                           level='info',
                                           location="tasks")
                    try:
                        getattr(task[0], task[1])()
                    except Exception as e:
                        self.logging.write("Processing task failed: " + str(e),
                                           level="error",
                                           location="tasks")
                        self.logging.write("Could not execute task: " +
                                           class_name + "." + task[1],
                                           level="error",
                                           location="tasks")
                    if task[3] == 0 and task[4] == 0:
                        del self.scheduled_tasks[i]
                    elif task[3] != 0:
                        task[3] = task[3] - 1  ##repeat n times
                        task[2] = cur_time + task[
                            4]  ## add period for next time
                        timestamp = datetime.datetime.fromtimestamp(
                            task[2]).strftime('%c')
                        self.logging.write("Repeating task: " + class_name +
                                           "." + task[1] + " scheduled at " +
                                           str(timestamp),
                                           level=2,
                                           location="tasks")
                    elif task[4] != 0:
                        if type(task[4]) == str:
                            task[2] = self.calculatenexttime(task[2], task[4])
                        else:
                            task[2] = cur_time + task[
                                4]  ## add period for next time
                        timestamp = datetime.datetime.fromtimestamp(
                            task[2]).strftime('%c')
                        self.logging.write("Repeating task: " + class_name +
                                           "." + task[1] + " scheduled at " +
                                           str(timestamp),
                                           level=4,
                                           location="tasks")
                    else:
                        ##delete task anyway
                        del self.scheduled_tasks[i]
                    gc.collect()
            except Exception as e:
                self.logging.write("Could not handle task in list: " + str(e),
                                   level="error",
                                   location="tasks")

    def add_task(self,
                 class_item,
                 functionname,
                 next_time,
                 repeat=0,
                 period=0):
        self.scheduled_tasks.append(
            [class_item, functionname, next_time, repeat, period])
        task = self.scheduled_tasks[-1]
        class_name = task[0].get_name()
        if type(next_time) == str:
            next_time = self.calculatetimestamp(next_time)
        timestamp = datetime.datetime.fromtimestamp(next_time).strftime('%c')
        self.logging.write("Added task: " + class_name + "." + task[1] +
                           " scheduled at " + str(timestamp),
                           level='info',
                           location="tasks")

    def list_tasks(self):
        self.logging.write("Listing tasks: " + str(len(self.scheduled_tasks)) +
                           " tasks active",
                           level='info',
                           location="tasks")
        tasks = []
        for i in range(len(self.scheduled_tasks)):
            try:
                task = self.scheduled_tasks[i]
                class_name = task[0].get_name()
                timestamp = datetime.datetime.fromtimestamp(
                    task[2]).strftime('%c')
                try:
                    item_name = task[0].get_item().get_name()
                    if len(item_name) > 20:
                        item_name = item_name[0:19]
                    task_string = (class_name + "." + task[1]).ljust(
                        25) + " for item: " + (item_name).ljust(
                            20) + " scheduled at: " + str(timestamp)
                    tasks.append([
                        class_name + "." + task[1],
                        str(timestamp), item_name
                    ])
                except:
                    task_string = (class_name + "." + task[1]).ljust(
                        56) + " scheduled at: " + str(timestamp)
                    tasks.append([class_name + "." + task[1], str(timestamp)])
                self.logging.write(
                    ("Task " + str(i + 1) + ": ").ljust(9) + task_string,
                    level='debug',
                    location="tasks")
            except:
                pass
        return tasks

    def delete_tasks(self):
        self.logging.write("Deleting tasks: " +
                           str(len(self.scheduled_tasks)) + " tasks active",
                           level="warning",
                           location="tasks")
        self.scheduled_tasks = []
        self.add_task(self.logging,
                      "log_rotate", (time.time() + 4 * 60 * 60),
                      period=24 * 60 * 60)

    def calculatetimestamp(self, next_time):
        date = datetime.datetime.strptime(next_time, "%c")
        return int(date.strftime("%s"))

    def calculatenexttime(self, now, nexttime):
        nexttime = str(nexttime).lower()
        date = datetime.datetime.fromtimestamp(now)
        if "year" in nexttime:
            nd = date + datetime.timedelta(
                years=int(nexttime[0:nexttime.find(" ")]))
        if "mon" in nexttime:
            nd = date + datetime.timedelta(
                months=int(nexttime[0:nexttime.find(" ")]))
        if "week" in nexttime:
            nd = date + datetime.timedelta(
                weeks=int(nexttime[0:nexttime.find(" ")]))
        if "day" in nexttime:
            nd = date + datetime.timedelta(
                days=int(nexttime[0:nexttime.find(" ")]))
        if "hour" in nexttime:
            nd = date + datetime.timedelta(
                hours=int(nexttime[0:nexttime.find(" ")]))
        if "min" in nexttime:
            nd = date + datetime.timedelta(
                minutes=int(nexttime[0:nexttime.find(" ")]))
        return int(nd.strftime("%s"))

    def getHourMinuteTomorrow(self, hour, minute, days=1):
        dtnow = datetime.datetime.now()
        dt6 = None
        # If today's hour is < 6 AM
        if dtnow.hour < hour - 1:
            dt6 = datetime.datetime(dtnow.year, dtnow.month, dtnow.day, hour,
                                    minute, 0, 0)
        # If today is past 6 AM, increment date by 1 day
        else:
            day = datetime.timedelta(days=days)
            tomorrow = dtnow + day
            dt6 = datetime.datetime(tomorrow.year, tomorrow.month,
                                    tomorrow.day, hour, minute, 0, 0)
        timestamp = time.mktime(dt6.timetuple())
        return timestamp
Beispiel #3
0
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)
Beispiel #4
0
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)
Beispiel #5
0
class page_handler():
    def __init__(self):
        self.openhab = pf_openhab()
        self.name = "page_handler"
        self.database = main_database()
        self.setting_handler = setting_handler()
        self.message_handler = message_handler()
        self.widgets_handler = widgets_handler()
        self.state_handler = state_handler()
        self.logging = Logging()
        settings_c = Settings()
        self.host = settings_c.get_setting("main", "hostname")
        self.port = settings_c.get_setting("main", "port")
        self.enable_screen_control = settings_c.get_setting(
            "main", "enable_screen_control")
        self.openhab_host = settings_c.get_setting("main", "openhab_ip")
        self.openhab_port = settings_c.get_setting("main", "openhab_port")

    def get_page(self, request):
        pagelist = request["page"]
        dataget = request["data_get"]
        page = []
        lowerpage = [0]
        if len(pagelist) > 3:
            lowerpage = pagelist[3:]
            subsubpage = pagelist[2]
            subpage = pagelist[1]
        elif len(pagelist) > 2:
            subsubpage = pagelist[2]
            subpage = pagelist[1]
        elif len(pagelist) > 1:
            subpage = pagelist[1]
            subsubpage = "none"
        else:
            subsubpage = "none"
            subpage = "none"
        pagename = pagelist[0]

        if pagename == "main":
            self.logging.info("Loading main page: " + subpage + "/" +
                              subsubpage,
                              location=self.name)
            if self.message_handler.get_popup_flag() and subpage != "reload":
                self.message_handler.del_popup_flag()
            self.state_handler.toggle_screen(state=True)
            self.state_handler.refresh_screensaver()
            return self.create_main_page()
        elif pagename == "maindiv":
            self.logging.info("Loading main div: " + subpage + "/" +
                              subsubpage,
                              location=self.name)
            ##turn on screen
            if subpage != "screensaver":
                self.state_handler.toggle_screen(state=True)
            if not "reload" in pagelist and not "screensaver" in pagelist:
                ##enable popup of message when there is a new message
                self.message_handler.del_popup_flag()
                self.state_handler.refresh_screensaver()
                if subpage not in [
                        "none", "popup", "", "reload", "screensaver"
                ]:
                    self.state_handler.refresh_screensaver_subpage()
            else:
                self.logging.info("Not refreshing screensaver",
                                  location=self.name)
            if subpage in ["none", "popup", "", "reload", "screensaver"]:
                return self.create_main_div()
            elif subpage == "settings":
                return self.create_settings_page(subpage=subsubpage)
            elif subpage == "messages":
                return self.create_messages_page()
            else:
                if subsubpage == "reload":
                    subsubpage = 0
                if lowerpage[0] == "reload":
                    lowerpage = [0]
                return self.create_subpage(subpage, subsubpage, lowerpage[0])
        elif pagename == "menuwidget":
            self.logging.write("Loading menu widget: " + subpage + "/" +
                               subsubpage,
                               level=2,
                               location=self.name)
            if not "reload" in pagelist and not "screensaver" in pagelist:
                self.state_handler.toggle_screen(state=True)
                self.state_handler.refresh_screensaver_subpage()
            try:
                widget, title = self.widgets_handler.create_mainpage_popup(
                    subpage, lowerpage[0], True)
            except:
                widget = "gotomain"
                title = "none"
            page_format = {"title": title}
            page = render_template("subpage_widget.html", data=page_format)
            page = page.replace("[[WIDGET]]", widget)
            if (str(lowerpage) != "0"
                    and str(lowerpage)[0:2] != "m_") and subpage not in [
                        "none", "items_left", "items_right"
                    ]:
                d = self.openhab.get_items(subpage)
                pos = 0
                for i in range(len(d[0])):
                    b = d[0][i]
                    if b["type"] == "Frame" and b["label"] == lowerpage[0]:
                        pos = i
                N_items_pp, sensor_page = self._getNitemsPP(d[1], False)
                rb = "%s/%d" % (subpage, int(pos / N_items_pp))
            else:
                rb = False
            page = self.add_bottom_bar(page, rb)
            if widget == "widget not in sitemap":
                return "widget not in sitemap"
            elif widget == "gotomain":
                return widget
            else:
                return page
        elif pagename == "popup":  ##this is a popup widget
            self.logging.write("Loading popup div: " + subpage + "/" +
                               subsubpage,
                               level=2,
                               location=self.name)
            if not "reload" in pagelist and not "screensaver" in pagelist:
                self.state_handler.toggle_screen(state=True)
                self.state_handler.refresh_screensaver_subpage()
            page = self.widgets_handler.create_mainpage_popup(
                subpage, subsubpage)
            if page == "generic_button_page":
                return self.create_subpage(subpage, 0, subsubpage, True)
            elif page == "widget not in sitemap":
                return "widget not in sitemap"
            else:
                return page
        elif pagename in ["clock", "black"]:
            cl = self.setting_handler.get_setting("clock_type")
            return render_template("clock.html", data={"type_clock": cl})
        elif pagename == "clk_widget":
            return self.get_clock_page_widget()
        elif pagename == "photoframe":
            return self.create_photoframe()

        pagestr = ""
        for i in range(len(page)):
            pagestr = pagestr + page[i] + "\n"
        return pagestr

    def read_file(self, filename):
        PATH = os.path.dirname(os.path.abspath(__file__))
        with open(PATH + "/../" + filename) as f:
            content = f.readlines()
        content = [x.strip() for x in content]
        return content

    def create_main_page(self):
        page_data = {}
        page_data["host"] = [self.host, self.port]
        settings_c = Settings()
        page_data["mouse"] = self.setting_handler.get_setting("mouse")
        page_data["event_reload"] = settings_c.get_setting(
            "page", "event_check_reload")
        page_data["page_reload"] = settings_c.get_setting(
            "page", "page_reload")
        page_data["enable_album"] = settings_c.get_setting(
            "main", "enable_album")
        if settings_c.get_setting("main", "enable_album") == "1":
            page_data["album_display_time"] = self.setting_handler.get_setting(
                "frame_display_time")
        return render_template("main.html", data=page_data)

    def get_clock_page_widget(self):
        ml = self.openhab.get_items("clock_page")[0]
        data = []
        if len(ml) > 0:
            itemdata = ml[0]
            itemdata.update({"onclick": ""})
            itemtype = self.widgets_handler.check_widget_type(
                itemdata["label"])
            if itemtype[0:6] == "widget":  ##special item takes 3 rows
                data.append(itemdata)
                data[-1]["group"] = itemtype[7:8] + "rows"
                data[-1]["label_c"] = itemdata["label"]
                data[-1]["label"] = self.widgets_handler.get_widget_label(
                    itemdata["label"]).upper()
        if len(data) > 0:
            item = data[0]
            page = self.widgets_handler.render_widget("clock_page",
                                                      item["label_c"])
            return page
        return ""

    def create_main_div(self):
        ml = self.openhab.get_items("items_left")[0]
        page_data_ml = self.format_items_frontpage("items_left", ml)
        main_left = render_template("maindiv_half.html", data=page_data_ml)

        mr = self.openhab.get_items("items_right")[0]
        page_data_mr = self.format_items_frontpage("items_right", mr)
        main_right = render_template("maindiv_half.html", data=page_data_mr)

        page_data = {}
        page_data["bottom"] = self.openhab.get_pages("b_")
        page = render_template("maindiv.html", data=page_data)

        page = page.replace("[[MAINLEFT]]", main_left)
        page = page.replace("[[MAINRIGHT]]", main_right)

        for item in page_data_ml:
            if item["group"][1:] == "rows":
                page = page.replace(
                    "[[%s]]" % item["label"].upper(),
                    self.widgets_handler.render_widget("items_left",
                                                       item["label_c"]))

        for item in page_data_mr:
            if item["group"][1:] == "rows":
                page = page.replace(
                    "[[%s]]" % item["label"].upper(),
                    self.widgets_handler.render_widget("items_right",
                                                       item["label_c"]))
        return self.add_bottom_bar(page)

    def format_items_frontpage(self, name, itemdata):
        while len(itemdata) < 10:
            itemdata.append({
                "label": "",
                "state": "",
                "type": "text",
                "id": "",
                "icon": "static/pictures/black.png"
            })
        data = []
        row = 1
        item = 0
        while row < 6:
            itemdata[item].update({"onclick": ""})
            itemtype = self.widgets_handler.check_widget_type(
                itemdata[item]["label"])
            if itemtype == "menu_button":  ##this is a menu button
                itemdata[item].update({
                    "onclick":
                    "reload_main_div('page/maindiv/" + name + "/0/" +
                    itemdata[item]["label"] + "')"
                })
                data.append(itemdata[item])
                data[-1]["group"] = "menu_popup"
                data[-1]["label"] = self.widgets_handler.get_widget_label(
                    itemdata[item]["label"])
                if data[-1]["state"] != "":
                    data[-1]["label"] = data[-1]["state"]
                item += 1
                data[-1]["fontsize"] = self.determine_text_size(
                    data[-1]["label"], max_len=13, start_font="xlargefont")
            elif itemtype == "widget_subpage":  ##this is a menu button
                itemdata[item].update({
                    "onclick":
                    "reload_main_div('/page/menuwidget/" + name + "/0/" +
                    itemdata[item]["label"] + "')"
                })
                data.append(itemdata[item])
                data[-1]["group"] = "menu_popup"
                data[-1]["label"] = self.widgets_handler.get_widget_label(
                    itemdata[item]["label"])
                if data[-1]["state"] != "":
                    data[-1]["label"] = data[-1]["state"]
                item += 1
                data[-1]["fontsize"] = self.determine_text_size(
                    data[-1]["label"], max_len=13, start_font="xlargefont")
            elif itemtype == "menu_popup" or itemtype == "widget_popup":  ##this is a menu button
                itemdata[item].update({
                    "onclick":
                    "frontpage_action('" + name + "', '" +
                    itemdata[item]["label"] + "')"
                })
                data.append(itemdata[item])
                data[-1]["group"] = "menu_popup"
                data[-1]["label"] = self.widgets_handler.get_widget_label(
                    itemdata[item]["label"])
                if data[-1]["state"] != "":
                    data[-1]["label"] = data[-1]["state"]
                item += 1
                data[-1]["fontsize"] = self.determine_text_size(
                    data[-1]["label"], max_len=13, start_font="xlargefont")
            elif itemtype[0:6] == "widget" and row < 6 - int(
                    itemtype[7:8]) + 1:  ##special item takes 3 rows
                data.append(itemdata[item])
                data[-1]["group"] = itemtype[7:8] + "rows"
                data[-1]["label_c"] = itemdata[item]["label"]
                data[-1]["label"] = self.widgets_handler.get_widget_label(
                    itemdata[item]["label"]).upper()
                item += 1
                row += int(itemtype[7:8]) - 1
            elif itemtype[0:6] == "widget":  ## skip this item
                item += 1
                row -= 1
            else:
                col = 0
                data.append({"data": [0, 0], "group": "cols"})
                while col < 2:
                    itemtype = self.widgets_handler.check_widget_type(
                        itemdata[item]["label"])
                    if itemdata[item]["type"] == "Text":
                        data[-1]["data"][col] = itemdata[item]
                        data[-1]["data"][col]["group"] = "text"
                        item += 1
                    elif itemtype in ["menu_button", "menu_popup"] or itemtype[
                            0:
                            6] == "widget":  ##two columns needed for this type
                        data[-1]["data"][col] = {
                            "label": "",
                            "state": "",
                            "type": "text"
                        }
                        data[-1]["data"][col]["group"] = "empty"
                    else:
                        itemdata[item].update({
                            "onclick":
                            "item_action('" + itemdata[item]["type"] + "', '" +
                            itemdata[item]["id"] + "', 'main')"
                        })
                        data[-1]["data"][col] = itemdata[item]
                        data[-1]["data"][col]["group"] = "popup"
                        item += 1
                    col += 1
                if data[-1]["data"][1]["group"] != "empty":
                    if data[-1]["data"][1]["label"] == "" or (
                            data[-1]["data"][1]["label"] == "Empty"
                            and data[-1]["data"][1]["state"] == "Empty"):
                        d = data[-1]["data"][0]
                        d.update({"group": "wide_text"})
                        data[-1] = d
                        data[-1]["fontsize"] = self.determine_text_size(
                            data[-1]["state"], max_len=16)
                    else:
                        for i in [0, 1]:
                            data[-1]["data"][i][
                                "fontsize"] = self.determine_text_size(
                                    data[-1]["data"][i]["state"])
                else:
                    d = data[-1]["data"][0]
                    d.update({"group": "wide_text"})
                    data[-1] = d
                    data[-1]["fontsize"] = self.determine_text_size(
                        data[-1]["state"], max_len=16)

            row += 1
        return data

    def create_subpage(self,
                       page,
                       subpage=0,
                       lowerpage=0,
                       handle_as_popup=False):
        data = self.openhab.get_items(page, lowerpage)
        if subpage == "none":
            subpage = 0
        else:
            subpage = int(subpage)
        items = data[0]
        page_data = data[1]
        #print(page_data[0], self.widgets_handler.get_widget_label(page_data[0]))
        N_items_pp, sensor_page = self._getNitemsPP(page_data, handle_as_popup)
        page_format = self.__get_page_data__(len(items),
                                             N_items_pp,
                                             sensor_page=sensor_page)
        page_format.update({
            "title":
            self.widgets_handler.get_widget_label(page_data[0]),
            "returnbutton":
            False,
            "linkback":
            "",
            "linknext":
            "",
            "showbacknext":
            True
        })
        if handle_as_popup:
            sensor_page = False
            page_format["showbacknext"] = False
        if str(lowerpage) != "0" and str(lowerpage)[0:2] != "m_":
            d = self.openhab.get_items(page)
            pos = 0
            for i in range(len(d[0])):
                b = d[0][i]
                if b["type"] == "Frame" and b["label"] == lowerpage:
                    pos = i
            page_format["returnbutton"] = "%s/%d" % (page, int(
                pos / N_items_pp))
        if subpage != 0:
            page_format["linkback"] = str(page) + "/" + str(
                int(subpage) - 1) + "/" + str(lowerpage)
        if subpage < page_format["n_pages"] - 1:
            page_format["linknext"] = str(page) + "/" + str(
                int(subpage) + 1) + "/" + str(lowerpage)
        offset = subpage * N_items_pp
        page = render_template("subpage.html", data=page_format)
        n = 0
        ##iterator
        for row in range(page_format["n_rows"]):
            for col in range(page_format["n_cols"]):
                if n + offset < len(items) and (
                        items[n + offset]["name"] != "Empty"
                        and items[n + offset]["state"] != "Empty"
                        and items[n + offset]["label"] != "Empty"):
                    button = self.create_item_button(items[n + offset],
                                                     page_format["small_icon"],
                                                     sensor_page)
                else:
                    button = ""
                page = page.replace("[[button_" + str(n) + "]]", button)
                n += 1
        if handle_as_popup:
            page += render_template("popups/generic.html")
            return page
        else:
            return self.add_bottom_bar(
                page, returnbutton=page_format["returnbutton"])

    def create_settings_page(self, subpage=0):
        settings = sorted(self.setting_handler.get_settings())
        n = {'linkback': "", 'linknext': "", 'n': len(settings)}
        try:
            subpage = int(subpage)
        except:
            subpage = 0
        if subpage != 0:
            n["linkback"] = subpage - 1
        if subpage < np.ceil(len(settings) / 12) - 1:
            n["linknext"] = subpage + 1
        if subpage != 0:
            settings = settings[12 * subpage:]
        n['n'] = len(settings)
        return self.add_bottom_bar(
            render_template("settings.html", data=settings, n=n))

    def create_messages_page(self, start=0):
        page = render_template("messages.html")
        page = page.replace(
            "[[LIST]]", self.message_handler.format_message_list(start=start))
        page = page.replace("[[MESSAGE]]",
                            self.message_handler.format_message(message_id=-1))
        return self.add_bottom_bar(page)

    def add_bottom_bar(self, page, returnbutton=False):
        pages = self.openhab.get_pages(["m_", "a_", "b_", "c_"])
        for i in range(len(pages)):
            pages[i]["type"] = self.widgets_handler.check_widget_type(
                pages[i]["label"])
        page_format = {"bottom": pages}
        page_format["returnbutton"] = returnbutton
        page_format["habpanel_link"] = Settings().get_setting(
            "main", "habpanel_link")
        page += "\n\n\n"
        page += render_template("bottombar.html", data=page_format)
        return page

    def __get_page_data__(self, n_items, n_perpage, sensor_page=False):
        n_page = np.ceil(n_items / n_perpage)
        small_icon = False
        page_format = {
            "n_pages": n_page,
            "n_rows": 2,
            "n_cols": 3,
            "row_height": "50",
            "col_width": "33",
            "small_icon": False
        }
        if n_perpage == 8 and not sensor_page:
            page_format.update({
                "n_rows": 4,
                "n_cols": 2,
                "row_height": "25",
                "col_width": "50",
                "small_icon": True
            })
        elif n_perpage == 8 and sensor_page:
            page_format.update({
                "n_rows": 2,
                "n_cols": 4,
                "row_height": "50",
                "col_width": "25"
            })
        elif n_perpage == 9:
            page_format.update({
                "n_rows": 3,
                "n_cols": 3,
                "row_height": "33",
                "col_width": "33"
            })
        elif n_perpage == 12:
            page_format.update({
                "n_rows": 4,
                "n_cols": 3,
                "row_height": "25",
                "col_width": "33"
            })
        return page_format

    def create_item_button(self,
                           item_info,
                           small_icon=False,
                           sensor_button=False,
                           header=True):
        if not sensor_button:
            N_items_pp = self.setting_handler.get_setting("items_per_page")
            button_width = int(
                self.__get_page_data__(1, N_items_pp,
                                       sensor_button)["col_width"])
        else:
            N_items_pp = self.setting_handler.get_setting("sensors_per_page")
            button_width = int(
                float(
                    self.__get_page_data__(1, N_items_pp,
                                           sensor_button)["col_width"]) * 1.2)

        data = {
            "icon": item_info["icon"],
            "icon_width": 90,
            "icon_height": 60,
            "action_id": item_info["id"],
            "header": header
        }
        if small_icon:
            data.update({"icon_width": 70, "icon_height": 70})
        data.update({
            "onclick":
            "item_action('" + item_info["type"] + "', '" + item_info["id"] +
            "')"
        })

        itemtype = self.widgets_handler.check_widget_type(item_info["label"])
        if item_info["type"] == "Frame" and (
                itemtype != "widget_subpage") and (
                    itemtype == "widget_popup" or itemtype[0:6] == "widget"):
            data.update({
                "onclick":
                "frontpage_action('" + str(item_info["page"]) + "', '" +
                item_info["label"] + "')"
            })
            data["text"] = self.widgets_handler.get_widget_label(
                item_info["name"])
            data["text_width"] = 80
        elif item_info["type"] == "Frame" and (itemtype == "widget_subpage"):
            data.update({
                "onclick":
                "reload_main_div('/page/menuwidget/" + str(item_info["page"]) +
                "/0/" + str(item_info["subpage"]) + "')"
            })
            data["text"] = self.widgets_handler.get_widget_label(
                item_info["name"])
            data["text_width"] = 80
        elif item_info["type"] == "Frame":
            data.update({
                "onclick":
                "reload_main_div('/page/maindiv/" + str(item_info["page"]) +
                "/0/" + str(item_info["subpage"]) + "')",
                "text_width":
                80
            })
            data.update(
                self.format_item_string(item_info["label"], item_info["state"],
                                        button_width))
            if data["state"] != '':
                data.update({"type": "state"})
        elif item_info["type"] == "Switch":
            data.update({
                "text":
                self.format_string(item_info["label"],
                                   int(20 * (button_width / 100))),
                "state":
                item_info["state"].lower(),
                "text_width":
                60,
                "state_width":
                20
            })
            data.update({"type": "switch"})
        elif item_info["type"] == "Switch_single":
            data.update({
                "text":
                self.format_string(item_info["label"],
                                   int(20 * (button_width / 100))),
                "state":
                item_info["state"].lower(),
                "text_width":
                60,
                "state_width":
                20
            })
        elif item_info["type"] == "Colorpicker":  ##openhab item type
            data.update({
                "text":
                self.format_string(item_info["label"],
                                   int(20 * (button_width / 100))),
                "state":
                item_info["state"],
                "text_width":
                60,
                "state_width":
                20
            })
            data.update({"type": "Colorpicker"})
        else:
            data.update(
                self.format_item_string(item_info["label"], item_info["state"],
                                        button_width))
            data.update({"type": "state"})
        if sensor_button:
            data.update({
                "text_width": 70,
                "state_width": 70,
                "icon_width": 80
            })
            page = render_template("buttons/sensor.html", data=data)
        else:
            page = render_template("buttons/button.html", data=data)
        return page

    def create_popup(self, type, data, renew_screensaver=True):
        if renew_screensaver:
            self.state_handler.refresh_screensaver_subpage()
        page = render_template("popups/" + type + ".html", data=data)
        return page

    def create_photoframe(self):
        td = self.setting_handler.get_setting("frame_td")
        info = self.setting_handler.get_setting("frame_info")
        page_data = {
            "time": "none",
            "date": "none",
            "load": "none",
            "album": "none"
        }
        if td == "clock" or td == "both":
            page_data["time"] = ""
        if td == "date" or td == "both":
            page_data["date"] = ""
        if info == "load" or info == "both":
            page_data["load"] = ""
        if info == "album" or info == "both":
            page_data["album"] = ""
        return render_template("album.html", data=page_data)

    def format_item_string(self, text, state, button_width=50):
        if text == "_":
            return {
                "text":
                self.format_string(state,
                                   width=int(54 * (button_width / 100))),
                "state":
                "",
                "text_width":
                80,
                "state_width":
                0
            }
        elif state == "" and len(text) < 25:
            return {
                "text": text,
                "state": "",
                "text_width": 80,
                "state_width": 0
            }
        elif state == "":
            return {
                "text":
                self.format_string(text, width=int(32 * (button_width / 100))),
                "state":
                "",
                "text_width":
                80,
                "state_width":
                0
            }
        elif len(text) < 13 and len(state) > 7:
            return {
                "text":
                text,
                "state":
                self.format_string(state,
                                   width=int(26 * (button_width / 100))),
                "text_width":
                40,
                "state_width":
                40
            }
        elif len(text) > 20 and len(state) > 20:
            return {
                "text":
                self.format_string(text, width=int(26 * (button_width / 100))),
                "state":
                self.format_string(state,
                                   width=int(26 * (button_width / 100))),
                "text_width":
                40,
                "state_width":
                40
            }
        else:
            return {
                "text":
                self.format_string(text, width=int(38 * (button_width / 100))),
                "state":
                self.format_string(state,
                                   width=int(14 * (button_width / 100))),
                "text_width":
                40,
                "state_width":
                40
            }

    def format_string(self, string, width=27):
        position = 0
        for i in range(3):
            if len(string[position:]) > width:
                a = self.find(string[position:], " ")
                found = False
                for pos in range(len(a)):
                    val = a[len(a) - pos - 1]
                    if val < 27 and not found:
                        string = string[0:position +
                                        val] + "<br>" + string[position + val +
                                                               1:]
                        position = val + position + 4
                        found = True
        return Markup(string)

    def find(self, s, ch):
        return [i for i, ltr in enumerate(s) if ltr == ch]

    def determine_text_size(self, text, max_len=7, start_font="largefont"):
        if text == text.upper():
            max_len -= 1
        if start_font == "largefont":
            if len(text) < max_len + 1:
                return "largefont"
            else:
                return "smallfont"
        else:
            if len(text) < max_len + 1:
                return "xlargefont"
            else:
                return "smallfont"

    def _getNitemsPP(self, page_data, handle_as_popup):
        if page_data[1] != "temperature" and page_data[
                1] != "temp" and page_data[0].find("sensor") == -1:
            N_items_pp = self.setting_handler.get_setting("items_per_page")
            sensor_page = False
        else:
            N_items_pp = self.setting_handler.get_setting("sensors_per_page")
            if N_items_pp == 12:
                sensor_page = False
            else:
                sensor_page = True
        if handle_as_popup:
            N_items_pp = self.setting_handler.get_setting("items_per_page")
            if int(N_items_pp) < 9:
                N_items_pp = 6
            else:
                N_items_pp = 9
        return N_items_pp, sensor_page
#get the output from the remainlist.txt file and use the outputlist as input
'''if we want to use split methods, edit this part'''
#CHANGE BELOW
'''df_remains = pd.read_csv('remainlist.csv')
inputcsvs_all = df_remains.remainlist.tolist()
totalnum = len(inputcsvs_all)
splitnum = int(totalnum/4)
inputcsvs = inputcsvs_all[ : splitnum]'''
#inputcsvs_full = glob.glob(inputParameters.read_directory+'*.csv')
#inputcsvs = [file.split('/')[-1] for file in inputcsvs_full]
#CHANGE ABOVE
totalnum = 1
inputcsvs = ['163610_163610_ice_markets_2016-02-01_2016-02-29.csv']
totalnum = len(inputcsvs)
print('Total csv will be processed: {}'.format(totalnum))
Logger.write('Total csv will be processed: {}'.format(len(inputcsvs)))
Logger.write_separator(2)

#process all the csv step by step
counter = 0
for inputfilename in inputcsvs:
    counter += 1
    print(str(counter) + '/' + str(totalnum))
    print(inputfilename + '..is being processed')
    Logger.write(str(counter) + '/' + str(totalnum))
    Logger.write(inputfilename + '..is being processed')
    try:
        #print(inputParameters.read_directory)
        #print(inputfilename)
        ###read in file
        try:
Beispiel #7
0
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