Beispiel #1
0
def download_all_sql_databases_zipped():
    logger.network_logger.debug(
        "* Download Zip of All Databases Accessed by " +
        str(request.remote_addr))
    zip_name = _get_net_and_host_name_str("All_Databases", ".zip")

    try:
        return_names = [
            app_cached_variables.hostname + "_Main_Database.sqlite",
            app_cached_variables.hostname + "_Checkin_Database.sqlite",
            app_cached_variables.hostname + "_MQTT_Sub_Database.sqlite"
        ]
        return_files = [
            get_file_content(file_locations.sensor_database, open_type="rb"),
            get_file_content(file_locations.sensor_checkin_database,
                             open_type="rb"),
            get_file_content(file_locations.mqtt_subscriber_database,
                             open_type="rb")
        ]
        return_zip = zip_files(return_names, return_files)
        return send_file(return_zip,
                         attachment_filename=zip_name,
                         as_attachment=True)
    except Exception as error:
        logger.primary_logger.error("* Download All Databases Zip: " +
                                    str(error))
        return_zip = "Error Creating Zip on " + app_cached_variables.ip + " - " + app_cached_variables.hostname
        return send_file(return_zip + " - " + str(error),
                         attachment_filename=zip_name + ".txt",
                         as_attachment=True)
def _change_program_version(new_version):
    ks_version_file = get_file_content(
        original_source_dir + "operations_modules/software_version.py")
    control_version_file_content = get_file_content(
        original_source_dir + "extras/deb_package_files/DEBIAN/control")

    new_ks_version_file = ""
    for line in ks_version_file.split("\n"):
        if line.split("=")[0].strip() == "version":
            new_ks_version_file += f'version = "{new_version.get_version_string()}"\n'
        else:
            new_ks_version_file += f"{line}\n"
    new_ks_version_file = new_ks_version_file.strip() + "\n"
    write_file_to_disk(
        original_source_dir + "operations_modules/software_version.py",
        new_ks_version_file)

    new_control_version = ""
    for line in control_version_file_content.split("\n"):
        if line.split(":")[0].strip() == "Version":
            nv = f"Version: {new_version.major_version}.{new_version.feature_version}-{new_version.minor_version}\n"
            new_control_version += nv
        else:
            new_control_version += f"{line}\n"
    new_control_version = new_control_version.strip() + "\n"
    write_file_to_disk(
        original_source_dir + "extras/deb_package_files/DEBIAN/control",
        new_control_version)
def send_db_graph_emails(email_address_list):
    generate_plotly_graph(None,
                          graph_config=app_config_access.email_db_graph_config)
    sleep(5)
    while server_plotly_graph_variables.graph_creation_in_progress:
        sleep(5)

    date_time = datetime.utcnow().strftime("%Y-%m-%d_%H:%M")
    filename = app_cached_variables.hostname + "_" + date_time + "_KS_Graph"
    message = get_new_email_message("Kootnet Sensor Graph - " +
                                    app_cached_variables.hostname)
    message.attach(
        MIMEText(_get_default_email_body_text("Plotly Graph"), "plain"))

    try:
        zipped_graph = zip_files([filename + ".html"], [
            get_file_content(app_config_access.email_db_graph_config.
                             plotly_graph_saved_location,
                             open_type="rb")
        ])
        payload = MIMEBase("application", "zip")
        payload.set_payload(zipped_graph.read())
        encoders.encode_base64(payload)
        payload.add_header("Content-Disposition",
                           "attachment",
                           filename=filename + ".zip")
        message.attach(payload)
    except Exception as error:
        logger.network_logger.error("Graph Email did not send: " + str(error))
        payload = MIMEText("\n\nError Generating Zip of Plotly Graph\n\n",
                           "plain")
        message.attach(payload)

    for email_address in email_address_list:
        send_email(email_address, message)
Beispiel #4
0
def _zip_checkin_db_worker():
    app_cached_variables.creating_zip_checkin_db = True
    sql_filename = _add_host_and_ip_to_filename("Checkin_Database", "sqlite")
    zip_content = get_file_content(file_locations.sensor_checkin_database,
                                   open_type="rb")
    _zip_db(file_locations.checkin_database_zipped, sql_filename, zip_content)
    app_cached_variables.creating_zip_checkin_db = False
