7 Commits

Author SHA1 Message Date
Patrick McDonagh
630f5960dc Updating for adding offset 2018-08-10 15:08:29 -05:00
Patrick McDonagh
e87e405580 Fixes bug in config.txt that prevents data being sent 2018-07-09 13:09:51 -05:00
Patrick McDonagh
3688d62539 Adds public_ip_address, fixes pressure graph 2018-07-03 16:51:51 -05:00
Patrick McDonagh
261ceba0b4 Merge pull request #1 from Henry-Pump/add-pressure-transmitter
Add pressure transmitter
2018-05-15 16:03:56 -05:00
Patrick McDonagh
f017805093 Fix Overview to show pressure alarm config 2018-05-15 15:49:09 -05:00
Patrick McDonagh
115f5ed9f0 Templates for pressure transmitter and sets level/volume to only send every 5 min 2018-04-30 14:07:22 -05:00
Patrick McDonagh
50f64b41c2 Adds code for pressure transmitter 2018-04-24 11:58:53 -05:00
19 changed files with 515 additions and 58 deletions

1
.gitignore vendored
View File

@@ -100,3 +100,4 @@ ENV/
# mypy
.mypy_cache/
/python_driver/cal_data.db
/.pytest_cache

6
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"python.unitTest.promptToConfigure": false,
"python.unitTest.pyTestEnabled": false,
"python.unitTest.unittestEnabled": false,
"python.unitTest.nosetestsEnabled": false
}

View File

@@ -0,0 +1,47 @@
<div class="row row-flex box-me">
<div class="col-md-6 text-center">
<h2 class="uppercase">Public IP Address</h2>
<p><%= channels["pondlevel.public_ip_address"].value %><p>
<div class- "timestamp-box">
<a href="#" data-channelId="<%= channels['pondlevel.public_ip_address'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
</div>
</div>
<style>
.uppercase {
text-transform: uppercase;
font-size: 14px;
color: #666;
font-weight: 400;
letter-spacing: 1px;
z-index: 100;
}
.box-me {
position: relative;
padding: 0.5em;
padding-bottom: 1.5em;
border: 1px solid #eee;
/*margin: 1em 0;*/
}
.row-flex {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
flex-wrap: wrap;
}
.row-flex > [class*='col-'] {
display: flex;
flex-direction: column;
}
p {
font-size: 1.25em;
}
</style>

View File

@@ -65,9 +65,44 @@
</div>
</div>
<% } %>
<% if (channels["pondlevel.pressure_psi"].value > 0.0){ %>
<div class="row row-flex box-me">
<div class='col-xs-4 text-center'>
<h2>Pressure</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-pressure_psi"
data-chart="solidgauge"
data-nodename="pondlevel.pressure_psi"
data-units="PSI"
data-min="0"
data-max="600"
data-decimalplaces="1"
data-colors="0.1:#DF5353,0.5:#DDDF0D,0.9:#55BF3B"
data-valuefontsize="18px">
</div>
<div class- "timestamp-box">
<a href="#" data-channelId="<%= channels['pondlevel.pressure_psi'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="pond_level">
<%= channels["pondlevel.pressure_psi"].timestamp %>
</span>
</div>
</div>
<div class='col-xs-8'>
<div style="height:300px" id="chart-pressure_psi" data-chart="chart" data-nodename1="pondlevel.pressure_psi" data-datalabel1="Pressure" data-daysofhistory="2" data-chartlabel="Pressure" data-ylabel="" data-xlabel="Date" data-units=" PSI"></div>
</div>
</div>
<% } %>
<h1 class="pad15">Configuration</h1>
<div class="row row-flex">
<div class="col-md-6 box-me entry-top-level" id="low_level_limit">
<div class="col-md-4 box-me entry-top-level" id="low_level_limit">
<div class="pad15">
<h2>Low Level Limit</h2>
<form class="form-inline">
@@ -92,7 +127,7 @@
</div>
</div>
<div class="col-md-6 box-me entry-top-level" id="high_level_limit">
<div class="col-md-4 box-me entry-top-level" id="high_level_limit">
<div class="pad15">
<h2>High Level Limit</h2>
<form class="form-inline">
@@ -116,6 +151,32 @@
</form>
</div>
</div>
<div class="col-md-4 box-me entry-top-level" id="high_pressure_limit">
<div class="pad15">
<h2>High Pressure Limit</h2>
<form class="form-inline">
<div class="form-group">
<input class="form-control val_box"
type="number"
step="any"
value="<%=channels['pondlevel.high_pressure_limit'].value %>">
</div>
<a href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=25.0
data-channelId="<%= channels["pondlevel.high_pressure_limit"].channelId %>"
data-techname="<%=channels["pondlevel.high_pressure_limit"].techName %>"
data-name="<%= channels["pondlevel.high_pressure_limit"].name%>"
data-nodechannelcurrentId="<%= channels["pondlevel.high_pressure_limit"].nodechannelcurrentId %>"
id="<%= channels["pondlevel.high_pressure_limit"].channelId %>"
class="btn btn-large btn-theme animated setstatic material-icons">send</a>
</form>
</div>
</div>
</div>

