diff --git a/html_templates/calibration.html b/html_templates/calibration.html new file mode 100644 index 0000000..df7791e --- /dev/null +++ b/html_templates/calibration.html @@ -0,0 +1,74 @@ + + + + + + + + + +
Level (Ft.)Volume
+ +
+
+

Add a new Calibration Point

+
+
+ + +
+ +
+ + +
+ + " + data-techname="<%=channels["pondlevel.addcalibrationpoint"].techName %>" + data-name="<%= channels["pondlevel.addcalibrationpoint"].name%>" + data-nodechannelcurrentId="<%= channels["pondlevel.addcalibrationpoint"].nodechannelcurrentId %>" + id="<%= channels["pondlevel.addcalibrationpoint"].channelId %>" + class="btn btn-large btn-theme animated setstatic material-icons">send +
+
+
+ + diff --git a/python_driver/calibration_db.py b/python_driver/calibration_db.py index 9435f9a..20e6735 100644 --- a/python_driver/calibration_db.py +++ b/python_driver/calibration_db.py @@ -3,7 +3,7 @@ import sqlite3 SQLITE_DB = "cal_data.db" -SQLITE_CONN = sqlite3.connect(SQLITE_DB) +SQLITE_CONN = sqlite3.connect(SQLITE_DB, check_same_thread=False) def setup_calibration_table(drop_first=False): @@ -53,6 +53,8 @@ def get_calibration_data(single_entry=False): def get_volume_for_height(height): """Interpret a volume for a given height.""" calibration_data = get_calibration_data() + print("Calibration Data\n===") + print(calibration_data) cal_min_height = calibration_data[0][1] cal_max_height = calibration_data[-1][1] diff --git a/python_driver/pondlevel.py b/python_driver/pondlevel.py index 31f2e63..76e27e6 100644 --- a/python_driver/pondlevel.py +++ b/python_driver/pondlevel.py @@ -2,7 +2,6 @@ import threading from device_base import deviceBase -import calibration_db as db import time import json import persistence @@ -18,7 +17,8 @@ send_time = 300 temp_pl = pond_level['value'] -persist_data = persistence.load() +scaling_persist = persistence.load(filename="scaling_persist.json") +strapping_persist = persistence.load(filename="strapping_persist.json") def scale_to_eu(inp_measurement, raw_max, raw_min, eu_max, eu_min): @@ -48,6 +48,15 @@ class start(threading.Thread, deviceBase): self.PL_EUMAX = 23.068 self.PL_EUMIN = 0.0 + # Strapping table format + # { + # height: volume, + # height: volume, + # height: volume, + # etc... + # } + self.strapping_table = {} + # this is a required function for all drivers, its goal is to upload some piece of data # about your device so it can be seen on the web def register(self): @@ -59,20 +68,33 @@ class start(threading.Thread, deviceBase): global pond_level, temp_pl, send_delta, send_time try: - self.PL_RAWMAX = persist_data['raw_max'] - self.PL_RAWMIN = persist_data['raw_min'] - self.PL_EUMAX = persist_data['eu_max'] - self.PL_EUMIN = persist_data['eu_min'] + self.PL_RAWMAX = scaling_persist['raw_max'] + self.PL_RAWMIN = scaling_persist['raw_min'] + self.PL_EUMAX = scaling_persist['eu_max'] + self.PL_EUMIN = scaling_persist['eu_min'] except KeyError: print("No persistence data for scaling parameters.") except TypeError: print("No persistence data for scaling parameters.") + try: + if len(strapping_persist.keys()) > 0: + for k in strapping_persist.keys(): + self.strapping_table[float(k)] = strapping_persist[k] + print("Using stored strapping table:\n{}".format(self.strapping_table)) + else: + print("No stored strapping table found.") + except Exception as e: + print("No stored strapping table. Got Error: {}".format(e)) + wait_sec = 30 for i in range(0, wait_sec): print("pondlevel driver will start in {} seconds".format(wait_sec - i)) time.sleep(1) print("BOOM! Starting pondlevel driver...") + # db.setup_calibration_table(drop_first=False) + self.send_calibration_points() + self.sendtodb("setrawmax", self.PL_RAWMAX, 0) self.sendtodb("setrawmin", self.PL_RAWMIN, 0) self.sendtodb("seteumax", self.PL_EUMAX, 0) @@ -98,6 +120,13 @@ class start(threading.Thread, deviceBase): if send_now: self.sendtodb('pond_level', temp_pl, 0) + pond_volume = 0.0 + try: + pond_volume = self.get_volume_for_height(temp_pl) + except Exception: + pass + + self.sendtodb('pond_volume', pond_volume, 0) pond_level['value'] = temp_pl pond_level['timestamp'] = time.time() @@ -113,8 +142,14 @@ class start(threading.Thread, deviceBase): def send_calibration_points(self): """Send calibration data from database to Meshify.""" - cal_data = db.get_calibration_data() - self.sendtodb('pondlevel', json.dumps(cal_data), 0) + strapping_table_list = [] + height_list = self.strapping_table.keys() + height_list.sort() + for height in height_list: + strapping_table_list.append([height, self.strapping_table[height]]) + + strapping_table_string = json.dumps(strapping_table_list) + self.sendtodb('calibration_data', strapping_table_string, 0) def pondlevel_sync(self, name, value): """Sync all data from the driver.""" @@ -125,12 +160,27 @@ class start(threading.Thread, deviceBase): def pondlevel_addcalibrationpoint(self, name, value): """Add a JSON calibration point to the database.""" try: - new_point = json.loads(value) - db.insert_calibration_data(new_point['height'], new_point['volume']) + new_point = json.loads(value.replace("'", '"')) + print("Trying to add Height: {}, volume: {}".format(new_point['height'], new_point['volume'])) + self.strapping_table[float(new_point['height'])] = float(new_point['volume']) + self.store_strapping_table() + # db.insert_calibration_data(new_point['height'], new_point['volume']) self.send_calibration_points() return True - except KeyError: - return "Misformed JSON" + except Exception as e: + print("EXCEPTION: {}".format(e)) + + def pondlevel_deletecalibrationpoint(self, name, value): + """Delete a calibration point from the database.""" + try: + del self.strapping_table[float(value)] + self.store_strapping_table() + # db.delete_calibration_data(int(value)) + self.send_calibration_points() + return True + except Exception as e: + print("Error deleting calibration point: {}".format(e)) + return(e) def store_scaling_data(self): """Store scaling data in the persist file.""" @@ -140,7 +190,49 @@ class start(threading.Thread, deviceBase): 'eu_max': self.PL_EUMAX, 'eu_min': self.PL_EUMIN } - persistence.store(scale_obj) + persistence.store(scale_obj, filename="scaling_persist.json") + + def store_strapping_table(self): + """Store strapping table in the persist file.""" + persistence.store(self.strapping_table, filename="strapping_persist.json") + + def get_volume_for_height(self, height): + """Interpret a volume for a given height.""" + try: + height = float(height) + strapping_table_list = [] + height_list = self.strapping_table.keys() + height_list.sort() + for height_i in height_list: + strapping_table_list.append([float(height_i), float(self.strapping_table[height_i])]) + + print("Strapping Table Data\n===") + print(strapping_table_list) + cal_min_height = strapping_table_list[0][0] + cal_max_height = strapping_table_list[-1][0] + + lower_cal = [0.0, 0.0] + upper_cal = [0.0, 0.0] + + if (height <= cal_max_height and height >= cal_min_height): + for i in range(0, len(strapping_table_list) - 1): + if (height >= strapping_table_list[i][0] and height <= strapping_table_list[i+1][0]): + lower_cal = strapping_table_list[i] + upper_cal = strapping_table_list[i+1] + elif height > cal_max_height: + lower_cal = strapping_table_list[-2] + upper_cal = strapping_table_list[-1] + elif height < cal_min_height: + lower_cal = strapping_table_list[0] + upper_cal = strapping_table_list[1] + + line_m = (float(upper_cal[1]) - float(lower_cal[1])) / (float(upper_cal[0]) - float(lower_cal[0])) + line_b = float(upper_cal[1]) - line_m * float(upper_cal[0]) + + return line_m * height + line_b + except Exception as e: + print("Error in get_volume_for_height: {}".format(e)) + return 0.0 def pondlevel_setrawmin(self, name, value): """Set the raw min scaling value."""