diff --git a/web/dynamic.py b/web/dynamic.py deleted file mode 100755 index e7ed07a..0000000 --- a/web/dynamic.py +++ /dev/null @@ -1,330 +0,0 @@ -#!/usr/bin/python3 -import os -import sys -import cherrypy -import influxdb -import time -import datetime -import json -from cherrypy.lib.httputil import parse_query_string - - -# Universal variables -_SCRIPT_PATH = os.path.dirname(sys.argv[0]) - -influx_host = 'localhost' -influx_port = 8086 -influx_user = 'pi' -influx_pwd = 'freedavis' -influx_db = 'voltage' -influx_weather_db = 'weather' -influx_status_db = 'status' - -variables_known = ["range", "granularity", "start", "end"] -default_variables = {"range": "1h", "granularity": "30s", "end": "1s"} - - -class DynamicData(object): - def __init__(self): - self.influx_client = influxdb.client.InfluxDBClient( - influx_host, influx_port, influx_user, influx_pwd, influx_db - ) - self.influx_weather_client = influxdb.client.InfluxDBClient( - influx_host, influx_port, influx_user, influx_pwd, influx_weather_db - ) - self.influx_status_client = influxdb.client.InfluxDBClient( - influx_host, influx_port, influx_user, influx_pwd, influx_status_db - ) - - @cherrypy.expose - def index(self): - return "Index, MOFO" - - def check_GET(self, arguments): - ''' No other purpose than to make it more secure and only process the - values that are meant to be processed. Hardcoded on top, mate! - - sets: - list(): key values of those which should be processed, merged - with deault values - ''' - self.q = eval(str(arguments)) - keys_to_process = { - key:self.q[key] for key in self.q.keys() if key in variables_known} - resulting_variables = default_variables.copy() - resulting_variables.update(keys_to_process) - self.q = resulting_variables - - @cherrypy.expose - def solar_monitor(self, **kwargs): - ''' - Function to get solar readings from InfluxDB. - These parsed into a CSV - - yields: csv in raw, text format - time, V_solar, I_solar, P_solar - - ''' - - # GET variables now set, ready to reference them - self.check_GET(kwargs) - query1 = "SELECT mean(V_solar) as Usol, mean(I_solar) as Isol, " - query2 = "mean(V_array) as Varr, mean(I_consumption) as Icons FROM voltage " - query3 = "WHERE time > NOW() - {} AND time < NOW() - {} GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - query4 = "ORDER BY time DESC" - query = "{} {} {} {}".format(query1, query2, query3, query4) - measures = self.influx_client.query(query) - # Let's get the data from DB - header = "time,V_solar,I_solar,P_solar,P_cons\n" - yield header - for datapoint in measures["voltage"]: - tm = str(datapoint["time"]).strip() - solar_voltage = str(datapoint["Usol"]).strip() - solar_current = str(datapoint["Isol"]).strip() - array_voltage = str(datapoint["Varr"]).strip() - consumption_current = str(datapoint["Icons"]).strip() - if solar_voltage != 'None' and solar_current != 'None' \ - and array_voltage != 'None' and consumption_current != 'None': - solar_voltage = float(solar_voltage) / 1000.00 - solar_current = float(solar_current) / 1000.00 - array_voltage = float(array_voltage) / 1000.00 - consumption_current = float(consumption_current) / 1000.00 - else: - solar_voltage = 0.00 - solar_current = 0.00 - array_voltage = 0.00 - consumption_current = 0.00 - # The 8W is the approximate internal consumption of the mppt controller ~ 0.15A - # This value was removed, No idea why it appeared there in the first place. - solar_power = round(solar_voltage * solar_current, 2) - consumption_power = round(array_voltage * consumption_current, 2) - yield "{},{},{},{},{}\n".format(tm, solar_voltage, - solar_current, solar_power, - consumption_power) - - - @cherrypy.expose - def wind_monitor(self, **kwargs): - ''' - Function to get wind value readings from InfluxDB. - These parsed into a CSV - - yields: csv in raw, text format - time, Speed, Gusts, Direction - - ''' - - # GET variables now set, ready to reference them - self.check_GET(kwargs) - speed_q1 = "SELECT mean(value) as w_speed FROM wind" - gust_q1 = "SELECT mean(value) as w_gust FROM wind" - direction_q1 = "SELECT mean(value) as w_dir FROM wind" - speed_q2 = "WHERE time > NOW() - {} AND time < NOW() - {} AND type = 'speed' GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - gust_q2 = "WHERE time > NOW() - {} AND time < NOW() - {} AND type = 'windgust' GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - direction_q2 = "WHERE time > NOW() - {} AND time < NOW() - {} AND type = 'direction' GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - q3 = "ORDER BY time DESC" - speed_query = "{} {} {}".format(speed_q1, speed_q2, q3) - gust_query = "{} {} {}".format(gust_q1, gust_q2, q3) - direction_query = "{} {} {}".format(direction_q1, direction_q2, q3) - rs_speed = self.influx_weather_client.query(speed_query) - rs_gust = self.influx_weather_client.query(gust_query) - rs_direction = self.influx_weather_client.query(direction_query) - # Let's get the data from DB - header = "time,Speed,Gusts,Direction\n" - yield header - for speed, gust, direction in zip(rs_speed['wind'], rs_gust['wind'], rs_direction['wind']): - tm_speed = str(speed["time"]).strip() - tm_gust = str(gust["time"]).strip() - tm_direction = str(direction["time"]).strip() - speed_value = str(speed["w_speed"]).strip() - gust_value = str(gust["w_gust"]).strip() - direction_value = str(direction["w_dir"]).strip() - #if tm_speed == tm_gust and tm_speed == tm_direction: - #tm = strptime(speed["time"]).strip(), "%Y-%m-%dT%H:%M:%SZ") - yield "{},{},{},{}\n".format(tm_speed, speed_value, gust_value, direction_value) - - @cherrypy.expose - def temphumi_monitor(self, **kwargs): - ''' - Function to get temperature and humidity readings from InfluxDB. - These parsed into a CSV - - yields: csv in raw, text format - time, - - ''' - - # GET variables now set, ready to reference them - self.check_GET(kwargs) - temp_q1 = "SELECT mean(temperature) as temp FROM temphumi" - hum_q1 = "SELECT mean(humidity) as hum FROM temphumi" - in_q2 = "WHERE time > NOW() - {} AND time < NOW() - {} AND type = 'internal' GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - out_q2 = "WHERE time > NOW() - {} AND time < NOW() - {} AND type = 'external' GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - q3 = "ORDER BY time DESC" - temp_in_query = "{} {} {}".format(temp_q1, in_q2, q3) - temp_out_query = "{} {} {}".format(temp_q1, out_q2, q3) - hum_in_query = "{} {} {}".format(hum_q1, in_q2, q3) - hum_out_query = "{} {} {}".format(hum_q1, out_q2, q3) - rs_temp_in = self.influx_weather_client.query(temp_in_query) - rs_temp_out = self.influx_weather_client.query(temp_out_query) - #rs_hum_in = self.influx_weather_client.query(hum_in_query) - #rs_hum_out = self.influx_weather_client.query(hum_out_query) - - # Let's get the data from DB - header = "time,T(ins),T(out),Humi(ins),Humi(out)\n" - yield header - for Tout, Hout in zip(rs_temp_out['temphumi'], - rs_hum_out['temphumi']): - tm_temp = str(Tin["time"]).strip() - temp_out_val = str(Tout["temp"]).strip() - hum_out_val = str(Hout["hum"]).strip() - #if tm_speed == tm_gust and tm_speed == tm_direction: - #tm = strptime(speed["time"]).strip(), "%Y-%m-%dT%H:%M:%SZ") - yield "{},{},{},{},{}\n".format(tm_temp, temp_out_val, hum_out_val) - - @cherrypy.expose - def pressure_monitor(self, **kwargs): - ''' - Function to get pressure readings from InfluxDB. - These parsed into a CSV - - yields: csv in raw, text format - time, Pressure - - ''' - - # GET variables now set, ready to reference them - self.check_GET(kwargs) - query1 = "SELECT mean(pressure) as pressure FROM temphumi" - query2 = "WHERE type = 'adjusted' AND time > NOW() - {} AND time < NOW() - {} GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - query3 = "ORDER BY time DESC" - query = "{} {} {}".format(query1, query2, query3) - measures = self.influx_weather_client.query(query) - # Let's get the data from DB - header = "time,Pressure\n" - yield header - for datapoint in measures["temphumi"]: - tm = str(datapoint["time"]).strip() - pressure = str(datapoint["pressure"]).strip() - yield "{},{}\n".format(tm, pressure) - - - @cherrypy.expose - def solcap_monitor(self, **kwargs): - ''' - Function to get solar and supercap readings from InfluxDB. - These parsed into a CSV - - yields: csv in raw, text format - time, Solar Irradiance, Capacitor - - ''' - - # GET variables now set, ready to reference them - self.check_GET(kwargs) - solar_query1 = "SELECT mean(voltage) as solar FROM iss" - solar_query2 = "WHERE type = 'solar' AND time > NOW() - {} AND time < NOW() - {} GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - cap_query1 = "SELECT mean(voltage) as cap FROM iss" - cap_query2 = "WHERE type = 'capcaitor' AND time > NOW() - {} AND time < NOW() - {} GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - query3 = "ORDER BY time DESC" - query_solar = "{} {} {}".format(solar_query1, solar_query2, query3) - query_cap = "{} {} {}".format(cap_query1, cap_query2, query3) - measures_sol = self.influx_status_client.query(query_solar) - measures_cap = self.influx_status_client.query(query_cap) - # Let's get the data from DB - header = "time,Solar,Capacitor\n" - yield header - for Sol, Cap in zip(measures_sol['iss'], measures_cap['iss']): - tm = str(Sol["time"]).strip() - try: - solar_value = float(str(Sol["solar"]).strip()) / 100 - except: - solar_value = '' - try: - cap_value = float(str(Cap["cap"]).strip()) - except: - cap_value = '' - yield "{},{},{}\n".format(tm, solar_value, cap_value) - - - @cherrypy.expose - def cpumem_monitor(self, **kwargs): - ''' - Function to get cpu,mem, disk % from InfluxDB. - These parsed into a CSV - - yields: csv in raw, text format - time, Cpu Mem, Disk - - ''' - - # GET variables now set, ready to reference them - self.check_GET(kwargs) - cpu_query1 = "SELECT mean(usage) as Cpu " - mem_query1 = "SELECT mean(usage) as Mem " - disk_query1 = "SELECT mean(usage) as Disk " - query2 = "FROM RasPI " - cpu_query3 = "WHERE type = 'cpu' AND time > NOW() - {} AND time < NOW() - {} GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - mem_query3 = "WHERE type = 'mem' AND time > NOW() - {} AND time < NOW() - {} GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - disk_query3 = "WHERE type = 'disk' AND time > NOW() - {} AND time < NOW() - {} GROUP BY time({})".format( - self.q['range'], - self.q['end'], - self.q['granularity']) - query4 = "ORDER BY time DESC" - query_cpu = "{} {} {} {}".format(cpu_query1, query2, cpu_query3, query4) - query_mem = "{} {} {} {}".format(mem_query1, query2, mem_query3, query4) - query_disk = "{} {} {} {}".format(disk_query1, query2, disk_query3, query4) - measures_cpu = self.influx_status_client.query(query_cpu) - measures_mem = self.influx_status_client.query(query_mem) - measures_disk = self.influx_status_client.query(query_disk) - # Let's get the data from DB - header = "time,Cpu,Mem,Disk\n" - yield header - for cpu, mem, disk in zip(measures_cpu['RasPI'], measures_mem['RasPI'], measures_disk['RasPI']): - tm = str(cpu["time"]).strip() - try: - cpu_value = float(str(cpu["Cpu"]).strip()) - except: - cpu_value = '' - try: - mem_value = float(str(mem["Mem"]).strip()) - except: - mem_value = '' - try: - disk_value = float(str(disk["Disk"]).strip()) - except: - disk_value = '' - yield "{},{},{},{}\n".format(tm, cpu_value, mem_value, disk_value) diff --git a/web/status.py b/web/status.py deleted file mode 100755 index 0bcf2b9..0000000 --- a/web/status.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/python3 -import os -import sys -import cherrypy -import influxdb -import time -import json - -# Universal variables -_SCRIPT_PATH = os.path.dirname(sys.argv[0]) -_STATIC_DIR = '/templates/' # Needs to have trailing and leading slash '/' - -influx_host = 'localhost' -influx_port = 8086 -influx_user = 'pi' -influx_pwd = 'freedavis' -influx_status_db = 'status' - -# Icons -fs_sol_icon = '../static/img/iss_solar_icon.png' -fs_cap_icon = '../static/img/iss_capacitor_icon.png' - -# Functions -def read_html(filename): - read_path = _SCRIPT_PATH + _STATIC_DIR + filename + '.html' - try: - with open(read_path, 'r') as handle: - return handle.read() - except: - return """
ERROR!
""" + read_path - -# Set default structure - -html_start = '' -body_start = '' -body_close = '' -html_close = '' - -class StatusInfo(object): - @cherrypy.expose - def index(self): - header = read_html('header') - menu_raw = read_html('top_menu') - menu = menu_raw.format(energy = '', weather = '', status = 'active') - body = self.body() - footer = read_html('footer') - result = header\ - + menu\ - + body\ - + footer - return result - - def LastKnownState(self): - ''' - Function to get energy readings from InfluxDB. - - returns: - dict(): {"time": str(time_stamp), - "solar": solar, - "cap": cap} - ''' - - influx_status_client = influxdb.client.InfluxDBClient( - influx_host, influx_port, influx_user, influx_pwd, influx_status_db - ) - - # General query - query1 = "SELECT time, voltage FROM iss WHERE type = " - query2 = "ORDER BY time DESC LIMIT 1" - - # now parse the tag in the middle of the two q from above - solar_q = "{} '{}' {}".format(query1, "solar", query2) - cap_q = "{} '{}' {}".format(query1, "capcaitor", query2) - - # the actual query to DB - solar = influx_status_client.query(solar_q) - cap = influx_status_client.query(cap_q) - - # returned is a list, in this case, we just need one value [0] - result_solar = [sol for sol in solar][0][0] - result_cap = [cap_ for cap_ in cap][0][0] - - # Put the time to a uhman readable format, strip nanosecs - time_stamp = time.strptime(result_solar['time'].split('.')[0], - "%Y-%m-%dT%H:%M:%S") - result = {} - - # Construct the result to return - result.update({"time": time_stamp}) - result.update({"solar": round(result_solar['voltage'], 1)}) - result.update({"cap": round(result_cap['voltage'], 1)}) - return result - - - def body(self): - admin_preformat = read_html('status_admin') - current_status = self.LastKnownState() - admin_html = admin_preformat.format( - timestamp = time.strftime("%d.%m.%Y %H:%M:%S", - current_status['time']), - sol_icon = fs_sol_icon, - cap_icon = fs_cap_icon, - sol_value = round(current_status['solar'] / 100, 2), - cap_value = current_status['cap'] - ) - return admin_html diff --git a/web/weather.py b/web/weather.py deleted file mode 100755 index d8ed64e..0000000 --- a/web/weather.py +++ /dev/null @@ -1,230 +0,0 @@ -#!/usr/bin/python3 -import os -import sys -import cherrypy -import influxdb -import time -import json - -# Universal variables -_SCRIPT_PATH = os.path.dirname(sys.argv[0]) -_STATIC_DIR = '/templates/' # Needs to have trailing and leading slash '/' - -influx_host = 'localhost' -influx_port = 8086 -influx_user = 'pi' -influx_pwd = 'freedavis' -influx_weather_db = 'weather' -influx_status_db = 'status' - -# Icons -fs_wind_icon = '../static/img/wind_icon.png' -fs_pressure_icon = '../static/img/pressure_icon.png' -fs_in_temperature_icon = '../static/img/inside_temp_icon.png' -fs_out_temperature_icon = '../static/img/outside_temp_icon.png' -fs_windgust_icon = '../static/img/wind_gust_icon.png' -fs_winddirection_icon = '../static/img/wind_direction_icon.png' - - -# Functions -def read_html(filename): - read_path = _SCRIPT_PATH + _STATIC_DIR + filename + '.html' - try: - with open(read_path, 'r') as handle: - return handle.read() - except: - return """
ERROR!
""" + read_path - -# Set default structure - -html_start = '' -body_start = '' -body_close = '' -html_close = '' - - -class WeatherInfo(object): - @cherrypy.expose - def index(self): - header = read_html('header') - menu_raw = read_html('top_menu') - menu = menu_raw.format(energy='', weather='active', status='') - body = self.body() - footer = read_html('footer') - result = header\ - + menu\ - + body\ - + footer - return result - - def winddirName(self, direction): - ''' - Function to get energy readings from InfluxDB. - - returns: - str(): The linguistic representation of wind direction - ''' - if 10.5 <= direction < 34.5: - result = "NNE" - elif 34.5 <= direction < 58.5: - result = "NE" - elif 58.5 <= direction < 82.5: - result = "ENE" - elif 82.5 <= direction < 106.5: - result = "E" - elif 106.5 <= direction < 130.5: - result = "ESE" - elif 130.5 <= direction < 154.5: - result = "SE" - elif 154.5 <= direction < 178.5: - result = "SSE" - elif 178.5 <= direction < 202.5: - result = "S" - elif 202.5 <= direction < 226.5: - result = "SSW" - elif 226.5 <= direction < 250.5: - result = "SW" - elif 250.5 <= direction < 274.5: - result = "W" - elif 274.5 <= direction < 298.5: - result = "WNW" - elif 298.5 <= direction < 322.5: - result = "NW" - elif 322.5 <= direction < 346.5: - result = "NNW" - elif 346.5 <= direction <= 359.9 or 0 < direction < 10.5: - result = "N" - elif direction == 0: - # it is being said that 0 means error, not sure. - result = "ERROR, windvane broken" - else: - result = "NaN" - return result - - def LastKnownState(self): - """ - Returns a dict full of weather data. - :param self: - """ - influx_weather_client = influxdb.client.InfluxDBClient( - influx_host, - influx_port, - influx_user, - influx_pwd, - influx_weather_db - ) - - # General query - query1 = "SELECT time, value FROM wind WHERE type = " - query2 = "AND time > NOW() - 5m ORDER BY time DESC LIMIT 1" - - # now parse the tag in the middle of the two q from above - wind_speed_q = "{} '{}' {}".format(query1, "speed", query2) - wind_direction_q = "{} '{}' {}".format(query1, "direction", query2) - wind_gust_q = "{} '{}' {}".format(query1, "windgust", query2) - hum_ext_q = "SELECT time, humidity FROM temphumi\ - WHERE type = 'external' {}".format(query2) - hum_int_q = "SELECT time, humidity FROM temphumi\ - WHERE type = 'internal' {}".format(query2) - press_q = "SELECT time, pressure FROM temphumi\ - WHERE type = 'adjusted' {}".format(query2) - presr_q = "SELECT time, pressure FROM temphumi\ - WHERE type = 'raw' {}".format(query2) - t_ext_q = "SELECT time, temperature FROM temphumi\ - WHERE type = 'external' {}".format(query2) - t_int_q = "SELECT time, temperature FROM temphumi\ - WHERE type = 'internal' {}".format(query2) - - # the actual query to DB - wind_speed = influx_weather_client.query(wind_speed_q) - wind_direction = influx_weather_client.query(wind_direction_q) - wind_gust = influx_weather_client.query(wind_gust_q) - hum_ext = influx_weather_client.query(hum_ext_q) - #hum_int = influx_weather_client.query(hum_int_q) - #press = influx_weather_client.query(press_q) - #presr = influx_weather_client.query(presr_q) - t_ext = influx_weather_client.query(t_ext_q) - #t_int = influx_weather_client.query(t_int_q) - - # returned is a list, in this case, we just need one value [0] - try: - result_windspeed = [speed for speed in wind_speed][0][0] - except: - result_windspeed = {'value': 1024} - try: - result_winddir = [direction for direction in wind_direction][0][0] - except: - result_winddir = {'value': 1024} - try: - result_windgust = [gust for gust in wind_gust][0][0] - except: - result_windgust = {'value': 1024} - #result_hum_int = [y for y in hum_int][0][0] - #result_t_int = [c for c in t_int][0][0] - #result_press = [z for z in press][0][0] - #result_presr = [a for a in presr][0][0] - try: - result_t_ext = [b for b in t_ext][0][0] - except: - result_t_ext = {'value': 1024} - try: - result_hum_ext = [x for x in hum_ext][0][0] - except: - result_hum_ext = {'value': 1024} - - # Put the time to a uhman readable format, strip nanosecs - try: - time_stamp = time.strptime(result_windspeed['time'].split('.')[0], - "%Y-%m-%dT%H:%M:%S") - try: - time_stamp = time.strptime(result_t_ext['time'].split('.')[0], - "%Y-%m-%dT%H:%M:%S") - except: - time_stamp = 1024 - except: - time_stamp = 2048 - - - result = {} - - # Construct the result to return - result.update({"time": time_stamp}) - result.update({"speed": round(result_windspeed['value'], 1)}) - result.update({"direction": round(result_winddir['value'], 1)}) - result.update({"windgust": round(result_windgust['value'], 1)}) - result.update({"humidity_ext": round(result_hum_ext['humidity'], 1)}) - #result.update({"humidity_int": round(result_hum_int['humidity'], 1)}) - #result.update({"pressure": round(result_press['pressure'], 1)}) - #result.update({"pressure_raw": round(result_presr['pressure'], 1)}) - result.update({"temp_ext": round(result_t_ext['temperature'], 1)}) - #result.update({"temp_int": round(result_t_int['temperature'], 1)}) - return result - - def body(self): - """ - A fully formated body of a HTML document, taken from ./templates/ - :param self: - """ - admin_preformat = read_html('weather_admin') - current_weather = self.LastKnownState() - admin_html = admin_preformat.format( - timestamp=time.strftime("%d.%m.%Y %H:%M:%S", - current_weather['time']), - w_speed_icon=fs_wind_icon, - w_speed_km=current_weather['speed'], - w_speed_ms=round(current_weather['speed'] / 3.6, 1), - w_gust_icon=fs_windgust_icon, - w_gust_km=current_weather['windgust'], - w_gust_ms=round(current_weather['windgust'] / 3.6, 1), - w_dir_icon=fs_winddirection_icon, - w_dir_name=self.winddirName(current_weather['direction']), - w_dir_deg=current_weather['direction'], - out_temp_icon=fs_out_temperature_icon, - out_temp=current_weather['temp_ext'], - in_temp_icon=fs_in_temperature_icon, - #in_temp=current_weather['temp_int'], - pressure_icon=fs_pressure_icon - #pressure=current_weather['pressure'], - #raw_pressure=current_weather['pressure_raw'] - ) - return admin_html