Beispiel #5
0
    def _enable_psm5003_serial():
        logger.sensors_logger.debug("Enabling Serial for Pimoroni PSM5003")
        try:
            serial_disabled = True
            boot_config_lines = get_file_content("/boot/config.txt").split(
                "\n")

            new_config = ""
            for line in boot_config_lines:
                if line.strip() == "dtoverlay=pi3-miniuart-bt":
                    serial_disabled = False
                new_config += line + "\n"

            if serial_disabled:
                logger.sensors_logger.info(
                    "Serial not enabled for PSM5003 - Enabling")
                logger.primary_logger.warning(
                    "You must reboot the System before the PSM5003 will function properly"
                )
                os.system(
                    "raspi-config nonint set_config_var enable_uart 1 /boot/config.txt"
                )
                os.system("raspi-config nonint do_serial 1")
                time.sleep(0.5)
                new_config = new_config.strip()
                new_config += "\n\n# Kootnet Sensors Addition\ndtoverlay=pi3-miniuart-bt\n"
                write_file_to_disk("/boot/config.txt", new_config)
        except Exception as error:
            logger.sensors_logger.error(
                "Pimoroni PSM5003 Enable Serial - Failed: " + str(error))
Beispiel #6
0
    def load_from_file(self):
        try:
            ip_list_content = get_file_content(self.ip_list_location).strip()
            ip_list = ip_list_content.split("\n")

            self.sensor_ip_dns1 = ip_list[0].split("=")[0].strip()
            self.sensor_ip_dns2 = ip_list[1].split("=")[0].strip()
            self.sensor_ip_dns3 = ip_list[2].split("=")[0].strip()
            self.sensor_ip_dns4 = ip_list[3].split("=")[0].strip()
            self.sensor_ip_dns5 = ip_list[4].split("=")[0].strip()
            self.sensor_ip_dns6 = ip_list[5].split("=")[0].strip()
            self.sensor_ip_dns7 = ip_list[6].split("=")[0].strip()
            self.sensor_ip_dns8 = ip_list[7].split("=")[0].strip()
            self.sensor_ip_dns9 = ip_list[8].split("=")[0].strip()
            self.sensor_ip_dns10 = ip_list[9].split("=")[0].strip()
            self.sensor_ip_dns11 = ip_list[10].split("=")[0].strip()
            self.sensor_ip_dns12 = ip_list[11].split("=")[0].strip()
            self.sensor_ip_dns13 = ip_list[12].split("=")[0].strip()
            self.sensor_ip_dns14 = ip_list[13].split("=")[0].strip()
            self.sensor_ip_dns15 = ip_list[14].split("=")[0].strip()
            self.sensor_ip_dns16 = ip_list[15].split("=")[0].strip()
            self.sensor_ip_dns17 = ip_list[16].split("=")[0].strip()
            self.sensor_ip_dns18 = ip_list[17].split("=")[0].strip()
            self.sensor_ip_dns19 = ip_list[18].split("=")[0].strip()
            self.sensor_ip_dns20 = ip_list[19].split("=")[0].strip()
        except Exception as error:
            logger.network_logger.warning("IP List: " + str(error))
            self.save_list_to_file()
Beispiel #7
0
def charts_min_js_fun():
    global charts_min_js
    charts_min_js_loc = file_locations.program_root_dir + "/http_server/extras/chart.min.js"
    if charts_min_js is None:
        charts_min_js = get_file_content(charts_min_js_loc)
    return_response = make_response(charts_min_js)
    return_response.headers["Cache-Control"] = "public, max-age=432000"
    return return_response
Beispiel #8
0
def jquery_min_js_fun():
    global jquery_min_js
    jquery_min_js_loc = file_locations.program_root_dir + "/http_server/extras/jquery-3.6.0.min.js"
    if jquery_min_js is None:
        jquery_min_js = get_file_content(jquery_min_js_loc)
    return_response = make_response(jquery_min_js)
    return_response.headers["Cache-Control"] = "public, max-age=432000"
    return return_response
Beispiel #9
0
def _zip_mqtt_sub_db_worker():
    app_cached_variables.creating_zip_mqtt_sub_db = True
    sql_filename = _add_host_and_ip_to_filename("MQTT_Subscriber_Database",
                                                "sqlite")
    zip_content = get_file_content(file_locations.mqtt_subscriber_database,
                                   open_type="rb")
    _zip_db(file_locations.mqtt_database_zipped, sql_filename, zip_content)
    app_cached_variables.creating_zip_mqtt_sub_db = False
Beispiel #10
0
def sensor_unit_help():
    global help_index_page
    if help_index_page is None:
        help_index_page = get_file_content(documentation_root_dir +
                                           "/index.html")
    return_response = make_response(help_index_page)
    return_response.headers["Cache-Control"] = "public, max-age=432000"
    return return_response
Beispiel #11
0
def fav_icon_func():
    global fav_icon_file_content
    fav_icon_loc = file_locations.program_root_dir + "/http_server/templates/ATPro_admin/assets/AT-pro-logo.png"
    if fav_icon_file_content is None:
        fav_icon_file_content = get_file_content(fav_icon_loc, open_type="rb")
    return_response = make_response(
        send_file(BytesIO(fav_icon_file_content), mimetype="image/jpeg"))
    return_response.headers["Cache-Control"] = "public, max-age=432000"
    return return_response
