7 Commits
v1.0 ... master

Author SHA1 Message Date
Patrick McDonagh
0fe4826e39 Adds channels 2018-08-10 15:13:55 -05:00
Patrick McDonagh
ca1aa5e0f6 Increments to version 12 2018-05-15 15:23:34 -05:00
Patrick McDonagh
0249503d6c Persistence stores the json file with indentation 2018-04-05 18:24:21 -05:00
Patrick McDonagh
1fc60e9f7d Fix units and scaling on gauge 2018-04-05 18:17:55 -05:00
Patrick McDonagh
b4c29f51ee Merge pull request #2 from Henry-Pump/add-pressure-transmitter
Completes #1.
2018-04-05 16:43:26 -05:00
Patrick McDonagh
91096b2291 Completes #1.
- Adds Pressure Transmitter on Analog 1
- Updates device driver for reading Analog 1
- Updates device driver to store scaling parameters in persist.json
- Increments version to 11
- Adds migration script to convert from using SQLite scaling storage
- Updates HTML Templates
- Updates README
2018-04-05 16:41:54 -05:00
Patrick McDonagh
f48c165aff Fix for MAXH2O-96. 2018-01-10 11:52:08 -06:00
13 changed files with 523 additions and 133 deletions

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

@@ -0,0 +1,3 @@
{
"python.pythonPath": "/usr/local/bin/python"
}

View File

@@ -106,6 +106,45 @@
</form>
</div>
</div>
<div class="col-md-6 text-center box-me" id="pressure-transmitter-toggle">
<% if (channels['flowmonitor.psi_pressure_enabled'].value == "True"){ %>
<h2>Pressure Transmitter Enabled</h2>
<% } else { %>
<h2>Pressure Transmitter Disabled</h2>
<% } %>
<div data-valueupdate="psi_pressure_enabled" data-refreshonupdate=true>
<form>
<% if (channels['flowmonitor.psi_pressure_enabled'].value == "True"){ %>
<a
href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend="False"
data-channelId="<%= channels["flowmonitor.psi_pressure_enabled"].channelId %>"
data-techname="<%=channels["flowmonitor.psi_pressure_enabled"].techName %>"
data-name="<%= channels["flowmonitor.psi_pressure_enabled"].name%>"
data-nodechannelcurrentId="<%= channels["flowmonitor.psi_pressure_enabled"].nodechannelcurrentId %>"
id="<%= channels["flowmonitor.psi_pressure_enabled"].channelId %>"
class="btn btn-large btn-theme animated setstatic">Disable Pressure Transmitter</a>
<% } else { %>
<a
href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend="True"
data-channelId="<%= channels["flowmonitor.psi_pressure_enabled"].channelId %>"
data-techname="<%=channels["flowmonitor.psi_pressure_enabled"].techName %>"
data-name="<%= channels["flowmonitor.psi_pressure_enabled"].name%>"
data-nodechannelcurrentId="<%= channels["flowmonitor.psi_pressure_enabled"].nodechannelcurrentId %>"
id="<%= channels["flowmonitor.psi_pressure_enabled"].channelId %>"
class="btn btn-large btn-theme animated setstatic">Enable Pressure Transmitter</a>
<% } %>
</form>
</div>
</div>
</div>

View File

@@ -82,6 +82,35 @@
</span>
</div>
</div>
<% if (channels["flowmonitor.psi_pressure_enabled"].value == "True") { %>
<div class='col-xs-6 col-offset-xs-3 text-center box-me'>
<h2>Pressure Transmitter</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-psi_pressure"
data-chart="solidgauge"
data-nodename="flowmonitor.psi_pressure"
data-units="PSI"
data-min="0"
data-max="600"
data-decimalplaces="2"
data-colors="0.1:#DF5353,0.5:#DDDF0D,0.9:#55BF3B"
data-valuefontsize="18px">
</div>
<div class- "timestamp-box">
<a href="#" data-channelId="<%= channels['flowmonitor.psi_pressure'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="psi_pressure">
<%= channels["flowmonitor.psi_pressure"].timestamp %>
</span>
</div>
</div>
<% } %>
</div>
<div class="row box-me">
@@ -133,6 +162,10 @@
data-chart="chart"
data-nodename1="flowmonitor.bpd_flow"
data-datalabel1="Flow Rate (BPD)"
<% if (channels["flowmonitor.psi_pressure_enabled"].value === "True") { %>
data-nodename2="flowmonitor.psi_pressure"
data-datalabel2="Pressure (PSI)"
<% } %>
data-daysofhistory="2"
data-chartlabel="Last 48 Hours"
data-ylabel=""

View File

