diff --git a/additional_files/html_template_readings1.html b/additional_files/html_template_readings1.html
new file mode 100644
index 0000000..50b4930
--- /dev/null
+++ b/additional_files/html_template_readings1.html
@@ -0,0 +1,29 @@
+
+
+
+
+ Sensors System Details
+
+
+
+
+ Sensor Interval Readings |
+ Sensor Trigger Readings |
+
diff --git a/additional_files/html_template_readings2.html b/additional_files/html_template_readings2.html
new file mode 100644
index 0000000..cffe9a8
--- /dev/null
+++ b/additional_files/html_template_readings2.html
@@ -0,0 +1,8 @@
+
+ _{{IntervalTypes}}_ |
+ _{{TriggerTypes}}_ |
+
+
+ _{{IntervalReadings}}_ |
+ _{{TriggerReadings}}_ |
+
diff --git a/additional_files/html_template_readings3.html b/additional_files/html_template_readings3.html
new file mode 100644
index 0000000..1c7c43e
--- /dev/null
+++ b/additional_files/html_template_readings3.html
@@ -0,0 +1,5 @@
+
+Sensor Readings File
+
+
+
diff --git a/app_config.py b/app_config.py
index b17e0b1..9e02ea2 100644
--- a/app_config.py
+++ b/app_config.py
@@ -17,17 +17,21 @@
along with this program. If not, see .
"""
import os
-import sys
import logging
from logging.handlers import RotatingFileHandler
from datetime import datetime
+script_directory = str(os.path.dirname(os.path.realpath(__file__))).replace("\\", "/")
+
+if not os.path.exists(os.path.dirname(script_directory + "/logs/")):
+ os.makedirs(os.path.dirname(script_directory + "/logs/"))
+
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(funcName)s: %(message)s', '%Y-%m-%d %H:%M:%S')
-file_handler = RotatingFileHandler('logs/KootNet_log.txt', maxBytes=256000, backupCount=5)
+file_handler = RotatingFileHandler(script_directory + '/logs/KootNet_log.txt', maxBytes=256000, backupCount=5)
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
@@ -35,57 +39,74 @@
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
-app_location_directory = str(os.path.dirname(sys.argv[0])) + "/"
-config_file = app_location_directory + "config.txt"
-
-class CreateConfigSettings:
+class CreateDefaultConfigSettings:
+ """ Creates a object holding all the Control Centers default configuration options. """
def __init__(self):
- save_to = str(os.path.join(os.path.join(os.environ['USERPROFILE']), 'Desktop\\'))
- self.save_to = save_to.replace('\\', '/')
+ self.script_directory = str(os.path.dirname(os.path.realpath(__file__))).replace("\\", "/")
+ self.logs_directory = script_directory + "/logs"
+ self.additional_files_directory = self.script_directory + "/additional_files"
+ self.config_file = self.script_directory + "/config.txt"
+ self.about_text = self.additional_files_directory + "/about_text.txt"
+ self.app_version = "Tested on Python 3.7 / KootNet Sensors - PC Control Center / Ver. Alpha.19.2"
+
+ # Start of user configurable options
+ self.save_to = str(os.path.expanduser('~/Desktop/')).replace('\\', '/')
self.graph_start = "2018-09-12 00:00:01"
self.graph_end = "2200-01-01 00:00:01"
- self.time_offset = "-7"
- self.sql_queries_skip = "3"
- self.temperature_offset = "-4"
- self.network_check_timeout = "2"
- self.network_details_timeout = "5"
- self.allow_power_controls = 0
- self.allow_reset_config = 0
+ self.datetime_offset = -7.0
+ self.sql_queries_skip = 3
+ self.temperature_offset = -4.0
+ self.live_refresh = 5
+ self.network_timeout_sensor_check = 2
+ self.network_timeout_data = 5
+ self.allow_advanced_controls = 0
self.ip_list = ["192.168.10.11", "192.168.10.12", "192.168.10.13", "192.168.10.14",
"192.168.10.15", "192.168.10.16", "192.168.10.17", "192.168.10.18",
"192.168.10.19", "192.168.10.20", "192.168.10.21", "192.168.10.22",
"192.168.10.23", "192.168.10.24", "192.168.10.25", "192.168.10.26"]
+ def reset_to_defaults(self):
+ default_config = CreateDefaultConfigSettings()
+
+ self.save_to = default_config.save_to
+ self.graph_start = default_config.graph_start
+ self.graph_end = default_config.graph_end
+ self.datetime_offset = default_config.datetime_offset
+ self.sql_queries_skip = default_config.sql_queries_skip
+ self.temperature_offset = default_config.temperature_offset
+ self.live_refresh = default_config.live_refresh
+ self.network_timeout_sensor_check = default_config.network_timeout_sensor_check
+ self.network_timeout_data = default_config.network_timeout_data
+ self.allow_advanced_controls = default_config.allow_advanced_controls
+ self.ip_list = default_config.ip_list
+
-def load_file():
- config_settings = CreateConfigSettings()
+def get_from_file():
+ """ Loads the Control Center configurations from file and returns the Verified settings. """
+ config_settings = CreateDefaultConfigSettings()
try:
- os.path.isfile(config_file)
- local_file = open(config_file, 'r')
+ os.path.isfile(config_settings.config_file)
+ local_file = open(config_settings.config_file, 'r')
tmp_config_settings = local_file.read().split(',')
local_file.close()
config_settings.save_to = tmp_config_settings[0]
config_settings.graph_start = tmp_config_settings[1]
config_settings.graph_end = tmp_config_settings[2]
- config_settings.time_offset = tmp_config_settings[3]
+ config_settings.datetime_offset = tmp_config_settings[3]
config_settings.sql_queries_skip = tmp_config_settings[4]
config_settings.temperature_offset = tmp_config_settings[5]
- config_settings.network_check_timeout = tmp_config_settings[6]
- config_settings.network_details_timeout = tmp_config_settings[7]
+ config_settings.live_refresh = tmp_config_settings[6]
+ config_settings.network_timeout_sensor_check = tmp_config_settings[7]
+ config_settings.network_timeout_data = tmp_config_settings[8]
- if int(tmp_config_settings[8]) >= 0:
- config_settings.allow_power_controls = int(tmp_config_settings[8])
- else:
- logger.error("Setting Enable Sensor Shutdown/Reboot - BAD - Using Default")
-
- if int(tmp_config_settings[9]) >= 0:
- config_settings.allow_reset_config = int(tmp_config_settings[9])
- else:
- logger.error("Setting Enable Config Reset - BAD - Using Default")
+ try:
+ config_settings.allow_advanced_controls = int(tmp_config_settings[9])
+ except Exception as error:
+ logger.error("Setting Enable Sensor Shutdown/Reboot - Using Default: " + str(error))
count = 0
while count < 16:
@@ -98,16 +119,22 @@ def load_file():
count = count + 1
logger.debug("Configuration File Load - OK")
- return config_settings
except Exception as error:
logger.warning("Configuration File Load Failed - Using All or Some Defaults: " + str(error))
- return config_settings
+
+ check_config(config_settings)
+ return config_settings
def check_config(config_settings):
+ """
+ Checks the provided Control Center configuration for validity and returns it.
+
+ Invalid options are replaced with defaults.
+ """
logger.debug("Checking Configuration Settings")
- default_settings = CreateConfigSettings()
+ default_settings = CreateDefaultConfigSettings()
if os.path.isdir(config_settings.save_to):
logger.debug("Setting Save to Folder - OK")
@@ -130,53 +157,54 @@ def check_config(config_settings):
config_settings.graph_end = default_settings.graph_end
try:
- float(config_settings.time_offset)
+ config_settings.datetime_offset = float(config_settings.datetime_offset)
logger.debug("Setting DataBase Hours Offset - OK")
except Exception as error:
logger.error("Setting DataBase Hours Offset - BAD - Using Default: " + str(error))
- config_settings.time_offset = default_settings.time_offset
+ config_settings.datetime_offset = default_settings.datetime_offset
try:
- int(config_settings.sql_queries_skip)
+ config_settings.sql_queries_skip = int(config_settings.sql_queries_skip)
logger.debug("Setting Skip SQL Queries - OK")
except Exception as error:
logger.error("Setting Skip SQL Queries - BAD - Using Default: " + str(error))
config_settings.sql_queries_skip = default_settings.sql_queries_skip
try:
- float(config_settings.temperature_offset)
+ config_settings.temperature_offset = float(config_settings.temperature_offset)
logger.debug("Setting Temperature Offset - OK")
except Exception as error:
logger.error("Setting Temperature Offset - BAD - Using Default: " + str(error))
config_settings.temperature_offset = default_settings.temperature_offset
try:
- int(config_settings.network_check_timeout)
+ config_settings.live_refresh = int(config_settings.live_refresh)
+ logger.debug("Setting Live Refresh - OK")
+ except Exception as error:
+ logger.error("Setting Live Refresh - BAD - Using Default: " + str(error))
+ config_settings.live_refresh = default_settings.live_refresh
+
+ try:
+ config_settings.network_timeout_sensor_check = int(config_settings.network_timeout_sensor_check)
logger.debug("Setting Sensor Check Timeout - OK")
except Exception as error:
logger.error("Setting Sensor Check Timeout - BAD - Using Default: " + str(error))
- config_settings.network_check_timeout = default_settings.network_check_timeout
+ config_settings.network_timeout_sensor_check = default_settings.network_timeout_sensor_check
try:
- int(config_settings.network_details_timeout)
+ config_settings.network_timeout_data = int(config_settings.network_timeout_data)
logger.debug("Setting Get Details Timeout - OK")
except Exception as error:
logger.error("Setting Get Details Timeout - BAD - Using Default: " + str(error))
- config_settings.network_details_timeout = default_settings.network_details_timeout
+ config_settings.network_timeout_data = default_settings.network_timeout_data
try:
- if config_settings.allow_power_controls >= 0:
+ config_settings.allow_advanced_controls = int(config_settings.allow_advanced_controls)
+ if 2 > config_settings.allow_advanced_controls >= 0:
logger.debug("Setting Enable Sensor Shutdown/Reboot - OK")
except Exception as error:
logger.error("Setting Enable Sensor Shutdown/Reboot - BAD - Using Default: " + str(error))
- config_settings.allow_power_controls = default_settings.allow_power_controls
-
- try:
- if config_settings.allow_reset_config >= 0:
- logger.debug("Setting Enable Config Reset - OK")
- except Exception as error:
- logger.error("Setting Enable Config Reset - BAD - Using Default: " + str(error))
- config_settings.allow_reset_config = default_settings.allow_reset_config
+ config_settings.allow_advanced_controls = default_settings.allow_advanced_controls
count = 0
while count < 16:
@@ -187,27 +215,26 @@ def check_config(config_settings):
config_settings.ip_list[count] = default_settings.ip_list[count]
count = count + 1
- return config_settings
-
-def save_config_to_file(temp_config_settings):
- config_settings = check_config(temp_config_settings)
+def save_config_to_file(config_settings):
+ """ Saves provided Control Center configuration to file. """
+ check_config(config_settings)
var_final_write = str(config_settings.save_to)
var_final_write = var_final_write + ',' + str(config_settings.graph_start)
var_final_write = var_final_write + ',' + str(config_settings.graph_end)
- var_final_write = var_final_write + ',' + str(config_settings.time_offset)
+ var_final_write = var_final_write + ',' + str(config_settings.datetime_offset)
var_final_write = var_final_write + ',' + str(config_settings.sql_queries_skip)
var_final_write = var_final_write + ',' + str(config_settings.temperature_offset)
- var_final_write = var_final_write + ',' + str(config_settings.network_check_timeout)
- var_final_write = var_final_write + ',' + str(config_settings.network_details_timeout)
- var_final_write = var_final_write + ',' + str(config_settings.allow_power_controls)
- var_final_write = var_final_write + ',' + str(config_settings.allow_reset_config)
+ var_final_write = var_final_write + ',' + str(config_settings.live_refresh)
+ var_final_write = var_final_write + ',' + str(config_settings.network_timeout_sensor_check)
+ var_final_write = var_final_write + ',' + str(config_settings.network_timeout_data)
+ var_final_write = var_final_write + ',' + str(config_settings.allow_advanced_controls)
for ip in config_settings.ip_list:
var_final_write = var_final_write + ',' + str(ip)
try:
- local_file = open(config_file, 'w')
+ local_file = open(config_settings.config_file, 'w')
local_file.write(var_final_write)
local_file.close()
logger.debug("Configuration Settings Save to File - OK")
diff --git a/app_graph.py b/app_graph.py
index 9745203..7ae93ca 100644
--- a/app_graph.py
+++ b/app_graph.py
@@ -16,21 +16,25 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
+import sensor_commands
import plotly
import sqlite3
-import plotly.graph_objs as go
+import os
import logging
from logging.handlers import RotatingFileHandler
from datetime import datetime, timedelta
-from plotly import tools
+from plotly import tools, graph_objs as go
+from matplotlib import pyplot, animation, style
from guizero import warn
+script_directory = str(os.path.dirname(os.path.realpath(__file__)))
+
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(funcName)s: %(message)s', '%Y-%m-%d %H:%M:%S')
-file_handler = RotatingFileHandler('logs/KootNet_log.txt', maxBytes=256000, backupCount=5)
+file_handler = RotatingFileHandler(script_directory + '/logs/KootNet_log.txt', maxBytes=256000, backupCount=5)
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler()
@@ -39,6 +43,8 @@
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
+style.use("dark_background")
+
class CreateGraphData:
""" Creates an object to hold all the data needed for a graph. """
@@ -52,8 +58,6 @@ def __init__(self):
self.time_offset = 0.0
self.graph_start = "1111-08-21 00:00:01"
self.graph_end = "9999-01-01 00:00:01"
- self.graph_type = ""
- self.graph_table = "IntervalData"
self.graph_columns = ["DateTime", "SensorName", "SensorUpTime", "IP", "SystemTemp", "EnvironmentTemp",
"Pressure", "Humidity", "Lumen", "Red", "Green", "Blue"]
self.max_sql_queries = 200000
@@ -84,131 +88,273 @@ def __init__(self):
self.sql_data_gyro_z = []
-def start_graph(graph_data):
+class CreateLiveGraph:
+ def __init__(self, sensor_type, ip, current_config):
+ self.current_config = current_config
+ self.sensor_type = sensor_type
+ self.ip = ip
+ self.first_datetime = str(datetime.time(datetime.now()))[:8]
+
+ self.fig = pyplot.figure()
+ self.fig.canvas.set_window_title('Live Sensor Graph')
+ self.ax1 = self.fig.add_subplot(1, 1, 1)
+ self.x = []
+ self.y = []
+
+ self.ani = animation.FuncAnimation(self.fig,
+ self._update_graph,
+ interval=float(self.current_config.live_refresh) * 1000)
+ pyplot.show()
+
+ def _update_graph(self, x_frame):
+ current_time = str(datetime.time(datetime.now()))[:8]
+ sensor_name = sensor_commands.get_sensor_hostname(self.ip,
+ self.current_config.network_timeout_data)
+ try:
+ if self.sensor_type is "SensorUpTime":
+ sensor_reading = sensor_commands.get_sensor_uptime(self.ip,
+ self.current_config.network_timeout_data)
+ sensor_type_name = "Sensor Uptime"
+ measurement_type = ""
+ elif self.sensor_type is "SystemTemp":
+ sensor_reading = sensor_commands.get_sensor_cpu_temperature(self.ip,
+ self.current_config.network_timeout_data)
+
+ try:
+ sensor_reading = round(float(sensor_reading), 3)
+ except Exception as error:
+ logger.warning(str(error))
+
+ sensor_type_name = "CPU Temperature"
+ measurement_type = " °C"
+ elif self.sensor_type is "EnvironmentTemp":
+ sensor_reading = sensor_commands.get_sensor_temperature(self.ip,
+ self.current_config.network_timeout_data)
+
+ try:
+ sensor_reading = round(float(sensor_reading) +
+ float(self.current_config.temperature_offset), 3)
+ except Exception as error:
+ logger.warning(str(error))
+
+ sensor_type_name = "Environmental Temperature"
+ measurement_type = " °C"
+ elif self.sensor_type is "Pressure":
+ sensor_reading = sensor_commands.get_sensor_pressure(self.ip,
+ self.current_config.network_timeout_data)
+ sensor_type_name = "Pressure"
+ measurement_type = " hPa"
+ elif self.sensor_type is "Humidity":
+ sensor_reading = sensor_commands.get_sensor_humidity(self.ip,
+ self.current_config.network_timeout_data)
+
+ try:
+ sensor_reading = int(round(float(sensor_reading), 0))
+ except Exception as error:
+ logger.warning(str(error))
+
+ sensor_type_name = "Humidity"
+ measurement_type = " %RH"
+ elif self.sensor_type is "Lumen":
+ sensor_reading = sensor_commands.get_sensor_lumen(self.ip,
+ self.current_config.network_timeout_data)
+ sensor_type_name = "Lumen"
+ measurement_type = " Lumen"
+ elif self.sensor_type[0] == "Red":
+ sensor_reading = sensor_commands.get_sensor_rgb(self.ip,
+ self.current_config.network_timeout_data)
+ sensor_type_name = "RGB"
+ measurement_type = ""
+ elif self.sensor_type[0] == "Acc_X":
+ sensor_reading = 0
+ sensor_type_name = "Accelerometer XYZ"
+ measurement_type = ""
+ elif self.sensor_type[0] == "Mag_X":
+ sensor_reading = 0
+ sensor_type_name = "Magnetometer XYZ"
+ measurement_type = ""
+ elif self.sensor_type[0] == "Gyro_X":
+ sensor_reading = 0
+ sensor_type_name = "Gyroscope XYZ"
+ measurement_type = ""
+ else:
+ sensor_reading = 0
+ sensor_type_name = "Invalid Sensor"
+ measurement_type = ""
+
+ self.ax1.clear()
+ self.y.append(sensor_reading)
+ self.x.append(x_frame)
+ self.ax1.plot(self.x, self.y)
+
+ if self.sensor_type is "SensorUpTime":
+ try:
+ uptime_days = int(float(sensor_reading) // 1440)
+ uptime_hours = int((float(sensor_reading) % 1440) // 60)
+ uptime_min = int(float(sensor_reading) % 60)
+ sensor_reading = str(uptime_days) + " Days / " + \
+ str(uptime_hours) + "." + \
+ str(uptime_min) + " Hours"
+ except Exception as error:
+ logger.warning(str(error))
+
+ pyplot.title("Sensor: " + sensor_name + " || IP: " + self.ip)
+ pyplot.xlabel("Start Time: " + self.first_datetime +
+ " || Last Updated: " + current_time +
+ " || Reading: " + str(sensor_reading) + measurement_type)
+
+ if self.sensor_type is "SensorUpTime":
+ measurement_type = " in Minutes"
+ elif self.sensor_type is "Lumen":
+ measurement_type = ""
+
+ pyplot.ylabel(sensor_type_name + measurement_type)
+ pyplot.xticks([])
+ except Exception as error:
+ logger.error("Live Graph - Invalid Sensor Data: " + str(error))
+
+
+def start_graph_interval(graph_data):
+ graph_data.graph_table = "IntervalData"
logger.debug("SQL Columns: " + str(graph_data.graph_columns))
logger.debug("SQL Table(s): " + str(graph_data.graph_table))
logger.debug("SQL Start DateTime: " + str(graph_data.graph_start))
logger.debug("SQL End DateTime: " + str(graph_data.graph_end))
logger.debug("SQL DataBase Location: " + str(graph_data.db_location))
+ # Adjust dates to Database timezone in UTC 0
new_time_offset = int(graph_data.time_offset) * -1
- get_sql_graph_start = adjust_interval_datetime(graph_data.graph_start, new_time_offset)
- get_sql_graph_end = adjust_interval_datetime(graph_data.graph_end, new_time_offset)
- if graph_data.graph_table == "IntervalData":
- for var_column in graph_data.graph_columns:
- var_sql_query = "SELECT " + \
- str(var_column) + \
- " FROM " + \
- str(graph_data.graph_table) + \
- " WHERE " + \
- var_column + \
- " IS NOT NULL AND DateTime BETWEEN datetime('" + \
- str(get_sql_graph_start) + \
- "') AND datetime('" + \
- str(get_sql_graph_end) + \
- "') LIMIT " + \
- str(graph_data.max_sql_queries)
-
- sql_column_data = get_sql_data(graph_data, var_sql_query)
-
- if str(var_column) == "DateTime":
- count = 0
- for data in sql_column_data:
- sql_column_data[count] = adjust_interval_datetime(data, int(graph_data.time_offset))
+ get_sql_graph_start = _adjust_interval_datetime(graph_data.graph_start, new_time_offset)
+ get_sql_graph_end = _adjust_interval_datetime(graph_data.graph_end, new_time_offset)
+ for var_column in graph_data.graph_columns:
+ var_sql_query = "SELECT " + \
+ str(var_column) + \
+ " FROM " + \
+ str(graph_data.graph_table) + \
+ " WHERE " + \
+ var_column + \
+ " IS NOT NULL AND DateTime BETWEEN datetime('" + \
+ str(get_sql_graph_start) + \
+ "') AND datetime('" + \
+ str(get_sql_graph_end) + \
+ "') LIMIT " + \
+ str(graph_data.max_sql_queries)
+
+ sql_column_data = _get_sql_data(graph_data, var_sql_query)
+
+ # Adjust SQL data from its UTC time, to user set timezone (Hour Offset)
+ if str(var_column) == "DateTime":
+ count = 0
+ for data in sql_column_data:
+ sql_column_data[count] = _adjust_interval_datetime(data, int(graph_data.time_offset))
+ count = count + 1
+
+ graph_data.sql_data_time = sql_column_data
+
+ elif str(var_column) == "SensorName":
+ graph_data.sql_data_host_name = sql_column_data
+ elif str(var_column) == "SensorUpTime":
+ graph_data.sql_data_up_time = sql_column_data
+ elif str(var_column) == "IP":
+ graph_data.sql_data_ip = sql_column_data
+ elif str(var_column) == "SystemTemp":
+ graph_data.sql_data_cpu_temp = sql_column_data
+ elif str(var_column) == "EnvironmentTemp":
+ count = 0
+ for data in sql_column_data:
+ try:
+ sql_column_data[count] = str(float(data) + float(graph_data.temperature_offset))
count = count + 1
-
- graph_data.sql_data_time = sql_column_data
-
- elif str(var_column) == "SensorName":
- graph_data.sql_data_host_name = sql_column_data
- elif str(var_column) == "SensorUpTime":
- graph_data.sql_data_up_time = sql_column_data
- elif str(var_column) == "IP":
- graph_data.sql_data_ip = sql_column_data
- elif str(var_column) == "SystemTemp":
- graph_data.sql_data_cpu_temp = sql_column_data
- elif str(var_column) == "EnvironmentTemp":
- count = 0
- for data in sql_column_data:
- try:
- sql_column_data[count] = str(float(data) + float(graph_data.temperature_offset))
- count = count + 1
- except Exception as error:
- count = count + 1
- logger.error("Bad SQL entry from Column 'EnvironmentTemp' - " + str(error))
-
- graph_data.sql_data_hat_temp = sql_column_data
-
- elif str(var_column) == "Pressure":
- graph_data.sql_data_pressure = sql_column_data
- elif str(var_column) == "Humidity":
- graph_data.sql_data_humidity = sql_column_data
- elif str(var_column) == "Lumen":
- graph_data.sql_data_lumen = sql_column_data
- elif str(var_column) == "Red":
- graph_data.sql_data_red = sql_column_data
- elif str(var_column) == "Green":
- graph_data.sql_data_green = sql_column_data
- elif str(var_column) == "Blue":
- graph_data.sql_data_blue = sql_column_data
- else:
- logger.error(var_column + " - Does Not Exist")
-
- elif graph_data.graph_table == "TriggerData":
- for var_column in graph_data.graph_columns:
- var_sql_query = "SELECT " + \
- str(var_column) + \
- " FROM " + \
- str(graph_data.graph_table) + \
- " WHERE " + \
- var_column + \
- " IS NOT NULL AND DateTime BETWEEN datetime('" + \
- str(get_sql_graph_start) + \
- ".000') AND datetime('" + \
- str(get_sql_graph_end) + \
- ".000') LIMIT " + \
- str(graph_data.max_sql_queries)
-
- sql_column_data = get_sql_data(graph_data, var_sql_query)
-
- if str(var_column) == "DateTime":
- count = 0
- for data in sql_column_data:
- sql_column_data[count] = adjust_trigger_datetime(data, int(graph_data.time_offset))
+ except Exception as error:
count = count + 1
-
- graph_data.sql_data_time = sql_column_data
-
- elif str(var_column) == "SensorName":
- graph_data.sql_data_host_name = sql_column_data
- elif str(var_column) == "IP":
- graph_data.sql_data_ip = sql_column_data
- elif str(var_column) == "Acc_X":
- graph_data.sql_data_acc_x = sql_column_data
- elif str(var_column) == "Acc_Y":
- graph_data.sql_data_acc_y = sql_column_data
- elif str(var_column) == "Acc_Z":
- graph_data.sql_data_acc_z = sql_column_data
- elif str(var_column) == "Mag_X":
- graph_data.sql_data_mg_x = sql_column_data
- elif str(var_column) == "Mag_Y":
- graph_data.sql_data_mg_y = sql_column_data
- elif str(var_column) == "Mag_Z":
- graph_data.sql_data_mg_z = sql_column_data
- elif str(var_column) == "Gyro_X":
- graph_data.sql_data_gyro_x = sql_column_data
- elif str(var_column) == "Gyro_Y":
- graph_data.sql_data_gyro_y = sql_column_data
- elif str(var_column) == "Gyro_Z":
- graph_data.sql_data_gyro_z = sql_column_data
- else:
- logger.error(var_column + " - Does Not Exist")
-
- trace_graph(graph_data)
+ logger.error("Bad SQL entry from Column 'EnvironmentTemp' - " + str(error))
+
+ graph_data.sql_data_hat_temp = sql_column_data
+
+ elif str(var_column) == "Pressure":
+ graph_data.sql_data_pressure = sql_column_data
+ elif str(var_column) == "Humidity":
+ graph_data.sql_data_humidity = sql_column_data
+ elif str(var_column) == "Lumen":
+ graph_data.sql_data_lumen = sql_column_data
+ elif str(var_column) == "Red":
+ graph_data.sql_data_red = sql_column_data
+ elif str(var_column) == "Green":
+ graph_data.sql_data_green = sql_column_data
+ elif str(var_column) == "Blue":
+ graph_data.sql_data_blue = sql_column_data
+ else:
+ logger.error(var_column + " - Does Not Exist")
+ _plotly_graph(graph_data)
logger.debug("Interval DB Graph Complete")
-def adjust_interval_datetime(var_datetime, time_offset):
+def start_graph_trigger(graph_data):
+ graph_data.graph_table = "TriggerData"
+ logger.debug("SQL Columns: " + str(graph_data.graph_columns))
+ logger.debug("SQL Table(s): " + str(graph_data.graph_table))
+ logger.debug("SQL Start DateTime: " + str(graph_data.graph_start))
+ logger.debug("SQL End DateTime: " + str(graph_data.graph_end))
+ logger.debug("SQL DataBase Location: " + str(graph_data.db_location))
+
+ # Adjust dates to Database timezone in UTC 0
+ new_time_offset = int(graph_data.time_offset) * -1
+ get_sql_graph_start = _adjust_interval_datetime(graph_data.graph_start, new_time_offset)
+ get_sql_graph_end = _adjust_interval_datetime(graph_data.graph_end, new_time_offset)
+
+ for var_column in graph_data.graph_columns:
+ var_sql_query = "SELECT " + \
+ str(var_column) + \
+ " FROM " + \
+ str(graph_data.graph_table) + \
+ " WHERE " + \
+ var_column + \
+ " IS NOT NULL AND DateTime BETWEEN datetime('" + \
+ str(get_sql_graph_start) + \
+ ".000') AND datetime('" + \
+ str(get_sql_graph_end) + \
+ ".000') LIMIT " + \
+ str(graph_data.max_sql_queries)
+
+ sql_column_data = _get_sql_data(graph_data, var_sql_query)
+
+ if str(var_column) == "DateTime":
+ count = 0
+ for data in sql_column_data:
+ sql_column_data[count] = _adjust_trigger_datetime(data, int(graph_data.time_offset))
+ count = count + 1
+
+ graph_data.sql_data_time = sql_column_data
+
+ elif str(var_column) == "SensorName":
+ graph_data.sql_data_host_name = sql_column_data
+ elif str(var_column) == "IP":
+ graph_data.sql_data_ip = sql_column_data
+ elif str(var_column) == "Acc_X":
+ graph_data.sql_data_acc_x = sql_column_data
+ elif str(var_column) == "Acc_Y":
+ graph_data.sql_data_acc_y = sql_column_data
+ elif str(var_column) == "Acc_Z":
+ graph_data.sql_data_acc_z = sql_column_data
+ elif str(var_column) == "Mag_X":
+ graph_data.sql_data_mg_x = sql_column_data
+ elif str(var_column) == "Mag_Y":
+ graph_data.sql_data_mg_y = sql_column_data
+ elif str(var_column) == "Mag_Z":
+ graph_data.sql_data_mg_z = sql_column_data
+ elif str(var_column) == "Gyro_X":
+ graph_data.sql_data_gyro_x = sql_column_data
+ elif str(var_column) == "Gyro_Y":
+ graph_data.sql_data_gyro_y = sql_column_data
+ elif str(var_column) == "Gyro_Z":
+ graph_data.sql_data_gyro_z = sql_column_data
+ else:
+ logger.error(var_column + " - Does Not Exist")
+ _plotly_graph(graph_data)
+ logger.debug("Trigger DB Graph Complete")
+
+
+def _adjust_interval_datetime(var_datetime, time_offset):
"""
Adjusts the provided datetime by the provided hour offset and returns the result.
@@ -229,7 +375,7 @@ def adjust_interval_datetime(var_datetime, time_offset):
return str(new_time)
-def adjust_trigger_datetime(var_datetime, time_offset):
+def _adjust_trigger_datetime(var_datetime, time_offset):
"""
Adjusts the provided datetime by the provided hour offset and returns the result.
@@ -258,7 +404,7 @@ def adjust_trigger_datetime(var_datetime, time_offset):
return str(new_time) + tmp_ms
-def get_sql_data(graph_interval_data, sql_command):
+def _get_sql_data(graph_interval_data, sql_command):
""" Execute SQLite3 command and return the results. """
return_data = []
@@ -288,7 +434,7 @@ def get_sql_data(graph_interval_data, sql_command):
return return_data
-def trace_graph(graph_interval_data):
+def _plotly_graph(graph_interval_data):
""" Create and open a HTML offline Plotly graph with the data provided. """
sub_plots = []
row_count = 0
@@ -336,7 +482,7 @@ def trace_graph(graph_interval_data):
sub_plots.append('Sensor Uptime')
logger.debug("Graph Sensor Uptime Added")
- if len(graph_interval_data.sql_data_cpu_temp) > 1:
+ if len(graph_interval_data.sql_data_cpu_temp) > 1 or len(graph_interval_data.sql_data_hat_temp) > 1:
row_count = row_count + 1
trace_cpu_temp = go.Scatter(x=graph_interval_data.sql_data_time,
@@ -495,7 +641,7 @@ def trace_graph(graph_interval_data):
fig['layout'].update(height=2048)
try:
- plotly.offline.plot(fig, filename=graph_interval_data.save_file_to + 'PlotSensors.html', auto_open=True)
+ plotly.offline.plot(fig, filename=graph_interval_data.save_file_to + 'SensorGraph.html', auto_open=True)
logger.debug("Graph Creation - OK")
except Exception as error:
logger.error("Graph Creation - Failed - " + str(error))
diff --git a/app_reports.py b/app_reports.py
index a3bd6ea..b318d77 100644
--- a/app_reports.py
+++ b/app_reports.py
@@ -16,20 +16,21 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
+import sensor_commands
import webbrowser
-import sys
import os
import logging
-from sensor_commands import get_system_info, get_sensor_config
-from app_config import load_file as load_config
+import app_config
from logging.handlers import RotatingFileHandler
+script_directory = str(os.path.dirname(os.path.realpath(__file__))).replace("\\", "/")
+
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(funcName)s: %(message)s', '%Y-%m-%d %H:%M:%S')
-file_handler = RotatingFileHandler('logs/KootNet_log.txt', maxBytes=256000, backupCount=5)
+file_handler = RotatingFileHandler(script_directory + '/logs/KootNet_log.txt', maxBytes=256000, backupCount=5)
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
@@ -37,176 +38,164 @@
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
-app_location_directory = str(os.path.dirname(sys.argv[0])) + "/"
-html_template_system1 = "additional_files/html_template_system1.html"
-html_template_system2 = "additional_files/html_template_system2.html"
-html_template_system3 = "additional_files/html_template_system3.html"
-html_template_config1 = "additional_files/html_template_config1.html"
-html_template_config2 = "additional_files/html_template_config2.html"
-html_template_config3 = "additional_files/html_template_config3.html"
-
-
-def html_system_codes():
- logger.debug("Getting Sensor Details HTML replacement Codes")
-
- html_replacement_vars = ["{{HostName}}",
- "{{IP}}",
- "{{DateTime}}",
- "{{UpTime}}",
- "{{CPUTemp}}",
- "{{FreeDisk}}",
- "{{IntervalSize}}",
- "{{TriggerSize}}",
- "{{SQLWriteEnabled}}",
- "{{CustomEnabled}}"]
-
- return html_replacement_vars
+class HTMLSystem:
+ def __init__(self):
+ self.config_settings = app_config.get_from_file()
+ self.template1 = script_directory + "/additional_files/html_template_system1.html"
+ self.template2 = script_directory + "/additional_files/html_template_system2.html"
+ self.template3 = script_directory + "/additional_files/html_template_system3.html"
+ self.file_output_name = "SensorsSystem.html"
+
+ self.replacement_codes = ["{{HostName}}",
+ "{{IP}}",
+ "{{DateTime}}",
+ "{{UpTime}}",
+ "{{CPUTemp}}",
+ "{{FreeDisk}}",
+ "{{IntervalSize}}",
+ "{{TriggerSize}}",
+ "{{SQLWriteEnabled}}",
+ "{{CustomEnabled}}"]
+
+ def get_sensor_data(self, ip):
+ sensor_data = sensor_commands.get_sensor_system(ip, self.config_settings.network_timeout_data)
+ # Convert the sensor's system uptime of minutes to human readable day/hour.min
+ sensor_data[3] = _convert_minutes_string(sensor_data[3])
+
+ return sensor_data
+
+
+class HTMLReadings:
+ def __init__(self):
+ self.config_settings = app_config.get_from_file()
+ self.template1 = script_directory + "/additional_files/html_template_readings1.html"
+ self.template2 = script_directory + "/additional_files/html_template_readings2.html"
+ self.template3 = script_directory + "/additional_files/html_template_readings3.html"
+ self.file_output_name = "SensorsSystem.html"
+
+ self.replacement_codes = ["{{IntervalTypes}}",
+ "{{IntervalReadings}}",
+ "{{TriggerTypes}}",
+ "{{TriggerReadings}}"]
+
+ def get_sensor_data(self, ip):
+ sensor_data = sensor_commands.get_sensor_readings(ip, self.config_settings.network_timeout_data)
+
+ return sensor_data
+
+
+class HTMLConfig:
+ def __init__(self):
+ self.config_settings = app_config.get_from_file()
+ self.template1 = script_directory + "/additional_files/html_template_config1.html"
+ self.template2 = script_directory + "/additional_files/html_template_config2.html"
+ self.template3 = script_directory + "/additional_files/html_template_config3.html"
+ self.file_output_name = "SensorsConfig.html"
+
+ self.replacement_codes = ["{{HostName}}",
+ "{{IP}}",
+ "{{DateTime}}",
+ "{{IntervalDuration}}",
+ "{{TriggerDuration}}",
+ "{{SQLWriteEnabled}}",
+ "{{CustomEnabled}}",
+ "{{CustomAcc}}",
+ "{{CustomMag}}",
+ "{{CustomGyro}}"]
+
+ def get_sensor_data(self, ip):
+ sensor_data = sensor_commands.get_sensor_config(ip, self.config_settings.network_timeout_data)
+
+ return sensor_data
+
+
+def sensor_html_report(report_configuration, ip_list):
+ """ Creates and opens a HTML Report based on provided IP's and report configurations data. """
+ final_file = _get_file_content(report_configuration.template1)
+ sensor_html_template = _get_file_content(report_configuration.template2)
+
+ # Add first HTML Template file to final HTML output file
+ # Insert each sensors data into final HTML output file through the 2nd template & replacement codes
+ for ip in ip_list:
+ try:
+ current_sensor_html = sensor_html_template
+ sensor_data = report_configuration.get_sensor_data(ip)
-def html_config_codes():
- logger.debug("Getting Sensor Config HTML replacement Codes")
-
- html_replacement_vars = ["{{HostName}}",
- "{{IP}}",
- "{{DateTime}}",
- "{{IntervalDuration}}",
- "{{TriggerDuration}}",
- "{{SQLWriteEnabled}}",
- "{{CustomEnabled}}",
- "{{CustomAcc}}",
- "{{CustomMag}}",
- "{{CustomGyro}}"]
+ current_sensor_html = _replace_with_codes(sensor_data,
+ report_configuration.replacement_codes,
+ current_sensor_html)
- return html_replacement_vars
+ final_file = final_file + current_sensor_html
+ except Exception as error:
+ logger.error("Report Failure: " + str(error))
+ # Merge the result with the Final HTML Template file.
+ template3 = _get_file_content(report_configuration.template3)
+ final_file = final_file + template3
-def open_html(outfile):
try:
- file_var = "file:///" + outfile
- webbrowser.open(file_var, new=2)
- logger.debug("Graph HTML File Opened - OK")
+ save_to_location = str(report_configuration.config_settings.save_to + report_configuration.file_output_name)
+ _save_data_to_file(final_file, save_to_location)
+ _open_html(save_to_location)
+ logger.debug("Sensor Report - HTML Save File - OK")
except Exception as error:
- logger.error("Graph HTML File Opened - Failed - " + str(error))
-
-
-def open_url(url):
- webbrowser.open(url)
+ logger.error("Sensor Report - HTML Save File - Failed: " + str(error))
-def sensor_system_report(ip_list):
- final_file = ''
- sensor_html = ''
- temp_config = load_config()
- net_timeout = int(temp_config.network_details_timeout)
-
+def _get_file_content(file_location):
try:
- html_file_part = open(str(app_location_directory + html_template_system1), 'r')
- final_file = html_file_part.read()
- html_file_part.close()
- html_file_part = open(str(app_location_directory + html_template_system2), 'r')
- sensor_html = html_file_part.read()
- html_file_part.close()
- logger.debug("Open First 2 System Report Templates - OK")
+ tmp_file = open(file_location, "r")
+ file_content = tmp_file.read()
+ tmp_file.close()
except Exception as error:
- logger.error("Open First 2 System Report Templates - Failed: " + str(error))
+ logger.error("Unable to get file contents: " + str(error))
+ file_content = "Unable to get file contents: " + str(error)
- # For each IP in the list, Get its data per Report "Type"
- # Inserting them into a final HTML file, based on a 3 part template
- replacement_codes = html_system_codes()
- for ip in ip_list:
- try:
- current_sensor_html = sensor_html
- sensor_data = get_system_info(ip, net_timeout)
-
- uptime_days = int(float(sensor_data[3]) // 1440)
- uptime_hours = int((float(sensor_data[3]) % 1440) // 60)
- uptime_min = int(float(sensor_data[3]) % 60)
- sensor_data[3] = str(uptime_days) + " Days / " + str(uptime_hours) + "." + str(uptime_min) + " Hours"
-
- count = 0
- for code in replacement_codes:
- try:
- replace_word = str(sensor_data[count])
- except Exception as error:
- replace_word = "Failed"
- logger.error("Invalid Sensor Data: " + str(error))
-
- print(code + " / " + replace_word)
- current_sensor_html = current_sensor_html.replace(code, replace_word)
- count = count + 1
- final_file = final_file + current_sensor_html
- except Exception as error:
- logger.error("System Report Failure: " + str(error))
+ return file_content
- try:
- html_file_part = open(str(app_location_directory + html_template_system3), 'r')
- html_end = html_file_part.read()
- html_file_part.close()
- final_file = final_file + html_end
- logger.debug("Created System Report - HTML File - OK")
- except Exception as error:
- logger.error("Open 3rd System Report Template File Failed: " + str(error))
+def _convert_minutes_string(var_minutes):
try:
- save_to_location = str(temp_config.save_to + "SensorsSystem.html")
- file_out = open(save_to_location, 'w')
- file_out.write(final_file)
- file_out.close()
- open_html(save_to_location)
- logger.debug("Sensor System Report - HTML Save File - OK")
+ uptime_days = int(float(var_minutes) // 1440)
+ uptime_hours = int((float(var_minutes) % 1440) // 60)
+ uptime_min = int(float(var_minutes) % 60)
+ str_day_hour_min = str(uptime_days) + " Days / " + str(uptime_hours) + "." + str(uptime_min) + " Hours"
except Exception as error:
- logger.error("Sensor System Report - HTML Save File - Failed: " + str(error))
+ logger.error("Unable to convert Minutes to days/hours.min: " + str(error))
+ str_day_hour_min = var_minutes
+ return str_day_hour_min
-def sensor_config_report(ip_list):
- final_file = ''
- sensor_html = ''
- temp_config = load_config()
- net_timeout = int(temp_config.network_details_timeout)
- try:
- html_file_part = open(str(app_location_directory + html_template_config1), 'r')
- final_file = html_file_part.read()
- html_file_part.close()
- html_file_part = open(str(app_location_directory + html_template_config2), 'r')
- sensor_html = html_file_part.read()
- html_file_part.close()
- logger.debug("Open First 2 Config Report Templates - OK")
- except Exception as error:
- logger.error("Open First 2 Config Report Templates - Failed: " + str(error))
-
- # For each IP in the list, Get its data per Report "Type"
- # Inserting them into a final HTML file, based on a 3 part template
- replacement_codes = html_config_codes()
- for ip in ip_list:
+def _replace_with_codes(data, codes, template):
+ count = 0
+ for code in codes:
try:
- current_sensor_html = sensor_html
- sensor_data = get_sensor_config(ip, net_timeout)
-
- count = 0
- for code in replacement_codes:
- current_sensor_html = current_sensor_html.replace(code, str(sensor_data[count]))
- count = count + 1
- final_file = final_file + current_sensor_html
+ replace_word = str(data[count])
except Exception as error:
- logger.error("Config Report Failure: " + str(error))
+ replace_word = "No Data"
+ logger.error("Invalid Sensor Data: " + str(error))
+
+ template = template.replace(code, replace_word)
+ count = count + 1
+
+ return template
+
+def _save_data_to_file(data, file_location):
try:
- html_file_part = open(str(app_location_directory + html_template_config3), 'r')
- html_end = html_file_part.read()
- html_file_part.close()
- final_file = final_file + html_end
- logger.debug("Created Sensor Config Report - HTML File - OK")
+ file_out = open(file_location, "w")
+ file_out.write(data)
+ file_out.close()
except Exception as error:
- logger.error("Open 3rd Template File Failed: " + str(error))
+ logger.error("Unable to save file: " + str(error))
- # Write to a HTML file
+
+def _open_html(outfile):
+ """ Opens a HTML file in the default web browser. """
try:
- save_to_location = str(temp_config.save_to + "SensorsConfig.html")
- file_out = open(save_to_location, 'w')
- file_out.write(final_file)
- file_out.close()
- open_html(save_to_location)
- logger.debug("Sensor Config Report - HTML Save File - OK")
+ webbrowser.open_new_tab("file:///" + outfile)
+ logger.debug("Graph HTML File Opened - OK")
except Exception as error:
- logger.error("Sensor Config Report - HTML Save File - Failed: " + str(error))
+ logger.error("Graph HTML File Opened - Failed - " + str(error))
diff --git a/main_guizero.py b/main_guizero.py
index ff210ee..ec02a6c 100644
--- a/main_guizero.py
+++ b/main_guizero.py
@@ -20,7 +20,6 @@
DEBUG - Detailed information, typically of interest only when diagnosing problems. test
INFO - Confirmation that things are working as expected.
WARNING - An indication that something unexpected happened, or indicative of some problem in the near future
- (e.g. ‘disk space low’). The software is still working as expected.
ERROR - Due to a more serious problem, the software has not been able to perform some function.
CRITICAL - A serious error, indicating that the program itself may be unable to continue running.
"""
@@ -29,43 +28,112 @@
import app_reports
import app_graph
import os
-import sys
import platform
import subprocess
-from guizero import App, Window, CheckBox, PushButton, Text, TextBox, MenuBar, info, ButtonGroup
+import webbrowser
+from guizero import App, Window, CheckBox, PushButton, Text, TextBox, MenuBar, info, warn, ButtonGroup
from tkinter import filedialog
+from matplotlib import pyplot
from threading import Thread
from queue import Queue
import logging
from logging.handlers import RotatingFileHandler
-logger = logging.getLogger(__name__)
+script_directory = str(os.path.dirname(os.path.realpath(__file__))).replace("\\", "/")
+logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
-formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', '%Y-%m-%d %H:%M:%S')
-file_handler = RotatingFileHandler('logs/KootNet_log.txt', maxBytes=256000, backupCount=5)
+file_handler = RotatingFileHandler(script_directory + '/logs/KootNet_log.txt',
+ maxBytes=256000,
+ backupCount=5)
+formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s',
+ '%Y-%m-%d %H:%M:%S')
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
-
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
-app_location_directory = str(os.path.dirname(sys.argv[0])) + "/"
-config_file = app_location_directory + "/config.txt"
-app_version = "Tested on Python 3.7 / KootNet Sensors - PC Control Center / Ver. Alpha.19.1"
-app_about_location = app_location_directory + "/additional_files/about_text.txt"
-
-sensor_ip_queue = Queue()
-sensor_data_queue = Queue()
-
-
-def set_about_text():
+current_config = app_config.get_from_file()
+data_queue = Queue()
+
+
+def _app_custom_configurations():
+ """ Apply system & user specific settings to application. Used just before application start. """
+ # Add extra tk options to guizero windows
+ app.on_close(_app_exit)
+ app.tk.resizable(False, False)
+ window_graph.tk.resizable(False, False)
+ window_sensor_commands.tk.resizable(False, False)
+ window_sensor_config.tk.resizable(False, False)
+ window_sensor_reports.tk.resizable(False, False)
+ window_app_about.tk.resizable(False, False)
+ window_config.tk.resizable(False, False)
+
+ # Add custom selections and GUI settings
+ app_checkbox_all_column1.value = 0
+ app_checkbox_all_column2.value = 0
+ graph_checkbox_up_time.value = 1
+ graph_checkbox_temperature.value = 1
+ graph_checkbox_pressure.value = 0
+ graph_checkbox_humidity.value = 0
+ graph_checkbox_lumen.value = 0
+ graph_checkbox_colour.value = 0
+ sensor_config_checkbox_db_record.value = 1
+ sensor_config_checkbox_custom.value = 0
+
+ _set_about_text()
+ app_check_all_ip_checkboxes(1)
+ app_check_all_ip_checkboxes(2)
+ _graph_radio_selection()
+ sensor_config_enable_recording()
+ sensor_config_enable_custom()
+
+ about_textbox.disable()
+ config_textbox_save_to.disable()
+ sensor_config_button_set_config.disable()
+ commands_button_os_Upgrade.disable()
+
+ # Platform specific adjustments
+ if platform.system() == "Windows":
+ app.tk.iconbitmap(current_config.additional_files_directory + "/icon.ico")
+ elif platform.system() == "Linux":
+ app.width = 490
+ app.height = 250
+ window_config.width = 675
+ window_config.height = 275
+ window_graph.width = 325
+ window_graph.height = 440
+ window_sensor_config.width = 365
+ window_sensor_config.height = 240
+ window_sensor_commands.width = 300
+ window_sensor_commands.height = 260
+ window_app_about.width = 555
+ window_app_about.height = 290
+
+ set_config()
+ if not os.path.isfile(current_config.config_file):
+ logger.info('No Configuration File Found - Saving Default')
+ app_config.save_config_to_file(current_config)
+
+
+def _app_exit():
+ """ Clean ups before application closes. """
+ log_handlers = logger.handlers[:]
+ for handler in log_handlers:
+ handler.close()
+ logger.removeHandler(handler)
+
+ pyplot.close()
+ app.destroy()
+
+
+def _set_about_text():
""" Loads and sets the about text from file. """
try:
- local_file = open(app_about_location, 'r')
+ local_file = open(current_config.about_text, 'r')
new_text = local_file.read()
local_file.close()
about_textbox.value = new_text
@@ -74,94 +142,82 @@ def set_about_text():
logger.error("About Text Load - Failed: " + str(error))
-def app_menu_open_log():
+def app_menu_open_logs():
""" Opens the folder where the logs are kept. """
logger.debug("Open Logs Folder")
- log_path = app_location_directory + "logs/"
if platform.system() == "Windows":
- os.startfile(log_path)
+ os.startfile(current_config.logs_directory)
elif platform.system() == "Darwin":
- subprocess.Popen(["open", log_path])
+ subprocess.Popen(["open", current_config.logs_directory])
else:
- subprocess.Popen(["xdg-open", log_path])
-
-
-def app_menu_open_config():
- """ Open's the Configuration window. """
- window_config.show()
-
-
-def app_menu_open_commands():
- """ Open's the Sensor Commands window. """
- window_sensor_commands.show()
-
-
-def app_menu_open_sensor_config():
- """ Open's the Sensor Configuration window. """
- window_sensor_config.show()
+ subprocess.Popen(["xdg-open", current_config.logs_directory])
def app_menu_download_interval_db():
""" Downloads the Interval SQLite3 database to the chosen location, from the selected sensors. """
- ip_list = check_sensors()
- threads = []
- download_to_location = filedialog.askdirectory()
+ ip_list = get_verified_ip_list()
+ if len(ip_list) >= 1:
+ threads = []
+ download_to_location = filedialog.askdirectory()
- for ip in ip_list:
- threads.append(Thread(target=sensor_commands.download_interval_db, args=[ip, download_to_location]))
+ if download_to_location is not "" and download_to_location is not None:
+ for ip in ip_list:
+ threads.append(Thread(target=sensor_commands.download_interval_db,
+ args=[ip, download_to_location]))
- for thread in threads:
- thread.start()
+ for thread in threads:
+ thread.start()
- for thread in threads:
- thread.join()
+ for thread in threads:
+ thread.join()
- info("Downloads", "Interval Database Downloads Complete")
+ info("Downloads", "Interval Database Downloads Complete")
+ else:
+ warn("Warning", "User Cancelled Download Operation")
+ else:
+ warn("No IP Selected", "Please Select at least 1 Sensor IP")
def app_menu_download_trigger_db():
""" Downloads the Trigger SQLite3 database to the chosen location, from the selected sensors. """
- ip_list = check_sensors()
- threads = []
- download_to_location = filedialog.askdirectory()
+ ip_list = get_verified_ip_list()
+ if len(ip_list) >= 1:
+ threads = []
+ download_to_location = filedialog.askdirectory()
- for ip in ip_list:
- threads.append(Thread(target=sensor_commands.download_trigger_db, args=[ip, download_to_location]))
-
- for thread in threads:
- thread.start()
-
- for thread in threads:
- thread.join()
+ if download_to_location is not "" and download_to_location is not None:
+ for ip in ip_list:
+ threads.append(Thread(target=sensor_commands.download_trigger_db,
+ args=[ip, download_to_location]))
- info("Downloads", "Trigger Database Downloads Complete")
+ for thread in threads:
+ thread.start()
+ for thread in threads:
+ thread.join()
-def app_menu_open_graph():
- """ Open the graphing window. """
- window_graph_interval.show()
+ info("Downloads", "Trigger Database Downloads Complete")
+ else:
+ warn("Warning", "User Cancelled Download Operation")
+ else:
+ warn("No IP Selected", "Please Select at least 1 Sensor IP")
def app_menu_open_website():
""" Open the program's Website. """
- app_reports.open_url("http://kootenay-networks.com/?page_id=170")
-
-
-def app_menu_open_about():
- """ Open the About window. """
- window_app_about.show()
+ webbrowser.open_new_tab("http://kootenay-networks.com/?page_id=170")
def app_menu_open_build_sensor():
""" Open the help file for building a Sensor Unit. """
- help_file_location = app_location_directory + "additional_files/BuildSensors.html"
- app_reports.open_html(help_file_location)
+ help_file_location = current_config.additional_files_directory + "/BuildSensors.html"
+ webbrowser.open_new_tab(help_file_location)
def app_menu_open_sensor_help():
""" Open the help file for Sensor Units. """
- help_file_location = app_location_directory + "additional_files/SensorUnitHelp.html"
- app_reports.open_html(help_file_location)
+ help_file_location = current_config.additional_files_directory + "/SensorUnitHelp.html"
+ webbrowser.open_new_tab(help_file_location)
def app_check_all_ip_checkboxes(var_column):
@@ -207,31 +263,25 @@ def app_check_all_ip_checkboxes(var_column):
app_checkbox_ip16.value = 0
-def worker_sensor_check(net_timeout):
+def _worker_sensor_check(ip):
""" Used in Threads. Socket connects to sensor by IP's in queue. Puts results in a data queue. """
- while not sensor_ip_queue.empty():
- ip = sensor_ip_queue.get()
- data = [ip, sensor_commands.check_online_status(ip, net_timeout)]
+ data = [ip, sensor_commands.check_sensor_status(ip, current_config.network_timeout_sensor_check)]
+ data_queue.put(data)
- sensor_data_queue.put(data)
- sensor_ip_queue.task_done()
-
-def check_sensors():
+def get_verified_ip_list():
"""
Checks sensor online status and changes the programs IP textbox depending on the returned results.
The sensor checks are Threaded by the IP's provided in the IP list.
"""
- ip_list = get_checked_ip()
+ ip_list = _make_ip_list()
ip_list_final = []
- net_timeout = int(config_textbox_network_check.value)
sensor_data_pool = []
threads = []
for ip in ip_list:
- threads.append(Thread(target=worker_sensor_check, args=[net_timeout]))
- sensor_ip_queue.put(ip)
+ threads.append(Thread(target=_worker_sensor_check, args=[ip]))
for thread in threads:
thread.start()
@@ -239,9 +289,9 @@ def check_sensors():
for thread in threads:
thread.join()
- while not sensor_data_queue.empty():
- sensor_data_pool.append(sensor_data_queue.get())
- sensor_data_queue.task_done()
+ while not data_queue.empty():
+ sensor_data_pool.append(data_queue.get())
+ data_queue.task_done()
sensor_data_pool.sort()
@@ -330,7 +380,7 @@ def check_sensors():
# Returns selected IP's from Main App Window & Re-Sets unselected IP background to white
-def get_checked_ip():
+def _make_ip_list():
""" Returns a list of all checked IP's, skipping duplicates """
checkbox_ip_list = []
@@ -418,94 +468,100 @@ def get_checked_ip():
return checkbox_ip_list
+def app_sensor_readings_report():
+ """ Create a HTML sensor Readings Report containing each IP selected and online. """
+ var_ip_list = get_verified_ip_list()
+ readings_config = app_reports.HTMLReadings()
+ app_reports.sensor_html_report(readings_config, var_ip_list)
+
+
def app_sensor_system_report():
""" Create a HTML sensor System Report containing each IP selected and online. """
- var_ip_list = check_sensors()
- app_reports.sensor_system_report(var_ip_list)
+ var_ip_list = get_verified_ip_list()
+ system_config = app_reports.HTMLSystem()
+ app_reports.sensor_html_report(system_config, var_ip_list)
def app_sensor_config_report():
""" Create a HTML sensor Configuration Report containing each IP selected and online. """
- var_ip_list = check_sensors()
- app_reports.sensor_config_report(var_ip_list)
+ var_ip_list = get_verified_ip_list()
+ sensor_config_config = app_reports.HTMLConfig()
+ app_reports.sensor_html_report(sensor_config_config, var_ip_list)
def config_button_save():
""" Save the programs Configuration and IP list to file """
logger.debug("Applying Configuration & Saving to File")
- config_settings = app_config.CreateConfigSettings()
-
- config_settings.save_to = config_textbox_save_to.value
- config_settings.graph_start = config_textbox_start.value
- config_settings.graph_end = config_textbox_end.value
- config_settings.time_offset = config_textbox_time_offset.value
- config_settings.sql_queries_skip = config_textbox_sql_skip.value
- config_settings.temperature_offset = config_textbox_temperature_offset.value
- config_settings.network_check_timeout = config_textbox_network_check.value
- config_settings.network_details_timeout = config_textbox_network_details.value
- config_settings.allow_power_controls = config_checkbox_power_controls.value
- config_settings.allow_reset_config = config_checkbox_reset.value
- config_settings.ip_list[0] = app_textbox_ip1.value
- config_settings.ip_list[1] = app_textbox_ip2.value
- config_settings.ip_list[2] = app_textbox_ip3.value
- config_settings.ip_list[3] = app_textbox_ip4.value
- config_settings.ip_list[4] = app_textbox_ip5.value
- config_settings.ip_list[5] = app_textbox_ip6.value
- config_settings.ip_list[6] = app_textbox_ip7.value
- config_settings.ip_list[7] = app_textbox_ip8.value
- config_settings.ip_list[8] = app_textbox_ip9.value
- config_settings.ip_list[9] = app_textbox_ip10.value
- config_settings.ip_list[10] = app_textbox_ip11.value
- config_settings.ip_list[11] = app_textbox_ip12.value
- config_settings.ip_list[12] = app_textbox_ip13.value
- config_settings.ip_list[13] = app_textbox_ip14.value
- config_settings.ip_list[14] = app_textbox_ip15.value
- config_settings.ip_list[15] = app_textbox_ip16.value
-
- config_settings = app_config.check_config(config_settings)
-
- app_config.save_config_to_file(config_settings)
- set_config(config_settings)
-
-
-def set_config(config_settings):
+ current_config.save_to = config_textbox_save_to.value
+ current_config.graph_start = config_textbox_start.value
+ current_config.graph_end = config_textbox_end.value
+ current_config.datetime_offset = config_textbox_time_offset.value
+ current_config.sql_queries_skip = config_textbox_sql_skip.value
+ current_config.temperature_offset = config_textbox_temperature_offset.value
+ current_config.live_refresh = graph_textbox_refresh_time.value
+ current_config.network_timeout_sensor_check = config_textbox_network_check.value
+ current_config.network_timeout_data = config_textbox_network_details.value
+ current_config.allow_advanced_controls = config_checkbox_power_controls.value
+ current_config.ip_list[0] = app_textbox_ip1.value
+ current_config.ip_list[1] = app_textbox_ip2.value
+ current_config.ip_list[2] = app_textbox_ip3.value
+ current_config.ip_list[3] = app_textbox_ip4.value
+ current_config.ip_list[4] = app_textbox_ip5.value
+ current_config.ip_list[5] = app_textbox_ip6.value
+ current_config.ip_list[6] = app_textbox_ip7.value
+ current_config.ip_list[7] = app_textbox_ip8.value
+ current_config.ip_list[8] = app_textbox_ip9.value
+ current_config.ip_list[9] = app_textbox_ip10.value
+ current_config.ip_list[10] = app_textbox_ip11.value
+ current_config.ip_list[11] = app_textbox_ip12.value
+ current_config.ip_list[12] = app_textbox_ip13.value
+ current_config.ip_list[13] = app_textbox_ip14.value
+ current_config.ip_list[14] = app_textbox_ip15.value
+ current_config.ip_list[15] = app_textbox_ip16.value
+
+ app_config.save_config_to_file(current_config)
+ set_config()
+
+
+def set_config():
""" Sets the programs Configuration to the provided settings. """
- final_config_settings = app_config.check_config(config_settings)
-
try:
- config_textbox_save_to.value = final_config_settings.save_to
- config_textbox_start.value = final_config_settings.graph_start
- graph_textbox_start.value = final_config_settings.graph_start
- config_textbox_end.value = final_config_settings.graph_end
- graph_textbox_end.value = final_config_settings.graph_end
- config_textbox_time_offset.value = final_config_settings.time_offset
- config_textbox_sql_skip.value = final_config_settings.sql_queries_skip
- graph_textbox_sql_skip.value = final_config_settings.sql_queries_skip
- config_textbox_temperature_offset.value = final_config_settings.temperature_offset
- graph_textbox_temperature_offset.value = final_config_settings.temperature_offset
- config_textbox_network_check.value = final_config_settings.network_check_timeout
- config_textbox_network_details.value = final_config_settings.network_details_timeout
- config_checkbox_power_controls.value = final_config_settings.allow_power_controls
- config_checkbox_reset.value = final_config_settings.allow_reset_config
- app_textbox_ip1.value = config_settings.ip_list[0]
- app_textbox_ip2.value = config_settings.ip_list[1]
- app_textbox_ip3.value = config_settings.ip_list[2]
- app_textbox_ip4.value = config_settings.ip_list[3]
- app_textbox_ip5.value = config_settings.ip_list[4]
- app_textbox_ip6.value = config_settings.ip_list[5]
- app_textbox_ip7.value = config_settings.ip_list[6]
- app_textbox_ip8.value = config_settings.ip_list[7]
- app_textbox_ip9.value = config_settings.ip_list[8]
- app_textbox_ip10.value = config_settings.ip_list[9]
- app_textbox_ip11.value = config_settings.ip_list[10]
- app_textbox_ip12.value = config_settings.ip_list[11]
- app_textbox_ip13.value = config_settings.ip_list[12]
- app_textbox_ip14.value = config_settings.ip_list[13]
- app_textbox_ip15.value = config_settings.ip_list[14]
- app_textbox_ip16.value = config_settings.ip_list[15]
- config_checkbox_enable_reset()
- config_checkbox_enable_shutdown()
+ config_textbox_save_to.value = current_config.save_to
+ config_textbox_start.value = current_config.graph_start
+ config_textbox_end.value = current_config.graph_end
+ config_textbox_time_offset.value = current_config.datetime_offset
+ config_textbox_sql_skip.value = current_config.sql_queries_skip
+ config_textbox_temperature_offset.value = current_config.temperature_offset
+ config_textbox_network_check.value = current_config.network_timeout_sensor_check
+ config_textbox_network_details.value = current_config.network_timeout_data
+ config_checkbox_power_controls.value = current_config.allow_advanced_controls
+
+ graph_textbox_start.value = current_config.graph_start
+ graph_textbox_end.value = current_config.graph_end
+ graph_textbox_sql_skip.value = current_config.sql_queries_skip
+ graph_textbox_temperature_offset.value = current_config.temperature_offset
+ graph_textbox_refresh_time.value = current_config.live_refresh
+
+ app_textbox_ip1.value = current_config.ip_list[0]
+ app_textbox_ip2.value = current_config.ip_list[1]
+ app_textbox_ip3.value = current_config.ip_list[2]
+ app_textbox_ip4.value = current_config.ip_list[3]
+ app_textbox_ip5.value = current_config.ip_list[4]
+ app_textbox_ip6.value = current_config.ip_list[5]
+ app_textbox_ip7.value = current_config.ip_list[6]
+ app_textbox_ip8.value = current_config.ip_list[7]
+ app_textbox_ip9.value = current_config.ip_list[8]
+ app_textbox_ip10.value = current_config.ip_list[9]
+ app_textbox_ip11.value = current_config.ip_list[10]
+ app_textbox_ip12.value = current_config.ip_list[11]
+ app_textbox_ip13.value = current_config.ip_list[12]
+ app_textbox_ip14.value = current_config.ip_list[13]
+ app_textbox_ip15.value = current_config.ip_list[14]
+ app_textbox_ip16.value = current_config.ip_list[15]
+
+ config_checkbox_enable_advanced()
+
logger.debug("Configuration Set - OK")
except Exception as error:
logger.error("Configuration Set - One or More Items Failed - " + str(error))
@@ -523,114 +579,119 @@ def config_button_save_directory():
def config_button_reset_defaults():
+ """ Resets all Control Center Configurations to default. """
logger.info("Resetting Configuration to Defaults")
- default_settings = app_config.CreateConfigSettings()
- set_config(default_settings)
+ current_config.reset_to_defaults()
+ set_config()
-def config_checkbox_enable_reset():
- if config_checkbox_reset.value == 1:
- config_button_reset.enable()
- else:
- config_button_reset.disable()
-
-
-def config_checkbox_enable_shutdown():
+def config_checkbox_enable_advanced():
+ """ Enables disabled buttons in the Control Center application. """
if config_checkbox_power_controls.value == 1:
- commands_button_reboot.enable()
+ config_button_reset.enable()
commands_button_shutdown.enable()
commands_button_os_Upgrade.enable()
+ sensor_config_button_update_datetime.enable()
sensor_config_button_set_config.enable()
else:
- commands_button_reboot.disable()
+ config_button_reset.disable()
commands_button_shutdown.disable()
commands_button_os_Upgrade.disable()
+ sensor_config_button_update_datetime.disable()
sensor_config_button_set_config.disable()
def commands_upgrade_smb():
+ """ Sends the upgrade by SMB command to the Sensor Units IP. """
logger.debug("Sensor Upgrade - SMB")
- ip_list = check_sensors()
+ ip_list = get_verified_ip_list()
for ip in ip_list:
sensor_commands.upgrade_program_smb(ip)
- info("Information", "Sensor(s) Upgrading\n"
- "Please Wait up to 30 seconds for the Services to restart")
+ info("Sensors Upgrading SMB", "Please Wait up to 30 seconds for the Services to restart")
def commands_upgrade_http():
+ """ Sends the upgrade by HTTP command to the Sensor Units IP. """
logger.debug("Sensor Upgrade - HTTP")
- ip_list = check_sensors()
+ ip_list = get_verified_ip_list()
for ip in ip_list:
sensor_commands.upgrade_program_online(ip)
- info("Information", "Sensor(s) Upgrading\n"
- "Please Wait up to 30 seconds for the Services to restart")
+ info("Sensors Upgrading HTTP", "Please Wait up to 30 seconds for the Services to restart")
def commands_os_upgrade():
+ """ Sends the upgrade Operating System command to the Sensor Units IP. """
logger.debug("Sensor OS Upgrade")
- ip_list = check_sensors()
+ ip_list = get_verified_ip_list()
for ip in ip_list:
sensor_commands.upgrade_os_linux(ip)
- info("Information", "Sensor Operating System Upgrade Started\n"
- "Once complete, the Sensor(s) will automatically reboot\n"
- "This may take awhile ...")
+ info("Sensors Operating System Upgrade Started",
+ "Once complete, the Sensors will automatically reboot\n"
+ "Sensor should continue to Operate with minor interruptions\n\n"
+ "This process can take anywhere from 5 Min to 1 Hour")
def commands_sensor_reboot():
+ """ Sends the reboot system command to the Sensor Units IP. """
logger.debug("Sensor Reboot")
- ip_list = check_sensors()
+ ip_list = get_verified_ip_list()
for ip in ip_list:
sensor_commands.reboot_sensor(ip)
- info("Information", "Sensor(s) Rebooting")
+ info("Sensors Rebooting", "Allow up to 3 Min to reboot")
def commands_sensor_shutdown():
- logger.debug("Sensor Reboot")
- ip_list = check_sensors()
+ """ Sends the shutdown system command to the Sensor Units IP. """
+ logger.debug("Sensor Shutdown")
+ ip_list = get_verified_ip_list()
for ip in ip_list:
sensor_commands.shutdown_sensor(ip)
- info("Information", "Sensor(s) Shutting Down")
+ info("Sensors Shutting Down", "Allow up to 15 seconds to fully shutdown")
def commands_restart_services():
+ """ Sends the restart services command to the Sensor Units IP. """
logger.info("Sensor(s) Services Restarting - Please allow up to 20 Seconds to restart")
- ip_list = check_sensors()
+ ip_list = get_verified_ip_list()
for ip in ip_list:
sensor_commands.restart_services(ip)
- info("Information", "Sensor(s) Programs Restarting\nPlease allow up to 20 Seconds to restart")
+ info("Sensors Services Restarting", "Please allow up to 20 Seconds to restart")
def commands_hostname_change():
+ """ Sends the host name change command to the Sensor Units IP, along with the new host name. """
logger.debug("Change Sensor Hostname")
- ip_list = check_sensors()
+ ip_list = get_verified_ip_list()
for ip in ip_list:
sensor_commands.set_hostname(ip)
def commands_datetime_update():
+ """ Sends the Date & Time update command to the Sensor Units IP, along with the computers Date & Time. """
logger.debug("Updating Sensors DateTime")
- ip_list = check_sensors()
+ ip_list = get_verified_ip_list()
for ip in ip_list:
sensor_commands.set_datetime(ip)
- info("DateTime Set", "Sensors Date & Time Synchronized with local Computer's")
+ info("Sensors DateTime Set", "Sensors Date & Time Synchronized with local Computer's")
def sensor_config_enable_recording():
+ """ Enables or disables the timing Sensor Configuration Window text boxes. """
if sensor_config_checkbox_db_record.value:
sensor_config_textbox_interval.enable()
sensor_config_textbox_trigger.enable()
@@ -640,6 +701,7 @@ def sensor_config_enable_recording():
def sensor_config_enable_custom():
+ """ Enables or disables the custom Sensor Configuration Window text boxes. """
if sensor_config_checkbox_custom.value:
sensor_config_textbox_custom_acc.enable()
sensor_config_textbox_custom_mag.enable()
@@ -651,8 +713,9 @@ def sensor_config_enable_custom():
def sensor_config_set():
+ """ Sends the update configuration command to the Sensor Units IP, along with the new configuration. """
logger.debug("Setting Sensor Config")
- ip_list = check_sensors()
+ ip_list = get_verified_ip_list()
config_settings_str = "," + str(sensor_config_checkbox_db_record.value) + "," + \
str(sensor_config_textbox_interval.value) + "," + \
str(sensor_config_textbox_trigger.value) + "," + \
@@ -664,76 +727,142 @@ def sensor_config_set():
for ip in ip_list:
sensor_commands.set_sensor_config(ip, config_settings_str)
- info("Information", "Sensor(s) Configuration Set")
+ info("Sensors Configuration Set", "Configurations Set")
-def graph_radio_selection():
- if graph_radio_sensor_type.get() == "Interval":
+def _graph_radio_selection():
+ """ Enables or disables the Graph Window selections, based on graph type selected. """
+ _graph_enable_all_checkboxes()
+ if graph_radio_sensor_type.get() == "Interval SQL":
graph_checkbox_acc.disable()
graph_checkbox_mag.disable()
graph_checkbox_gyro.disable()
+ graph_button_live.disable()
+ graph_textbox_refresh_time.disable()
+ graph_checkbox_cpu_temp.enable()
+ graph_textbox_temperature_offset.enable()
graph_checkbox_temperature.enable()
graph_checkbox_pressure.enable()
graph_checkbox_humidity.enable()
graph_checkbox_lumen.enable()
graph_checkbox_colour.enable()
graph_checkbox_up_time.enable()
-
- if graph_radio_sensor_type.get() == "Trigger":
+ graph_textbox_start.enable()
+ graph_textbox_end.enable()
+ graph_textbox_sql_skip.enable()
+ graph_button_database.enable()
+
+ if graph_radio_sensor_type.get() == "Trigger SQL":
+ graph_textbox_sql_skip.disable()
+ graph_textbox_temperature_offset.disable()
+ graph_checkbox_cpu_temp.disable()
graph_checkbox_temperature.disable()
graph_checkbox_pressure.disable()
graph_checkbox_humidity.disable()
graph_checkbox_lumen.disable()
graph_checkbox_colour.disable()
graph_checkbox_up_time.disable()
+ graph_button_live.disable()
+ graph_textbox_refresh_time.disable()
graph_checkbox_acc.enable()
graph_checkbox_mag.enable()
graph_checkbox_gyro.enable()
+ graph_textbox_start.enable()
+ graph_textbox_end.enable()
+ graph_textbox_sql_skip.disable()
+ graph_button_database.enable()
+
+ if graph_radio_sensor_type.get() == "Live":
+ graph_button_database.disable()
+ graph_textbox_sql_skip.disable()
+ graph_textbox_start.disable()
+ graph_textbox_end.disable()
+ graph_textbox_temperature_offset.enable()
+ graph_textbox_refresh_time.enable()
+
+ graph_checkbox_up_time.enable()
+ graph_checkbox_up_time.value = 0
+ graph_checkbox_cpu_temp.enable()
+ graph_checkbox_cpu_temp.value = 0
+ graph_checkbox_temperature.enable()
+ graph_checkbox_temperature.value = 0
+ graph_checkbox_pressure.enable()
+ graph_checkbox_pressure.value = 0
+ graph_checkbox_humidity.enable()
+ graph_checkbox_humidity.value = 0
+ graph_checkbox_lumen.enable()
+ graph_checkbox_lumen.value = 0
+ graph_checkbox_colour.disable()
+ graph_checkbox_colour.value = 0
+ graph_checkbox_acc.disable()
+ graph_checkbox_acc.value = 0
+ graph_checkbox_mag.disable()
+ graph_checkbox_mag.value = 0
+ graph_checkbox_gyro.disable()
+ graph_checkbox_gyro.value = 0
-def graph_button_interval():
- new_interval_graph = app_graph.CreateGraphData()
- new_interval_graph.db_location = filedialog.askopenfilename()
- if graph_radio_sensor_type.get() == "Trigger":
- new_interval_graph.graph_table = "TriggerData"
+ graph_button_live.enable()
- config_settings_check = app_config.CreateConfigSettings()
- config_settings_check.save_to = config_textbox_save_to.value
- config_settings_check.graph_start = graph_textbox_start.value
- config_settings_check.graph_end = graph_textbox_end.value
- config_settings_check.time_offset = config_textbox_time_offset.value
- config_settings_check.sql_queries_skip = graph_textbox_sql_skip.value
- config_settings_check.temperature_offset = graph_textbox_temperature_offset.value
- config_settings_good = app_config.check_config(config_settings_check)
+def graph_plotly_button():
+ """ Create Plotly offline HTML Graph, based on user selections in the Graph Window. """
+ new_graph_data = app_graph.CreateGraphData()
+ new_graph_data.db_location = filedialog.askopenfilename()
- graph_textbox_start.value = str(config_settings_good.graph_start)
- graph_textbox_end.value = str(config_settings_good.graph_end)
- graph_textbox_sql_skip.value = str(config_settings_good.sql_queries_skip)
- graph_textbox_temperature_offset.value = str(config_settings_good.temperature_offset)
+ current_config.graph_start = graph_textbox_start.value
+ current_config.graph_end = graph_textbox_end.value
+ current_config.sql_queries_skip = graph_textbox_sql_skip.value
+ current_config.temperature_offset = graph_textbox_temperature_offset.value
- new_interval_graph.save_file_to = config_settings_good.save_to
- new_interval_graph.graph_start = config_settings_good.graph_start
- new_interval_graph.graph_end = config_settings_good.graph_end
- new_interval_graph.time_offset = config_settings_good.time_offset
- new_interval_graph.skip_sql = config_settings_good.sql_queries_skip
- new_interval_graph.temperature_offset = config_settings_good.temperature_offset
- # new_interval_graph.graph_type = ""
- new_interval_graph.graph_columns = get_graph_column_checkboxes()
- # new_interval_graph.get_sql_entries = ReplaceMe
+ app_config.check_config(current_config)
+ set_config()
- app_graph.start_graph(new_interval_graph)
+ new_graph_data.save_file_to = current_config.save_to
+ new_graph_data.graph_start = current_config.graph_start
+ new_graph_data.graph_end = current_config.graph_end
+ new_graph_data.time_offset = current_config.datetime_offset
+ new_graph_data.skip_sql = current_config.sql_queries_skip
+ new_graph_data.temperature_offset = current_config.temperature_offset
+ new_graph_data.graph_columns = _graph_get_column_checkboxes()
+ if graph_radio_sensor_type.get() == "Interval SQL":
+ app_graph.start_graph_interval(new_graph_data)
+ elif graph_radio_sensor_type.get() == "Trigger SQL":
+ app_graph.start_graph_trigger(new_graph_data)
-def get_graph_column_checkboxes():
+
+def graph_live_button():
+ pyplot.close()
+ try:
+ graph_checkbox = _graph_get_column_checkboxes()[3]
+ ip_list = get_verified_ip_list()
+
+ current_config.live_refresh = graph_textbox_refresh_time.value
+ current_config.temperature_offset = graph_textbox_temperature_offset.value
+ app_config.check_config(current_config)
+ set_config()
+
+ app_graph.CreateLiveGraph(graph_checkbox, ip_list[0], current_config)
+ except Exception as error:
+ logger.warning("No sensors selected in the main window - " + str(error))
+ warn("Select Sensor", "Please Select a Sensor IP from the Main window\n"
+ "& Sensor Type from the Graph window")
+
+
+def _graph_get_column_checkboxes():
+ """ Returns selected SQL Columns from the Graph Window, depending on the Data Source Selected. """
column_checkboxes = ["DateTime", "SensorName", "IP"]
- if graph_radio_sensor_type.get() == "Interval":
+
+ data_source_radio = graph_radio_sensor_type.get()
+ if data_source_radio == "Interval SQL" or data_source_radio == "Live":
if graph_checkbox_up_time.value:
column_checkboxes.append("SensorUpTime")
- if graph_checkbox_temperature.value:
+ if graph_checkbox_cpu_temp.value:
column_checkboxes.append("SystemTemp")
+ if graph_checkbox_temperature.value:
column_checkboxes.append("EnvironmentTemp")
if graph_checkbox_pressure.value:
column_checkboxes.append("Pressure")
@@ -745,7 +874,7 @@ def get_graph_column_checkboxes():
column_checkboxes.append("Red")
column_checkboxes.append("Green")
column_checkboxes.append("Blue")
- elif graph_radio_sensor_type.get() == "Trigger":
+ if data_source_radio == "Trigger SQL" or data_source_radio == "Live":
if graph_checkbox_acc.value:
column_checkboxes.append("Acc_X")
column_checkboxes.append("Acc_Y")
@@ -763,10 +892,158 @@ def get_graph_column_checkboxes():
return column_checkboxes
-# GUI Window Configurations
+def _graph_enable_all_checkboxes():
+ graph_checkbox_up_time.enable()
+ graph_checkbox_up_time.value = 0
+ graph_checkbox_cpu_temp.enable()
+ graph_checkbox_cpu_temp.value = 0
+ graph_checkbox_temperature.enable()
+ graph_checkbox_temperature.value = 0
+ graph_checkbox_pressure.enable()
+ graph_checkbox_pressure.value = 0
+ graph_checkbox_humidity.enable()
+ graph_checkbox_humidity.value = 0
+ graph_checkbox_lumen.enable()
+ graph_checkbox_lumen.value = 0
+ graph_checkbox_colour.enable()
+ graph_checkbox_colour.value = 0
+ graph_checkbox_acc.enable()
+ graph_checkbox_acc.value = 0
+ graph_checkbox_mag.enable()
+ graph_checkbox_mag.value = 0
+ graph_checkbox_gyro.enable()
+ graph_checkbox_gyro.value = 0
+
+
+def _graph_disable_other_checkboxes(var_checkbox):
+ if graph_radio_sensor_type.value == "Live":
+ if var_checkbox is "Uptime":
+ pass
+ else:
+ graph_checkbox_up_time.disable()
+ graph_checkbox_up_time.value = 0
+ if var_checkbox is "Temperature":
+ pass
+ else:
+ graph_checkbox_temperature.disable()
+ graph_checkbox_temperature.value = 0
+ if var_checkbox is "CPUTemperature":
+ pass
+ else:
+ graph_checkbox_cpu_temp.disable()
+ graph_checkbox_cpu_temp.value = 0
+ if var_checkbox is "Pressure":
+ pass
+ else:
+ graph_checkbox_pressure.disable()
+ graph_checkbox_pressure.value = 0
+ if var_checkbox is "Humidity":
+ pass
+ else:
+ graph_checkbox_humidity.disable()
+ graph_checkbox_humidity.value = 0
+ if var_checkbox is "Lumen":
+ pass
+ else:
+ graph_checkbox_lumen.disable()
+ graph_checkbox_lumen.value = 0
+ # if var_checkbox is "RGB":
+ # pass
+ # else:
+ # graph_checkbox_colour.disable()
+ # graph_checkbox_colour.value = 0
+ # if var_checkbox is "Accelerometer":
+ # pass
+ # else:
+ # graph_checkbox_acc.disable()
+ # graph_checkbox_acc.value = 0
+ # if var_checkbox is "Magnetometer":
+ # pass
+ # else:
+ # graph_checkbox_mag.disable()
+ # graph_checkbox_mag.value = 0
+ # if var_checkbox is "Gyroscopic":
+ # pass
+ # else:
+ # graph_checkbox_gyro.disable()
+ # graph_checkbox_gyro.value = 0
+
+ if var_checkbox is "Uptime":
+ if graph_checkbox_up_time.value == 0:
+ _graph_enable_all_checkboxes()
+ else:
+ graph_checkbox_up_time.enable()
+ graph_checkbox_up_time.value = 1
+ elif var_checkbox is "Temperature":
+ if graph_checkbox_temperature.value == 0:
+ _graph_enable_all_checkboxes()
+ else:
+ graph_checkbox_temperature.enable()
+ graph_checkbox_temperature.value = 1
+ elif var_checkbox is "CPUTemperature":
+ if graph_checkbox_cpu_temp.value == 0:
+ _graph_enable_all_checkboxes()
+ else:
+ graph_checkbox_cpu_temp.enable()
+ graph_checkbox_cpu_temp.value = 1
+ elif var_checkbox is "Pressure":
+ if graph_checkbox_pressure.value == 0:
+ _graph_enable_all_checkboxes()
+ else:
+ graph_checkbox_pressure.enable()
+ graph_checkbox_pressure.value = 1
+ elif var_checkbox is "Humidity":
+ if graph_checkbox_humidity.value == 0:
+ _graph_enable_all_checkboxes()
+ else:
+ graph_checkbox_humidity.enable()
+ graph_checkbox_humidity.value = 1
+ elif var_checkbox is "Lumen":
+ if graph_checkbox_lumen.value == 0:
+ _graph_enable_all_checkboxes()
+ else:
+ graph_checkbox_lumen.enable()
+ graph_checkbox_lumen.value = 1
+ # elif var_checkbox is "RGB":
+ # if graph_checkbox_colour.value == 0:
+ # _graph_enable_all_checkboxes()
+ # else:
+ # graph_checkbox_colour.enable()
+ # graph_checkbox_colour.value = 1
+ # elif var_checkbox is "Accelerometer":
+ # if graph_checkbox_acc.value == 0:
+ # _graph_enable_all_checkboxes()
+ # else:
+ # graph_checkbox_acc.enable()
+ # graph_checkbox_acc.value = 1
+ # elif var_checkbox is "Magnetometer":
+ # if graph_checkbox_mag.value == 0:
+ # _graph_enable_all_checkboxes()
+ # else:
+ # graph_checkbox_mag.enable()
+ # graph_checkbox_mag.value = 1
+ # elif var_checkbox is "Gyroscopic":
+ # if graph_checkbox_gyro.value == 0:
+ # _graph_enable_all_checkboxes()
+ # else:
+ # graph_checkbox_gyro.enable()
+ # graph_checkbox_gyro.value = 1
+
+ graph_checkbox_colour.disable()
+ graph_checkbox_colour.value = 0
+ graph_checkbox_acc.disable()
+ graph_checkbox_acc.value = 0
+ graph_checkbox_mag.disable()
+ graph_checkbox_mag.value = 0
+ graph_checkbox_gyro.disable()
+ graph_checkbox_gyro.value = 0
+
+
+# GUI Window Setup
app = App(title="KootNet Sensors - PC Control Center",
width=405,
height=295,
+
layout="grid")
window_app_about = Window(app,
@@ -777,19 +1054,12 @@ def get_graph_column_checkboxes():
visible=False)
window_config = Window(app,
- title="Configuration",
+ title="Control Center Configuration",
width=580,
height=300,
layout="grid",
visible=False)
-window_graph_interval = Window(app,
- title="Plotly Graphing",
- width=270,
- height=410,
- layout="grid",
- visible=False)
-
window_sensor_commands = Window(app,
title="Sensor Commands",
width=290,
@@ -798,35 +1068,49 @@ def get_graph_column_checkboxes():
visible=False)
window_sensor_config = Window(app,
- title="Update Sensors Configuration",
+ title="Sensors Configuration Updater",
width=340,
height=265,
layout="grid",
visible=False)
+window_sensor_reports = Window(app,
+ title="Sensor Reports",
+ width=475,
+ height=100,
+ layout="grid",
+ visible=False)
+
+window_graph = Window(app,
+ title="Graphing",
+ width=275,
+ height=505,
+ layout="grid",
+ visible=False)
+
app_menubar = MenuBar(app,
toplevel=[["File"],
- ["Download"],
+ ["Sensors"],
["Graphing"],
["Help"]],
- options=[[["Control Center Configuration",
- app_menu_open_config],
- ["Open Logs",
- app_menu_open_log],
- ["Save IP List",
+ options=[[["Open Logs",
+ app_menu_open_logs],
+ ["Save ALL Configurations & IP's",
config_button_save],
- ["Sensors Configuration",
- app_menu_open_sensor_config],
- ["Sensor Commands",
- app_menu_open_commands]],
- [["Download Interval Database(s)",
- app_menu_download_interval_db],
- ["Download Trigger Database(s)",
- app_menu_download_trigger_db]],
- [["Plotly Offline Graphing",
- app_menu_open_graph]],
+ ["Control Center Configuration",
+ window_config.show],
+ ["Quit",
+ _app_exit]],
+ [["Send Commands",
+ window_sensor_commands.show],
+ ["Update Configurations",
+ window_sensor_config.show],
+ ["Create Reports",
+ window_sensor_reports.show]],
+ [["Open Graph Window",
+ window_graph.show]],
[["KootNet Sensors - About",
- app_menu_open_about],
+ window_app_about.show],
["KootNet Sensors - Website",
app_menu_open_website],
["Sensor Units - DIY",
@@ -834,23 +1118,23 @@ def get_graph_column_checkboxes():
["Sensor Units - Help",
app_menu_open_sensor_help],
["PC Control Center - Help *WIP",
- app_menu_open_about]]])
+ window_app_about.show]]])
app_button_check_sensor = PushButton(app,
text="Check Sensors\nStatus",
- command=check_sensors,
+ command=get_verified_ip_list,
grid=[1, 15, 2, 1],
align="left")
app_button_sensor_detail = PushButton(app,
- text="View Sensors\nSystem Report",
- command=app_sensor_system_report,
+ text="Download Sensor\nInterval Databases",
+ command=app_menu_download_interval_db,
grid=[2, 15, 2, 1],
align="right")
app_button_sensor_config = PushButton(app,
- text="View Sensors\nConfiguration Report",
- command=app_sensor_config_report,
+ text="Download Sensor\nTrigger Databases",
+ command=app_menu_download_trigger_db,
grid=[4, 15],
align="right")
@@ -1048,7 +1332,7 @@ def get_graph_column_checkboxes():
# About Window Section
about_text1 = Text(window_app_about,
- text=app_version,
+ text=current_config.app_version,
grid=[1, 1],
align="right")
@@ -1067,18 +1351,11 @@ def get_graph_column_checkboxes():
grid=[1, 1],
align="right")
-config_checkbox_power_controls = \
- CheckBox(window_config,
- text="Enable Advanced\nSensor Commands &\nConfiguration Options",
- command=config_checkbox_enable_shutdown,
- grid=[1, 1],
- align="top")
-
-config_checkbox_reset = CheckBox(window_config,
- text="Enable Configuration Reset button",
- command=config_checkbox_enable_reset,
- grid=[1, 2],
- align="top")
+config_checkbox_power_controls = CheckBox(window_config,
+ text="Enable Advanced\nSensor Commands &\nConfiguration Options",
+ command=config_checkbox_enable_advanced,
+ grid=[1, 1],
+ align="top")
config_button_save_apply = PushButton(window_config,
text="Save &\nApply",
@@ -1217,150 +1494,247 @@ def get_graph_column_checkboxes():
grid=[2, 10],
align="top")
+# Sensor Reports Window Section
+reports_text_select = Text(window_sensor_reports,
+ text="Check Sensor IPs from The Main Window",
+ grid=[1, 1, 3, 1],
+ color='#CB0000',
+ align="top")
+
+reports_text1 = Text(window_sensor_reports,
+ text="Live Readings Report |",
+ color='blue',
+ grid=[1, 6],
+ align="top")
+
+reports_button_check_sensor = PushButton(window_sensor_reports,
+ text="Create",
+ command=app_sensor_readings_report,
+ grid=[1, 7],
+ align="top")
+
+reports_text2 = Text(window_sensor_reports,
+ text="| System Report |",
+ color='blue',
+ grid=[2, 6],
+ align="top")
+
+reports_button_sensor_detail = PushButton(window_sensor_reports,
+ text="Create",
+ command=app_sensor_system_report,
+ grid=[2, 7],
+ align="top")
+
+reports_text3 = Text(window_sensor_reports,
+ text="| Configuration Report",
+ color='blue',
+ grid=[3, 6],
+ align="top")
+
+reports_button_sensor_config = PushButton(window_sensor_reports,
+ text="Create",
+ command=app_sensor_config_report,
+ grid=[3, 7],
+ align="top")
+
# Graph Window Section
-graph_text_start = Text(window_graph_interval,
+graph_text_sensor_type_name = Text(window_graph,
+ text="Data Source",
+ color='blue',
+ grid=[1, 1, 2, 1],
+ align="top")
+
+graph_radio_sensor_type = ButtonGroup(window_graph,
+ options=["Live", "Interval SQL", "Trigger SQL"],
+ horizontal="True",
+ command=_graph_radio_selection,
+ grid=[1, 2, 2, 1],
+ align="top")
+
+graph_text_space1 = Text(window_graph,
+ text=" ",
+ grid=[1, 3],
+ align="right")
+
+graph_text_start = Text(window_graph,
text="Start DateTime: ",
color='green',
- grid=[1, 2],
+ grid=[1, 6],
align="left")
-graph_textbox_start = TextBox(window_graph_interval,
+graph_textbox_start = TextBox(window_graph,
text="",
width=20,
- grid=[2, 2],
+ grid=[2, 6],
align="left")
-graph_text_end = Text(window_graph_interval,
+graph_text_end = Text(window_graph,
text="End DateTime:",
color='green',
- grid=[1, 3],
+ grid=[1, 7],
align="left")
-graph_textbox_end = TextBox(window_graph_interval,
+graph_textbox_end = TextBox(window_graph,
text="",
width=20,
- grid=[2, 3],
+ grid=[2, 7],
align="left")
-graph_text_sql_skip = Text(window_graph_interval,
+graph_text_sql_skip = Text(window_graph,
text="Add row every:",
color='green',
- grid=[1, 4],
+ grid=[1, 8],
align="left")
-graph_textbox_sql_skip = TextBox(window_graph_interval,
+graph_textbox_sql_skip = TextBox(window_graph,
text="",
width=10,
- grid=[2, 4],
+ grid=[2, 8],
align="left")
-graph_text_sql_skip2 = Text(window_graph_interval,
+graph_text_sql_skip2 = Text(window_graph,
text="rows ",
color='green',
- grid=[2, 4],
+ grid=[2, 8],
align="right")
-graph_text_temperature_offset = Text(window_graph_interval,
+graph_text_temperature_offset = Text(window_graph,
text="Environmental:",
color='green',
- grid=[1, 5],
+ grid=[1, 9],
align="left")
-graph_textbox_temperature_offset = TextBox(window_graph_interval,
+graph_textbox_temperature_offset = TextBox(window_graph,
text="",
- width=4,
- grid=[2, 5],
+ width=5,
+ grid=[2, 9],
align="left")
-graph_text_temperature_offset2 = Text(window_graph_interval,
+graph_text_temperature_offset2 = Text(window_graph,
text="Temp Offset",
color='green',
- grid=[2, 5],
+ grid=[2, 9],
align="right")
-graph_text_sensor_type_space = Text(window_graph_interval,
- text=" ",
- grid=[1, 6],
- align="right")
+graph_text_refresh_time = Text(window_graph,
+ text="Live refresh (Sec):",
+ color='green',
+ grid=[1, 10],
+ align="left")
-graph_text_sensor_type_name = Text(window_graph_interval,
- text="Database Type",
- color='blue',
- grid=[1, 7, 2, 1],
- align="top")
+graph_textbox_refresh_time = TextBox(window_graph,
+ text="2",
+ width=5,
+ grid=[2, 10],
+ align="left")
-graph_radio_sensor_type = ButtonGroup(window_graph_interval,
- options=["Interval", "Trigger"],
- horizontal="True",
- command=graph_radio_selection,
- grid=[1, 8, 2, 1],
- align="top")
+graph_text_space2 = Text(window_graph,
+ text=" ",
+ grid=[1, 11],
+ align="right")
-graph_text_column_selection = Text(window_graph_interval,
+graph_text_column_selection = Text(window_graph,
text="Interval Sensors",
color='blue',
- grid=[1, 10, 2, 1],
+ grid=[1, 15, 2, 1],
align="top")
-graph_checkbox_up_time = CheckBox(window_graph_interval,
+graph_checkbox_up_time = CheckBox(window_graph,
text="System Uptime",
- grid=[1, 11],
+ command=_graph_disable_other_checkboxes,
+ args=["Uptime"],
+ grid=[1, 16],
align="left")
-graph_checkbox_temperature = CheckBox(window_graph_interval,
- text="Temperature",
- grid=[1, 12],
+graph_checkbox_cpu_temp = CheckBox(window_graph,
+ text="CPU Temperature",
+ command=_graph_disable_other_checkboxes,
+ args=["CPUTemperature"],
+ grid=[1, 17],
+ align="left")
+
+graph_checkbox_temperature = CheckBox(window_graph,
+ text="Env Temperature",
+ command=_graph_disable_other_checkboxes,
+ args=["Temperature"],
+ grid=[1, 18],
align="left")
-graph_checkbox_pressure = CheckBox(window_graph_interval,
+graph_checkbox_pressure = CheckBox(window_graph,
text="Pressure",
- grid=[1, 13],
+ command=_graph_disable_other_checkboxes,
+ args=["Pressure"],
+ grid=[1, 19],
align="left")
-graph_checkbox_humidity = CheckBox(window_graph_interval,
+graph_checkbox_humidity = CheckBox(window_graph,
text="Humidity",
- grid=[2, 11],
+ command=_graph_disable_other_checkboxes,
+ args=["Humidity"],
+ grid=[2, 16],
align="left")
-graph_checkbox_lumen = CheckBox(window_graph_interval,
+graph_checkbox_lumen = CheckBox(window_graph,
text="Lumen",
- grid=[2, 12],
+ command=_graph_disable_other_checkboxes,
+ args=["Lumen"],
+ grid=[2, 17],
align="left")
-graph_checkbox_colour = CheckBox(window_graph_interval,
+graph_checkbox_colour = CheckBox(window_graph,
text="Colour RGB",
- grid=[2, 13],
+ command=_graph_disable_other_checkboxes,
+ args=["RGB"],
+ grid=[2, 18],
align="left")
-graph_text_column_selection2 = Text(window_graph_interval,
+graph_text_column_selection2 = Text(window_graph,
text="Trigger Sensors",
color='blue',
- grid=[1, 14, 2, 1],
+ grid=[1, 24, 2, 1],
align="bottom")
-graph_checkbox_acc = CheckBox(window_graph_interval,
+graph_checkbox_acc = CheckBox(window_graph,
text="Accelerometer XYZ",
- grid=[1, 15],
+ command=_graph_disable_other_checkboxes,
+ args=["Accelerometer"],
+ grid=[1, 25],
align="left")
-graph_checkbox_mag = CheckBox(window_graph_interval,
+graph_checkbox_mag = CheckBox(window_graph,
text="Magnetometer XYZ",
- grid=[2, 15],
+ command=_graph_disable_other_checkboxes,
+ args=["Magnetometer"],
+ grid=[2, 25],
align="left")
-graph_checkbox_gyro = CheckBox(window_graph_interval,
+graph_checkbox_gyro = CheckBox(window_graph,
text="Gyroscopic XYZ",
- grid=[1, 16],
+ command=_graph_disable_other_checkboxes,
+ args=["Gyroscopic"],
+ grid=[1, 26],
align="left")
-graph_button_sensors = PushButton(window_graph_interval,
- text="Open Database &\nGraph Sensors",
- command=graph_button_interval,
- grid=[1, 18, 2, 1],
- align="bottom")
+graph_text_space3 = Text(window_graph,
+ text=" ",
+ grid=[1, 35],
+ align="right")
+
+graph_button_database = PushButton(window_graph,
+ text="Open & Graph\nDatabase",
+ command=graph_plotly_button,
+ grid=[1, 36, 2, 1],
+ align="left")
+
+graph_button_live = PushButton(window_graph,
+ text="Start Live Graph",
+ command=graph_live_button,
+ grid=[2, 36],
+ align="left")
+# Sensor Commands Window
commands_text_select = Text(window_sensor_commands,
- text="Select Sensors from the Main Window",
+ text="Check Sensor IPs from the Main Window",
grid=[1, 1, 3, 1],
color='#CB0000',
align="left")
@@ -1433,7 +1807,7 @@ def get_graph_column_checkboxes():
# Update Sensor Configuration Section
sensor_config_text_select = Text(window_sensor_config,
- text="Select Sensors from the Main Window",
+ text="Check Sensor IPs from the Main Window",
grid=[1, 1, 3, 1],
color='#CB0000',
align="left")
@@ -1516,40 +1890,8 @@ def get_graph_column_checkboxes():
grid=[2, 14],
align="right")
-# Add extra tk options to windows
-app.tk.iconbitmap(default="additional_files/icon.ico")
-app.tk.resizable(False, False)
-window_graph_interval.tk.resizable(False, False)
-window_sensor_commands.tk.resizable(False, False)
-window_sensor_config.tk.resizable(False, False)
-window_app_about.tk.resizable(False, False)
-window_config.tk.resizable(False, False)
-
-# Change other options before loading app
-app_checkbox_all_column1.value = 0
-app_checkbox_all_column2.value = 0
-app_check_all_ip_checkboxes(1)
-app_check_all_ip_checkboxes(2)
-commands_button_os_Upgrade.disable()
-graph_checkbox_up_time.value = 1
-graph_checkbox_temperature.value = 1
-graph_checkbox_pressure.value = 0
-graph_checkbox_humidity.value = 0
-graph_checkbox_lumen.value = 0
-graph_checkbox_colour.value = 0
-graph_radio_selection()
-sensor_config_checkbox_db_record.value = 1
-sensor_config_checkbox_custom.value = 0
-sensor_config_enable_recording()
-sensor_config_enable_custom()
-sensor_config_button_set_config.disable()
-
-set_about_text()
-about_textbox.disable()
-config_textbox_save_to.disable()
-
-loaded_config_settings = app_config.load_file()
-set_config(loaded_config_settings)
+# Set custom app configurations
+_app_custom_configurations()
# Start the App
logger.info('KootNet Sensors - PC Control Center - Started')
diff --git a/miscTest.py b/miscTest.py
new file mode 100644
index 0000000..bd1f702
--- /dev/null
+++ b/miscTest.py
@@ -0,0 +1,48 @@
+class Test1:
+ def __init__(self):
+ self.var1 = "test1: var1"
+ self.var2 = "test1: var2"
+
+
+class Test2:
+ def __init__(self):
+ self.var1 = "test2: var1"
+ self.var2 = "test2: var2"
+
+
+class Test3:
+ def __init__(self):
+ self.var1 = "test3: var1"
+ self.var2 = "test3: var2"
+
+
+def print_test(test):
+ print(test.var1)
+ print(test.var2)
+
+
+def mod_var1(test):
+ test.var1 = "Changed"
+
+
+def mod_var2(test):
+ test.var2 = "Changed2"
+
+
+test_1 = Test1()
+test_2 = Test2()
+test_3 = Test3()
+
+print_test(test_1)
+print_test(test_2)
+print_test(test_3)
+
+mod_var1(test_1)
+print_test(test_1)
+print_test(test_2)
+print_test(test_3)
+mod_var2(test_3)
+
+print_test(test_1)
+print_test(test_2)
+print_test(test_3)
diff --git a/sensor_commands.py b/sensor_commands.py
index ea50168..2b0c924 100644
--- a/sensor_commands.py
+++ b/sensor_commands.py
@@ -18,21 +18,22 @@
"""
import socket
import pickle
-import os
-import sys
import re
+import os
import logging
from logging.handlers import RotatingFileHandler
from tkinter import simpledialog
from datetime import datetime
from urllib.request import urlopen
+script_directory = str(os.path.dirname(os.path.realpath(__file__)))
+
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(funcName)s: %(message)s', '%Y-%m-%d %H:%M:%S')
-file_handler = RotatingFileHandler('logs/Sensor_Commands_log.txt', maxBytes=256000, backupCount=5)
+file_handler = RotatingFileHandler(script_directory + '/logs/Sensor_Commands_log.txt', maxBytes=256000, backupCount=5)
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
@@ -40,11 +41,8 @@
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
-app_location_directory = str(os.path.dirname(sys.argv[0])) + "/"
-config_file = app_location_directory + "config.txt"
-
-def check_online_status(ip, net_timeout):
+def check_sensor_status(ip, net_timeout):
""" Socket connection to sensor IP. Return sensor status. """
socket.setdefaulttimeout(net_timeout)
sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -59,10 +57,11 @@ def check_online_status(ip, net_timeout):
sensor_status = "Offline"
sock_g.close()
+
return sensor_status
-def get_system_info(ip, net_timeout):
+def get_sensor_system(ip, net_timeout):
""" Socket connection to sensor IP. Return sensor system information. """
socket.setdefaulttimeout(net_timeout)
sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -82,6 +81,174 @@ def get_system_info(ip, net_timeout):
return final_data
+def get_sensor_readings(ip, net_timeout):
+ """
+ Socket connection to sensor IP. Return sensor's readings.
+
+ Returned data is a list of 2 comma separated strings.
+
+ The first string is the Interval readings, the second, Trigger readings.
+ """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetSensorReadings')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = ["Readings Failed on " + ip, str(error), "Readings Failed on " + ip, str(error)]
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
+def get_sensor_hostname(ip, net_timeout):
+ """ Socket connection to sensor IP. Return sensor's hostname. """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetHostName')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = 0
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
+def get_sensor_uptime(ip, net_timeout):
+ """ Socket connection to sensor IP. Return sensor's System Uptime. """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetSystemUptime')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = 0
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
+def get_sensor_cpu_temperature(ip, net_timeout):
+ """ Socket connection to sensor IP. Return sensor's System CPU Temperature. """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetCPUTemperature')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = 0
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
+def get_sensor_temperature(ip, net_timeout):
+ """ Socket connection to sensor IP. Return sensor's temperature. """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetEnvTemperature')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = 0
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
+def get_sensor_pressure(ip, net_timeout):
+ """ Socket connection to sensor IP. Return sensor's Pressure in hPa. """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetPressure')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = 0
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
+def get_sensor_humidity(ip, net_timeout):
+ """ Socket connection to sensor IP. Return sensor's Humidity in %RH. """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetHumidity')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = 0
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
+def get_sensor_lumen(ip, net_timeout):
+ """ Socket connection to sensor IP. Return sensor's Lumen. """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetLumen')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = 0
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
+def get_sensor_rgb(ip, net_timeout):
+ """ Socket connection to sensor IP. Return sensor's Red, Green, Blue readings. """
+ socket.setdefaulttimeout(net_timeout)
+ sock_g = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock_g.connect((ip, 10065))
+ sock_g.send(b'GetRGB')
+ var_data = pickle.loads(sock_g.recv(4096))
+ sock_g.close()
+ logger.debug("Getting Sensor Readings from " + str(ip) + " - OK")
+ except Exception as error:
+ var_data = 0
+ logger.warning("Getting Sensor Readings from " + ip + " - Failed: " + str(error))
+
+ return var_data
+
+
def get_sensor_config(ip, net_timeout):
""" Socket connection to sensor IP. Return sensor configuration. """
socket.setdefaulttimeout(net_timeout)
@@ -98,7 +265,7 @@ def get_sensor_config(ip, net_timeout):
logger.warning("Configuration Received from " + ip + " - Failed: " + str(error))
sock_g.close()
- sensor_system = get_system_info(ip, net_timeout)
+ sensor_system = get_sensor_system(ip, net_timeout)
final_sensor_config = [str(sensor_system[0]),
str(sensor_system[1]),