View File

@@ -1,7 +1,10 @@
<div class="row row-flex">
<div class="col-xs-12">
<h1>Level</h1>
</div>
<div class="col-md-6 box-me entry-top-level" id="setrawmax">
<div class="pad15">
<h2>Raw Max (mA)</h2>
@@ -102,8 +105,141 @@
</div>
</div>
<div class="col-md-6 box-me entry-top-level" id="setleveloffset">
<div class="pad15">
<h2>Level Offset (Ft.)</h2>
<form class="form-inline">
<div class="form-group">
<input class="form-control val_box"
type="number"
step="any"
value="<%=channels['pondlevel.setleveloffset'].value %>">
</div>
<a href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=25.0
data-channelId="<%= channels["pondlevel.setleveloffset"].channelId %>"
data-techname="<%=channels["pondlevel.setleveloffset"].techName %>"
data-name="<%= channels["pondlevel.setleveloffset"].name%>"
data-nodechannelcurrentId="<%= channels["pondlevel.setleveloffset"].nodechannelcurrentId %>"
id="<%= channels["pondlevel.setleveloffset"].channelId %>"
class="btn btn-large btn-theme animated setstatic material-icons">send</a>
</form>
</div>
</div>
</div>
<div class="row row-flex">
<div class="col-xs-12">
<h1>Pressure</h1>
</div>
<div class="col-md-6 box-me entry-top-level" id="setpsirawmax">
<div class="pad15">
<h2>Raw Max (V)</h2>
<form class="form-inline">
<div class="form-group">
<input class="form-control val_box"
type="number"
step="any"
value="<%=channels['pondlevel.setpsirawmax'].value %>">
</div>
<a href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=25.0
data-channelId="<%= channels["pondlevel.setpsirawmax"].channelId %>"
data-techname="<%=channels["pondlevel.setpsirawmax"].techName %>"
data-name="<%= channels["pondlevel.setpsirawmax"].name%>"
data-nodechannelcurrentId="<%= channels["pondlevel.setpsirawmax"].nodechannelcurrentId %>"
id="<%= channels["pondlevel.setpsirawmax"].channelId %>"
class="btn btn-large btn-theme animated setstatic material-icons">send</a>
</form>
</div>
</div>
<div class="col-md-6 box-me entry-top-level" id="setpsirawmin">
<div class="pad15">
<h2>Raw Min (V)</h2>
<form class="form-inline">
<div class="form-group">
<input class="form-control val_box"
type="number"
step="any"
value="<%=channels['pondlevel.setpsirawmin'].value %>">
</div>
<a href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=25.0
data-channelId="<%= channels["pondlevel.setpsirawmin"].channelId %>"
data-techname="<%=channels["pondlevel.setpsirawmin"].techName %>"
data-name="<%= channels["pondlevel.setpsirawmin"].name%>"
data-nodechannelcurrentId="<%= channels["pondlevel.setpsirawmin"].nodechannelcurrentId %>"
id="<%= channels["pondlevel.setpsirawmin"].channelId %>"
class="btn btn-large btn-theme animated setstatic material-icons">send</a>
</form>
</div>
</div>
<div class="col-md-6 box-me entry-top-level" id="setpsieumax">
<div class="pad15">
<h2>EU Max (PSI)</h2>
<form class="form-inline">
<div class="form-group">
<input class="form-control val_box"
type="number"
step="any"
value="<%=channels['pondlevel.setpsieumax'].value %>">
</div>
<a href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=25.0
data-channelId="<%= channels["pondlevel.setpsieumax"].channelId %>"
data-techname="<%=channels["pondlevel.setpsieumax"].techName %>"
data-name="<%= channels["pondlevel.setpsieumax"].name%>"
data-nodechannelcurrentId="<%= channels["pondlevel.setpsieumax"].nodechannelcurrentId %>"
id="<%= channels["pondlevel.setpsieumax"].channelId %>"
class="btn btn-large btn-theme animated setstatic material-icons">send</a>
</form>
</div>
</div>
<div class="col-md-6 box-me entry-top-level" id="seteumin">
<div class="pad15">
<h2>EU Min (PSI)</h2>
<form class="form-inline">
<div class="form-group">
<input class="form-control val_box"
type="number"
step="any"
value="<%=channels['pondlevel.setpsieumin'].value %>">
</div>
<a href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=25.0
data-channelId="<%= channels["pondlevel.setpsieumin"].channelId %>"
data-techname="<%=channels["pondlevel.setpsieumin"].techName %>"
data-name="<%= channels["pondlevel.setpsieumin"].name%>"
data-nodechannelcurrentId="<%= channels["pondlevel.setpsieumin"].nodechannelcurrentId %>"
id="<%= channels["pondlevel.setpsieumin"].channelId %>"
class="btn btn-large btn-theme animated setstatic material-icons">send</a>
</form>
</div>
</div>
</div>
<style>
.box-me {

View File

@@ -9,7 +9,7 @@
</div>
</div>
<hr>
<div class='clearfix col-xs-12' style='height: 450px' id="dynamicChart" data-chart="dynamicchart" data-daysofhistory="7" data-chartlabel="Data" data-ylabel="" data-xlabel="Date" data-units="" data-channelnames="pondlevel.pond_level,pondlevel.pond_volume"></div>
<div class='clearfix col-xs-12' style='height: 450px' id="dynamicChart" data-chart="dynamicchart" data-daysofhistory="7" data-chartlabel="Data" data-ylabel="" data-xlabel="Date" data-units="" data-channelnames="pondlevel.pond_level,pondlevel.pond_volume,pondlevel.pressure_psi"></div>
<style>
.dynamic-chart-form {
background-color: whiteSmoke;

BIN
python-driver/cal_data.db Normal file

Binary file not shown.

View File

@@ -0,0 +1,21 @@
id,name,deviceTypeId,fromMe,io,subTitle,helpExplanation,channelType,dataType,defaultValue,regex,regexErrMsg,units,min,max,change,guaranteedReportPeriod,minReportTime
12764,pond_level,412,FALSE,readonly,Pond Level,Level in Ft.,device,float,,,,,,,,,
12769,high_level_limit,412,FALSE,readwrite,High Level Limit,Limit in ft.,user input,float,25,,,,,,,,
12770,low_level_limit,412,FALSE,readwrite,Low Level Limit, Limit in ft.,user input,float,1,,,,,,,,
13352,setrawmax,412,FALSE,readwrite,Raw Max Setpoint,in mA,device,float,,,,,,,,,
13353,setrawmin,412,FALSE,readwrite,Raw Min Setpoint,in mA,device,float,,,,,,,,,
13354,seteumax,412,FALSE,readwrite,EU Max Setpoint,in Ft.,device,float,,,,,,,,,
13355,seteumin,412,FALSE,readwrite,EU Min Setpoint,in Ft.,device,float,,,,,,,,,
13356,log,412,FALSE,readwrite,Log,Log,device,string,,,,,,,,,
13357,sync,412,FALSE,readwrite,Sync,Sycn,device,string,,,,,,,,,
13358,calibration_data,412,FALSE,readonly,Calibration Data,All calibration data,device,string,,,,,,,,,
13359,addcalibrationpoint,412,FALSE,readwrite,Add Calibration Point,Add a single calibration point,device,string,,,,,,,,,
13360,deletecalibrationpoint,412,FALSE,readwrite,Delete Calibration Point,Delete a Calibration Point,device,integer,,,,,,,,,
13361,pond_volume,412,FALSE,readonly,Pond Volume,in BBL,device,float,0,,,,,,,,
13642,pressure_psi,412,FALSE,readonly,Pressure,in PSI,device,float,,,,,,,,,
13643,setpsirawmin,412,FALSE,readwrite,Pressure Raw Min Setpoint,in PSI,device,float,,,,,,,,,
13644,setpsirawmax,412,FALSE,readwrite,Pressure Raw Max Setpoint,in PSI,device,float,,,,,,,,,
13645,setpsieumax,412,FALSE,readwrite,Pressure EU Max Setpoint,in PSI,device,float,,,,,,,,,
13646,setpsieumin,412,FALSE,readwrite,Pressure EU Min Setpoint,in PSI,device,float,,,,,,,,,
13647,high_pressure_limit,412,FALSE,readwrite,High Pressure Input,Send an alert when pressure > high_pressure_input,user input,float,30,,,,,,,,
,public_ip_address,412,FALSE,readonly,Public IP Address,Network Address,device,string,,,,,,,,,
1 id name deviceTypeId fromMe io subTitle helpExplanation channelType dataType defaultValue regex regexErrMsg units min max change guaranteedReportPeriod minReportTime
2 12764 pond_level 412 FALSE readonly Pond Level Level in Ft. device float
3 12769 high_level_limit 412 FALSE readwrite High Level Limit Limit in ft. user input float 25
4 12770 low_level_limit 412 FALSE readwrite Low Level Limit Limit in ft. user input float 1
5 13352 setrawmax 412 FALSE readwrite Raw Max Setpoint in mA device float
6 13353 setrawmin 412 FALSE readwrite Raw Min Setpoint in mA device float
7 13354 seteumax 412 FALSE readwrite EU Max Setpoint in Ft. device float
8 13355 seteumin 412 FALSE readwrite EU Min Setpoint in Ft. device float
9 13356 log 412 FALSE readwrite Log Log device string
10 13357 sync 412 FALSE readwrite Sync Sycn device string
11 13358 calibration_data 412 FALSE readonly Calibration Data All calibration data device string
12 13359 addcalibrationpoint 412 FALSE readwrite Add Calibration Point Add a single calibration point device string
13 13360 deletecalibrationpoint 412 FALSE readwrite Delete Calibration Point Delete a Calibration Point device integer
14 13361 pond_volume 412 FALSE readonly Pond Volume in BBL device float 0
15 13642 pressure_psi 412 FALSE readonly Pressure in PSI device float
16 13643 setpsirawmin 412 FALSE readwrite Pressure Raw Min Setpoint in PSI device float
17 13644 setpsirawmax 412 FALSE readwrite Pressure Raw Max Setpoint in PSI device float
18 13645 setpsieumax 412 FALSE readwrite Pressure EU Max Setpoint in PSI device float
19 13646 setpsieumin 412 FALSE readwrite Pressure EU Min Setpoint in PSI device float
20 13647 high_pressure_limit 412 FALSE readwrite High Pressure Input Send an alert when pressure > high_pressure_input user input float 30
21 public_ip_address 412 FALSE readonly Public IP Address Network Address device string

13
python-driver/config.txt Normal file
View File

@@ -0,0 +1,13 @@
{
"driverFileName": "pondlevel.py",
"deviceName": "pondlevel",
"driverId": "0130",
"releaseVersion": "5",
"files": {
"file1": "pondlevel.py",
"file2": "calibration_db.py",
"file3": "persistence.py",
"file4": "utilities.py",
"file5": "file_logger.py"
}
}

View File

@@ -0,0 +1,2 @@
class deviceBase(object):
pass

View File

@@ -4,8 +4,10 @@
"driverId": "0130",
"additionalDriverFiles": [
"calibration_db.py",
"persistence.py"
"persistence.py",
"utilities.py",
"file_logger.py"
],
"version": 1,
"version": 5,
"s3BucketName": "pondlevel"
}
}