Beispiel #12
0
def upgrade_python_pip_modules(python_location=None):
    requirements_file_location = file_locations.program_root_dir + "/requirements.txt"
    hardware_requirements_location = file_locations.program_root_dir + "/requirements_hw_sensors.txt"
    all_python_modules_list = []
    if app_cached_variables.pip_ready_for_upgrades and app_cached_variables.sensor_ready_for_upgrade:
        if os.path.isfile(file_locations.program_root_dir + "/requirements.txt"):
            requirements_text = get_file_content(requirements_file_location).strip()
            all_python_modules_list = requirements_text.split("\n")
        if app_cached_variables.running_with_root and running_on_pi():
            if os.path.isfile(file_locations.program_root_dir + "/requirements_hw_sensors.txt"):
                requirements_text = get_file_content(hardware_requirements_location).strip()
                all_python_modules_list = all_python_modules_list + requirements_text.split("\n")
        app_cached_variables.pip_ready_for_upgrades = False
        if python_location is not None:
            _pip_upgrades_thread([all_python_modules_list, python_location])
        else:
            thread_function(_pip_upgrades_thread, args=[all_python_modules_list, python_location])
    else:
        logger.network_logger.warning("Unable to start Python Module Upgrades - already running")
Beispiel #13
0
def _get_zipped_logs():
    try:
        return_names = [
            app_cached_variables.hostname + "_" +
            os.path.basename(file_locations.primary_log),
            app_cached_variables.hostname + "_" +
            os.path.basename(file_locations.network_log),
            app_cached_variables.hostname + "_" +
            os.path.basename(file_locations.sensors_log)
        ]
        return_files = [
            get_file_content(file_locations.primary_log, open_type="rb"),
            get_file_content(file_locations.network_log, open_type="rb"),
            get_file_content(file_locations.sensors_log, open_type="rb")
        ]
        return zip_files(return_names, return_files)
    except Exception as error:
        logger.primary_logger.error("* Unable to Zip Logs: " + str(error))
        return None
Beispiel #14
0
def _add_pip_modules_to_list(requirements_locations_list):
    modules_list = []
    for requirements_location in requirements_locations_list:
        if os.path.isfile(requirements_location):
            requirements_text = get_file_content(requirements_location).strip()
            for requirement in requirements_text.split("\n"):
                requirement = requirement.strip()
                if requirement[0] != "#":
                    modules_list.append(requirement)
    return modules_list
    def _init_config_variables(self):
        """ Sets configuration settings from file, saves default if missing. """

        try:
            if self.check_config_file_exists():
                self.set_config_with_str(get_file_content(self.config_file_location))
        except Exception as error:
            log_msg = "Error setting variables from "
            log_msg2 = "Saving Default Configuration for "
            logger.primary_logger.warning(log_msg + str(self.config_file_location) + " - " + str(error))
            logger.primary_logger.warning(log_msg2 + str(self.config_file_location))
            self.save_config_to_file()
Beispiel #16
0
def upgrade_config_load_and_save(configuration_creation_class, upgrade_msg=True, new_location=None):
    """ Creates configuration class, loads the config and saves it without logging. """
    new_config_instance = configuration_creation_class(load_from_file=False)
    if new_location is not None:
        new_config_instance.config_file_location = new_location
    try:
        old_config_text = get_file_content(new_config_instance.config_file_location)
        new_config_instance.set_config_with_str(old_config_text)
        new_config_instance.save_config_to_file()
        if upgrade_msg:
            logger.primary_logger.info(" ** Configuration " + new_config_instance.config_file_location + " Upgraded")
    except Exception as error:
        log_msg = " ***** Configuration " + new_config_instance.config_file_location
        logger.primary_logger.error(log_msg + " Upgrade Failed: " + str(error))
def _zip_and_delete_database(database_location, db_save_name):
    """ Creates a zip of linked database in the database backup folder then deletes the original database. """
    filename_start = app_cached_variables.ip.split(".")[-1] + app_cached_variables.hostname + "_"
    sql_filename = filename_start + db_save_name + ".sqlite"
    zip_filename = filename_start + str(datetime.utcnow().strftime("%Y-%m-%d_%H_%M_%S")) + db_save_name + ".zip"
    zip_full_path = file_locations.database_backup_folder + "/" + zip_filename
    try:
        zip_content = get_file_content(database_location, open_type="rb")
        zip_files([sql_filename], [zip_content], save_type="save_to_disk", file_location=zip_full_path)
        os.remove(database_location)
        backup_db_zip_filenames = get_list_of_filenames_in_dir(file_locations.database_backup_folder)
        app_cached_variables.zipped_db_backup_list = backup_db_zip_filenames
        return True
    except Exception as error:
        print(str(error))
    backup_db_zip_filenames = get_list_of_filenames_in_dir(file_locations.database_backup_folder)
    app_cached_variables.zipped_db_backup_list = backup_db_zip_filenames
    return False