@@ -1,4 +1,8 @@
<div class="row row-flex">
<div class="col-xs-12" style="text-align: center;">
<h1>Flowmeter</h1>
</div>
<div class="col-md-6 box-me entry-top-level" id="setrawmin">
<div style="margin-left:15px;">
<h2>Raw Min</h2>
@@ -172,6 +176,149 @@
</div>
<div class="row row-flex">
<div class="col-xs-12" style="text-align: center;">
<h1>Pressure Transmitter</h1>
</div>
<div class="col-md-6 box-me entry-top-level" id="setpressurerawmin">
<div style="margin-left:15px;">
<h2>Raw Min</h2>
<form class="form-inline">
<div class="form-group" style="margin-bottom:15px;">
<label
class="sr-only"
for="<%= channels["flowmonitor.setpressurerawmin"].channelId %>">Raw Min Value</label>
<div class="input-group">
<input
class="form-control channel_value"
type="number"
step="any"
value="<%=channels['flowmonitor.setpressurerawmin'].value %>">
<div class="input-group-addon">V</div>
</div>
</div>
<hr />
<a
href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=1.0
data-channelId="<%= channels["flowmonitor.setpressurerawmin"].channelId %>"
data-techname="<%=channels["flowmonitor.setpressurerawmin"].techName %>"
data-name="<%= channels["flowmonitor.setpressurerawmin"].name%>"
data-nodechannelcurrentId="<%= channels["flowmonitor.setpressurerawmin"].nodechannelcurrentId %>"
id="<%= channels["flowmonitor.setpressurerawmin"].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="setpressurerawmax">
<div style="margin-left:15px;">
<h2>Raw Max</h2>
<form class="form-inline">
<div class="form-group" style="margin-bottom:15px;">
<label
class="sr-only"
for="<%= channels["flowmonitor.setpressurerawmax"].channelId %>">Raw Max Value</label>
<div class="input-group">
<input
class="form-control channel_value"
type="number"
step="any"
value="<%=channels['flowmonitor.setpressurerawmax'].value %>">
<div class="input-group-addon">V</div>
</div>
</div>
<hr />
<a
href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=1.0
data-channelId="<%= channels["flowmonitor.setpressurerawmax"].channelId %>"
data-techname="<%=channels["flowmonitor.setpressurerawmax"].techName %>"
data-name="<%= channels["flowmonitor.setpressurerawmax"].name%>"
data-nodechannelcurrentId="<%= channels["flowmonitor.setpressurerawmax"].nodechannelcurrentId %>"
id="<%= channels["flowmonitor.setpressurerawmax"].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="setpressurepsimin">
<div style="margin-left:15px;">
<h2>PSI Min</h2>
<form class="form-inline">
<div class="form-group" style="margin-bottom:15px;">
<label
class="sr-only"
for="<%= channels["flowmonitor.setpressurepsimin"].channelId %>">PSI Min Value</label>
<div class="input-group">
<input
class="form-control channel_value"
type="number"
step="any"
value="<%=channels['flowmonitor.setpressurepsimin'].value %>">
<div class="input-group-addon">PSI</div>
</div>
</div>
<hr />
<a
href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=1.0
data-channelId="<%= channels["flowmonitor.setpressurepsimin"].channelId %>"
data-techname="<%=channels["flowmonitor.setpressurepsimin"].techName %>"
data-name="<%= channels["flowmonitor.setpressurepsimin"].name%>"
data-nodechannelcurrentId="<%= channels["flowmonitor.setpressurepsimin"].nodechannelcurrentId %>"
id="<%= channels["flowmonitor.setpressurepsimin"].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="setpressurepsimax">
<div style="margin-left:15px;">
<h2>PSI Max</h2>
<form class="form-inline">
<div class="form-group" style="margin-bottom:15px;">
<label
class="sr-only"
for="<%= channels["flowmonitor.setpressurepsimax"].channelId %>">PSI Max Value</label>
<div class="input-group">
<input
class="form-control channel_value"
type="number"
step="any"
value="<%=channels['flowmonitor.setpressurepsimax'].value %>">
<div class="input-group-addon">PSI</div>
</div>
</div>
<hr />
<a
href="#"
data-confirm-message="Are you sure you want to do this?"
data-refreshpause="1"
data-command=""
data-staticsend=1.0
data-channelId="<%= channels["flowmonitor.setpressurepsimax"].channelId %>"
data-techname="<%=channels["flowmonitor.setpressurepsimax"].techName %>"
data-name="<%= channels["flowmonitor.setpressurepsimax"].name%>"
data-nodechannelcurrentId="<%= channels["flowmonitor.setpressurepsimax"].nodechannelcurrentId %>"
id="<%= channels["flowmonitor.setpressurepsimax"].channelId %>"
class="btn btn-large btn-theme animated setstatic material-icons">send</a>
</form>
</div>
</div>
</div>
<script>
$('.channel_value').each(function(topLevel){
$(this).change(function(){

View File

@@ -30,7 +30,7 @@
data-ylabel=""
data-xlabel="Date"
data-units=""
data-channelnames="flowmonitor.gal_total,flowmonitor.gal_total_yesterday,flowmonitor.bbl_total,flowmonitor.bbl_total_yesterday,flowmonitor.gpm_flow,flowmonitor.gal_total_thismonth,flowmonitor.gal_total_lastmonth,flowmonitor.bbl_total_thismonth,flowmonitor.bbl_total_lastmonth,flowmonitor.bpd_flow"></div>
data-channelnames="flowmonitor.gal_total,flowmonitor.gal_total_yesterday,flowmonitor.bbl_total,flowmonitor.bbl_total_yesterday,flowmonitor.gpm_flow,flowmonitor.gal_total_thismonth,flowmonitor.gal_total_lastmonth,flowmonitor.bbl_total_thismonth,flowmonitor.bbl_total_lastmonth,flowmonitor.bpd_flow<% if (channels['flowmonitor.psi_pressure_enabled'].value == 'True') { %>,flowmonitor.psi_pressure<% } %>"></div>
<style>
.dynamic-chart-form {

View File

@@ -1,22 +1,15 @@
# flow-monitor
# Max Water System Lite
## To set up sqlite database
```
sqlite3 flow-monitor.db
## Wiring
CREATE TABLE flow_data (
id integer PRIMARY KEY,
gal_totalizer_value float,
bbl_totalizer_value float,
last_measured_timestamp integer
);
| Channel | Device |
| -------------- | -------------------- |
| Relay 1 | Starter Output |
| Digital In 1 | Auto Switch |
| Digital In 2 | Start Button |
| Current Loop | Flowmeter |
| Analog Input 1 | Pressure Transmitter |
INSERT INTO flow_data (id, gal_totalizer_value, bbl_totalizer_value, last_measured_timestamp) VALUES (1, 0.0, 0.0, 0);
```
## Contributors
## To reset the sqlite database
```
sqlite3 flow-monitor.db
UPDATE flow_data SET gal_totalizer_value=0.0, bbl_totalizer_value=0.0, last_measured_timestamp=0 WHERE id=1;
```
- [Patrick McDonagh](https://github.com/patrickjmcd) - Owner

View File

@@ -0,0 +1,33 @@
name,subTitle,defaultValue,dataType
gpm_flow,GPM Flow Rate,,number
run_status,Run Status,,number
bpd_flow,BPD Flow Rate,,number
gal_total,Total Gallons Today,,number
bbl_total,Barrel Total Today,,number
low_flow_gpm,Low Flow Setpoint,10,number
gal_total_yesterday,Gal Total Yesterday,0,number
bbl_total_yesterday,BBL Total Yesterday,0,number
setrawmin,Set Raw Min Scaling,,number
setrawmax,Set Raw Max Scaling,,number
setgpmmin,Set GPM Min Scaling,,number
setgpmmax,Set GPM Max Scaling,,number
log,Log,,string
gal_total_lastmonth,Last Month Total Gallons,,number
bbl_total_lastmonth,Barrel Total Last Month,,number
gal_total_thismonth,Gallons This Month,,number
bbl_total_thismonth,Barrel Total This Month,,number
resetdatabase,Reset Database Command,,string
public_ip_address,Public IP Address,Unknown,string
cost_per_bbl,Cost per BBL,0,number
cost_lastmonth,Cost Last Month,,number
cost_thismonth,Cost This Month,,number
startcmd,Start Command,,string
stopcmd,Stop Command,,string
setgpmignorelimit,Set GPM Ignore Limit,1,number
start_stop_enabled,Start/ Stop Enabled,TRUE,string
psi_pressure,Pressure Transmitter,,number
psi_pressure_enabled,Pressure Transmitter Enabled,FALSE,string
setpressurerawmin,Set Pressure Raw Min Scaling,,number
setpressurerawmax,Set Pressure Raw Max Scaling,,number
setpressurepsimin,Set Pressure PSI Min,,number
setpressurepsimax,Set Pressure PSI Max,,number
1 name subTitle defaultValue dataType
2 gpm_flow GPM Flow Rate number
3 run_status Run Status number
4 bpd_flow BPD Flow Rate number
5 gal_total Total Gallons Today number
6 bbl_total Barrel Total Today number
7 low_flow_gpm Low Flow Setpoint 10 number
8 gal_total_yesterday Gal Total Yesterday 0 number
9 bbl_total_yesterday BBL Total Yesterday 0 number
10 setrawmin Set Raw Min Scaling number
11 setrawmax Set Raw Max Scaling number
12 setgpmmin Set GPM Min Scaling number
13 setgpmmax Set GPM Max Scaling number
14 log Log string
15 gal_total_lastmonth Last Month Total Gallons number
16 bbl_total_lastmonth Barrel Total Last Month number
17 gal_total_thismonth Gallons This Month number
18 bbl_total_thismonth Barrel Total This Month number
19 resetdatabase Reset Database Command string
20 public_ip_address Public IP Address Unknown string
21 cost_per_bbl Cost per BBL 0 number
22 cost_lastmonth Cost Last Month number
23 cost_thismonth Cost This Month number
24 startcmd Start Command string
25 stopcmd Stop Command string
26 setgpmignorelimit Set GPM Ignore Limit 1 number
27 start_stop_enabled Start/ Stop Enabled TRUE string
28 psi_pressure Pressure Transmitter number
29 psi_pressure_enabled Pressure Transmitter Enabled FALSE string
30 setpressurerawmin Set Pressure Raw Min Scaling number
31 setpressurerawmax Set Pressure Raw Max Scaling number
32 setpressurepsimin Set Pressure PSI Min number
33 setpressurepsimax Set Pressure PSI Max number

33
channels_flowmonitor.csv Normal file
View File

@@ -0,0 +1,33 @@
id,name,deviceTypeId,fromMe,io,subTitle,helpExplanation,channelType,dataType,defaultValue,regex,regexErrMsg,units,min,max,change,guaranteedReportPeriod,minReportTime
13163,gpm_flow,433,FALSE,readonly,GPM Flow Rate,Flow Rate in Gallons per Minute,device,float,,,,,,,,,
13164,run_status,433,FALSE,readonly,Run Status,Status of Digital Input 1,device,integer,,,,,,,,,
13165,bpd_flow,433,FALSE,readonly,BPD Flow Rate,Flow Rate in Barrels per Day,device,float,,,,,,,,,
13166,gal_total,433,FALSE,readonly,Total Gallons Today,Total Gallons flowed today,device,float,,,,,,,,,
13167,bbl_total,433,FALSE,readonly,Barrel Total Today,Total Barrels flowed today,device,float,,,,,,,,,
13168,low_flow_gpm,433,FALSE,readwrite,Low Flow Setpoint,in Gallons per Minute,user input,float,10,,,,,,,,
13169,gal_total_yesterday,433,FALSE,readonly,Gal Total Yesterday,Gallons from Midnight to Midnight,device,float,0,,,,,,,,
13170,bbl_total_yesterday,433,FALSE,readonly,BBL Total Yesterday,BBL from Midnight to Midnight,device,float,0,,,,,,,,
13256,setrawmin,433,FALSE,readwrite,Set Raw Min Scaling,raw value,device,float,,,,,,,,,
13257,setrawmax,433,FALSE,readwrite,Set Raw Max Scaling,raw value,device,float,,,,,,,,,
13258,setgpmmin,433,FALSE,readwrite,Set GPM Min Scaling,GPM Value,device,float,,,,,,,,,
13259,setgpmmax,433,FALSE,readwrite,Set GPM Max Scaling,GPM Value,device,float,,,,,,,,,
13260,log,433,FALSE,readwrite,Log,Log,device,string,,,,,,,,,
13310,gal_total_lastmonth,433,FALSE,readonly,Last Month Total Gallons,in Gallons,device,float,,,,,,,,,
13311,bbl_total_lastmonth,433,FALSE,readonly,Barrel Total Last Month,in BBL,device,float,,,,,,,,,
13312,gal_total_thismonth,433,FALSE,readonly,Gallons This Month,in Gallons,device,float,,,,,,,,,
13313,bbl_total_thismonth,433,FALSE,readonly,Barrel Total This Month,in BBL,device,float,,,,,,,,,
13314,resetdatabase,433,FALSE,readwrite,Reset Database Command,Command to reset the database on the M1,device,string,,,,,,,,,
13315,public_ip_address,433,FALSE,readonly,Public IP Address,Address of the M1,device,string,Unknown,,,,,,,,
13316,cost_per_bbl,433,FALSE,readwrite,Cost per BBL,Selling cost per bbl in dollars,user input,float,0,,,,,,,,
13317,cost_lastmonth,433,FALSE,readonly,Cost Last Month,Last Month BBL cost in Dollars,device,float,,,,,,,,,
13318,cost_thismonth,433,FALSE,readonly,Cost This Month,Cost This months in dollars,device,float,,,,,,,,,
13362,startcmd,433,FALSE,readwrite,Start Command,Starts well if wired for remote start,device,string,,,,,,,,,
13363,stopcmd,433,FALSE,readwrite,Stop Command,Stops the well if wired to stop,device,string,,,,,,,,,
13364,setgpmignorelimit,433,FALSE,readwrite,Set GPM Ignore Limit,Value at which GPM will be effectively 0,device,float,1,,,,,,,,
13365,start_stop_enabled,433,FALSE,readwrite,Start/ Stop Enabled,The device is equipped with a start/stop relay,user input,string,TRUE,,,,,,,,
13635,psi_pressure,433,FALSE,readonly,Pressure Transmitter,in PSI,device,float,,,,,,,,,
13637,psi_pressure_enabled,433,FALSE,readwrite,Pressure Transmitter Enabled,Pressure Transmitter Enabled,user input,string,FALSE,,,,,,,,
13638,setpressurerawmin,433,FALSE,readwrite,Set Pressure Raw Min Scaling,in V,device,float,,,,,,,,,
13639,setpressurerawmax,433,FALSE,readwrite,Set Pressure Raw Max Scaling,in V,device,float,,,,,,,,,
13640,setpressurepsimin,433,FALSE,readwrite,Set Pressure PSI Min,in PSI,device,float,,,,,,,,,
13641,setpressurepsimax,433,FALSE,readwrite,Set Pressure PSI Max,in PSI,device,float,,,,,,,,,
1 id name deviceTypeId fromMe io subTitle helpExplanation channelType dataType defaultValue regex regexErrMsg units min max change guaranteedReportPeriod minReportTime
2 13163 gpm_flow 433 FALSE readonly GPM Flow Rate Flow Rate in Gallons per Minute device float
3 13164 run_status 433 FALSE readonly Run Status Status of Digital Input 1 device integer
4 13165 bpd_flow 433 FALSE readonly BPD Flow Rate Flow Rate in Barrels per Day device float
5 13166 gal_total 433 FALSE readonly Total Gallons Today Total Gallons flowed today device float
6 13167 bbl_total 433 FALSE readonly Barrel Total Today Total Barrels flowed today device float
7 13168 low_flow_gpm 433 FALSE readwrite Low Flow Setpoint in Gallons per Minute user input float 10
8 13169 gal_total_yesterday 433 FALSE readonly Gal Total Yesterday Gallons from Midnight to Midnight device float 0
9 13170 bbl_total_yesterday 433 FALSE readonly BBL Total Yesterday BBL from Midnight to Midnight device float 0
10 13256 setrawmin 433 FALSE readwrite Set Raw Min Scaling raw value device float
11 13257 setrawmax 433 FALSE readwrite Set Raw Max Scaling raw value device float
12 13258 setgpmmin 433 FALSE readwrite Set GPM Min Scaling GPM Value device float
13 13259 setgpmmax 433 FALSE readwrite Set GPM Max Scaling GPM Value device float
14 13260 log 433 FALSE readwrite Log Log device string
15 13310 gal_total_lastmonth 433 FALSE readonly Last Month Total Gallons in Gallons device float
16 13311 bbl_total_lastmonth 433 FALSE readonly Barrel Total Last Month in BBL device float
17 13312 gal_total_thismonth 433 FALSE readonly Gallons This Month in Gallons device float
18 13313 bbl_total_thismonth 433 FALSE readonly Barrel Total This Month in BBL device float
19 13314 resetdatabase 433 FALSE readwrite Reset Database Command Command to reset the database on the M1 device string
20 13315 public_ip_address 433 FALSE readonly Public IP Address Address of the M1 device string Unknown
21 13316 cost_per_bbl 433 FALSE readwrite Cost per BBL Selling cost per bbl in dollars user input float 0
22 13317 cost_lastmonth 433 FALSE readonly Cost Last Month Last Month BBL cost in Dollars device float
23 13318 cost_thismonth 433 FALSE readonly Cost This Month Cost This months in dollars device float
24 13362 startcmd 433 FALSE readwrite Start Command Starts well if wired for remote start device string
25 13363 stopcmd 433 FALSE readwrite Stop Command Stops the well if wired to stop device string
26 13364 setgpmignorelimit 433 FALSE readwrite Set GPM Ignore Limit Value at which GPM will be effectively 0 device float 1
27 13365 start_stop_enabled 433 FALSE readwrite Start/ Stop Enabled The device is equipped with a start/stop relay user input string TRUE
28 13635 psi_pressure 433 FALSE readonly Pressure Transmitter in PSI device float
29 13637 psi_pressure_enabled 433 FALSE readwrite Pressure Transmitter Enabled Pressure Transmitter Enabled user input string FALSE
30 13638 setpressurerawmin 433 FALSE readwrite Set Pressure Raw Min Scaling in V device float
31 13639 setpressurerawmax 433 FALSE readwrite Set Pressure Raw Max Scaling in V device float
32 13640 setpressurepsimin 433 FALSE readwrite Set Pressure PSI Min in PSI device float
33 13641 setpressurepsimax 433 FALSE readwrite Set Pressure PSI Max in PSI device float

View File

@@ -1,11 +1,11 @@
{
"files": {
"file3": "persistence.py",
"file2": "utilities.py",
"file3": "persistence.py",
"file2": "utilities.py",
"file1": "flow-monitor.py"
},
"deviceName": "flowmonitor",
"driverId": "0140",
"releaseVersion": "9",
},
"deviceName": "flowmonitor",
"driverId": "0140",
"releaseVersion": "12",
"driverFileName": "flow-monitor.py"
}
}

2
device_base.py Normal file
View File

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

View File

@@ -1,10 +1,10 @@
{
"version": 11,
"driverFilename": "flow-monitor.py",
"s3BucketName": "flow-monitor",
"name": "flowmonitor",
"additionalDriverFiles": [
"utilities.py",
"persistence.py"
],
"name": "flowmonitor",
"version": 9,
"driverFilename": "flow-monitor.py"
]
}

View File

@@ -3,10 +3,30 @@ import threading
import time
from datetime import datetime
import sqlite3
import logging
import sys
from device_base import deviceBase
import persistence
from utilities import get_public_ip_address
# LOGGING SETUP
from logging.handlers import RotatingFileHandler
log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s')
logFile = './flowmonitor.log'
my_handler = RotatingFileHandler(logFile, mode='a', maxBytes=500*1024, backupCount=2, encoding=None, delay=0)
my_handler.setFormatter(log_formatter)
my_handler.setLevel(logging.INFO)
logger = logging.getLogger('flowmonitor')
logger.setLevel(logging.INFO)
logger.addHandler(my_handler)
console_out = logging.StreamHandler(sys.stdout)
console_out.setFormatter(log_formatter)
logger.addHandler(console_out)
logger.info("flowmonitor startup")
CREATE_FLOWDATA_TABLE = """CREATE TABLE flow_data (
id integer PRIMARY KEY,
gal_totalizer_value float,
@@ -39,30 +59,43 @@ UPDATE_FLOWDATA = """UPDATE flow_data SET
bbl_monthly_totalizer=?,
last_measured_timestamp=? WHERE id=1"""
CREATE_SCALINGDATA_TABLE = """CREATE TABLE scaling_data (
id integer PRIMARY KEY,
raw_min float,
raw_max float,
gpm_min float,
gpm_max float
);"""
INSERT_SCALINGDATA = """INSERT INTO scaling_data (
id,
raw_min,
raw_max,
gpm_min,
gpm_max) VALUES (1, ?, ?, ?, ?);"""
UPDATE_SCALINGDATA = """UPDATE scaling_data SET
raw_min=?,
raw_max=?,
gpm_min=?,
gpm_max=? WHERE id=1;"""
PERSIST = persistence.load()
def migrate_from_sqlite_to_json_scaling():
"""Migrate data from SQLite db to JSON, if needed"""
global PERSIST
try:
PERSIST['flow_raw_min']
logger.info("Don't need to migrate from SQLite to JSON.")
return False
except (KeyError, TypeError):
logger.info("Migrating from SQLite to JSON.")
if not PERSIST:
PERSIST = {}
conn = sqlite3.connect('/root/python_firmware/drivers/flow-monitor.db')
cursor = conn.cursor()
try:
cursor.execute('SELECT * FROM scaling_data WHERE id = 1') # dummy query for checking database
stored_data = cursor.fetchone()
flow_raw_min = stored_data[1]
flow_raw_max = stored_data[2]
flow_gpm_min = stored_data[3]
flow_gpm_max = stored_data[4]
except (sqlite3.OperationalError, TypeError):
logger.info("No stored data in SQLite for scaling, we'll just use default values")
return False
PERSIST["flow_raw_min"] = flow_raw_min
PERSIST["flow_raw_max"] = flow_raw_max
PERSIST["flow_gpm_min"] = flow_gpm_min
PERSIST["flow_gpm_max"] = flow_gpm_max
persistence.store(PERSIST)
class ChannelSimple(object):
"""Simple Meshify channel structure."""
@@ -126,14 +159,20 @@ class start(threading.Thread, deviceBase):
mcu=mcu, companyId=companyId, offset=offset,
mqtt=mqtt, Nodes=Nodes)
# Default Scaling Values for Flowmeter
self.RAW_MIN = 3.89
self.RAW_MAX = 19.54
self.GPM_MIN = 0.0
self.GPM_MAX = 100.0
self.flow_raw_min = 3.89
self.flow_raw_max = 19.54
self.flow_gpm_min = 0.0
self.flow_gpm_max = 100.0
self.pressure_raw_min = 0.00
self.pressure_raw_max = 10.00
self.pressure_psi_min = 0.00
self.pressure_psi_max = 600.0
self.GPM_IGNORE_LIMIT = 1.0
self.daemon = True
self.version = "8"
self.version = "12"
self.finished = threading.Event()
threading.Thread.start(self)
@@ -149,6 +188,7 @@ class start(threading.Thread, deviceBase):
# Configuration Parameters
total_time_store_delta = 600 # seconds
flow_time_store_delta = 600 # seconds
pressure_time_store_delta = 600 # seconds
gal_per_bbl = 42.0
startup_wait_seconds = 30
ip_check_after = 3600 # check public IP address after an hour
@@ -169,13 +209,14 @@ class start(threading.Thread, deviceBase):
bbltotalthismonth_ch = ChannelSimple('bbl_total_thismonth', galtotalthismonth_ch.senddelta_value/gal_per_bbl, total_time_store_delta)
gpmflow_ch = ChannelSimple('gpm_flow', 10.0, flow_time_store_delta)
bpdflow_ch = ChannelSimple('bpd_flow', gpmflow_ch.senddelta_value * 34.2857, flow_time_store_delta)
psipressure_ch = ChannelSimple('psi_pressure', 10.0, pressure_time_store_delta)
runstatus_ch = ChannelSimple('run_status', 0.5, 600)
# Startup timer.
# Waits for connection to Meshify before attempting to send data
wait_loops = 0
while wait_loops < startup_wait_seconds:
print("Waiting to start flowmonitor driver in {} seconds".format(startup_wait_seconds - wait_loops))
logger.info("Waiting to start flowmonitor driver in {} seconds".format(startup_wait_seconds - wait_loops))
wait_loops += 1
time.sleep(1)
@@ -203,7 +244,7 @@ class start(threading.Thread, deviceBase):
last_measured_timestamp = stored_data[5]
except sqlite3.OperationalError:
# Caught if the table does not exist in the database.
print("No table flow_data in the database. I'll create it now.")
logger.warning("No table flow_data in the database. I'll create it now.")
cursor.execute(CREATE_FLOWDATA_TABLE)
cursor.execute(INSERT_BLANK_FLOWDATA)
conn.commit()
@@ -211,32 +252,50 @@ class start(threading.Thread, deviceBase):
# Reset the database if the correct size data is not in the database.
self.flowmonitor_resetdatabase(None, None)
# Load scaling data
migrate_from_sqlite_to_json_scaling()
try:
cursor.execute('SELECT * FROM scaling_data WHERE id = 1') # dummy query for checking database
stored_data = cursor.fetchone()
self.RAW_MIN = stored_data[1]
self.RAW_MAX = stored_data[2]
self.GPM_MIN = stored_data[3]
self.GPM_MAX = stored_data[4]
self.sendtodb("setrawmin", self.RAW_MIN, 0)
self.sendtodb("setrawmax", self.RAW_MAX, 0)
self.sendtodb("setgpmmin", self.GPM_MIN, 0)
self.sendtodb("setgpmmax", self.GPM_MAX, 0)
except (sqlite3.OperationalError, TypeError):
# Caught if the table does not exist in the database.
print("No table scaling_data in the database. I'll create it now.")
cursor.execute(CREATE_SCALINGDATA_TABLE)
cursor.execute(INSERT_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
self.sendtodb("setrawmin", self.RAW_MIN, 0)
self.sendtodb("setrawmax", self.RAW_MAX, 0)
self.sendtodb("setgpmmin", self.GPM_MIN, 0)
self.sendtodb("setgpmmax", self.GPM_MAX, 0)
conn.commit()
self.flow_raw_min = PERSIST["flow_raw_min"]
self.flow_raw_max = PERSIST["flow_raw_max"]
self.flow_gpm_min = PERSIST["flow_gpm_min"]
self.flow_gpm_max = PERSIST["flow_gpm_max"]
except KeyError:
logger.warning("No flow scaling data exists in persist file. We'll add some now")
PERSIST["flow_raw_min"] = self.flow_raw_min
PERSIST["flow_raw_max"] = self.flow_raw_max
PERSIST["flow_gpm_min"] = self.flow_gpm_min
PERSIST["flow_gpm_max"] = self.flow_gpm_max
persistence.store(PERSIST)
self.sendtodb("setrawmin", self.flow_raw_min, 0)
self.sendtodb("setrawmax", self.flow_raw_max, 0)
self.sendtodb("setgpmmin", self.flow_gpm_min, 0)
self.sendtodb("setgpmmax", self.flow_gpm_max, 0)
try:
self.pressure_raw_min = PERSIST["pressure_raw_min"]
self.pressure_raw_max = PERSIST["pressure_raw_max"]
self.pressure_psi_min = PERSIST["pressure_psi_min"]
self.pressure_psi_max = PERSIST["pressure_psi_max"]
except KeyError:
logger.warning("No flow scaling data exists in persist file. We'll add some now")
PERSIST["pressure_raw_min"] = self.pressure_raw_min
PERSIST["pressure_raw_max"] = self.pressure_raw_max
PERSIST["pressure_psi_min"] = self.pressure_psi_min
PERSIST["pressure_psi_max"] = self.pressure_psi_max
persistence.store(PERSIST)
self.sendtodb("setpressurerawmin", self.pressure_raw_min, 0)
self.sendtodb("setpressurerawmax", self.pressure_raw_max, 0)
self.sendtodb("setpressurepsimin", self.pressure_psi_min, 0)
self.sendtodb("setpressurepsimax", self.pressure_psi_max, 0)
try:
self.GPM_IGNORE_LIMIT = PERSIST['gpm_ignore_limit']
except KeyError:
print("no persisted GPM Ignore Limit. Using default of {}".format(self.GPM_IGNORE_LIMIT))
except Exception:
logger.warning("no persisted GPM Ignore Limit. Using default of {}".format(self.GPM_IGNORE_LIMIT))
self.flowmonitor_setgpmignorelimit("gpm_ignore_limit", self.GPM_IGNORE_LIMIT)
# on bootup, if the day has changed, clear the totalizers.
# this would happen if the device is off when the time changes to Midnight.
@@ -249,11 +308,31 @@ class start(threading.Thread, deviceBase):
while True:
try:
mcu_status = self.mcu.getDict() # Gets a dictionary of the IO states
# {
# 'bat': u'23.10',
# 'ver': u'Mar 16 2016 21:29:31',
# 'dout3': 'Off',
# 'temp': u'40.37',
# 'vin': u'24.6',
# 'pulse': u'0',
# 'dout4': 'Off',
# 'dout1': 'Off',
# 'din2': 'Off',
# 'din1': 'Off',
# 'dout2': 'On',
# 'cloop': u'0.0',
# 'analog4': u'0.0',
# 'analog3': u'0.0',
# 'analog2': u'0.0',
# 'analog1': u'0.0',
# 'relay1': 'Off'
# }
cloop_val = float(mcu_status['cloop'])
analog1_val = float(mcu_status['analog1'])
din1_val = 1 if mcu_status['din1'] == 'On' else 0 # Check DIGITAL INPUT 1 for run status
gpm_val = scale(cloop_val, self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX)
if gpm_val < GPM_IGNORE_LIMIT:
gpm_val = scale(cloop_val, self.flow_raw_min, self.flow_raw_max, self.flow_gpm_min, self.flow_gpm_max)
psi_val = scale(analog1_val, self.pressure_raw_min, self.pressure_raw_max, self.pressure_psi_min, self.pressure_psi_max)
if gpm_val < self.GPM_IGNORE_LIMIT:
gpm_val = 0
bpd_val = (gpm_val / gal_per_bbl) * 60.0 * 24.0 # Computes BPD from GPM
@@ -277,8 +356,8 @@ class start(threading.Thread, deviceBase):
cursor.execute(UPDATE_FLOWDATA, (gal_totalizer_value, bbl_totalizer_value, gal_monthly_totalizer, bbl_monthly_totalizer, last_measured_timestamp))
conn.commit()
print('gpm: {}, bpd: {}, gal: {}, bbl:{}, month_gal:{}, month_bbl:{}'.format(
gpm_val, bpd_val, gal_totalizer_value, bbl_totalizer_value, gal_monthly_totalizer, bbl_monthly_totalizer))
logger.info('gpm: {}, bpd: {}, psi: {}, gal: {}, bbl:{}, month_gal:{}, month_bbl:{}'.format(
gpm_val, bpd_val, psi_val, gal_totalizer_value, bbl_totalizer_value, gal_monthly_totalizer, bbl_monthly_totalizer))
# Channel Checks:
# check to see if the value needs to be sent to Meshify
@@ -306,6 +385,10 @@ class start(threading.Thread, deviceBase):
self.sendtodb(bpdflow_ch.meshify_name, bpd_val, 0)
bpdflow_ch.update(bpd_val, now)
if psipressure_ch.check_if_send_needed(psi_val, now):
self.sendtodb(psipressure_ch.meshify_name, psi_val, 0)
psipressure_ch.update(psi_val, now)
if runstatus_ch.check_if_send_needed(din1_val, now):
self.sendtodb(runstatus_ch.meshify_name, din1_val, 0)
runstatus_ch.update(din1_val, now)
@@ -357,7 +440,7 @@ class start(threading.Thread, deviceBase):
self.flowmonitor_stopcmd(None, None)
except Exception as e:
print("problem in the driver: {}".format(e))
logger.error("problem in the driver: {}".format(e))
time.sleep(2)
def flowmonitor_startcmd(self, name, value):
@@ -380,9 +463,9 @@ class start(threading.Thread, deviceBase):
cursor.execute(CREATE_FLOWDATA_TABLE)
cursor.execute(INSERT_BLANK_FLOWDATA)
conn.commit()
print("DATABASE HAS BEEN RESET!")
logger.info("DATABASE HAS BEEN RESET!")
except sqlite3.OperationalError:
print("No table flow_data in the database. I'll create it now.")
logger.warning("No table flow_data in the database. I'll create it now.")
cursor.execute(CREATE_FLOWDATA_TABLE)
cursor.execute(INSERT_BLANK_FLOWDATA)
conn.commit()
@@ -390,66 +473,90 @@ class start(threading.Thread, deviceBase):
def flowmonitor_setrawmin(self, name, value):
"""Set the raw min scaling value."""
conn = sqlite3.connect('/root/python_firmware/drivers/flow-monitor.db')
cursor = conn.cursor()
try:
self.RAW_MIN = float(value)
cursor.execute(UPDATE_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
self.sendtodb("setrawmin", self.RAW_MIN, 0)
conn.commit()
except sqlite3.OperationalError:
print("No table flow_data in the database. I'll create it now.")
cursor.execute(CREATE_SCALINGDATA_TABLE)
cursor.execute(INSERT_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
conn.commit()
self.flow_raw_min = float(value)
self.sendtodb("setrawmin", self.flow_raw_min, 0)
PERSIST['flow_raw_min'] = self.flow_raw_min
persistence.store(PERSIST)
except Exception as e:
logger.error("Could not set self.flow_raw_min: {}".format(e))
return(True)
def flowmonitor_setrawmax(self, name, value):
"""Set the raw max scaling value."""
conn = sqlite3.connect('/root/python_firmware/drivers/flow-monitor.db')
cursor = conn.cursor()
try:
self.RAW_MAX = float(value)
self.sendtodb("setrawmax", self.RAW_MAX, 0)
cursor.execute(UPDATE_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
conn.commit()
except sqlite3.OperationalError:
print("No table flow_data in the database. I'll create it now.")
cursor.execute(CREATE_SCALINGDATA_TABLE)
cursor.execute(INSERT_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
conn.commit()
self.flow_raw_max = float(value)
self.sendtodb("setrawmax", self.flow_raw_max, 0)
PERSIST['flow_raw_max'] = self.flow_raw_max
persistence.store(PERSIST)
except Exception as e:
logger.error("Could not set self.flow_raw_max: {}".format(e))
return(True)
def flowmonitor_setgpmmin(self, name, value):
"""Set the gpm min scaling value."""
conn = sqlite3.connect('/root/python_firmware/drivers/flow-monitor.db')
cursor = conn.cursor()
try:
self.GPM_MIN = float(value)
self.sendtodb("setgpmmin", self.GPM_MIN, 0)
cursor.execute(UPDATE_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
conn.commit()
except sqlite3.OperationalError:
print("No table flow_data in the database. I'll create it now.")
cursor.execute(CREATE_SCALINGDATA_TABLE)
cursor.execute(INSERT_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
conn.commit()
self.flow_gpm_min = float(value)
self.sendtodb("setgpmmin", self.flow_gpm_min, 0)
PERSIST['flow_gpm_min'] = self.flow_gpm_min
persistence.store(PERSIST)
except Exception as e:
logger.error("Could not set self.flow_gpm_min: {}".format(e))
return(True)
def flowmonitor_setgpmmax(self, name, value):
"""Set the gpm max scaling value."""
conn = sqlite3.connect('/root/python_firmware/drivers/flow-monitor.db')
cursor = conn.cursor()
try:
self.GPM_MAX = float(value)
self.sendtodb("setgpmmax", self.GPM_MAX, 0)
cursor.execute(UPDATE_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
conn.commit()
except sqlite3.OperationalError:
print("No table flow_data in the database. I'll create it now.")
cursor.execute(CREATE_SCALINGDATA_TABLE)
cursor.execute(INSERT_SCALINGDATA, (self.RAW_MIN, self.RAW_MAX, self.GPM_MIN, self.GPM_MAX))
conn.commit()
self.flow_gpm_max = float(value)
self.sendtodb("setgpmmax", self.flow_gpm_max, 0)
PERSIST['flow_gpm_max'] = self.flow_gpm_max
persistence.store(PERSIST)
except Exception as e:
logger.error("Could not set self.flow_gpm_max: {}".format(e))
return(True)
def flowmonitor_setpressurerawmin(self, name, value):
"""Set the pressure raw min scaling value."""
try:
self.pressure_raw_min = float(value)
self.sendtodb("setpressurerawmin", self.pressure_raw_min, 0)
PERSIST['pressure_raw_min'] = self.pressure_raw_min
persistence.store(PERSIST)
except Exception as e:
logger.error("Could not set self.pressure_raw_min: {}".format(e))
return(True)
def flowmonitor_setpressurerawmax(self, name, value):
"""Set the pressure raw max scaling value."""
try:
self.pressure_raw_max = float(value)
self.sendtodb("setpressurerawmax", self.pressure_raw_max, 0)
PERSIST['pressure_raw_max'] = self.pressure_raw_max
persistence.store(PERSIST)
except Exception as e:
logger.error("Could not set self.pressure_raw_max: {}".format(e))
return(True)
def flowmonitor_setpressurepsimin(self, name, value):
"""Set the pressure psi min scaling value."""
try:
self.pressure_psi_min = float(value)
self.sendtodb("setpressurepsimin", self.pressure_psi_min, 0)
PERSIST['pressure_psi_min'] = self.pressure_psi_min
persistence.store(PERSIST)
except Exception as e:
logger.error("Could not set self.pressure_psi_min: {}".format(e))
return(True)
def flowmonitor_setpressurepsimax(self, name, value):
"""Set the pressure psi max scaling value."""
try:
self.pressure_psi_max = float(value)
self.sendtodb("setpressurepsimax", self.pressure_psi_max, 0)
PERSIST['pressure_psi_max'] = self.pressure_psi_max
persistence.store(PERSIST)
except Exception as e:
logger.error("Could not set self.pressure_psi_max: {}".format(e))
return(True)
def flowmonitor_setgpmignorelimit(self, name, value):
@@ -459,5 +566,5 @@ class start(threading.Thread, deviceBase):
self.sendtodb("setgpmignorelimit", self.GPM_IGNORE_LIMIT, 0)
return True
except Exception as e:
print("Error during flowmonitor_setgpmignorelimit: {}".format(e))
logger.error("Error during flowmonitor_setgpmignorelimit: {}".format(e))
return False

View File

@@ -16,6 +16,6 @@ def store(persist_obj, filename="persist.json"):
"""Store the persisting settings into the specified file."""
try:
with open(filename, 'w') as persist_file:
return json.dump(persist_obj, persist_file)
return json.dump(persist_obj, persist_file, indent=4)
except Exception:
return False