View File

@@ -0,0 +1,18 @@
"""Logging setup for pondlevel"""
import logging
from logging.handlers import RotatingFileHandler
import sys
log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s')
log_file = './pondlevel.log'
my_handler = RotatingFileHandler(log_file, mode='a', maxBytes=500*1024,
backupCount=2, encoding=None, delay=0)
my_handler.setFormatter(log_formatter)
my_handler.setLevel(logging.INFO)
filelogger = logging.getLogger('pondlevel')
filelogger.setLevel(logging.INFO)
filelogger.addHandler(my_handler)
console_out = logging.StreamHandler(sys.stdout)
console_out.setFormatter(log_formatter)
filelogger.addHandler(console_out)

View File

@@ -5,6 +5,8 @@ from device_base import deviceBase
import time
import json
import persistence
from utilities import get_public_ip_address
from file_logger import filelogger as log
_ = None
@@ -12,21 +14,28 @@ pond_level = {
'value': 15.0,
'timestamp': 0
}
send_delta = 0.5
psi_reading = {
'value': 0.0,
'timestamp': 0
}
send_delta = 2.0
send_time = 300
temp_pl = pond_level['value']
temp_psi = psi_reading['value']
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):
def scale_to_eu(inp_measurement, raw_max, raw_min, eu_max, eu_min, offset=0.0):
"""Scale the inp_measurement to engineering units."""
m = (eu_max - eu_min) / (raw_max - raw_min)
b = eu_max - raw_max * m
scaled = inp_measurement * m + b
return scaled
return scaled + offset
class start(threading.Thread, deviceBase):
@@ -38,22 +47,31 @@ class start(threading.Thread, deviceBase):
deviceBase.__init__(self, name=name, number=number, mac=mac, Q=Q, mcu=mcu, companyId=companyId, offset=offset, mqtt=mqtt, Nodes=Nodes)
self.daemon = True
self.version = "1"
self.version = "5"
self.finished = threading.Event()
self.forceSend = False
threading.Thread.start(self)
self.public_ip_address = ""
self.public_ip_address_last_checked = 0
self.PL_RAWMAX = 20.0
self.PL_RAWMIN = 4.0
self.PL_EUMAX = 23.068
self.PL_EUMIN = 0.0
self.PL_OFFSET = 0.0
self.PSI_RAWMAX = 10.0
self.PSI_RAWMIN = 0.0
self.PSI_EUMAX = 600.0
self.PSI_EUMIN = 0.0
# Strapping table format
# {
# height: volume,
# height: volume,
# height: volume,
# etc...
# height: volume,
# height: volume,
# height: volume,
# etc...
# }
self.strapping_table = {}
@@ -65,60 +83,96 @@ class start(threading.Thread, deviceBase):
def run(self):
"""Actually run the driver."""
global pond_level, temp_pl, send_delta, send_time
global pond_level, temp_pl, psi_reading, temp_psi, send_delta, send_time
try:
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']
self.PL_OFFSET = scaling_persist['eu_offset']
except KeyError:
print("No persistence data for scaling parameters.")
log.warning("No persistence data for pond level scaling parameters.")
except TypeError:
print("No persistence data for scaling parameters.")
log.warning("No persistence data for pond level scaling parameters.")
try:
self.PSI_RAWMAX = scaling_persist['psi_raw_max']
self.PSI_RAWMIN = scaling_persist['psi_raw_min']
self.PSI_EUMAX = scaling_persist['psi_eu_max']
self.PSI_EUMIN = scaling_persist['psi_eu_min']
except KeyError:
log.warning("No persistence data for pressure scaling parameters.")
except TypeError:
log.warning("No persistence data for pressure 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))
log.info("Using stored strapping table:\n{}".format(self.strapping_table))
else:
print("No stored strapping table found.")
log.warning("No stored strapping table found.")
except Exception as e:
print("No stored strapping table. Got Error: {}".format(e))
log.warning("No stored strapping table. Got Error: {}".format(e))
wait_sec = 30
wait_sec = 60
for i in range(0, wait_sec):
print("pondlevel driver will start in {} seconds".format(wait_sec - i))
log.info("pondlevel driver will start in {} seconds".format(wait_sec - i))
time.sleep(1)
print("BOOM! Starting pondlevel driver...")
log.info("BOOM! Starting pondlevel driver...")
# db.setup_calibration_table(drop_first=False)
self.send_calibration_points()
self._check_ip_address()
self.sendtodb("setrawmax", self.PL_RAWMAX, 0)
self.sendtodb("setrawmin", self.PL_RAWMIN, 0)
self.sendtodb("seteumax", self.PL_EUMAX, 0)
self.sendtodb("seteumin", self.PL_EUMIN, 0)
self.sendtodb("setleveloffset", self.PL_OFFSET, 0)
self.sendtodb("setpsirawmax", self.PSI_RAWMAX, 0)
self.sendtodb("setpsirawmin", self.PSI_RAWMIN, 0)
self.sendtodb("setpsieumax", self.PSI_EUMAX, 0)
self.sendtodb("setpsieumin", self.PSI_EUMIN, 0)
send_loops = 0
ip_check_after = 60
while True:
send_now = False
now = time.time()
pl_send_now = False
psi_send_now = False
if self.forceSend:
print "FORCE SEND: TRUE"
send_now = True
log.warning("FORCE SEND: TRUE")
pl_send_now = True
psi_send_now = True
try:
mcu_status = self.mcu.getDict() # Gets a dictionary of the IO states
cloop_val = float(mcu_status['cloop'])
analog1_val = float(mcu_status['analog1'])
temp_pl = scale_to_eu(cloop_val, self.PL_RAWMAX, self.PL_RAWMIN, self.PL_EUMAX, self.PL_EUMIN, offset=self.PL_OFFSET)
temp_psi = scale_to_eu(analog1_val, self.PSI_RAWMAX, self.PSI_RAWMIN, self.PSI_EUMAX, self.PSI_EUMIN)
except AttributeError as err:
log.error("Could not connect to MCU object, this device might not have an MCU: {}".format(err))
pass
except KeyError as err:
log.error("Connected to MCU, but {} does not exist.".format(err))
pass
if (now - pond_level['timestamp']) > send_time:
log.info("Sending pond level {} due to time limit".format(temp_pl))
pl_send_now = True
mcu_status = self.mcu.getDict() # Gets a dictionary of the IO states
cloop_val = float(mcu_status['cloop'])
temp_pl = scale_to_eu(cloop_val, self.PL_RAWMAX, self.PL_RAWMIN, self.PL_EUMAX, self.PL_EUMIN)
# Check if pressure needs to be sent
if abs(temp_psi - psi_reading['value']) > send_delta:
log.info("Sending pressure psi {} due to value change".format(temp_psi))
psi_send_now = True
if (now - psi_reading['timestamp']) > send_time:
log.info("Sending pressure psi {} due to time limit".format(temp_psi))
psi_send_now = True
if abs(temp_pl - pond_level['value']) > send_delta:
print("Sending {} due to value change".format(temp_pl))
send_now = True
elif (time.time() - pond_level['timestamp']) > send_time:
print("Sending {} due to time limit".format(temp_pl))
send_now = True
if send_now:
if pl_send_now:
self.sendtodb('pond_level', temp_pl, 0)
pond_volume = 0.0
try:
@@ -128,18 +182,34 @@ class start(threading.Thread, deviceBase):
self.sendtodb('pond_volume', pond_volume, 0)
pond_level['value'] = temp_pl
pond_level['timestamp'] = time.time()
pond_level['timestamp'] = now
print("pondlevel driver still alive...")
if psi_send_now:
self.sendtodb('pressure_psi', temp_psi, 0)
psi_reading['value'] = temp_psi
psi_reading['timestamp'] = now
if (now - self.public_ip_address_last_checked) > ip_check_after or self.forceSend:
self._check_ip_address()
log.info("pondlevel driver still alive...")
if self.forceSend:
if send_loops > 2:
print("Turning off forceSend")
log.info("Turning off forceSend")
self.forceSend = False
send_loops = 0
else:
send_loops += 1
time.sleep(10)
def _check_ip_address(self):
"""Check the public IP address and send to Meshify if changed."""
self.public_ip_address_last_checked = time.time()
test_public_ip = get_public_ip_address()
if not test_public_ip == self.public_ip_address:
self.sendtodb('public_ip_address', test_public_ip, 0)
self.public_ip_address = test_public_ip
def send_calibration_points(self):
"""Send calibration data from database to Meshify."""
strapping_table_list = []
@@ -161,14 +231,14 @@ class start(threading.Thread, deviceBase):
"""Add a JSON calibration point to the database."""
try:
new_point = json.loads(value.replace("'", '"'))
print("Trying to add Height: {}, volume: {}".format(new_point['height'], new_point['volume']))
log.info("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 Exception as e:
print("EXCEPTION: {}".format(e))
log.error("EXCEPTION: {}".format(e))
def pondlevel_deletecalibrationpoint(self, name, value):
"""Delete a calibration point from the database."""
@@ -179,7 +249,7 @@ class start(threading.Thread, deviceBase):
self.send_calibration_points()
return True
except Exception as e:
print("Error deleting calibration point: {}".format(e))
log.error("Error deleting calibration point: {}".format(e))
return(e)
def store_scaling_data(self):
@@ -188,7 +258,11 @@ class start(threading.Thread, deviceBase):
'raw_max': self.PL_RAWMAX,
'raw_min': self.PL_RAWMIN,
'eu_max': self.PL_EUMAX,
'eu_min': self.PL_EUMIN
'eu_min': self.PL_EUMIN,
'psi_raw_max': self.PSI_RAWMAX,
'psi_raw_min': self.PSI_RAWMIN,
'psi_eu_max': self.PSI_EUMAX,
'psi_eu_min': self.PSI_EUMIN
}
persistence.store(scale_obj, filename="scaling_persist.json")
@@ -206,8 +280,8 @@ class start(threading.Thread, deviceBase):
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)
# 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]
@@ -231,7 +305,7 @@ class start(threading.Thread, deviceBase):
return line_m * height + line_b
except Exception as e:
print("Error in get_volume_for_height: {}".format(e))
log.error("Error in get_volume_for_height: {}".format(e))
return 0.0
def pondlevel_setrawmin(self, name, value):
@@ -261,3 +335,38 @@ class start(threading.Thread, deviceBase):
self.sendtodb("seteumax", self.PL_EUMAX, 0)
self.store_scaling_data()
return(True)
def pondlevel_setleveloffset(self, name, value):
"""Set the Pond level offset scaling value."""
self.PL_OFFSET = float(value)
self.sendtodb("setleveloffset", self.PL_OFFSET, 0)
self.store_scaling_data()
return(True)
def pondlevel_setpsirawmin(self, name, value):
"""Set the raw min pressure scaling value."""
self.PSI_RAWMIN = float(value)
self.sendtodb("setpsirawmin", self.PSI_RAWMIN, 0)
self.store_scaling_data()
return(True)
def pondlevel_setpsirawmax(self, name, value):
"""Set the raw max pressure scaling value."""
self.PSI_RAWMAX = float(value)
self.sendtodb("setpsirawmax", self.PSI_RAWMAX, 0)
self.store_scaling_data()
return(True)
def pondlevel_setpsieumin(self, name, value):
"""Set the psi min pressure scaling value."""
self.PSI_EUMIN = float(value)
self.sendtodb("setpsieumin", self.PSI_EUMIN, 0)
self.store_scaling_data()
return(True)
def pondlevel_setpsieumax(self, name, value):
"""Set the psi max pressure scaling value."""
self.PSI_EUMAX = float(value)
self.sendtodb("setpsieumax", self.PSI_EUMAX, 0)
self.store_scaling_data()
return(True)