Beispiel #18
0
def upgrade_beta_34_x_to_35_x():
    reset_live_graph_config(log_reset=False)
    reset_database_graph_config(log_reset=False)
    reset_upgrade_config(log_reset=False)
    reset_checkin_config(log_reset=False)
    reset_urls_config(log_reset=False)
    reset_email_reports_config(log_reset=False)
    reset_email_db_graphs_config(log_reset=False)
    reset_flask_login_credentials()
    reset_email_config()

    sensor_offsets_config = CreateSensorOffsetsConfiguration(
        load_from_file=False)
    new_primary_config = CreatePrimaryConfiguration(load_from_file=False)
    try:
        old_primary_config_string = get_file_content(
            file_locations.primary_config).strip()
        old_primary_config_list = old_primary_config_string.split("\n")[1:]

        new_primary_config.web_portal_port = int(
            old_primary_config_list[0].split("=")[0].strip())
        new_primary_config.enable_debug_logging = int(
            old_primary_config_list[1].split("=")[0].strip())
        sensor_offsets_config.enable_temp_offset = int(
            old_primary_config_list[2].split("=")[0].strip())
        sensor_offsets_config.temperature_offset = float(
            old_primary_config_list[3].split("=")[0].strip())
        sensor_offsets_config.enable_temperature_comp_factor = int(
            old_primary_config_list[4].split("=")[0].strip())
        sensor_offsets_config.temperature_comp_factor = float(
            old_primary_config_list[5].split("=")[0].strip())
        new_primary_config.utc0_hour_offset = float(
            old_primary_config_list[6].split("=")[0].strip())

        new_primary_config.update_configuration_settings_list()
        new_primary_config.save_config_to_file()
        sensor_offsets_config.update_configuration_settings_list()
        sensor_offsets_config.save_config_to_file()
        successful_upgrade_message("Primary & Sensor Offsets")
    except Exception as error:
        logger.primary_logger.warning(
            "Primary & Sensor Offsets Config Upgrade: " + str(error))
        new_primary_config.save_config_to_file()
        sensor_offsets_config.save_config_to_file()
def _check_sensor_id():
    """
    Checks for Sensor Checkin ID file, if missing, creates one.
    The Sensor ID is Randomly Generated and used to track Software Usage and Online History of Sensors.
    """
    try:
        if not os.path.isfile(file_locations.sensor_id):
            random_id = ''.join([
                random.choice(string.ascii_letters + string.digits)
                for _ in range(32)
            ])
            write_file_to_disk(file_locations.sensor_id, random_id)
        else:
            random_id = get_file_content(file_locations.sensor_id).strip()
    except Exception as error:
        logger.primary_logger.error("Problem Creating Sensor ID: " +
                                    str(error))
        random_id = "Error"
    app_cached_variables.tmp_sensor_id = "KS" + random_id
def html_atpro_sensor_settings_mqtt_broker():
    if request.method == "POST":
        app_config_access.mqtt_broker_config.update_with_html_request(request)
        app_config_access.mqtt_broker_config.save_config_to_file()
        if app_config_access.mqtt_broker_config.enable_mqtt_broker:
            if check_mqtt_broker_server_running():
                return_text = "MQTT Broker Service Re-Started"
                restart_mqtt_broker_server()
            else:
                return_text = "MQTT Broker Service Starting"
                start_mqtt_broker_server()
        else:
            return_text = "MQTT Broker Service Stopped"
            stop_mqtt_broker_server()
        return get_message_page("MQTT Broker Settings Updated", return_text, page_url="sensor-settings")
    mosquitto_configuration = "listener 1883\nallow_anonymous true"
    if os.path.isfile(file_locations.mosquitto_configuration):
        mosquitto_configuration = get_file_content(file_locations.mosquitto_configuration)
    return render_template(
        "ATPro_admin/page_templates/settings/settings-mqtt-broker.html",
        BrokerServerChecked=get_html_checkbox_state(check_mqtt_broker_server_running()),
        BrokerMosquittoConfig=mosquitto_configuration
    )
