11 Commits

Author SHA1 Message Date
Patrick McDonagh
b8778389e5 Adds device IP address to channels 2018-07-11 15:21:46 -05:00
Patrick McDonagh
668cbf3b9f v7 allows for up to 5000 mcf total 2017-08-14 11:13:54 -05:00
Patrick McDonagh
b6e3587344 Gets Yesterday Total every 6 hours to ensure correct data for daily updates 2017-05-24 09:54:20 -05:00
Patrick McDonagh
79767d383b Removes sleep logic and grabs daily total every 12 hours
Also increments version number to 6
2017-05-24 09:48:07 -05:00
Patrick McDonagh
273f29b851 Shows todays volume and yesterday's volume on NodeList 2017-02-23 09:56:54 -06:00
Patrick McDonagh
6ca7d16132 Fixes multiple flowmeter devices error, adds sleep log to sidebar, increments version to 5 2017-02-22 15:29:23 -06:00
Patrick McDonagh
42afcda071 Fixes sleep error. Increments version to 4 2017-02-22 12:28:20 -06:00
Patrick McDonagh
4faa6aa296 Changes sleep schedule to allow longer on-time 2017-02-15 16:35:13 -06:00
Patrick McDonagh
ec72749c2a Moved notes from NodeDetailHeader to Dashboard 2017-02-10 10:20:31 -06:00
Patrick McDonagh
3badad56b8 Incremented driver version number 2017-02-10 09:08:59 -06:00
Patrick McDonagh
f452dfeeb7 Fixed wrong use of "true", added logging to sleep and awake 2017-02-10 09:03:08 -06:00
14 changed files with 632 additions and 478 deletions

View File

@@ -1,37 +0,0 @@
<div class='col-xs-1'>
<div class="<%= nodecolors.statuscolor %> nodecolor"></div>
</div>
<div class='col-xs-6'>
<h3><%= node.vanityname %></h3>
</div>
<div class='col-xs-4'>
<div class="text-center">
<h2>Last Note</h2>
<p class="note-text"><%= channels['advvfdipp.notes'].value %></p>
<p> at <%= channels["advvfdipp.notes"].timestamp %></p>
<button href="#" data-channelId="<%= channels['advvfdipp.notes'].channelId %>" class="data-table btn btn-theme note-btn" title="Note History"><i style='margin-left: 0.5em; cursor: pointer' class="fa fa-th-list icon-theme"></i> All Notes</button>
<br />
<button type="button" class="btn btn-theme note-btn" data-toggle="modal" data-target="#note-modal"><i style='margin-left: 0.5em; cursor: pointer' class="fa fa-pencil icon-theme"></i> New Note</button>
</div>
</div>
<style>
#note-modal{
position: absolute;
}
.modal-backdrop {
position: relative;
}
.modal-dialog {
top:5%;
}
.note-btn {
margin-top: 10px;
width: 75%;
}
.note-text {
font-size: 1.5em;
font-style: italic;
}
</style>

View File

@@ -1,32 +0,0 @@
import threading
import time
from device_base import deviceBase
from datetime import datetime
class start(threading.Thread, deviceBase):
def __init__(self, name=None, number=None, mac=None, Q=None, mcu=None,
companyId=None, offset=None, mqtt=None, Nodes=None):
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)
self.sleep_minutes = 25
# 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):
self.channels["status"]["last_value"] = ""
def run(self):
while (true):
t = datetime.now()
if (t.minute == 5 or t.minute == 35):
self.mcu.sleep(self.sleep_minutes * 60)

14
channels_abbflow.csv Normal file
View File