View File

@@ -0,0 +1,51 @@
"""Utility functions for the driver."""
import socket
import struct
def get_public_ip_address():
"""Find the public IP Address of the host device."""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
return ip
def int_to_float16(int_to_convert):
"""Convert integer into float16 representation."""
bin_rep = ('0' * 16 + '{0:b}'.format(int_to_convert))[-16:]
sign = 1.0
if int(bin_rep[0]) == 1:
sign = -1.0
exponent = float(int(bin_rep[1:6], 2))
fraction = float(int(bin_rep[6:17], 2))
if exponent == float(0b00000):
return sign * 2 ** -14 * fraction / (2.0 ** 10.0)
elif exponent == float(0b11111):
if fraction == 0:
return sign * float("inf")
else:
return float("NaN")
else:
frac_part = 1.0 + fraction / (2.0 ** 10.0)
return sign * (2 ** (exponent - 15)) * frac_part
def ints_to_float(int1, int2):
"""Convert 2 registers into a floating point number."""
mypack = struct.pack('>HH', int1, int2)
f = struct.unpack('>f', mypack)
print("[{}, {}] >> {}".format(int1, int2, f[0]))
return f[0]
def degf_to_degc(temp_f):
"""Convert deg F to deg C."""
return (temp_f - 32.0) * (5.0/9.0)
def degc_to_degf(temp_c):
"""Convert deg C to deg F."""
return temp_c * 1.8 + 32.0

View File

@@ -1,10 +0,0 @@
{
"files": {
"file2": "calibration_db.py",
"file1": "pondlevel.py"
},
"deviceName": "pondlevel",
"driverId": "0130",
"releaseVersion": "1",
"driverFileName": "pondlevel.py"
}