def html_request_to_config_wifi(html_request):
    """ Takes the provided HTML wireless settings and creates a new WPA Supplicant string and returns it. """
    logger.network_logger.debug(
        "Starting HTML WiFi Configuration Update Check")
    if html_request.form.get("ssid1") is not None:
        wifi_template = get_file_content(
            file_locations.wifi_config_file_template)

        wifi_country_code = "CA"
        if len(html_request.form.get("country_code")) == 2:
            wifi_country_code = html_request.form.get("country_code").upper()

        wifi_ssid1 = html_request.form.get("ssid1")
        wifi_security_type1 = html_request.form.get("wifi_security1")
        wifi_psk1 = html_request.form.get("wifi_key1")

        if wifi_security_type1 == "wireless_wpa":
            wifi_security_type1 = wifi_type_secured
            if wifi_psk1 is not "":
                wifi_template = wifi_template.replace(
                    "{{ WirelessPSK1 }}", 'psk="' + wifi_psk1 + '"')
            else:
                wifi_psk1 = app_cached_variables.wifi_psk
                wifi_template = wifi_template.replace(
                    "{{ WirelessPSK1 }}", 'psk="' + wifi_psk1 + '"')
        else:
            wifi_security_type1 = "None"
            wifi_template = wifi_template.replace("{{ WirelessPSK1 }}", "")

        wifi_template = wifi_template.replace("{{ WirelessCountryCode }}",
                                              wifi_country_code)
        wifi_template = wifi_template.replace("{{ WirelessSSID1 }}",
                                              wifi_ssid1)
        wifi_template = wifi_template.replace("{{ WirelessKeyMgmt1 }}",
                                              wifi_security_type1)
        return wifi_template
    return ""
        <title>Kootnet Sensors</title>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
    </head>
    <body style='background-color: black;'>
        <h2 style='text-decoration: underline; color: red;'>Report Not Found</h3>
        <p style='color: white;'>No report found, please generated the report first</p>
    </body>
