Files
datalogger-POC/dataLogger_SQLite.py
2016-04-19 17:25:16 -05:00

405 lines
16 KiB
Python

#!/usr/bin/env python
'''
Created on Oct 1, 2014
@author: Patrick McDonagh
'''
# import csv
from datetime import datetime
import time
import sqlite3 as lite
from pycomm.ab_comm.clx import Driver as ClxDriver
# import logging
from tag.tag_sqlite import Tag
import traceback
con = lite.connect("/mnt/usb/data.db")
# con = lite.connect("/Users/patrickjmcd/Desktop/data.db")
PLC_IP_ADDRESS = "192.168.1.10"
PLC_TYPE = "VFD"
def readConfig():
global PLC_IP_ADDRESS, PLC_TYPE
with con:
cur = con.cursor()
query = "SELECT * FROM config ORDER BY dateChanged DESC LIMIT 1;"
cur.execute(query)
setup = cur.fetchall()
PLC_IP_ADDRESS = setup[0][2]
PLC_TYPE = setup[0][1]
def readTag(addr, tag):
time.sleep(0.01)
c = ClxDriver()
if c.open(addr):
try:
v = c.read_tag(tag)
# print(v)
return v
except Exception:
print("ERROR RETRIEVING TAG: {}".format(tag))
err = c.get_status()
c.close()
print traceback.print_exc()
pass
c.close()
def readArray(addr, arr, length):
# logging.basicConfig(filename="clx.log", format="%(levelname)-10s %(asctime)s %(message)s", level=logging.DEBUG)
c = ClxDriver()
if c.open(addr):
try:
v = c.read_array(arr, length)
# print(v)
return map(lambda x: x[1], v)
except Exception:
print("ERROR RETRIEVING ARRAY: {}".format(arr))
err = c.get_status()
c.close()
print err
pass
c.close()
def checkDateInDB(da):
y = int(da[0:4])
m = int(da[4:6])
d = int(da[6:8])
dquery = "SELECT id FROM card_history_dates WHERE year = {0} AND month = {1} AND day = {2};".format(y, m, d)
# dquery = "SELECT id FROM WellData.card_history_dates WHERE year = 2016 AND month = 1 AND day = 5;"
with con:
cur = con.cursor()
cur.execute(dquery)
dates = cur.fetchall()
if len(dates) > 0:
print("Date {0} already in db".format(da))
else:
ins_query = "INSERT INTO card_history_dates (year, month, day, first_id) VALUES ({0}, {1}, {2}, (SELECT MAX(id) FROM card_history));".format(y, m, d)
print(ins_query)
with con:
cur = con.cursor()
cur.execute(ins_query)
con.commit()
class Status(Tag):
def sendToDB(self):
query = "INSERT INTO run_status (dtime, status) VALUES ({}, '{}')".format(time.time(), self.value)
print query
with con:
cur = con.cursor()
cur.execute(query)
con.commit()
self.last_send_time = time.time()
if statusChanged:
self.lastStatusCheckVal = self.status
# ---------- MAP FUNCTIONS ---------- #
maps = {
'modeMap':{
0: "Error",
1: "Auto",
2: "POC",
3: "Timer",
4: "Manual",
5: "DH PID"
},
'card_type_map': {
0: "Normal",
1: "Shutdown",
2: "Alarm",
3: "Startup",
4: "Low Fillage"
},
'statusMap': {
0: 'Stopped',
1: 'Running',
2: 'Pumped Off',
3: 'Faulted',
4: 'Starting',
5: 'Recovering',
100: 'Read Error',
1000: 'PLC Error',
9999: 'No Response'
},
'conditionMap': {
20: "Low",
21: "High",
24: "LoLo",
25: "HiHi",
32: "Input Failure",
34: "Configuration Error",
16: "Failure to Stop",
17: "Failure to Start",
18: "Drive Fault"
}
}
# ---------- TAGS ---------- #
stroke_tags = {} # Tags stored for every single stroke
history_tags = {} # Tags stored on value change or age
gaugeoff_tags = {} # Tags stored at gauge off
welltest_tags = {} # Tags stored at well test submit
bit_tags = {}
safety_tags = {}
status = Status('run_status', 'Pump.Run_Status', 'STRING', 0, 3600, 0, mapFn=maps['statusMap'])
def setupTags():
with con:
cur = con.cursor()
query = "SELECT t.name as name, c.tag_class as class, t.tag as tag, t.data_type as data_type, t.change_threshold as change_threshold, t.guarantee_sec as guarantee_sec, t.id as id, t.map_function as map_function FROM tags t JOIN tag_classes c ON c.id = t.class;"
cur.execute(query)
tags = cur.fetchall()
# 0: name, 1: class, 2: tag, 3: data_type, 4: change_threshold, 5: guarantee_sec, 6: db id, 7: map_function
for x in tags:
print(x)
if str(x[1]) == 'stroke':
if x[7]:
stroke_tags[x[0]] = Tag(str(x[0]), str(x[2]), str(x[3]), x[4], x[5], x[6], mapFn=maps[str(x[7])])
else:
stroke_tags[x[0]] = Tag(str(x[0]), str(x[2]), str(x[3]), x[4], x[5], x[6])
elif str(x[1]) == 'history':
if x[7]:
history_tags[x[0]] = Tag(str(x[0]), str(x[2]), str(x[3]), x[4], x[5], x[6], mapFn=maps[str(x[7])])
else:
history_tags[x[0]] = Tag(str(x[0]), str(x[2]), str(x[3]), x[4], x[5], x[6])
elif str(x[1]) == 'gaugeoff':
if x[7]:
gaugeoff_tags[x[0]] = Tag(str(x[0]), str(x[2]), str(x[3]), x[4], x[5], x[6], mapFn=maps[str(x[7])])
else:
gaugeoff_tags[x[0]] = Tag(str(x[0]), str(x[2]), str(x[3]), x[4], x[5], x[6])
elif str(x[1]) == 'welltest':
if x[7]:
welltest_tags[x[0]] = Tag(str(x[0]), str(x[2]), str(x[3]), x[4], x[5], x[6], mapFn=maps[str(x[7])])
else:
welltest_tags[x[0]] = Tag(str(x[0]), str(x[2]), str(x[3]), x[4], x[5], x[6])
with con:
cur = con.cursor()
query = "SELECT c.alarm_class as class, a.name as name, a.tag as tag, a.condition as condition, t.id as id FROM alarms a JOIN alarm_classes c ON a.class = c.id;"
cur.execute(query)
alarms = cur.fetchall()
for x in alarms:
# 0: class, 1: name, 2: tag, 3: condition
if str(x[0]) == 'analog':
safety_tags[x[1]] = AnalogAlarm(str(x[1]), str(x[2]), int(x[4]), device_type="CLX", ip_address=PLC_IP_ADDRESS)
elif str(x[0]) == 'bit':
bit_tags[x[1]] = bitAlarm(str(x[1]), str(x[2]), str(x[3]), int(x[4]), device_type="CLX", ip_address=PLC_IP_ADDRESS)
print('===== STROKE TAGS =====')
for t in stroke_tags:
print(t)
print('===== HISTORY TAGS =====')
for t in history_tags:
print(t)
print('===== WELLTEST TAGS =====')
for t in welltest_tags:
print(t)
print('===== GAUGEOFF TAGS =====')
for t in gaugeoff_tags:
print(t)
print('===== BIT SAFETIES =====')
for t in bit_tags:
print(t)
print('===== ANALOG SAFETIES =====')
for t in safety_tags:
print(t)
setupTags()
def readPoints():
global PLC_IP_ADDRESS
num_points = readTag(PLC_IP_ADDRESS, "Card_Past[1].Num_Points")[0]
surf_pos = readArray(PLC_IP_ADDRESS, "Card_Past[1].Surface_Position", num_points + 1)[1:]
surf_pos.append(surf_pos[0])
surf_lod = readArray(PLC_IP_ADDRESS, "Card_Past[1].Surface_Load", num_points + 1)[1:]
surf_lod.append(surf_lod[0])
down_pos = readArray(PLC_IP_ADDRESS, "Card_Past[1].Downhole_Position", num_points + 1)[1:]
down_pos.append(down_pos[0])
down_lod = readArray(PLC_IP_ADDRESS, "Card_Past[1].Downhole_Load", num_points + 1)[1:]
down_lod.append(down_lod[0])
return([surf_pos, surf_lod, down_pos, down_lod])
def evalTapers():
ts = time.time()
numTapers = int(readTag(PLC_IP_ADDRESS, 'Card_Current.Params.Num_Tapers')[0])
for t in range(1, numTapers + 1):
taper_length = readTag(PLC_IP_ADDRESS, 'Taper.Taper[{}].Setup.Length'.format(t))[0]
taper_diameter = readTag(PLC_IP_ADDRESS, 'Taper.Taper[{}].Setup.Diameter'.format(t))[0]
taper_material = readTag(PLC_IP_ADDRESS, 'Taper.Taper[{}].Setup.Material'.format(t))[0]
if (taper_material == 1):
taper_material = "Steel"
elif (taper_material == 2):
taper_material = "Fiberglass"
tStr = "{{'taper':{}, 'length': {}, 'diameter': {}, 'material':'{}'}}".format(t, taper_length, taper_diameter, taper_material)
tQuery = 'INSERT INTO well_config (tstamp, type, val) VALUES ({}, "taper", "{}")'.format(ts, tStr)
print tQuery
with con:
cur = con.cursor()
cur.execute(tQuery)
con.commit()
pump_diameter = readTag(PLC_IP_ADDRESS, 'UnitConfig.Pump_Diameter')[0]
cfgQuery = "INSERT INTO well_config (tstamp, type, val) VALUES ({}, 'pump_diameter', '{}')".format(ts, pump_diameter)
with con:
cur = con.cursor()
cur.execute(cfgQuery)
con.commit()
print "TAPER DATA READ!"
return True
def main():
readConfig()
read_tapers = False
already_gauged_off = False
already_entered_well_test = False
last_date = ""
last_stroke = 0
while True:
try:
status.read("test")
#############
# CARD DATA #
#############
EOS = readTag(PLC_IP_ADDRESS, "End_Of_Stroke")[0]
stroke_tags['card_id'].read('test')
if (EOS and not (last_stroke == stroke_tags['card_id'].value)):
sData = {}
last_stroke = stroke_tags['card_id'].value
stroke_time = time.time()
dt = datetime.fromtimestamp(stroke_time)
sData['localtime'] = dt
sData['stroke_time'] = dt
sData['utctime'] = datetime.utcfromtimestamp(stroke_time)
for t in stroke_tags:
stroke_tags[t].read(True)
[sData['Surface_Position'], sData['Surface_Load'], sData['Downhole_Position'], sData['Downhole_Load']] = readPoints()
# st = datetime.strftime(dt, "%Y%m%d_%H%M%S")
date = datetime.strftime(dt, "%Y%m%d")
if not date == last_date:
checkDateInDB(date)
last_date = date
sData["card_type"] = stroke_tags['card_type'].value
sData["card_id"] = stroke_tags['card_id'].value
sData['sp_string'] = ', '.join(map(str, sData['Surface_Position']))
sData['sl_string'] = ', '.join(map(str, sData['Surface_Load']))
sData['dp_string'] = ', '.join(map(str, sData['Downhole_Position']))
sData['dl_string'] = ', '.join(map(str, sData['Downhole_Load']))
insert_query = "INSERT INTO card_history (Card_ID, Card_Type, Stroke_Time, Surface_Position, Surface_Load, Downhole_Position, Downhole_Load) VALUES (:card_id, :card_type, :stroke_time, :sp_string, :sl_string, :dp_string, :dl_string)"
with con:
cur = con.cursor()
cur.execute(insert_query, sData)
con.commit()
print "CARD NUMBER " + str(sData["card_id"]) + " READ!"
###################
# HISTORICAL DATA #
###################
for hist in history_tags:
h = history_tags[hist]
h.read("test")
##############
# TAPER DATA #
##############
update_taper = readTag(PLC_IP_ADDRESS, "Write_Tapers")[0] > 0
if (update_taper == 0):
if read_tapers:
read_tapers = False
print "Update Tapers = False"
if (update_taper and (not read_tapers)):
print "reading taper file"
read_tapers = evalTapers()
##################
# GAUGE OFF DATA #
##################
gauge_off = readTag(PLC_IP_ADDRESS, "Gauge_Off_Command")[0]
if (gauge_off == 0):
if already_gauged_off:
already_gauged_off = False
print "Already gauged off... Setting gauge_off to False"
if (gauge_off and (not already_gauged_off)):
print "Gauging off..."
for goff in gaugeoff_tags:
g = gaugeoff_tags[goff]
g.read(True)
gauge_date = datetime(year=gaugeoff_tags['year'].value, month=gaugeoff_tags['month'].value, day=gaugeoff_tags['day'].value, hour=gaugeoff_tags['hour'].value, minute=gaugeoff_tags['min'].value, second=gaugeoff_tags['sec'].value)
with con:
cur = con.cursor()
con.execute("""INSERT INTO Hist_Day (gauge_date, percent_run, kWh, electricity_cost, peak_load, min_load, average_SPM, production_calculated, full_card_production, polished_rod_HP, lifting_cost, fluid_above_pump, pump_intake_pressure, kWh_regen, inflow_rate) VALUES ('%s', '%f', '%f', '%f', '%f', '%f', '%f', '%f', '%f', '%f', '%f', '%f', '%f', '%f', '%f');""" % (gauge_date, gaugeoff_tags['percent_run'].value, gaugeoff_tags['kwh'].value, gaugeoff_tags['electricity_cost'].value, gaugeoff_tags['max_load'].value, gaugeoff_tags['min_load'].value, gaugeoff_tags['average_spm'].value, gaugeoff_tags['production_calculated'].value, gaugeoff_tags['full_card_production'].value, gaugeoff_tags['polished_rod_hp'].value, gaugeoff_tags['lifting_cost'].value, gaugeoff_tags['fluid_level'].value, gaugeoff_tags['pump_intake_pressure'].value, gaugeoff_tags['kwh_regen'].value, gaugeoff_tags['inflow_rate'].value))
con.commit()
already_gauged_off = True
print "Gauged off!"
##################
# WELL TEST DATA #
##################
well_test_entered = readTag(PLC_IP_ADDRESS, "Well_Test.Test_Submit")[0] > 0
if (well_test_entered == 0):
if already_entered_well_test:
already_entered_well_test = False
print "Already entered well Test... Setting well_test_entered to False"
if (well_test_entered and (not already_entered_well_test)):
for wtest in welltest_tags:
w = welltest_tags[wtest]
w.read(True)
print "Well Test Entered"
print('{}/{}/{} {}:{}:{}'.format(welltest_tags['year'].value, welltest_tags['month'].value, welltest_tags['day'].value, welltest_tags['hour'].value, welltest_tags['min'].value, welltest_tags['sec'].value))
test_date = datetime(year=welltest_tags['year'].value, month=welltest_tags['month'].value, day=welltest_tags['day'].value, hour=welltest_tags['hour'].value, minute=welltest_tags['min'].value, second=welltest_tags['sec'].value)
with con:
cur = con.cursor()
test_query = "INSERT INTO Well_Test (test_date, test_volume_oil, test_volume_water, test_volume_gas, k_factor, projected_volume_oil, projected_volume_water, api_gravity_oil, sg_water, test_hours) VALUES ('{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}');".format(test_date, welltest_tags['v_oil'].value, welltest_tags['v_water'].value, welltest_tags['v_gas'].value, welltest_tags['k_factor'].value, welltest_tags['p_v_oil'].value, welltest_tags['p_v_water'].value, welltest_tags['api_oil'].value, welltest_tags['sg_water'].value, welltest_tags['test_duration'].value)
# print test_query
con.execute(test_query)
con.commit()
already_entered_well_test = True
print "Well Test Stored!"
###################
# ALARMS & EVENTS #
###################
for t in safety_tags:
safety_tags[t].checkStatus(stroke_tags['card_id'].value)
for b in bit_tags:
bit_tags[b].checkStatus(stroke_tags['card_id'].value)
time.sleep(.20)
except Exception, e:
print("Error during loop: {}".format(e))
traceback.print_exc()
if __name__ == '__main__':
main()