Adds version 1 of files for testing
This commit is contained in:
41
HTML/NodeList.html
Normal file
41
HTML/NodeList.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<style>
|
||||
.header h4 {
|
||||
position: relative;
|
||||
top: 0.9em;
|
||||
}
|
||||
.header h2 {
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
color: #aaa;
|
||||
margin: 0.75em 0;
|
||||
}
|
||||
.header p {
|
||||
font-size: 24px;
|
||||
color: black;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="row header">
|
||||
<div class="col-xs-1">
|
||||
<div class="<%= nodecolors.statuscolor %> nodecolor"></div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-2">
|
||||
<img src="<%= nodeimgurl %>" />
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3">
|
||||
<h4><%= node.vanityname %></h4>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3">
|
||||
<h2>Flow Rate</h2>
|
||||
<p><span data-valueupdate="gpm_flow"><%= round(channels["flowmonitor.gpm_flow"].value * 100) / 100 %></span> GPM</p>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3">
|
||||
<h2>Run Status</h2>
|
||||
<p><span data-valueupdate="run_status"><%= channels["flowmonitor.run_status"].value %></span></p>
|
||||
</div>
|
||||
</div>
|
||||
23
README.md
23
README.md
@@ -1 +1,22 @@
|
||||
# flow-monitor
|
||||
# flow-monitor
|
||||
|
||||
## To set up sqlite database
|
||||
```
|
||||
sqlite3 flow-monitor.db
|
||||
|
||||
CREATE TABLE flow_data (
|
||||
id integer PRIMARY KEY,
|
||||
gal_totalizer_value float,
|
||||
bbl_totalizer_value float,
|
||||
last_measured_timestamp integer
|
||||
);
|
||||
|
||||
INSERT INTO flow_data (id, gal_totalizer_value, bbl_totalizer_value, last_measured_timestamp) VALUES (1, 0.0, 0.0, 0);
|
||||
```
|
||||
|
||||
## 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;
|
||||
```
|
||||
|
||||
10
config.txt
Normal file
10
config.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
|
||||
"driverFileName":"flow-monitor.py",
|
||||
"deviceName":"flowmonitor",
|
||||
"driverId":"0140",
|
||||
"releaseVersion":"1",
|
||||
"files": {
|
||||
"file1":"flow-monitor.py"}
|
||||
|
||||
}
|
||||
BIN
flow-monitor.db
Normal file
BIN
flow-monitor.db
Normal file
Binary file not shown.
170
flow-monitor.py
Normal file
170
flow-monitor.py
Normal file
@@ -0,0 +1,170 @@
|
||||
"""Driver for connecting Flow Monitor to Meshify."""
|
||||
import threading
|
||||
from device_base import deviceBase
|
||||
import time
|
||||
from datetime import datetime
|
||||
import sqlite3
|
||||
|
||||
|
||||
class Channel:
|
||||
"""Meshify channel structure."""
|
||||
|
||||
def __init__(self, meshify_name, senddelta_value, senddelta_time):
|
||||
"""Initialize the channel with variables."""
|
||||
self.meshify_name = meshify_name
|
||||
self.senddelta_time = senddelta_time
|
||||
self.senddelta_value = senddelta_value
|
||||
|
||||
self.last_sent_value = None
|
||||
self.last_sent_timestamp = 0
|
||||
|
||||
def check_if_send_needed(self, value, timestamp):
|
||||
"""Check to see if the value needs to be pushed."""
|
||||
if self.last_sent_value is None or self.last_sent_timestamp == 0:
|
||||
return True
|
||||
|
||||
if abs(value - self.last_sent_value) > self.senddelta_value:
|
||||
return True
|
||||
|
||||
if (timestamp - self.last_sent_timestamp) > self.senddelta_time:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def update(self, last_sent_value, last_sent_timestamp):
|
||||
"""Update values after a push."""
|
||||
self.last_sent_value = last_sent_value
|
||||
self.last_sent_timestamp = last_sent_timestamp
|
||||
|
||||
|
||||
def scale(raw_val, raw_min, raw_max, eu_min, eu_max):
|
||||
"""Scale a raw value."""
|
||||
m = (eu_max - eu_min) / (raw_max - raw_min)
|
||||
b = eu_max - (m * raw_max)
|
||||
return m * raw_val + b
|
||||
|
||||
|
||||
def is_today(tstamp):
|
||||
"""Check if a given timestamp belongs to the current date."""
|
||||
midnight_today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
midnight_ts = (midnight_today - datetime(1970, 1, 1)).total_seconds()
|
||||
return tstamp >= midnight_ts
|
||||
|
||||
|
||||
class start(threading.Thread, deviceBase):
|
||||
"""Start class required for driver."""
|
||||
|
||||
def __init__(self, name=None, number=None, mac=None, Q=None, mcu=None,
|
||||
companyId=None, offset=None, mqtt=None, Nodes=None):
|
||||
"""Initalize the driver."""
|
||||
threading.Thread.__init__(self)
|
||||
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.finished = threading.Event()
|
||||
threading.Thread.start(self)
|
||||
|
||||
# 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):
|
||||
"""Register the driver."""
|
||||
self.channels["status"]["last_value"] = ""
|
||||
|
||||
|
||||
def run(self):
|
||||
"""Run the driver."""
|
||||
|
||||
# Configuration Parameters
|
||||
total_time_store_delta = 60 # seconds
|
||||
flow_time_store_delta = 60 # seconds
|
||||
|
||||
raw_min = 3.89
|
||||
raw_max = 19.54
|
||||
|
||||
gpm_min = 0.0
|
||||
gpm_max = 600.0
|
||||
|
||||
gal_per_bbl = 42.0
|
||||
|
||||
galtotal_ch = Channel('gal_total', 100.0, total_time_store_delta)
|
||||
bbltotal_ch = Channel('bbl_total', galtotal_ch.senddelta_value/gal_per_bbl, total_time_store_delta)
|
||||
|
||||
gpmflow_ch = Channel('gpm_flow', 10.0, flow_time_store_delta)
|
||||
bpdflow_ch = Channel('bpd_flow', gpmflow_ch.senddelta_value/gal_per_bbl, total_time_store_delta)
|
||||
|
||||
runstatus_ch = Channel('run_status', 0.5, 600)
|
||||
|
||||
last_measured_timestamp = time.time()
|
||||
conn = sqlite3.connect('/root/python_firmware/drivers/flow-monitor.db')
|
||||
c = conn.cursor()
|
||||
c.execute('SELECT * FROM flow_data WHERE id = 1')
|
||||
stored_data = c.fetchone()
|
||||
gal_totalizer_value = stored_data[1]
|
||||
bbl_totalizer_value = stored_data[2]
|
||||
last_measured_timestamp = stored_data[3]
|
||||
if not is_today(last_measured_timestamp):
|
||||
gal_totalizer_value = 0
|
||||
bbl_totalizer_value = 0
|
||||
last_measured_timestamp = time.time()
|
||||
|
||||
wait_loops = 0
|
||||
while wait_loops < 15:
|
||||
print("Waiting to start driver in {} seconds".format(15 - wait_loops))
|
||||
wait_loops += 1
|
||||
time.sleep(1)
|
||||
|
||||
while True:
|
||||
try:
|
||||
mcu_status = self.mcu.getDict()
|
||||
print(mcu_status)
|
||||
cloop_val = float(mcu_status['cloop'])
|
||||
|
||||
din1_val = 1 if mcu_status['din1'] == 'On' else 0
|
||||
gpm_val = scale(cloop_val, raw_min, raw_max, gpm_min, gpm_max)
|
||||
if gpm_val < 0:
|
||||
gpm_val = 0
|
||||
|
||||
bpd_val = (gpm_val / gal_per_bbl) * 60.0 * 24.0
|
||||
|
||||
now = time.time()
|
||||
time_diff = now - last_measured_timestamp
|
||||
gal_flow_delta = (time_diff / 60.0) * gpm_val
|
||||
bbl_flow_delta = (time_diff / 60.0) * (1.0 / 60.0) * (1.0 / 24.0) * bpd_val
|
||||
|
||||
gal_totalizer_value += gal_flow_delta
|
||||
bbl_totalizer_value += bbl_flow_delta
|
||||
last_measured_timestamp = now
|
||||
|
||||
c.execute('UPDATE flow_data SET gal_totalizer_value=?, bbl_totalizer_value=?, last_measured_timestamp=?',
|
||||
(gal_totalizer_value, bbl_totalizer_value, last_measured_timestamp))
|
||||
conn.commit()
|
||||
|
||||
print('gpm: {}, bpd: {}, gal: {}, bbl:{}'.format(gpm_val, bpd_val, gal_totalizer_value, bbl_totalizer_value))
|
||||
|
||||
if galtotal_ch.check_if_send_needed(gal_totalizer_value, now):
|
||||
self.sendtodb(galtotal_ch.meshify_name, gal_totalizer_value, 0)
|
||||
galtotal_ch.update(gal_totalizer_value, now)
|
||||
|
||||
if bbltotal_ch.check_if_send_needed(bbl_totalizer_value, now):
|
||||
self.sendtodb(bbltotal_ch.meshify_name, bbl_totalizer_value, 0)
|
||||
bbltotal_ch.update(bbl_totalizer_value, now)
|
||||
|
||||
if gpmflow_ch.check_if_send_needed(gpm_val, now):
|
||||
self.sendtodb(gpmflow_ch.meshify_name, gpm_val, 0)
|
||||
gpmflow_ch.update(gpm_val, now)
|
||||
|
||||
if bpdflow_ch.check_if_send_needed(bpd_val, now):
|
||||
self.sendtodb(bpdflow_ch.meshify_name, bpd_val, 0)
|
||||
bpdflow_ch.update(bpd_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)
|
||||
|
||||
except Exception as e:
|
||||
print("problem in the driver: {}".format(e))
|
||||
time.sleep(5)
|
||||
150
test_totalizer.py
Normal file
150
test_totalizer.py
Normal file
@@ -0,0 +1,150 @@
|
||||
"""Driver for testing Flow Monitor to Meshify."""
|
||||
import time
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class Channel:
|
||||
"""Meshify channel structure."""
|
||||
|
||||
def __init__(self, meshify_name, senddelta_value, senddelta_time):
|
||||
"""Initialize the channel with variables."""
|
||||
self.meshify_name = meshify_name
|
||||
self.senddelta_time = senddelta_time
|
||||
self.senddelta_value = senddelta_value
|
||||
|
||||
self.last_sent_value = None
|
||||
self.last_sent_timestamp = 0
|
||||
|
||||
def check_if_send_needed(self, value, timestamp):
|
||||
"""Check to see if the value needs to be pushed."""
|
||||
if self.last_sent_value is None or self.last_sent_timestamp == 0:
|
||||
return True
|
||||
|
||||
if abs(value - self.last_sent_value) > self.senddelta_value:
|
||||
return True
|
||||
|
||||
if (timestamp - self.last_sent_timestamp) > self.senddelta_time:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def update(self, last_sent_value, last_sent_timestamp):
|
||||
"""Update values after a push."""
|
||||
self.last_sent_value = last_sent_value
|
||||
self.last_sent_timestamp = last_sent_timestamp
|
||||
|
||||
|
||||
def scale(raw_val, raw_min, raw_max, eu_min, eu_max):
|
||||
"""Scale a raw value."""
|
||||
m = (eu_max - eu_min) / (raw_max - raw_min)
|
||||
b = eu_max - (m * raw_max)
|
||||
return m * raw_val + b
|
||||
|
||||
|
||||
def is_today(tstamp):
|
||||
"""Check if a given timestamp belongs to the current date."""
|
||||
midnight_today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
midnight_ts = (midnight_today - datetime(1970, 1, 1)).total_seconds()
|
||||
return tstamp >= midnight_ts
|
||||
|
||||
|
||||
def loop():
|
||||
"""Run the driver."""
|
||||
# Configuration Parameters
|
||||
total_time_store_delta = 600 # seconds
|
||||
flow_time_store_delta = 600 # seconds
|
||||
|
||||
raw_min = 3.89
|
||||
raw_max = 19.54
|
||||
|
||||
gpm_min = 0.0
|
||||
gpm_max = 600.0
|
||||
|
||||
gal_per_bbl = 42.0
|
||||
|
||||
galtotal_ch = Channel('gal_total', 100.0, total_time_store_delta)
|
||||
bbltotal_ch = Channel('bbl_total', galtotal_ch.senddelta_value/gal_per_bbl, total_time_store_delta)
|
||||
|
||||
gpmflow_ch = Channel('gpm_flow', 10.0, flow_time_store_delta)
|
||||
bpdflow_ch = Channel('bpd_flow', gpmflow_ch.senddelta_value/gal_per_bbl, total_time_store_delta)
|
||||
|
||||
runstatus_ch = Channel('run_status', 0.5, 600)
|
||||
|
||||
last_measured_timestamp = time.time()
|
||||
conn = sqlite3.connect('flow-monitor.db')
|
||||
c = conn.cursor()
|
||||
|
||||
conn.commit()
|
||||
c.execute('SELECT * FROM flow_data WHERE id = 1')
|
||||
stored_data = c.fetchone()
|
||||
gal_totalizer_value = stored_data[1]
|
||||
bbl_totalizer_value = stored_data[2]
|
||||
last_measured_timestamp = stored_data[3]
|
||||
if not is_today(last_measured_timestamp):
|
||||
gal_totalizer_value = 0
|
||||
bbl_totalizer_value = 0
|
||||
last_measured_timestamp = time.time()
|
||||
|
||||
wait_loops = 0
|
||||
while wait_loops < 15:
|
||||
print("Waiting to start driver in {} seconds".format(15 - wait_loops))
|
||||
wait_loops += 1
|
||||
time.sleep(1)
|
||||
|
||||
while True:
|
||||
try:
|
||||
mcu_status = {}
|
||||
mcu_status['cloop'] = '12.0'
|
||||
mcu_status['din1'] = 'Off'
|
||||
print(mcu_status)
|
||||
cloop_val = float(mcu_status['cloop'])
|
||||
|
||||
din1_val = 1 if mcu_status['din1'] == 'On' else 0
|
||||
gpm_val = scale(cloop_val, raw_min, raw_max, gpm_min, gpm_max)
|
||||
if gpm_val < 0:
|
||||
gpm_val = 0
|
||||
|
||||
bpd_val = (gpm_val / gal_per_bbl) * 60.0 * 24.0
|
||||
|
||||
now = time.time()
|
||||
time_diff = now - last_measured_timestamp
|
||||
gal_flow_delta = (time_diff / 60.0) * gpm_val
|
||||
bbl_flow_delta = (time_diff / 60.0) * (1.0 / 60.0) * (1.0 / 24.0) * bpd_val
|
||||
|
||||
gal_totalizer_value += gal_flow_delta
|
||||
bbl_totalizer_value += bbl_flow_delta
|
||||
last_measured_timestamp = now
|
||||
|
||||
c.execute('UPDATE flow_data SET gal_totalizer_value=?, bbl_totalizer_value=?, last_measured_timestamp=?',
|
||||
(gal_totalizer_value, bbl_totalizer_value, last_measured_timestamp))
|
||||
conn.commit()
|
||||
|
||||
print('gpm: {}, bpd: {}, gal: {}, bbl:{}'.format(gpm_val, bpd_val, gal_totalizer_value, bbl_totalizer_value))
|
||||
|
||||
# if galtotal_ch.check_if_send_needed(gal_totalizer_value, now):
|
||||
# self.sendtodb(galtotal_ch.meshify_name, gal_totalizer_value, 0)
|
||||
# galtotal_ch.update(gal_totalizer_value, now)
|
||||
#
|
||||
# if bbltotal_ch.check_if_send_needed(bbl_totalizer_value, now):
|
||||
# self.sendtodb(bbltotal_ch.meshify_name, bbl_totalizer_value, 0)
|
||||
# bbltotal_ch.update(bbl_totalizer_value, now)
|
||||
#
|
||||
# if gpmflow_ch.check_if_send_needed(gpm_val, now):
|
||||
# self.sendtodb(gpmflow_ch.meshify_name, gpm_val, 0)
|
||||
# gpmflow_ch.update(gpm_val, now)
|
||||
#
|
||||
# if bpdflow_ch.check_if_send_needed(bpd_val, now):
|
||||
# self.sendtodb(bpdflow_ch.meshify_name, bpd_val, 0)
|
||||
# bpdflow_ch.update(bpd_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)
|
||||
|
||||
except Exception as e:
|
||||
print("problem in the driver: {}".format(e))
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
loop()
|
||||
Reference in New Issue
Block a user