</html>
"""
html_combo_report = default_report
html_system_report = default_report
html_config_report = default_report
html_readings_report = default_report
html_latency_report = default_report

html_pure_css = get_file_content(html_report_pure_css).strip()
html_pure_css_menu = get_file_content(html_pure_css_menu).strip()
html_report_css = get_file_content(html_report_css).strip()
html_report_js = get_file_content(html_report_js).strip()

html_report_combo = get_file_content(file_locations.html_combo_report).strip()
html_report_combo = html_report_combo.replace("{{ ReportCSSStyles }}",
                                              html_report_css)
html_report_combo = html_report_combo.replace("{{ PureCSS }}", html_pure_css)
html_report_combo = html_report_combo.replace("{{ PureCSSHorizontalMenu }}",
                                              html_pure_css_menu)

html_report_start = get_file_content(html_report_all_start).strip()
html_report_start = html_report_start.replace("{{ ReportCSSStyles }}",
                                              html_report_css)
html_report_end = get_file_content(html_report_all_end).strip()
from operations_modules.app_generic_disk import get_file_content
from operations_modules.sqlite_database import sql_execute_get_data, write_to_sql_database, get_clean_sql_table_name, \
    get_sql_element, get_sqlite_tables_in_list, get_one_db_entry
from configuration_modules import app_config_access
from http_server.server_http_auth import auth
from http_server.flask_blueprints.atpro.atpro_generic import get_message_page
from http_server.flask_blueprints.sensor_checkin_server import check_sensor_checkin_columns

html_atpro_sensor_check_ins_routes = Blueprint(
    "html_atpro_sensor_check_ins_routes", __name__)
db_loc = file_locations.sensor_checkin_database
db_v = app_cached_variables.database_variables

checkin_temp_location = file_locations.program_root_dir + "/http_server/templates/ATPro_admin/page_templates/"
checkin_temp_location += "sensor_checkins/sensor-checkin-table-entry-template.html"
checkin_table_entry_template = get_file_content(checkin_temp_location).strip()
updating_checkin_info_html_msg = "<h3><strong><a style='color: red;'>Updating Information, please wait ...</a></strong></h3>"
checkin_table_failed = "<h3><strong><a style='color: red;'>Sensor Checkins List Generation Failed</a></strong></h3>"


@html_atpro_sensor_check_ins_routes.route("/atpro/sensor-checkin-view")
@auth.login_required
def html_atpro_sensor_checkin_main_view():
    sensor_count = len(get_sqlite_tables_in_list(db_loc))
    app_cached_variables.checkins_db_sensors_count = sensor_count
    if os.path.isfile(db_loc):
        db_size_mb = get_file_size(db_loc, round_to=3)
    else:
        db_size_mb = 0.0

    enabled_text = "<span style='color: red;'>Disabled</span>"
Beispiel #24
0
from operations_modules.app_generic_functions import get_file_size, adjust_datetime, thread_function
from operations_modules.app_generic_disk import get_file_content
from operations_modules.sqlite_database import get_sqlite_tables_in_list, get_clean_sql_table_name, get_one_db_entry
from configuration_modules import app_config_access
from sensor_modules import sensor_access
from http_server.server_http_auth import auth
from http_server.flask_blueprints.atpro.atpro_generic import get_html_atpro_index

html_atpro_mqtt_subscriber_routes = Blueprint(
    "html_atpro_mqtt_subscriber_routes", __name__)
db_loc = file_locations.mqtt_subscriber_database
db_v = app_cached_variables.database_variables

mqtt_sub_tet_location = file_locations.program_root_dir + "/http_server/templates/ATPro_admin/page_templates/"
mqtt_sub_tet_location += "mqtt-subscriber-table-entry-template.html"
mqtt_sub_table_entry_template = get_file_content(mqtt_sub_tet_location).strip()
generating_mqtt_table_html = "<h3><strong><a style='color: red;'>Generating Table, please wait ...</a></strong></h3>"


@html_atpro_mqtt_subscriber_routes.route(
    "/atpro/mqtt-subscriber-view-data-stream")
@auth.login_required
def html_atpro_mqtt_subscriber_data_stream_view():
    mqtt_subscriber_log = file_locations.mqtt_subscriber_log
    max_entries = app_config_access.mqtt_subscriber_config.mqtt_page_view_max_entries
    mqtt_subscriber_log_content = logger.get_sensor_log(
        mqtt_subscriber_log, max_lines=max_entries).strip()
    if mqtt_subscriber_log_content == "":
        mqtt_subscriber_log_content = _mqtt_sub_entry_to_html("")
    else:
        new_return = ""
Beispiel #25
0
def atpro_raw_config_urls(url_path):
    if url_path == "config-software-ver":
        config_name = "<i class='fas fa-code-branch'></i> Software Versions"
        module_version_text = "This will be removed\n" + \
                              kootnet_version + "=Kootnet Sensors\n" + \
                              python_version_str + "=Python\n" + \
                              str(flask_version) + "=Flask\n" + \
                              str(gevent_version) + "=Gevent\n" + \
                              str(greenlet_version) + "=Greenlet\n" + \
                              str(requests_version) + "=Requests\n" + \
                              str(plotly_version) + "=Plotly Graphing\n"
        return _config_to_html_view(config_name, "NA", module_version_text)
    elif url_path == "config-main":
        config_name = "<i class='fas fa-clipboard-check'></i> Main Configuration"
        config_content = app_config_access.primary_config.get_config_as_str()
        return _config_to_html_view(config_name, file_locations.primary_config,
                                    config_content)
    elif url_path == "config-urls":
        config_name = "<i class='fas fa-link'></i> URLs Configuration"
        config_content = app_config_access.urls_config.get_config_as_str()
        return _config_to_html_view(config_name,
                                    file_locations.urls_configuration,
                                    config_content)
    elif url_path == "config-upgrades":
        config_name = "<i class='fas fa-arrow-circle-up'></i> Upgrades Configuration"
        config_content = remove_line_from_text(
            app_config_access.upgrades_config.get_config_as_str(), [3, 4])
        return _config_to_html_view(config_name,
                                    file_locations.upgrades_config,
                                    config_content)
    elif url_path == "config-is":
        config_name = "<i class='fas fa-microchip'></i> Installed Sensors"
        config_content = app_config_access.installed_sensors.get_config_as_str(
        )
        return _config_to_html_view(config_name,
                                    file_locations.installed_sensors_config,
                                    config_content)
    elif url_path == "config-sensor-offsets":
        config_name = "<i class='fas fa-sliders-h'></i> Sensor Offsets"
        config_content = app_config_access.sensor_offsets.get_config_as_str()
        return _config_to_html_view(config_name,
                                    file_locations.sensor_offsets_config,
                                    config_content)
    elif url_path == "config-display":
        config_name = "<i class='fas fa-tv'></i> Display"
        config_content = app_config_access.display_config.get_config_as_str()
        return _config_to_html_view(config_name, file_locations.display_config,
                                    config_content)
    elif url_path == "config-cs":
        config_name = "<i class='fas fa-satellite-dish'></i> Sensor Checkins"
        config_content = app_config_access.checkin_config.get_config_as_str()
        return _config_to_html_view(config_name,
                                    file_locations.checkin_configuration,
                                    config_content)
    elif url_path == "config-ir":
        config_name = "<i class='fas fa-database'></i> Interval Recording"
        config_content = app_config_access.interval_recording_config.get_config_as_str(
        )
        return _config_to_html_view(config_name,
                                    file_locations.interval_config,
                                    config_content)
    elif url_path == "config-high-low":
        config_name = "<i class='fas fa-database'></i> High/Low Trigger Recording"
        config_content = app_config_access.trigger_high_low.get_config_as_str()
        return _config_to_html_view(config_name,
                                    file_locations.trigger_high_low_config,
                                    config_content)
    elif url_path == "config-variance":
        config_name = "<i class='fas fa-database'></i> Variance Trigger Recording"
        config_content = app_config_access.trigger_variances.get_config_as_str(
        )
        return _config_to_html_view(config_name,
                                    file_locations.trigger_variances_config,
                                    config_content)
    elif url_path == "config-reports-email":
        config_name = "<i class='far fa-envelope'></i> Email Reports"
        config_content = app_config_access.email_reports_config.get_config_as_str(
        )
        return _config_to_html_view(config_name,
                                    file_locations.email_reports_config,
                                    config_content)
    elif url_path == "config-db-graphs-email":
        config_name = "<i class='far fa-envelope'></i> Email Database Graphs"
        config_content = app_config_access.email_db_graph_config.get_config_as_str(
        )
        return _config_to_html_view(config_name,
                                    file_locations.email_db_graph_config,
                                    config_content)
    elif url_path == "config-email":
        config_name = "<i class='far fa-envelope'></i> Email"
        config_content = remove_line_from_text(
            app_config_access.email_config.get_config_as_str(), [5, 6])
        return _config_to_html_view(config_name, file_locations.email_config,
                                    config_content)
    elif url_path == "config-mqtt-b":
        config_name = "<i class='fas fa-broadcast-tower'></i> MQTT Broker"
        config_content = app_config_access.mqtt_broker_config.get_config_as_str(
        )
        return _config_to_html_view(config_name,
                                    file_locations.mqtt_broker_config,
                                    config_content)
    elif url_path == "config-mqtt-p":
        config_name = "<i class='fas fa-broadcast-tower'></i> MQTT Publisher"
        config_content = remove_line_from_text(
            app_config_access.mqtt_publisher_config.get_config_as_str(),
            [5, 6])
        return _config_to_html_view(config_name,
                                    file_locations.mqtt_publisher_config,
                                    config_content)
    elif url_path == "config-mqtt-s":
        config_name = "<i class='fas fa-broadcast-tower'></i> MQTT Subscriber"
        config_content = remove_line_from_text(
            app_config_access.mqtt_subscriber_config.get_config_as_str(),
            [5, 6])
        return _config_to_html_view(config_name,
                                    file_locations.mqtt_subscriber_config,
                                    config_content)
    elif url_path == "config-osm":
        config_name = "<i class='fas fa-plus-circle'></i> Open Sense Map"
        config_content = remove_line_from_text(
            app_config_access.open_sense_map_config.get_config_as_str(), [2])
        return _config_to_html_view(config_name, file_locations.osm_config,
                                    config_content)
    elif url_path == "config-wu":
        config_name = "<i class='fas fa-plus-circle'></i> Weather Underground"
        config_content = remove_line_from_text(
            app_config_access.weather_underground_config.get_config_as_str(),
            [4, 5])
        return _config_to_html_view(config_name,
                                    file_locations.weather_underground_config,
                                    config_content)
    elif url_path == "config-luftdaten":
        config_name = "<i class='fas fa-plus-circle'></i> Luftdaten"
        config_content = app_config_access.luftdaten_config.get_config_as_str()
        return _config_to_html_view(config_name,
                                    file_locations.luftdaten_config,
                                    config_content)
    elif url_path == "config-networking":
        config_name = "<i class='fas fa-network-wired'></i> Networking (dhcpcd.conf)"
        if running_with_root and not app_config_access.primary_config.demo_mode:
            config_content = get_file_content(
                file_locations.dhcpcd_config_file)
        else:
            config_content = "Access Denied"
            if app_config_access.primary_config.demo_mode:
                config_content = config_content + " - Demo Mode Enabled"
        return _config_to_html_view(config_name,
                                    file_locations.dhcpcd_config_file,
                                    config_content,
                                    split_by_line=False)
    elif url_path == "config-wifi":
        config_name = "<i class='fas fa-wifi'></i> WiFi"
        if running_with_root and not app_config_access.primary_config.demo_mode:
            config_content = get_file_content(file_locations.wifi_config_file)
        else:
            config_content = "Access Denied"
            if app_config_access.primary_config.demo_mode:
                config_content = config_content + " - Demo Mode Enabled"
        return _config_to_html_view(config_name,
                                    file_locations.wifi_config_file,
                                    config_content,
                                    split_by_line=False)
    elif url_path == "config-sc":
        config_name = "<i class='fas fa-project-diagram'></i> Remote Management Configuration"
        config_content = app_config_access.sensor_control_config.get_config_as_str(
        )
        return _config_to_html_view(config_name,
                                    file_locations.html_sensor_control_config,
                                    config_content)
    elif url_path == "config-live-graph":
        config_name = "<i class='fas fa-chart-line'></i> Live Graphing"
        config_content = app_config_access.live_graphs_config.get_config_as_str(
        )
        return _config_to_html_view(config_name,
                                    file_locations.live_graphs_config,
                                    config_content)
    elif url_path == "config-db-graph":
        config_name = "<i class='fas fa-chart-bar'></i> Database Graphing - Plotly"
        config_content = app_config_access.db_graphs_config.get_config_as_str()
        return _config_to_html_view(config_name,
                                    file_locations.db_graphs_config,
                                    config_content)
    return "<h3>Error</h3>"
def update_cached_variables():
    """ Updates app_cached_variables.py variables. """
    global first_run
    if first_run:
        first_run = False
        thread_function(_update_ks_info_table_data)
        demo_mode = app_config_access.primary_config.demo_mode
        if not app_cached_variables.running_with_root:
            click_msg = "Without root access, the following functions will be unavailable - "
            click_msg += "Hardware Sensors, Network Configurations, Upgrade & Power commands"
            icon = "fas fa-exclamation-triangle"
            notification_short_msg = "Warning: Not running with root<br>Click Here for more information"
            atpro_notifications.add_custom_message(notification_short_msg,
                                                   click_msg=click_msg,
                                                   icon=icon)
        if demo_mode:
            click_msg = "In Demo mode, there are no login prompts and the following functions will be unavailable - "
            click_msg += "Network Configurations, SSL, Change Login, Upgrade & Power commands"
            notification_short_msg = "Info: Running in Demo mode<br>Click Here for more information"
            atpro_notifications.add_custom_message(notification_short_msg,
                                                   click_msg=click_msg)
        if default_http_flask_user == app_cached_variables.http_flask_user and not demo_mode:
            if verify_password_to_hash(default_http_flask_password):
                atpro_notifications.manage_default_login_detected()

    if app_cached_variables.current_platform == "Linux":
        try:
            os_release_content_lines = get_file_content(
                "/etc/os-release").split("\n")
            os_release_name = ""
            for line in os_release_content_lines:
                name_and_value = line.split("=")
                if name_and_value[0].strip() == "PRETTY_NAME":
                    os_release_name = name_and_value[1].strip()[1:-1]
            app_cached_variables.operating_system_name = str(os_release_name)
        except Exception as error:
            logger.sensors_logger.error("Error caching OS Name: " + str(error))
            app_cached_variables.operating_system_name = "NA"

        if app_cached_variables.operating_system_name[:8] == "Raspbian":
            try:
                if app_cached_variables.running_with_root:
                    wifi_config_lines = get_file_content(
                        file_locations.wifi_config_file).split("\n")
                else:
                    wifi_config_lines = ""
                app_cached_variables.wifi_country_code = network_wifi.get_wifi_country_code(
                    wifi_config_lines)
                app_cached_variables.wifi_ssid = network_wifi.get_wifi_ssid(
                    wifi_config_lines)
                app_cached_variables.wifi_security_type = network_wifi.get_wifi_security_type(
                    wifi_config_lines)
                app_cached_variables.wifi_psk = network_wifi.get_wifi_psk(
                    wifi_config_lines)
            except Exception as error:
                logger.primary_logger.warning(
                    "Error checking WiFi configuration: " + str(error))

            try:
                dhcpcd_config_lines = get_file_content(
                    file_locations.dhcpcd_config_file).split("\n")
                if not network_ip.check_for_dhcp(dhcpcd_config_lines):
                    app_cached_variables.ip = network_ip.get_dhcpcd_ip(
                        dhcpcd_config_lines)
                    app_cached_variables.ip_subnet = network_ip.get_subnet(
                        dhcpcd_config_lines)
                    app_cached_variables.gateway = network_ip.get_gateway(
                        dhcpcd_config_lines)
                    app_cached_variables.dns1 = network_ip.get_dns(
                        dhcpcd_config_lines)
                    app_cached_variables.dns2 = network_ip.get_dns(
                        dhcpcd_config_lines, dns_server=1)
            except Exception as error:
                logger.primary_logger.warning("Error checking dhcpcd.conf: " +
                                              str(error))

    try:
        app_cached_variables.total_ram_memory = round(
            psutil.virtual_memory().total / 1024 / 1024 / 1024, 3)
    except Exception as error:
        logger.primary_logger.warning("Error caching total RAM: " + str(error))

    try:
        app_cached_variables.total_disk_space = round(
            psutil.disk_usage("/").total / 1024 / 1024 / 1024, 2)
    except Exception as error:
        logger.primary_logger.warning("Error caching total Disk Space: " +
                                      str(error))

    last_updated = ""
    if not os.path.isfile(file_locations.program_last_updated):
        logger.sensors_logger.debug(
            "Previous version file not found - Creating version file")
        write_file_to_disk(file_locations.program_last_updated,
                           "No Update Detected")
    last_updated_file = get_file_content(file_locations.program_last_updated)
    last_updated_lines = last_updated_file.split("\n")
    for line in last_updated_lines:
        last_updated += str(line)

    app_cached_variables.program_last_updated = last_updated.strip()
    app_cached_variables.zipped_db_backup_list = get_names_list_from_dir(
        file_locations.database_backup_folder)
    app_cached_variables.uploaded_databases_list = get_names_list_from_dir(
        file_locations.uploaded_databases_folder)
    _update_cached_sensor_reboot_count()
    _update_cached_note_variables()
    _update_cached_ip()
    _update_cached_hostname()