Reorganize Files

This commit is contained in:
Patrick McDonagh
2018-05-22 12:02:18 -05:00
parent 27403b6db6
commit 034177f18d
23 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1 @@
<module>Alerts</module>

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["tanktransfer.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

@@ -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-2">
<h4><%= node.vanityname %></h4>
</div>
<div class="col-xs-3">
<h2>Flow In</h2>
<p><span data-valueupdate="system1_inlet_flowrate"><%= Math.round(channels["tanktransfer.system1_inlet_flowrate"].value * 100) / 100 %></span> BPD</p>
</div>
<div class="col-xs-3">
<h2>Flow Out</h2>
<p><span data-valueupdate="system1_outlet_flowrate"><%= Math.round(channels["tanktransfer.system1_outlet_flowrate"].value * 100) / 100 %></span> BPD</p>
</div>
</div>

View File

@@ -0,0 +1,330 @@
<div class="row row-flex box-me">
<div class="col-xs-12 text-center">
<h1>System 1</h1>
</div>
<div class="col-xs-4 text-center box-me">
<h2>Inlet 1 Flow Rate</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_inlet1_flowrate"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_inlet1_flowrate"
data-units="GPM"
data-min="0"
data-max="2000"
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['tanktransfer.system1_inlet1_flowrate'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_inlet1_flowrate">
<%= channels["tanktransfer.system1_inlet1_flowrate"].timestamp %>
</span>
</div>
</div>
<% if (channels["tanktransfer.system1_numinputft"].value == 2) { %>
<div class="col-xs-4 text-center box-me">
<h2>Inlet 2 Flow Rate</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_inlet2_flowrate"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_inlet2_flowrate"
data-units="GPM"
data-min="0"
data-max="2000"
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['tanktransfer.system1_inlet2_flowrate'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_inlet2_flowrate">
<%= channels["tanktransfer.system1_inlet2_flowrate"].timestamp %>
</span>
</div>
</div>
<% } %>
<div class="col-xs-4 text-center box-me">
<h2>Tank Level</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_level"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_level"
data-units="Ft."
data-min="0"
data-max="25"
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['tanktransfer.system1_level'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_level">
<%= channels["tanktransfer.system1_level"].timestamp %>
</span>
</div>
</div>
<div class="col-xs-4 text-center box-me">
<h2>Motor Frequency</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_motor_frequency"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_motor_frequency"
data-units="Hz"
data-min="0"
data-max="60"
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['tanktransfer.system1_motor_frequency'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_motor_frequency">
<%= channels["tanktransfer.system1_motor_frequency"].timestamp %>
</span>
</div>
</div>
<div class="col-xs-4 text-center box-me">
<h2>Motor Current</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_motor_current"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_motor_current"
data-units="Amps"
data-min="0"
data-max="100"
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['tanktransfer.system1_motor_current'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_motor_current">
<%= channels["tanktransfer.system1_motor_current"].timestamp %>
</span>
</div>
</div>
<div class="col-xs-4 text-center box-me">
<h2>Discharge Pressure</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_dischargepressure"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_dischargepressure"
data-units="PSI"
data-min="0"
data-max="400"
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['tanktransfer.system1_dischargepressure'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_dischargepressure">
<%= channels["tanktransfer.system1_dischargepressure"].timestamp %>
</span>
</div>
</div>
<div class="col-xs-4 text-center box-me">
<h2>Outlet Flow Rate</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_outlet_flowrate"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_outlet_flowrate"
data-units="BPD"
data-min="0"
data-max="2000"
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['tanktransfer.system1_outlet_flowrate'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_outlet_flowrate">
<%= channels["tanktransfer.system1_outlet_flowrate"].timestamp %>
</span>
</div>
</div>
<div class="col-xs-4 text-center box-me">
<h2>Inlet Flow Today</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_flowtotal_in_today"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_flowtotal_in_today"
data-units="BBL"
data-min="0"
data-max="10000"
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['tanktransfer.system1_flowtotal_in_today'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_outlet_flowrate">
<%= channels["tanktransfer.system1_outlet_flowrate"].timestamp %>
</span>
</div>
</div>
<div class="col-xs-4 text-center box-me">
<h2>Outlet Flow Today</h2>
<div class="gauge-box">
<div data-labelheight="10"
style="height: 170px; background: transparent; margin: 0 auto;"
id="gauge-system1_flowtotal_out_today"
data-chart="solidgauge"
data-nodename="tanktransfer.system1_flowtotal_out_today"
data-units="BBL"
data-min="0"
data-max="10000"
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['tanktransfer.system1_flowtotal_out_today'].channelId %>" class="data-table" title="Download Channel History">
<i class="fa fa-download"></i>
</a>
</div>
<span data-timeupdate="system1_flowtotal_out_today">
<%= channels["tanktransfer.system1_flowtotal_out_today"].timestamp %>
</span>
</div>
</div>
</div>
<style>
.box-me {
position: relative;
padding: 0.5em;
padding-bottom: 1.5em;
border: 1px solid #eee;
/*margin: 1em 0;*/
}
.box-me .gauge-box {
margin-top: -0.25em;
}
.pad15 {
margin: 15px 15px;
}
.box-me h2 {
text-transform: uppercase;
font-size: 14px;
color: #666;
font-weight: 400;
letter-spacing: 1px;
z-index: 100;
}
.dynamic-chart-form {
background-color: whiteSmoke;
padding: 1em 0.5em;
margin-top: 1em;
}
.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;
}
#systemStatusTimelineContainer h2 {
text-transform: uppercase;
font-size: 14px;
color: #666;
font-weight: 400;
letter-spacing: 1px;
z-index: 100;
}
.slice.node-detail hr {
border-color: #ccc;
}
.slice.node-detail #alarms li {
margin-bottom: 1em;
padding: 0.5em;
}
.slice.node-detail #alarms li:nth-child(even){
background-color: whiteSmoke;
}
.slice.node-detail #alarms li span {
margin-left: 1em;
color: #aaa;
}
</style>
<script>
$('.val_box').each(function(topLevel){
$(this).change(function(){
var id = "#" + $(this).closest(".entry-top-level").attr('id');
if (id !== "#undefined"){
var val = $(id).find('.val_box').val();
var tag = $(id).find('.setstatic').attr('data-staticsend', val);
console.log($(id).find('.setstatic').attr('data-staticsend'));
}
});
});
</script>

View File

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

View File

@@ -0,0 +1,37 @@
<div class='col-xs-12' style="padding-top: 1em; margin-bottom: 1em;">
<div class="input-daterange input-group" id="datepicker">
<input data-chartid="dynamicChart" id="fromDate" data-daysofhistory="7" type="text" class="form-control" name="start">
<span class="input-group-addon">to</span>
<input class="form-control" data-chartid="dynamicChart" id="toDate" type="text" name="end">
<span class='input-group-btn'>
<a href="#!" data-chartid="dynamicChart" data-otherchartids="statusTimeline" class="btn chart-update btn-theme">Run</a>
</span>
</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="tanktransfer.system1_inlet_flowrate,tanktransfer.system1_outlet_flowrate,tanktransfer.system1_inlet1_flowrate,tanktransfer.system1_inlet2_flowrate,tanktransfer.system1_motor_current,tanktransfer.system1_motor_frequency,tanktransfer.system1_dischargepressure,tanktransfer.system1_level">
</div>
<style>
.dynamic-chart-form {
background-color: whiteSmoke;
padding: 1em 0.5em;
margin-top: 1em;
}
#systemStatusTimelineContainer h2 {
text-transform: uppercase;
font-size: 14px;
color: #666;
font-weight: 400;
letter-spacing: 1px;
z-index: 100;
}
</style>

View File

@@ -0,0 +1,286 @@
"""Define Meshify channel class."""
from pycomm.ab_comm.clx import Driver as ClxDriver
from pycomm.cip.cip_base import CommError, DataError
import time
def binarray(intval):
"""Split an integer into its bits."""
bin_string = '{0:08b}'.format(intval)
bin_arr = [i for i in bin_string]
bin_arr.reverse()
return bin_arr
def read_tag(addr, tag, plc_type="CLX"):
"""Read a tag from the PLC."""
direct = plc_type == "Micro800"
c = ClxDriver()
try:
if c.open(addr, direct_connection=direct):
try:
v = c.read_tag(tag)
return v
except DataError as e:
c.close()
print("Data Error during readTag({}, {}): {}".format(addr, tag, e))
except CommError:
# err = c.get_status()
c.close()
print("Could not connect during readTag({}, {})".format(addr, tag))
# print err
except AttributeError as e:
c.close()
print("AttributeError during readTag({}, {}): \n{}".format(addr, tag, e))
c.close()
return False
def read_array(addr, tag, start, end, plc_type="CLX"):
"""Read an array from the PLC."""
direct = plc_type == "Micro800"
c = ClxDriver()
if c.open(addr, direct_connection=direct):
arr_vals = []
try:
for i in range(start, end):
tag_w_index = tag + "[{}]".format(i)
v = c.read_tag(tag_w_index)
# print('{} - {}'.format(tag_w_index, v))
arr_vals.append(round(v[0], 4))
# print(v)
if len(arr_vals) > 0:
return arr_vals
else:
print("No length for {}".format(addr))
return False
except Exception:
print("Error during readArray({}, {}, {}, {})".format(addr, tag, start, end))
err = c.get_status()
c.close()
print err
pass
c.close()
def write_tag(addr, tag, val, plc_type="CLX"):
"""Write a tag value to the PLC."""
direct = plc_type == "Micro800"
c = ClxDriver()
if c.open(addr, direct_connection=direct):
try:
cv = c.read_tag(tag)
print(cv)
wt = c.write_tag(tag, val, cv[1])
return wt
except Exception:
print("Error during writeTag({}, {}, {})".format(addr, tag, val))
err = c.get_status()
c.close()
print err
c.close()
class Channel(object):
"""Holds the configuration for a Meshify channel."""
def __init__(self, mesh_name, data_type, chg_threshold, guarantee_sec, map_=False, write_enabled=False):
"""Initialize the channel."""
self.mesh_name = mesh_name
self.data_type = data_type
self.last_value = None
self.value = None
self.last_send_time = 0
self.chg_threshold = chg_threshold
self.guarantee_sec = guarantee_sec
self.map_ = map_
self.write_enabled = write_enabled
def __str__(self):
"""Create a string for the channel."""
return "{}\nvalue: {}, last_send_time: {}".format(self.mesh_name, self.value, self.last_send_time)
def check(self, new_value, force_send=False):
"""Check to see if the new_value needs to be stored."""
send_needed = False
send_reason = ""
if self.data_type == 'BOOL' or self.data_type == 'STRING':
if self.last_send_time == 0:
send_needed = True
send_reason = "no send time"
elif self.value is None:
send_needed = True
send_reason = "no value"
elif not (self.value == new_value):
if self.map_:
if not self.value == self.map_[new_value]:
send_needed = True
send_reason = "value change"
else:
send_needed = True
send_reason = "value change"
elif (time.time() - self.last_send_time) > self.guarantee_sec:
send_needed = True
send_reason = "guarantee sec"
elif force_send:
send_needed = True
send_reason = "forced"
else:
if self.last_send_time == 0:
send_needed = True
send_reason = "no send time"
elif self.value is None:
send_needed = True
send_reason = "no value"
elif abs(self.value - new_value) > self.chg_threshold:
send_needed = True
send_reason = "change threshold"
elif (time.time() - self.last_send_time) > self.guarantee_sec:
send_needed = True
send_reason = "guarantee sec"
elif force_send:
send_needed = True
send_reason = "forced"
if send_needed:
self.last_value = self.value
if self.map_:
try:
self.value = self.map_[new_value]
except KeyError:
print("Cannot find a map value for {} in {} for {}".format(new_value, self.map_, self.mesh_name))
self.value = new_value
else:
self.value = new_value
self.last_send_time = time.time()
print("Sending {} for {} - {}".format(self.value, self.mesh_name, send_reason))
return send_needed
def read(self):
"""Read the value."""
pass
def identity(sent):
"""Return exactly what was sent to it."""
return sent
class ModbusChannel(Channel):
"""Modbus channel object."""
def __init__(self, mesh_name, register_number, data_type, chg_threshold, guarantee_sec, channel_size=1, map_=False, write_enabled=False, transformFn=identity):
"""Initialize the channel."""
super(ModbusChannel, self).__init__(mesh_name, data_type, chg_threshold, guarantee_sec, map_, write_enabled)
self.mesh_name = mesh_name
self.register_number = register_number
self.channel_size = channel_size
self.data_type = data_type
self.last_value = None
self.value = None
self.last_send_time = 0
self.chg_threshold = chg_threshold
self.guarantee_sec = guarantee_sec
self.map_ = map_
self.write_enabled = write_enabled
self.transformFn = transformFn
def read(self, mbsvalue):
"""Return the transformed read value."""
return self.transformFn(mbsvalue)
class PLCChannel(Channel):
"""PLC Channel Object."""
def __init__(self, ip, mesh_name, plc_tag, data_type, chg_threshold, guarantee_sec, map_=False, write_enabled=False):
"""Initialize the channel."""
super(PLCChannel, self).__init__(mesh_name, data_type, chg_threshold, guarantee_sec, map_, write_enabled)
self.plc_ip = ip
self.mesh_name = mesh_name
self.plc_tag = plc_tag
self.data_type = data_type
self.last_value = None
self.value = None
self.last_send_time = 0
self.chg_threshold = chg_threshold
self.guarantee_sec = guarantee_sec
self.map_ = map_
self.write_enabled = write_enabled
def read(self):
"""Read the value."""
plc_value = None
if self.plc_tag and self.plc_ip:
read_value = read_tag(self.plc_ip, self.plc_tag)
if read_value:
plc_value = read_value[0]
return plc_value
class BoolArrayChannels(Channel):
"""Hold the configuration for a set of boolean array channels."""
def __init__(self, ip, mesh_name, plc_tag, data_type, chg_threshold, guarantee_sec, map_=False, write_enabled=False):
"""Initialize the channel."""
self.plc_ip = ip
self.mesh_name = mesh_name
self.plc_tag = plc_tag
self.data_type = data_type
self.last_value = None
self.value = None
self.last_send_time = 0
self.chg_threshold = chg_threshold
self.guarantee_sec = guarantee_sec
self.map_ = map_
self.write_enabled = write_enabled
def compare_values(self, new_val_dict):
"""Compare new values to old values to see if the values need storing."""
send = False
for idx in new_val_dict:
try:
if new_val_dict[idx] != self.last_value[idx]:
send = True
except KeyError:
print("Key Error in self.compare_values for index {}".format(idx))
send = True
return send
def read(self, force_send=False):
"""Read the value and check to see if needs to be stored."""
send_needed = False
send_reason = ""
if self.plc_tag:
v = read_tag(self.plc_ip, self.plc_tag)
if v:
bool_arr = binarray(v[0])
new_val = {}
for idx in self.map_:
try:
new_val[self.map_[idx]] = bool_arr[idx]
except KeyError:
print("Not able to get value for index {}".format(idx))
if self.last_send_time == 0:
send_needed = True
send_reason = "no send time"
elif self.value is None:
send_needed = True
send_reason = "no value"
elif self.compare_values(new_val):
send_needed = True
send_reason = "value change"
elif (time.time() - self.last_send_time) > self.guarantee_sec:
send_needed = True
send_reason = "guarantee sec"
elif force_send:
send_needed = True
send_reason = "forced"
if send_needed:
self.value = new_val
self.last_value = self.value
self.last_send_time = time.time()
print("Sending {} for {} - {}".format(self.value, self.mesh_name, send_reason))
return send_needed

View File

@@ -0,0 +1,60 @@
id,name,deviceTypeId,fromMe,io,subTitle,helpExplanation,channelType,dataType,defaultValue,regex,regexErrMsg,units,min,max,change,guaranteedReportPeriod,minReportTime
,cfg_costperkwh,460,FALSE,readwrite,Cost per kWh (in $),cfg_CostPerkWh,device,float,0,,,$,0,1,0.01,600,60
,system1_alarmdowntimemin,460,FALSE,readwrite,System 1: Alarm Downtime Minutes,cfg_AlarmDowntimeMin[1],device,float,0,,,min,0,600,0.1,600,60
,system1_inlet1_flowrate,460,FALSE,readonly,System 1 Inlet 1 Flowrate,FTX1[1].Val_PV,device,float,0,,,GPM,0,2000,10,600,60
,system1_inlet1_nettotal,460,FALSE,readonly,System 1 Inlet 1 Net Total,FTX1[1].Val_SV,device,float,0,,,BBL,0,1000000,100,600,60
,system1_inlet1_fwdtotal,460,FALSE,readonly,System 1 Inlet 1 Forward Total,FTX1[1].Val_TV,device,float,0,,,BBL,0,1000000,100,600,60
,system1_inlet1_revtotal,460,FALSE,readonly,System 1 Inlet 1 Reverse Total,FTX1[1].Val_FV,device,float,0,,,BBL,0,1000000,100,600,60
,system1_inlet2_flowrate,460,FALSE,readonly,System 1 Inlet 2 Flowrate,FTX2[1].Val_PV,device,float,0,,,GPM,0,2000,10,600,60
,system1_inlet2_nettotal,460,FALSE,readonly,System 1 Inlet 2 Net Total,FTX2[1].Val_SV,device,float,0,,,BBL,0,1000000,100,600,60
,system1_inlet2_fwdtotal,460,FALSE,readonly,System 1 Inlet 2 Forward Total,FTX2[1].Val_TV,device,float,0,,,BBL,0,1000000,100,600,60
,system1_inlet2_revtotal,460,FALSE,readonly,System 1 Inlet 2 Reverse Total,FTX2[1].Val_FV,device,float,0,,,BBL,0,1000000,100,600,60
,system1_outlet_flowrate,460,FALSE,readonly,System 1 Outlet Flowrate,FTX3[1].Val,device,float,0,,,GPM,0,2000,10,600,60
,system1_outlet_nettotal,460,FALSE,readonly,System 1 Outlet Net Total,FTX3_Promag400[1].Val_Tot1,device,float,0,,,BBL,0,1000000,100,600,60
,system1_outlet_fwdtotal,460,FALSE,readonly,System 1 Outlet Forward Total,FTX3_Promag400[1].Val_Tot2,device,float,0,,,BBL,0,1000000,100,600,60
,system1_outlet_revtotal,460,FALSE,readonly,System 1 Outlet Reverse Total,FTX3_Promag400[1].Val_Tot3,device,float,0,,,BBL,0,1000000,100,600,60
,system1_level,460,FALSE,readonly,System 1 Level,LTX1[1].Val,device,float,0,,,Ft,0,25,0.5,600,60
,system1_motor_frequency,460,FALSE,readonly,System 1 Motor Frequency,MCX1[1].Val_SpeedFdbk,device,float,0,,,Hz,0,100,0.5,600,60
,system1_motor_current,460,FALSE,readonly,System 1 Motor Current,en_MC11:I.OutputCurrent,device,float,0,,,Amps,0,100,0.5,600,60
,system1_dischargepressure,460,FALSE,readonly,System 1 Discharge Pressure,PTX1[1].Val,device,float,0,,,PSI,0,400,1,600,60
,system1_minuntilrestartedok,460,FALSE,readwrite,System 1 Minutes Until Restarted OK,cfg_MinutesUntilRestartedOK[1],device,float,0,,,min,0,600,0.1,600,60
,system1_numinputft,460,FALSE,readwrite,System 1 Number of FT Inlets,cfg_SystemNumInpFT[1],device,float,0,,,,1,2,0.5,600,60
,system1_flowtotal_in_today,460,FALSE,readonly,System 1 Flow Total In Today,"hist_FlowTotalInDaily[1,0]",device,float,0,,,BBL,0,1000000,100,600,60
,system1_flowtotal_in_yesterday,460,FALSE,readonly,System 1 Flow Total In Yesterday,"hist_FlowTotalInDaily[1,1]",device,float,0,,,BBL,0,1000000,0.1,600,60
,system1_flowtotal_out_today,460,FALSE,readonly,System 1 Flow Total Out Today,"hist_FlowTotalOutDaily[1,0]",device,float,0,,,BBL,0,1000000,100,600,60
,system1_flowtotal_out_yesterday,460,FALSE,readonly,System 1 Flow Total Out Yesterday,"hist_FlowTotalOutDaily[1,1]",device,float,0,,,BBL,0,1000000,0.1,600,60
,system1_energycost_today,460,FALSE,readonly,System 1 Energy Cost Today,"hist_EnergyCostDaily[1,0]",device,float,0,,,$,0,500,10,600,60
,system1_energycost_yesterday,460,FALSE,readonly,System 1 Energy Cost Yesterday,"hist_EnergyCostDaily[1,1]",device,float,0,,,$,0,500,0.1,600,60
,system1_energyusage_today,460,FALSE,readonly,System 1 Energy Usage Today,"hist_EnergyUsageDaily[1,0]",device,float,0,,,kWh,0,50000,50,600,60
,system1_energyusage_yesterday,460,FALSE,readonly,System 1 Energy Usage Yesterday,"hist_EnergyUsageDaily[1,1]",device,float,0,,,kWh,0,50000,0.1,600,60
,system1_inlet_flowrate,460,FALSE,readonly,System 1 Combined Inlet Flow,val_FlowRateIn[1],device,float,0,,,BPD,0,10000,10,600,60
,system1_enabled,460,FALSE,readwrite,System 1 Enabled,cfg_TankEnabled[1],device,float,0,,,,0,1,1,3600,60
,system2_alarmdowntimemin,460,FALSE,readwrite,System 2: Alarm Downtime Minutes,cfg_AlarmDowntimeMin[2],device,float,0,,,min,0,600,0.1,600,60
,system2_inlet1_flowrate,460,FALSE,readonly,System 2 Inlet 1 Flowrate,FTX1[2].Val_PV,device,float,0,,,GPM,0,2000,10,600,60
,system2_inlet1_nettotal,460,FALSE,readonly,System 2 Inlet 1 Net Total,FTX1[2].Val_SV,device,float,0,,,BBL,0,1000000,100,600,60
,system2_inlet1_fwdtotal,460,FALSE,readonly,System 2 Inlet 1 Forward Total,FTX1[2].Val_TV,device,float,0,,,BBL,0,1000000,100,600,60
,system2_inlet1_revtotal,460,FALSE,readonly,System 2 Inlet 1 Reverse Total,FTX1[2].Val_FV,device,float,0,,,BBL,0,1000000,100,600,60
,system2_inlet2_flowrate,460,FALSE,readonly,System 2 Inlet 2 Flowrate,FTX2[2].Val_PV,device,float,0,,,GPM,0,2000,10,600,60
,system2_inlet2_nettotal,460,FALSE,readonly,System 2 Inlet 2 Net Total,FTX2[2].Val_SV,device,float,0,,,BBL,0,1000000,100,600,60
,system2_inlet2_fwdtotal,460,FALSE,readonly,System 2 Inlet 2 Forward Total,FTX2[2].Val_TV,device,float,0,,,BBL,0,1000000,100,600,60
,system2_inlet2_revtotal,460,FALSE,readonly,System 2 Inlet 2 Reverse Total,FTX2[2].Val_FV,device,float,0,,,BBL,0,1000000,100,600,60
,system2_outlet_flowrate,460,FALSE,readonly,System 2 Outlet Flowrate,FTX3[2].Val,device,float,0,,,GPM,0,2000,10,600,60
,system2_outlet_nettotal,460,FALSE,readonly,System 2 Outlet Net Total,FTX3_Promag400[2].Val_Tot1,device,float,0,,,BBL,0,1000000,100,600,60
,system2_outlet_fwdtotal,460,FALSE,readonly,System 2 Outlet Forward Total,FTX3_Promag400[2].Val_Tot2,device,float,0,,,BBL,0,1000000,100,600,60
,system2_outlet_revtotal,460,FALSE,readonly,System 2 Outlet Reverse Total,FTX3_Promag400[2].Val_Tot3,device,float,0,,,BBL,0,1000000,100,600,60
,system2_level,460,FALSE,readonly,System 2 Level,LTX1[2].Val,device,float,0,,,Ft,0,25,0.5,600,60
,system2_motor_frequency,460,FALSE,readonly,System 2 Motor Frequency,MCX1[2].Val_SpeedFdbk,device,float,0,,,Hz,0,100,0.5,600,60
,system2_motor_current,460,FALSE,readonly,System 2 Motor Current,en_MC21:I.OutputCurrent,device,float,0,,,Amps,0,100,0.5,600,60
,system2_dischargepressure,460,FALSE,readonly,System 2 Discharge Pressure,PTX1[2].Val,device,float,0,,,PSI,0,400,1,600,60
,system2_minuntilrestartedok,460,FALSE,readwrite,System 2 Minutes Until Restarted OK,cfg_MinutesUntilRestartedOK[2],device,float,0,,,min,0,600,0.1,600,60
,system2_numinputft,460,FALSE,readwrite,System 2 Number of FT Inlets,cfg_SystemNumInpFT[2],device,float,0,,,,1,2,0.5,600,60
,system2_flowtotal_in_today,460,FALSE,readonly,System 2 Flow Total In Today,"hist_FlowTotalInDaily[2,0]",device,float,0,,,BBL,0,1000000,100,600,60
,system2_flowtotal_in_yesterday,460,FALSE,readonly,System 2 Flow Total In Yesterday,"hist_FlowTotalInDaily[2,1]",device,float,0,,,BBL,0,1000000,0.1,600,60
,system2_flowtotal_out_today,460,FALSE,readonly,System 2 Flow Total Out Today,"hist_FlowTotalOutDaily[2,0]",device,float,0,,,BBL,0,1000000,100,600,60
,system2_flowtotal_out_yesterday,460,FALSE,readonly,System 2 Flow Total Out Yesterday,"hist_FlowTotalOutDaily[2,1]",device,float,0,,,BBL,0,1000000,0.1,600,60
,system2_energycost_today,460,FALSE,readonly,System 2 Energy Cost Today,"hist_EnergyCostDaily[2,0]",device,float,0,,,$,0,500,10,600,60
,system2_energycost_yesterday,460,FALSE,readonly,System 2 Energy Cost Yesterday,"hist_EnergyCostDaily[2,1]",device,float,0,,,$,0,500,0.1,600,60
,system2_energyusage_today,460,FALSE,readonly,System 2 Energy Usage Today,"hist_EnergyUsageDaily[2,0]",device,float,0,,,kWh,0,50000,50,600,60
,system2_energyusage_yesterday,460,FALSE,readonly,System 2 Energy Usage Yesterday,"hist_EnergyUsageDaily[2,1]",device,float,0,,,kWh,0,50000,0.1,600,60
,system2_inlet_flowrate,460,FALSE,readonly,System 2 Combined Inlet Flow,val_FlowRateIn[2],device,float,0,,,BPD,0,10000,10,600,60
,system2_enabled,460,FALSE,readwrite,System 2 Enabled,cfg_TankEnabled[2],device,float,0,,,,0,1,1,3600,60
1 id name deviceTypeId fromMe io subTitle helpExplanation channelType dataType defaultValue regex regexErrMsg units min max change guaranteedReportPeriod minReportTime
2 cfg_costperkwh 460 FALSE readwrite Cost per kWh (in $) cfg_CostPerkWh device float 0 $ 0 1 0.01 600 60
3 system1_alarmdowntimemin 460 FALSE readwrite System 1: Alarm Downtime Minutes cfg_AlarmDowntimeMin[1] device float 0 min 0 600 0.1 600 60
4 system1_inlet1_flowrate 460 FALSE readonly System 1 Inlet 1 Flowrate FTX1[1].Val_PV device float 0 GPM 0 2000 10 600 60
5 system1_inlet1_nettotal 460 FALSE readonly System 1 Inlet 1 Net Total FTX1[1].Val_SV device float 0 BBL 0 1000000 100 600 60
6 system1_inlet1_fwdtotal 460 FALSE readonly System 1 Inlet 1 Forward Total FTX1[1].Val_TV device float 0 BBL 0 1000000 100 600 60
7 system1_inlet1_revtotal 460 FALSE readonly System 1 Inlet 1 Reverse Total FTX1[1].Val_FV device float 0 BBL 0 1000000 100 600 60
8 system1_inlet2_flowrate 460 FALSE readonly System 1 Inlet 2 Flowrate FTX2[1].Val_PV device float 0 GPM 0 2000 10 600 60
9 system1_inlet2_nettotal 460 FALSE readonly System 1 Inlet 2 Net Total FTX2[1].Val_SV device float 0 BBL 0 1000000 100 600 60
10 system1_inlet2_fwdtotal 460 FALSE readonly System 1 Inlet 2 Forward Total FTX2[1].Val_TV device float 0 BBL 0 1000000 100 600 60
11 system1_inlet2_revtotal 460 FALSE readonly System 1 Inlet 2 Reverse Total FTX2[1].Val_FV device float 0 BBL 0 1000000 100 600 60
12 system1_outlet_flowrate 460 FALSE readonly System 1 Outlet Flowrate FTX3[1].Val device float 0 GPM 0 2000 10 600 60
13 system1_outlet_nettotal 460 FALSE readonly System 1 Outlet Net Total FTX3_Promag400[1].Val_Tot1 device float 0 BBL 0 1000000 100 600 60
14 system1_outlet_fwdtotal 460 FALSE readonly System 1 Outlet Forward Total FTX3_Promag400[1].Val_Tot2 device float 0 BBL 0 1000000 100 600 60
15 system1_outlet_revtotal 460 FALSE readonly System 1 Outlet Reverse Total FTX3_Promag400[1].Val_Tot3 device float 0 BBL 0 1000000 100 600 60
16 system1_level 460 FALSE readonly System 1 Level LTX1[1].Val device float 0 Ft 0 25 0.5 600 60
17 system1_motor_frequency 460 FALSE readonly System 1 Motor Frequency MCX1[1].Val_SpeedFdbk device float 0 Hz 0 100 0.5 600 60
18 system1_motor_current 460 FALSE readonly System 1 Motor Current en_MC11:I.OutputCurrent device float 0 Amps 0 100 0.5 600 60
19 system1_dischargepressure 460 FALSE readonly System 1 Discharge Pressure PTX1[1].Val device float 0 PSI 0 400 1 600 60
20 system1_minuntilrestartedok 460 FALSE readwrite System 1 Minutes Until Restarted OK cfg_MinutesUntilRestartedOK[1] device float 0 min 0 600 0.1 600 60
21 system1_numinputft 460 FALSE readwrite System 1 Number of FT Inlets cfg_SystemNumInpFT[1] device float 0 1 2 0.5 600 60
22 system1_flowtotal_in_today 460 FALSE readonly System 1 Flow Total In Today hist_FlowTotalInDaily[1,0] device float 0 BBL 0 1000000 100 600 60
23 system1_flowtotal_in_yesterday 460 FALSE readonly System 1 Flow Total In Yesterday hist_FlowTotalInDaily[1,1] device float 0 BBL 0 1000000 0.1 600 60
24 system1_flowtotal_out_today 460 FALSE readonly System 1 Flow Total Out Today hist_FlowTotalOutDaily[1,0] device float 0 BBL 0 1000000 100 600 60
25 system1_flowtotal_out_yesterday 460 FALSE readonly System 1 Flow Total Out Yesterday hist_FlowTotalOutDaily[1,1] device float 0 BBL 0 1000000 0.1 600 60
26 system1_energycost_today 460 FALSE readonly System 1 Energy Cost Today hist_EnergyCostDaily[1,0] device float 0 $ 0 500 10 600 60
27 system1_energycost_yesterday 460 FALSE readonly System 1 Energy Cost Yesterday hist_EnergyCostDaily[1,1] device float 0 $ 0 500 0.1 600 60
28 system1_energyusage_today 460 FALSE readonly System 1 Energy Usage Today hist_EnergyUsageDaily[1,0] device float 0 kWh 0 50000 50 600 60
29 system1_energyusage_yesterday 460 FALSE readonly System 1 Energy Usage Yesterday hist_EnergyUsageDaily[1,1] device float 0 kWh 0 50000 0.1 600 60
30 system1_inlet_flowrate 460 FALSE readonly System 1 Combined Inlet Flow val_FlowRateIn[1] device float 0 BPD 0 10000 10 600 60
31 system1_enabled 460 FALSE readwrite System 1 Enabled cfg_TankEnabled[1] device float 0 0 1 1 3600 60
32 system2_alarmdowntimemin 460 FALSE readwrite System 2: Alarm Downtime Minutes cfg_AlarmDowntimeMin[2] device float 0 min 0 600 0.1 600 60
33 system2_inlet1_flowrate 460 FALSE readonly System 2 Inlet 1 Flowrate FTX1[2].Val_PV device float 0 GPM 0 2000 10 600 60
34 system2_inlet1_nettotal 460 FALSE readonly System 2 Inlet 1 Net Total FTX1[2].Val_SV device float 0 BBL 0 1000000 100 600 60
35 system2_inlet1_fwdtotal 460 FALSE readonly System 2 Inlet 1 Forward Total FTX1[2].Val_TV device float 0 BBL 0 1000000 100 600 60
36 system2_inlet1_revtotal 460 FALSE readonly System 2 Inlet 1 Reverse Total FTX1[2].Val_FV device float 0 BBL 0 1000000 100 600 60
37 system2_inlet2_flowrate 460 FALSE readonly System 2 Inlet 2 Flowrate FTX2[2].Val_PV device float 0 GPM 0 2000 10 600 60
38 system2_inlet2_nettotal 460 FALSE readonly System 2 Inlet 2 Net Total FTX2[2].Val_SV device float 0 BBL 0 1000000 100 600 60
39 system2_inlet2_fwdtotal 460 FALSE readonly System 2 Inlet 2 Forward Total FTX2[2].Val_TV device float 0 BBL 0 1000000 100 600 60
40 system2_inlet2_revtotal 460 FALSE readonly System 2 Inlet 2 Reverse Total FTX2[2].Val_FV device float 0 BBL 0 1000000 100 600 60
41 system2_outlet_flowrate 460 FALSE readonly System 2 Outlet Flowrate FTX3[2].Val device float 0 GPM 0 2000 10 600 60
42 system2_outlet_nettotal 460 FALSE readonly System 2 Outlet Net Total FTX3_Promag400[2].Val_Tot1 device float 0 BBL 0 1000000 100 600 60
43 system2_outlet_fwdtotal 460 FALSE readonly System 2 Outlet Forward Total FTX3_Promag400[2].Val_Tot2 device float 0 BBL 0 1000000 100 600 60
44 system2_outlet_revtotal 460 FALSE readonly System 2 Outlet Reverse Total FTX3_Promag400[2].Val_Tot3 device float 0 BBL 0 1000000 100 600 60
45 system2_level 460 FALSE readonly System 2 Level LTX1[2].Val device float 0 Ft 0 25 0.5 600 60
46 system2_motor_frequency 460 FALSE readonly System 2 Motor Frequency MCX1[2].Val_SpeedFdbk device float 0 Hz 0 100 0.5 600 60
47 system2_motor_current 460 FALSE readonly System 2 Motor Current en_MC21:I.OutputCurrent device float 0 Amps 0 100 0.5 600 60
48 system2_dischargepressure 460 FALSE readonly System 2 Discharge Pressure PTX1[2].Val device float 0 PSI 0 400 1 600 60
49 system2_minuntilrestartedok 460 FALSE readwrite System 2 Minutes Until Restarted OK cfg_MinutesUntilRestartedOK[2] device float 0 min 0 600 0.1 600 60
50 system2_numinputft 460 FALSE readwrite System 2 Number of FT Inlets cfg_SystemNumInpFT[2] device float 0 1 2 0.5 600 60
51 system2_flowtotal_in_today 460 FALSE readonly System 2 Flow Total In Today hist_FlowTotalInDaily[2,0] device float 0 BBL 0 1000000 100 600 60
52 system2_flowtotal_in_yesterday 460 FALSE readonly System 2 Flow Total In Yesterday hist_FlowTotalInDaily[2,1] device float 0 BBL 0 1000000 0.1 600 60
53 system2_flowtotal_out_today 460 FALSE readonly System 2 Flow Total Out Today hist_FlowTotalOutDaily[2,0] device float 0 BBL 0 1000000 100 600 60
54 system2_flowtotal_out_yesterday 460 FALSE readonly System 2 Flow Total Out Yesterday hist_FlowTotalOutDaily[2,1] device float 0 BBL 0 1000000 0.1 600 60
55 system2_energycost_today 460 FALSE readonly System 2 Energy Cost Today hist_EnergyCostDaily[2,0] device float 0 $ 0 500 10 600 60
56 system2_energycost_yesterday 460 FALSE readonly System 2 Energy Cost Yesterday hist_EnergyCostDaily[2,1] device float 0 $ 0 500 0.1 600 60
57 system2_energyusage_today 460 FALSE readonly System 2 Energy Usage Today hist_EnergyUsageDaily[2,0] device float 0 kWh 0 50000 50 600 60
58 system2_energyusage_yesterday 460 FALSE readonly System 2 Energy Usage Yesterday hist_EnergyUsageDaily[2,1] device float 0 kWh 0 50000 0.1 600 60
59 system2_inlet_flowrate 460 FALSE readonly System 2 Combined Inlet Flow val_FlowRateIn[2] device float 0 BPD 0 10000 10 600 60
60 system2_enabled 460 FALSE readwrite System 2 Enabled cfg_TankEnabled[2] device float 0 0 1 1 3600 60

View File

@@ -0,0 +1,12 @@
{
"name": "tanktransfer",
"driverFilename": "tanktransfer.py",
"driverId": "0000",
"additionalDriverFiles": [
"utilities.py",
"persistence.py",
"Channel.py"
],
"version": 1,
"s3BucketName": "tanktransfer"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
"""Data persistance functions."""
# if more advanced persistence is needed, use a sqlite database
import json
def load(filename="persist.json"):
"""Load persisted settings from the specified file."""
try:
with open(filename, 'r') as persist_file:
return json.load(persist_file)
except Exception:
return False
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)
except Exception:
return False

View File

@@ -0,0 +1,141 @@
"""Driver for tanktransfer"""
import threading
import sys
from device_base import deviceBase
from Channel import Channel, read_tag, write_tag, BoolArrayChannels
from Maps import tanktransfer_map as maps
from Maps import reverse_map
import persistence
from random import randint
from utilities import get_public_ip_address
import json
import time
import logging
_ = None
# LOGGING SETUP
from logging.handlers import RotatingFileHandler
log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s')
logFile = './tanktransfer.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('tanktransfer')
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("tanktransfer startup")
# GLOBAL VARIABLES
WATCHDOG_SEND_PERIOD = 3600 # Seconds, the longest amount of time before sending the watchdog status
PLC_IP_ADDRESS = "192.168.1.10"
CHANNELS = []
# PERSISTENCE FILE
persist = persistence.load()
class start(threading.Thread, deviceBase):
"""Start class required by Meshify."""
def __init__(self, name=None, number=None, mac=None, Q=None, mcu=None, companyId=None, offset=None, mqtt=None, Nodes=None):
"""Initialize 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()
self.forceSend = False
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.sendtodb("log", "BOOM! Booted.", 0)
pass
def run(self):
"""Actually run the driver."""
global persist
wait_sec = 60
for i in range(0, wait_sec):
print("tanktransfer driver will start in {} seconds".format(wait_sec - i))
time.sleep(1)
logger.info("BOOM! Starting tanktransfer driver...")
public_ip_address = get_public_ip_address()
self.sendtodbDev(1, 'public_ip_address', public_ip_address, 0, 'tanktransfer')
watchdog = self.tanktransfer_watchdog()
self.sendtodbDev(1, 'watchdog', watchdog, 0, 'tanktransfer')
watchdog_send_timestamp = time.time()
send_loops = 0
watchdog_loops = 0
watchdog_check_after = 5000
while True:
if self.forceSend:
logger.warning("FORCE SEND: TRUE")
for c in CHANNELS:
if c.read(self.forceSend):
self.sendtodbDev(1, c.mesh_name, c.value, 0, 'tanktransfer')
# print("tanktransfer driver still alive...")
if self.forceSend:
if send_loops > 2:
logger.warning("Turning off forceSend")
self.forceSend = False
send_loops = 0
else:
send_loops += 1
watchdog_loops += 1
if (watchdog_loops >= watchdog_check_after):
test_watchdog = self.tanktransfer_watchdog()
if not test_watchdog == watchdog or (time.time() - watchdog_send_timestamp) > WATCHDOG_SEND_PERIOD:
self.sendtodbDev(1, 'watchdog', test_watchdog, 0, 'tanktransfer')
watchdog = test_watchdog
test_public_ip = get_public_ip_address()
if not test_public_ip == public_ip_address:
self.sendtodbDev(1, 'public_ip_address', test_public_ip, 0, 'tanktransfer')
public_ip_address = test_public_ip
watchdog_loops = 0
def tanktransfer_watchdog(self):
"""Write a random integer to the PLC and then 1 seconds later check that it has been decremented by 1."""
randval = randint(0, 32767)
write_tag(str(PLC_IP_ADDRESS), 'watchdog_INT', randval)
time.sleep(1)
watchdog_val = read_tag(str(PLC_IP_ADDRESS), 'watchdog_INT')
try:
return (randval - 1) == watchdog_val[0]
except (KeyError, TypeError):
return False
def tanktransfer_sync(self, name, value):
"""Sync all data from the driver."""
self.forceSend = True
# self.sendtodb("log", "synced", 0)
return True
def tanktransfer_writeplctag(self, name, value):
"""Write a value to the PLC."""
new_val = json.loads(str(value).replace("'", '"'))
tag_n = str(new_val['tag']) # "cmd_Start"
val_n = new_val['val']
w = write_tag(str(PLC_IP_ADDRESS), tag_n, val_n)
print("Result of tanktransfer_writeplctag(self, {}, {}) = {}".format(name, value, w))
if w is None:
w = "Error writing to PLC..."
return w

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