@@ -0,0 +1,14 @@
id,name,deviceTypeId,fromMe,io,subTitle,helpExplanation,channelType,dataType,defaultValue,regex,regexErrMsg,units,min,max,change,guaranteedReportPeriod,minReportTime
8333,battery_voltage,317,FALSE,readonly,Battery Voltage,V,device,float,,,,,,,,,
8334,volume_flow,317,FALSE,readonly,Volume Flow,MCF/Day,device,float,,,,,,,,,
8335,today_volume,317,FALSE,readonly,Today Volume,MCF,device,float,,,,,,,,,
8336,yesterday_volume,317,FALSE,readonly,Yesterday Volume,MCF,device,float,,,,,,,,,
8337,accumulated_volume,317,FALSE,readonly,Accumulated Volume,MCF,device,float,,,,,,,,,
8338,last_calculation_period_volume,317,FALSE,readonly,Last Calculation Period Volume,SCF,device,float,,,,,,,,,
8339,differential_pressure,317,FALSE,readonly,Differential Pressure,InH2O,device,float,,,,,,,,,
8340,static_pressure,317,FALSE,readonly,Static Pressure,PSIA,device,float,,,,,,,,,
8341,temperature,317,FALSE,readonly,Temperature,deg F,device,float,,,,,,,,,
8349,charger_voltage,317,FALSE,readonly,Charger Voltage,V,device,float,,,,,,,,,
8358,notes,317,FALSE,readwrite,Notes,User-entered notes,user input,string,No notes yet...,,,,,,,,
9018,sleeplog,317,FALSE,readonly,Sleep Log,Log of sleep and awakeness,device,string,Nothing here yet...,,,,,,,,
,public_ip_address,317,FALSE,readonly,Public IP Address,Network Address,device,string,n/a,,,,,,,,
1 id name deviceTypeId fromMe io subTitle helpExplanation channelType dataType defaultValue regex regexErrMsg units min max change guaranteedReportPeriod minReportTime
2 8333 battery_voltage 317 FALSE readonly Battery Voltage V device float
3 8334 volume_flow 317 FALSE readonly Volume Flow MCF/Day device float
4 8335 today_volume 317 FALSE readonly Today Volume MCF device float
5 8336 yesterday_volume 317 FALSE readonly Yesterday Volume MCF device float
6 8337 accumulated_volume 317 FALSE readonly Accumulated Volume MCF device float
7 8338 last_calculation_period_volume 317 FALSE readonly Last Calculation Period Volume SCF device float
8 8339 differential_pressure 317 FALSE readonly Differential Pressure InH2O device float
9 8340 static_pressure 317 FALSE readonly Static Pressure PSIA device float
10 8341 temperature 317 FALSE readonly Temperature deg F device float
11 8349 charger_voltage 317 FALSE readonly Charger Voltage V device float
12 8358 notes 317 FALSE readwrite Notes User-entered notes user input string No notes yet...
13 9018 sleeplog 317 FALSE readonly Sleep Log Log of sleep and awakeness device string Nothing here yet...
14 public_ip_address 317 FALSE readonly Public IP Address Network Address device string n/a

View File

@@ -0,0 +1,42 @@
<div class="row row-flex box-me">
<div class="col-md-6 text-center">
<h2 class="uppercase">Public IP Address</h2>
<p><%= channels["abbflow.public_ip_address"].value %><p>
</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

@@ -0,0 +1,6 @@
<div class='col-xs-1'>
<div class="<%= nodecolors.statuscolor %> nodecolor"></div>
</div>
<div class='col-xs-6'>
<h3><%= node.vanityname %></h3>
</div>

View File

@@ -29,13 +29,13 @@
<h4><%= node.vanityname %></h4>
</div>
<div class="col-xs-3">
<h2>Volume Flow</h2>
<p><span data-valueupdate="volume_flow"><%= channels["abbflow.volume_flow"].value %></span> MCF/Day</p>
</div>
<div class="col-xs-3">
<h2>Today Volume</h2>
<p><span data-valueupdate="today_volume"><%= channels["abbflow.today_volume"].value %></span> MCF</p>
</div>
<div class="col-xs-3">
<h2>Yesterday Volume</h2>
<p><span data-valueupdate="yesterday_volume"><%= channels["abbflow.yesterday_volume"].value %></span> MCF</p>
</div>
</div>

View File

@@ -26,6 +26,24 @@
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="row row-flex box-me">
<div class='col-xs-8'>
<div class="text-center">
<h2>Last Note</h2>
<p class="note-text"><%= channels['abbflow.notes'].value %></p>
<p> at <%= channels["abbflow.notes"].timestamp %></p>
</div>
</div>
<div class="col-xs-4">
<div class="text-center">
<button href="#" data-channelId="<%= channels['abbflow.notes'].channelId %>" class="data-table btn btn-theme note-btn" title="Note History"><i style='margin-left: 0.5em; cursor: pointer' class="fa fa-th-list icon-theme"></i> All Notes</button>
<br />
<button type="button" class="btn btn-theme note-btn" data-toggle="modal" data-target="#note-modal"><i style='margin-left: 0.5em; cursor: pointer' class="fa fa-pencil icon-theme"></i> New Note</button>
</div>
</div>
</div>
</div>
<div class='row row-flex box-me'>
<div class='col-xs-4 text-center'>
<h2>Volume Flow</h2>
@@ -373,4 +391,23 @@
letter-spacing: 1px;
z-index: 100;
}
#note-modal{
position: absolute;
}
.modal-backdrop {
position: relative;
}
.modal-dialog {
top:5%;
}
.note-btn {
margin-top: 10px;
width: 75%;
}
.note-text {
font-size: 1.5em;
font-style: italic;
}
</style>

View File

@@ -0,0 +1 @@
<a href="#" data-channelId="<%= channels['abbflow.sleeplog'].channelId %>" class="data-table" title="Sleep Log"><i style='margin-left: 0.5em; cursor: pointer' class="fa fa-th-list icon-theme"></i> Sleep Log</a>

53
python-driver/abbflow.py Normal file
View File

@@ -0,0 +1,53 @@
"""Driver for connecting ABB Flowmeter to Meshify."""
import threading
import time
from device_base import deviceBase
from utilities import get_public_ip_address
WAIT_FOR_CONNECTION_SECONDS = 60
IP_CHECK_PERIOD = 60
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 = "8"
self.finished = threading.Event()
self.public_ip_address = ""
self.public_ip_address_last_checked = 0
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."""
for i in range(0, WAIT_FOR_CONNECTION_SECONDS):
print("abbflow driver will start in {} seconds".format(WAIT_FOR_CONNECTION_SECONDS - i))
time.sleep(1)
while True:
if (time.time() - self.public_ip_address_last_checked) > IP_CHECK_PERIOD:
self._check_ip_address()
def _check_ip_address(self):
"""Check the public IP address and send to Meshify if changed."""
print("Checking IP Address...")
self.public_ip_address_last_checked = time.time()
test_public_ip = get_public_ip_address()
print("Got {} for IP Address".format(test_public_ip))
if not test_public_ip == self.public_ip_address:
self.sendtodbDev(1, 'public_ip_address', test_public_ip, 0, 'abbflow')
self.public_ip_address = test_public_ip

View File

@@ -3,7 +3,7 @@
"driverFileName":"abbflow.py",
"deviceName":"abbflow",
"driverId":"0110",
"releaseVersion":"2",
"releaseVersion":"8",
"files": {
"file1":"abbflow.py",
"file2":"modbusMap.p" }

View File

@@ -0,0 +1,11 @@
{
"name": "abbflow",
"driverFilename": "abbflow.py",
"driverId": "0110",
"additionalDriverFiles": [
"utilities.py",
"modbusMap.p"
],
"version": 8,
"s3BucketName": "abbflow"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
"""Utility functions for the driver."""
import socket
import struct
def get_public_ip_address():
"""Find the public IP Address of the host device."""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.connect(("8.8.8.8", 80))
ip_address = sock.getsockname()[0]
sock.close()
return ip_address
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")
return float("NaN")
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_unpacked = struct.unpack('>f', mypack)
print("[{}, {}] >> {}".format(int1, int2, f_unpacked[0]))
return f_unpacked[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