restructured files
This commit is contained in:
BIN
Pub_Sub.zip
Normal file
BIN
Pub_Sub.zip
Normal file
Binary file not shown.
BIN
Pub_Sub/.DS_Store
vendored
BIN
Pub_Sub/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
BIN
Pub_Sub/abbflow/.DS_Store
vendored
BIN
Pub_Sub/abbflow/.DS_Store
vendored
Binary file not shown.
388
Pub_Sub/abbflow_rtu/thingsboard/abbflow_rtu_tb_v3.cfg
Normal file
388
Pub_Sub/abbflow_rtu/thingsboard/abbflow_rtu_tb_v3.cfg
Normal file
File diff suppressed because one or more lines are too long
@@ -200,28 +200,27 @@ def sendData(message):
|
||||
logger.error(e)
|
||||
payload = {"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values": {}}
|
||||
resetPayload = {"ts": "", "values": {}}
|
||||
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
if abs(payload["ts"]/1000 - measure["timestamp"]) > 3600:
|
||||
reboot(reason="Poll timestamp and actual timestamp out of sync. Actual: {} Poll: {}".format(payload["ts"]/1000,measure["timestamp"]))
|
||||
|
||||
if measure["name"] in ["accumulated_volume"]:
|
||||
payload["values"]["today_volume"], dayReset = totalizeDay(measure["value"])
|
||||
payload["values"]["month_volume"], monthReset = totalizeMonth(measure["value"])
|
||||
if measure["name"] in ["today_volume", "yesterday_volume"]:
|
||||
pass
|
||||
else:
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
if measure["health"] == 1:
|
||||
if measure["name"] in ["accumulated_volume"]:
|
||||
payload["values"]["today_volume"], dayReset = totalizeDay(measure["value"])
|
||||
payload["values"]["month_volume"], monthReset = totalizeMonth(measure["value"])
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
elif measure["name"] in ["today_volume", "yesterday_volume"]:
|
||||
pass
|
||||
else:
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
if payload["values"]["today_volume"] < 0:
|
||||
del payload["values"]["today_volume"]
|
||||
if payload["values"]["month_volume"] < 0:
|
||||
del payload["values"]["month_volume"]
|
||||
|
||||
|
||||
for chunk in chunk_payload(payload=payload):
|
||||
publish(__topic__, json.dumps(chunk), __qos__)
|
||||
time.sleep(2)
|
||||
|
||||
publish("v1/devices/me/attributes", json.dumps({"latestReportTime": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__)
|
||||
|
||||
if dayReset:
|
||||
@@ -234,4 +233,4 @@ def sendData(message):
|
||||
if resetPayload["values"]:
|
||||
resetPayload["ts"] = 1 + (round(dt.timestamp(dt.now())/600)*600)*1000
|
||||
publish(__topic__, json.dumps(resetPayload), __qos__)
|
||||
|
||||
|
||||
387
Pub_Sub/abbflow_tcp/thingsboard/abbflow_tcp_tb_v3.cfg
Normal file
387
Pub_Sub/abbflow_tcp/thingsboard/abbflow_tcp_tb_v3.cfg
Normal file
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
# Enter your python code.
|
||||
import json, os
|
||||
import json, os, time
|
||||
from datetime import datetime as dt
|
||||
from datetime import timedelta as td
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from quickfaas.global_dict import get as get_params
|
||||
@@ -16,12 +17,12 @@ def reboot(reason="Rebooting for config file update"):
|
||||
def checkFileExist(filename):
|
||||
path = "/var/user/files"
|
||||
if not os.path.exists(path):
|
||||
logger.info("no folder making files folder in var/user")
|
||||
logger.debug("no folder making files folder in var/user")
|
||||
os.makedirs(path)
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
if not os.path.exists(path + "/" + filename):
|
||||
logger.info("no creds file making creds file")
|
||||
logger.debug("no creds file making creds file")
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
|
||||
@@ -38,21 +39,21 @@ def convertJSONtoDS(j):
|
||||
return d
|
||||
|
||||
def checkCredentialConfig():
|
||||
logger.info("CHECKING CONFIG")
|
||||
logger.debug("CHECKING CONFIG")
|
||||
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
|
||||
credspath = "/var/user/files/creds.json"
|
||||
cfg = dict()
|
||||
with open(cfgpath, "r") as f:
|
||||
cfg = json.load(f)
|
||||
clouds = cfg.get("clouds")
|
||||
logger.info(clouds)
|
||||
logger.debug(clouds)
|
||||
#if not configured then try to configure from stored values
|
||||
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
logger.info("updating config with stored data")
|
||||
logger.debug("updating config with stored data")
|
||||
clouds[0]["args"]["clientId"] = creds["clientId"]
|
||||
clouds[0]["args"]["username"] = creds["userName"]
|
||||
clouds[0]["args"]["passwd"] = creds["password"]
|
||||
@@ -65,7 +66,7 @@ def checkCredentialConfig():
|
||||
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
logger.info("updating stored file with new data")
|
||||
logger.debug("updating stored file with new data")
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
@@ -85,20 +86,20 @@ def checkCredentialConfig():
|
||||
json.dump(creds,cw)
|
||||
|
||||
def checkParameterConfig(cfg):
|
||||
logger.info("Checking Parameters!!!!")
|
||||
logger.debug("Checking Parameters!!!!")
|
||||
paramspath = "/var/user/files/params.json"
|
||||
cfgparams = convertDStoJSON(cfg.get("labels"))
|
||||
#check stored values
|
||||
checkFileExist("params.json")
|
||||
with open(paramspath, "r") as f:
|
||||
logger.info("Opened param storage file")
|
||||
logger.debug("Opened param storage file")
|
||||
params = json.load(f)
|
||||
if params:
|
||||
if cfgparams != params:
|
||||
#go through each param
|
||||
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
|
||||
#if key in cfg but not in params copy to params
|
||||
logger.info("equalizing params between cfg and stored")
|
||||
logger.debug("equalizing params between cfg and stored")
|
||||
for key in cfgparams.keys():
|
||||
try:
|
||||
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
|
||||
@@ -111,7 +112,7 @@ def checkParameterConfig(cfg):
|
||||
json.dump(params, p)
|
||||
else:
|
||||
with open(paramspath, "w") as p:
|
||||
logger.info("initializing param file with params in memory")
|
||||
logger.debug("initializing param file with params in memory")
|
||||
json.dump(convertDStoJSON(get_params()), p)
|
||||
cfg["labels"] = get_params()
|
||||
|
||||
@@ -122,11 +123,11 @@ def get_totalizers():
|
||||
with open("/var/user/files/totalizers.json", "r") as t:
|
||||
totalizers = json.load(t)
|
||||
if not totalizers:
|
||||
logger.info("-----INITIALIZING TOTALIZERS-----")
|
||||
logger.debug("-----INITIALIZING TOTALIZERS-----")
|
||||
totalizers = {
|
||||
"day": 0,
|
||||
"dayDate": "2022-01-01",
|
||||
"week": 0,
|
||||
"month": 0,
|
||||
"monthDate": "2022-01-01",
|
||||
"year": 0,
|
||||
"lifetime": 0,
|
||||
"dayHolding": 0,
|
||||
@@ -136,9 +137,9 @@ def get_totalizers():
|
||||
}
|
||||
except:
|
||||
totalizers = {
|
||||
"day": 0,
|
||||
"dayDate": "2022-01-01",
|
||||
"week": 0,
|
||||
"month": 0,
|
||||
"monthDate": "2022-01-01",
|
||||
"year": 0,
|
||||
"lifetime": 0,
|
||||
"dayHolding": 0,
|
||||
@@ -158,11 +159,12 @@ def saveTotalizers(totalizers):
|
||||
def totalizeDay(lifetime):
|
||||
totalizers = get_totalizers()
|
||||
now = dt.fromtimestamp(round(dt.timestamp(dt.now())/600)*600)
|
||||
now = now - td(seconds=60*60*8) #time shifted back 8 hours
|
||||
reset = False
|
||||
value = lifetime - totalizers["dayHolding"]
|
||||
if (not int(now.strftime("%d")) == int(totalizers["day"]) and now.hour >= 8 and now.minute == 0) or (abs(int(now.strftime("%d")) - int(totalizers["day"])) > 1 ):
|
||||
if not now.date() == dt.strptime(totalizers["dayDate"], "%Y-%m-%d").date():
|
||||
totalizers["dayHolding"] = lifetime
|
||||
totalizers["day"] = int(now.strftime("%d"))
|
||||
totalizers["dayDate"] = str(now.date())
|
||||
saveTotalizers(totalizers)
|
||||
reset = True
|
||||
return (value,reset)
|
||||
@@ -170,15 +172,26 @@ def totalizeDay(lifetime):
|
||||
def totalizeMonth(lifetime):
|
||||
totalizers = get_totalizers()
|
||||
now = dt.fromtimestamp(round(dt.timestamp(dt.now())/600)*600)
|
||||
now = now - td(seconds=60*60*8) #time shifted back 8 hours
|
||||
now = dt.strptime(f"{now.year}-{now.month}", "%Y-%m")
|
||||
reset = False
|
||||
value = lifetime - totalizers["monthHolding"]
|
||||
if (not int(now.strftime("%m")) == int(totalizers["month"]) and now.hour >= 8 and now.minute == 0) or (abs(int(now.strftime("%m")) - int(totalizers["month"])) > 1 ):
|
||||
if not now.date() == dt.strptime(totalizers["monthDate"], "%Y-%m-%d").date():
|
||||
totalizers["monthHolding"] = lifetime
|
||||
totalizers["month"] = now.strftime("%m")
|
||||
totalizers["monthDate"] = str(now.date())
|
||||
saveTotalizers(totalizers)
|
||||
reset = True
|
||||
return (value,reset)
|
||||
|
||||
# Helper function to split the payload into chunks
|
||||
def chunk_payload(payload, chunk_size=20):
|
||||
chunked_values = list(payload["values"].items())
|
||||
for i in range(0, len(chunked_values), chunk_size):
|
||||
yield {
|
||||
"ts": payload["ts"],
|
||||
"values": dict(chunked_values[i:i+chunk_size])
|
||||
}
|
||||
|
||||
def sendData(message):
|
||||
logger.debug(message)
|
||||
try:
|
||||
@@ -187,22 +200,27 @@ def sendData(message):
|
||||
logger.error(e)
|
||||
payload = {"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values": {}}
|
||||
resetPayload = {"ts": "", "values": {}}
|
||||
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
if abs(payload["ts"]/1000 - measure["timestamp"]) > 7200:
|
||||
if abs(payload["ts"]/1000 - measure["timestamp"]) > 3600:
|
||||
reboot(reason="Poll timestamp and actual timestamp out of sync. Actual: {} Poll: {}".format(payload["ts"]/1000,measure["timestamp"]))
|
||||
|
||||
if measure["name"] in ["accumulated_volume"]:
|
||||
payload["values"]["today_volume"], dayReset = totalizeDay(measure["value"])
|
||||
payload["values"]["month_volume"], monthReset = totalizeMonth(measure["value"])
|
||||
if measure["name"] in ["today_volume", "yesterday_volume"]:
|
||||
pass
|
||||
else:
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
if measure["health"] == 1:
|
||||
if measure["name"] in ["accumulated_volume"]:
|
||||
payload["values"]["today_volume"], dayReset = totalizeDay(measure["value"])
|
||||
payload["values"]["month_volume"], monthReset = totalizeMonth(measure["value"])
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
elif measure["name"] in ["today_volume", "yesterday_volume"]:
|
||||
pass
|
||||
else:
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
for chunk in chunk_payload(payload=payload):
|
||||
publish(__topic__, json.dumps(chunk), __qos__)
|
||||
time.sleep(2)
|
||||
|
||||
publish(__topic__, json.dumps(payload), __qos__)
|
||||
publish("v1/devices/me/attributes", json.dumps({"latestReportTime": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__)
|
||||
|
||||
if dayReset:
|
||||
@@ -215,4 +233,4 @@ def sendData(message):
|
||||
if resetPayload["values"]:
|
||||
resetPayload["ts"] = 1 + (round(dt.timestamp(dt.now())/600)*600)*1000
|
||||
publish(__topic__, json.dumps(resetPayload), __qos__)
|
||||
|
||||
|
||||
@@ -1,29 +1,42 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from quickfaas.measure import recall
|
||||
import json, time
|
||||
from datetime import datetime as dt
|
||||
from quickfaas.measure import recall, write
|
||||
from quickfaas.remotebus import publish
|
||||
from common.Logger import logger
|
||||
|
||||
def sync(wizard_api):
|
||||
# Helper function to split the payload into chunks
|
||||
def chunk_payload(payload, chunk_size=20):
|
||||
chunked_values = list(payload["values"].items())
|
||||
for i in range(0, len(chunked_values), chunk_size):
|
||||
yield {
|
||||
"ts": payload["ts"],
|
||||
"values": dict(chunked_values[i:i+chunk_size])
|
||||
}
|
||||
|
||||
def sync():
|
||||
#get new values and send
|
||||
payload = {}
|
||||
payload = {"ts": round(dt.timestamp(dt.now()))*1000, "values": {}}
|
||||
topic = "v1/devices/me/telemetry"
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.info(data)
|
||||
logger.debug(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
topic = "v1/devices/me/telemetry"
|
||||
payload[measure["name"]] = measure["value"]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
wizard_api.mqtt_publish(topic, json.dumps(payload))
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
for chunk in chunk_payload(payload=payload):
|
||||
publish(topic, json.dumps(chunk), 1)
|
||||
time.sleep(2)
|
||||
|
||||
def writeplctag(value, wizard_api):
|
||||
try:
|
||||
#value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
message = {"advvfdipp":{value["measurement"]: value["value"]}}
|
||||
message = {"abbflow":{value["measurement"]: value["value"]}}
|
||||
resp = wizard_api.write_plc_values(message)
|
||||
#logger.debug("RETURN FROM WRITE: {}".format(resp))
|
||||
return True
|
||||
@@ -44,7 +57,7 @@ def receiveCommand(topic, payload, wizard_api):
|
||||
if command == "setPLCTag":
|
||||
result = commands["writeplctag"](p["params"],wizard_api)
|
||||
if result:
|
||||
sync(wizard_api)
|
||||
sync()
|
||||
#commands[command](p["mac"].lower(),p["payload"]["value"], wizard_api)
|
||||
#logger.debug(command)
|
||||
ack(topic.split("/")[-1], wizard_api)
|
||||
BIN
Pub_Sub/advvfdipp/.DS_Store
vendored
BIN
Pub_Sub/advvfdipp/.DS_Store
vendored
Binary file not shown.
BIN
Pub_Sub/advvfdipp/guidon/.DS_Store
vendored
BIN
Pub_Sub/advvfdipp/guidon/.DS_Store
vendored
Binary file not shown.
BIN
Pub_Sub/advvfdipp/guidon/v1/.DS_Store
vendored
BIN
Pub_Sub/advvfdipp/guidon/v1/.DS_Store
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,191 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
import re, uuid
|
||||
|
||||
|
||||
def sendData(message):
|
||||
#logger.debug(message)
|
||||
mac = ':'.join(re.findall('..', '%012x' % uuid.getnode()))
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault"]:
|
||||
logger.debug("Converting DINT/BOOL to STRING")
|
||||
value = convert_int(measure["name"], measure["value"])
|
||||
logger.debug("Converted {} to {}".format(measure["value"], value))
|
||||
publish(__topic__ + mac + ":01:99/" + measure["name"], json.dumps({"value": value}), __qos__)
|
||||
else:
|
||||
publish(__topic__ + mac + ":01:99/" + measure["name"], json.dumps({"value": measure["value"]}), __qos__)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
#publish(__topic__, json.dumps({measure["name"]: measure["value"]}), __qos__)
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from quickfaas.measure import recall
|
||||
from common.Logger import logger
|
||||
|
||||
def sync(mac,value, wizard_api):
|
||||
#get new values and send
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.info(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
topic = "meshify/db/194/_/abbflow/" + mac + "/" + measure["name"]
|
||||
payload = [{"value": measure["value"]}]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
wizard_api.mqtt_publish(topic, json.dumps(payload))
|
||||
def writeplctag(mac, value, wizard_api):
|
||||
try:
|
||||
value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
message = {"advvfdipp":{value["tag"]: value["val"]}}
|
||||
wizard_api.write_plc_values(message)
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
|
||||
def receiveCommand(topic, payload, wizard_api):
|
||||
logger.debug(topic)
|
||||
logger.debug(json.loads(payload))
|
||||
p = json.loads(payload)[0]
|
||||
command = p["payload"]["name"].split(".")[1]
|
||||
commands = {
|
||||
"sync": sync,
|
||||
"writeplctag": writeplctag,
|
||||
}
|
||||
commands[command](p["mac"].lower(),p["payload"]["value"], wizard_api)
|
||||
#logger.debug(command)
|
||||
ack(p["msgId"], p["mac"], p["payload"]["name"].split(".")[1], p["payload"]["value"], wizard_api)
|
||||
|
||||
def ack(msgid, mac, name, value, wizard_api):
|
||||
#logger.debug(mac)
|
||||
mac = "".join(mac.split(":")[:-2])
|
||||
#logger.debug(msgid)
|
||||
#logger.debug(mac)
|
||||
#logger.debug(name)
|
||||
#logger.debug(value)
|
||||
wizard_api.mqtt_publish("meshify/responses/" + str(msgid), json.dumps([{"value": "{} Success Setting: {} To: {}".format(mac,name, value), "msgid": str(msgid)}]))
|
||||
BIN
Pub_Sub/advvfdipp/guidon/v2/.DS_Store
vendored
BIN
Pub_Sub/advvfdipp/guidon/v2/.DS_Store
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,357 +0,0 @@
|
||||
import json, os, uuid
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from paho.mqtt import client
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from quickfaas.global_dict import _set_global_args
|
||||
|
||||
def reboot():
|
||||
#basic = Basic()
|
||||
logger.info("!" * 10 + "REBOOTING DEVICE" + "!"*10)
|
||||
r = os.popen("kill -s SIGHUP `cat /var/run/python/supervisord.pid`").read()
|
||||
logger.info(f"REBOOT : {r}")
|
||||
|
||||
def checkFileExist(filename):
|
||||
path = "/var/user/files"
|
||||
if not os.path.exists(path):
|
||||
logger.info("no folder making files folder in var/user")
|
||||
os.makedirs(path)
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
if not os.path.exists(path + "/" + filename):
|
||||
logger.info("no creds file making creds file")
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
|
||||
def convertDStoJSON(ds):
|
||||
j = dict()
|
||||
for x in ds:
|
||||
j[x["key"]] = x["value"]
|
||||
return j
|
||||
|
||||
def convertJSONtoDS(j):
|
||||
d = []
|
||||
for key in j.keys():
|
||||
d.append({"key": key, "value": j[key]})
|
||||
return d
|
||||
|
||||
def checkCredentialConfig():
|
||||
logger.info("CHECKING CONFIG")
|
||||
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
|
||||
credspath = "/var/user/files/creds.json"
|
||||
cfg = dict()
|
||||
with open(cfgpath, "r") as f:
|
||||
cfg = json.load(f)
|
||||
clouds = cfg.get("clouds")
|
||||
logger.info(clouds)
|
||||
#if not configured then try to configure from stored values
|
||||
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
logger.info("updating config with stored data")
|
||||
clouds[0]["args"]["clientId"] = creds["clientId"]
|
||||
clouds[0]["args"]["username"] = creds["userName"]
|
||||
clouds[0]["args"]["passwd"] = creds["password"]
|
||||
cfg["clouds"] = clouds
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
reboot()
|
||||
else:
|
||||
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
logger.info("updating stored file with new data")
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
if creds["clientId"] != clouds[0]["args"]["clientId"]:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
if creds["userName"] != clouds[0]["args"]["username"]:
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
if creds["password"] != clouds[0]["args"]["passwd"]:
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
else:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
with open(credspath, "w") as cw:
|
||||
json.dump(creds,cw)
|
||||
|
||||
def checkParameterConfig(cfg):
|
||||
logger.info("Checking Parameters!!!!")
|
||||
paramspath = "/var/user/files/params.json"
|
||||
cfgparams = convertDStoJSON(cfg.get("labels"))
|
||||
#check stored values
|
||||
checkFileExist("params.json")
|
||||
with open(paramspath, "r") as f:
|
||||
logger.info("Opened param storage file")
|
||||
params = json.load(f)
|
||||
if params:
|
||||
if cfgparams != params:
|
||||
#go through each param
|
||||
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
|
||||
#if key in cfg but not in params copy to params
|
||||
logger.info("equalizing params between cfg and stored")
|
||||
for key in cfgparams.keys():
|
||||
try:
|
||||
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
|
||||
params[key] = cfgparams[key]
|
||||
except:
|
||||
params[key] = cfgparams[key]
|
||||
cfg["labels"] = convertJSONtoDS(params)
|
||||
_set_global_args(convertJSONtoDS(params))
|
||||
with open(paramspath, "w") as p:
|
||||
json.dump(params, p)
|
||||
else:
|
||||
with open(paramspath, "w") as p:
|
||||
logger.info("initializing param file with params in memory")
|
||||
json.dump(convertDStoJSON(get_params()), p)
|
||||
cfg["labels"] = get_params()
|
||||
|
||||
return cfg
|
||||
|
||||
lwtData = {
|
||||
"init":False,
|
||||
"client": client.Client(client_id=str(uuid.uuid4()), clean_session=True, userdata=None, protocol=client.MQTTv311, transport="tcp")
|
||||
}
|
||||
def lwt(mac):
|
||||
try:
|
||||
#if not lwtData["connected"]:
|
||||
if not lwtData["init"]:
|
||||
logger.info("INITIALIZING LWT CLIENT")
|
||||
lwtData["client"].username_pw_set(username="admin", password="columbus")
|
||||
lwtData["client"].will_set("meshify/db/194/_/mainHP/" + mac + ":00:00/connected",json.dumps({"value":False}))
|
||||
lwtData["init"] = True
|
||||
logger.info("Connecting to MQTT Broker for LWT purposes!!!!!!!")
|
||||
lwtData["client"].connect("mq194.imistaway.net",1883, 600)
|
||||
lwtData["client"].publish("meshify/db/194/_/mainHP/" + mac + ":00:00/connected", json.dumps({"value":True}))
|
||||
except Exception as e:
|
||||
logger.error("LWT DID NOT DO THE THING")
|
||||
logger.error(e)
|
||||
|
||||
def sendData(message):
|
||||
#logger.debug(message)
|
||||
mac = __topic__.split("/")[-1] #':'.join(re.findall('..', '%012x' % uuid.getnode()))
|
||||
lwt(mac)
|
||||
checkCredentialConfig()
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault", "external_commands", "remote_comm", "aux_pump_hand","aux_pump_auto","aux_pump_run", "aux_pump_fault"]:
|
||||
logger.debug("Converting DINT/BOOL to STRING")
|
||||
value = convert_int(measure["name"], measure["value"])
|
||||
logger.debug("Converted {} to {}".format(measure["value"], value))
|
||||
publish(__topic__ + ":01:99/" + measure["name"], json.dumps({"value": value}), __qos__)
|
||||
else:
|
||||
publish(__topic__ + ":01:99/" + measure["name"], json.dumps({"value": measure["value"]}), __qos__)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
external_commands = {
|
||||
0: "HP Control",
|
||||
1: "Customer Control"
|
||||
}
|
||||
|
||||
remote_comm = {
|
||||
0: "Good",
|
||||
1: "Comms Failure"
|
||||
}
|
||||
|
||||
aux_pump_hand = {
|
||||
0: "Off",
|
||||
1: "On"
|
||||
}
|
||||
|
||||
aux_pump_auto = {
|
||||
0: "Off",
|
||||
1: "On"
|
||||
}
|
||||
|
||||
aux_pump_run = {
|
||||
0: "Stopped",
|
||||
1: "Running"
|
||||
}
|
||||
|
||||
aux_pump_fault = {
|
||||
0: "Good",
|
||||
1: "Faulted"
|
||||
}
|
||||
|
||||
|
||||
plc_tags = {
|
||||
"external_commands": external_commands.get(value, "Invalid Code"),
|
||||
"remote_comm": remote_comm.get(value, "Invalid Code"),
|
||||
"aux_pump_hand": aux_pump_hand.get(value, "Invalid Code"),
|
||||
"aux_pump_auto": aux_pump_auto.get(value, "Invalid Code"),
|
||||
"aux_pump_run": aux_pump_run.get(value, "Invalid Code"),
|
||||
"aux_pump_fault": aux_pump_fault.get(value, "Invalid Code"),
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from quickfaas.measure import recall
|
||||
from common.Logger import logger
|
||||
|
||||
def sync(mac,value, wizard_api):
|
||||
#get new values and send
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.info(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
topic = "meshify/db/194/_/advvfdipp/" + mac + "/" + measure["name"]
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault", "external_commands", "remote_comm", "aux_pump_hand","aux_pump_auto","aux_pump_run", "aux_pump_fault"]:
|
||||
payload = [{"value": convert_int(measure["name"], measure["value"])}]
|
||||
else:
|
||||
payload = [{"value": measure["value"]}]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
wizard_api.mqtt_publish(topic, json.dumps(payload))
|
||||
def writeplctag(mac, value, wizard_api):
|
||||
try:
|
||||
value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
message = {"advvfdipp":{value["tag"]: value["val"]}}
|
||||
wizard_api.write_plc_values(message)
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
|
||||
def receiveCommand(topic, payload, wizard_api):
|
||||
logger.debug(topic)
|
||||
logger.debug(json.loads(payload))
|
||||
p = json.loads(payload)[0]
|
||||
command = p["payload"]["name"].split(".")[1]
|
||||
commands = {
|
||||
"sync": sync,
|
||||
"writeplctag": writeplctag,
|
||||
}
|
||||
commands[command](p["mac"].lower(),p["payload"]["value"], wizard_api)
|
||||
#logger.debug(command)
|
||||
ack(p["msgId"], p["mac"], p["payload"]["name"].split(".")[1], p["payload"]["value"], wizard_api)
|
||||
|
||||
def ack(msgid, mac, name, value, wizard_api):
|
||||
#logger.debug(mac)
|
||||
mac = "".join(mac.split(":")[:-2])
|
||||
#logger.debug(msgid)
|
||||
#logger.debug(mac)
|
||||
#logger.debug(name)
|
||||
#logger.debug(value)
|
||||
wizard_api.mqtt_publish("meshify/responses/" + str(msgid), json.dumps([{"value": "{} Success Setting: {} To: {}".format(mac,name, value), "msgid": str(msgid)}]))
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
external_commands = {
|
||||
0: "HP Control",
|
||||
1: "Customer Control"
|
||||
}
|
||||
|
||||
remote_comm = {
|
||||
0: "Good",
|
||||
1: "Comms Failure"
|
||||
}
|
||||
|
||||
aux_pump_hand = {
|
||||
0: "Off",
|
||||
1: "On"
|
||||
}
|
||||
|
||||
aux_pump_auto = {
|
||||
0: "Off",
|
||||
1: "On"
|
||||
}
|
||||
|
||||
aux_pump_run = {
|
||||
0: "Stopped",
|
||||
1: "Running"
|
||||
}
|
||||
|
||||
aux_pump_fault = {
|
||||
0: "Good",
|
||||
1: "Faulted"
|
||||
}
|
||||
|
||||
|
||||
plc_tags = {
|
||||
"external_commands": external_commands.get(value, "Invalid Code"),
|
||||
"remote_comm": remote_comm.get(value, "Invalid Code"),
|
||||
"aux_pump_hand": aux_pump_hand.get(value, "Invalid Code"),
|
||||
"aux_pump_auto": aux_pump_auto.get(value, "Invalid Code"),
|
||||
"aux_pump_run": aux_pump_run.get(value, "Invalid Code"),
|
||||
"aux_pump_fault": aux_pump_fault.get(value, "Invalid Code"),
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
@@ -1,191 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
import re, uuid
|
||||
|
||||
|
||||
def sendData(message):
|
||||
#logger.debug(message)
|
||||
mac = ':'.join(re.findall('..', '%012x' % uuid.getnode()))
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault"]:
|
||||
logger.debug("Converting DINT/BOOL to STRING")
|
||||
value = convert_int(measure["name"], measure["value"])
|
||||
logger.debug("Converted {} to {}".format(measure["value"], value))
|
||||
publish(__topic__ + mac + ":01:99/" + measure["name"], json.dumps({"value": value}), __qos__)
|
||||
else:
|
||||
publish(__topic__ + mac + ":01:99/" + measure["name"], json.dumps({"value": measure["value"]}), __qos__)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
#publish(__topic__, json.dumps({measure["name"]: measure["value"]}), __qos__)
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from quickfaas.measure import recall
|
||||
from common.Logger import logger
|
||||
|
||||
def sync(mac,value, wizard_api):
|
||||
#get new values and send
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.info(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
topic = "meshify/db/194/_/abbflow/" + mac + "/" + measure["name"]
|
||||
payload = [{"value": measure["value"]}]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
wizard_api.mqtt_publish(topic, json.dumps(payload))
|
||||
def writeplctag(mac, value, wizard_api):
|
||||
try:
|
||||
value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
message = {"advvfdipp":{value["tag"]: value["val"]}}
|
||||
wizard_api.write_plc_values(message)
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
|
||||
def receiveCommand(topic, payload, wizard_api):
|
||||
logger.debug(topic)
|
||||
logger.debug(json.loads(payload))
|
||||
p = json.loads(payload)[0]
|
||||
command = p["payload"]["name"].split(".")[1]
|
||||
commands = {
|
||||
"sync": sync,
|
||||
"writeplctag": writeplctag,
|
||||
}
|
||||
commands[command](p["mac"].lower(),p["payload"]["value"], wizard_api)
|
||||
#logger.debug(command)
|
||||
ack(p["msgId"], p["mac"], p["payload"]["name"].split(".")[1], p["payload"]["value"], wizard_api)
|
||||
|
||||
def ack(msgid, mac, name, value, wizard_api):
|
||||
#logger.debug(mac)
|
||||
mac = "".join(mac.split(":")[:-2])
|
||||
#logger.debug(msgid)
|
||||
#logger.debug(mac)
|
||||
#logger.debug(name)
|
||||
#logger.debug(value)
|
||||
wizard_api.mqtt_publish("meshify/responses/" + str(msgid), json.dumps([{"value": "{} Success Setting: {} To: {}".format(mac,name, value), "msgid": str(msgid)}]))
|
||||
@@ -1,211 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
import re, uuid
|
||||
from paho.mqtt import client
|
||||
|
||||
lwtData = {
|
||||
"init":False,
|
||||
"client": client.Client(client_id=str(uuid.uuid4()), clean_session=True, userdata=None, protocol=client.MQTTv311, transport="tcp")
|
||||
}
|
||||
def lwt(mac):
|
||||
try:
|
||||
#if not lwtData["connected"]:
|
||||
if not lwtData["init"]:
|
||||
logger.info("INITIALIZING LWT CLIENT")
|
||||
lwtData["client"].username_pw_set(username="admin", password="columbus")
|
||||
lwtData["client"].will_set("meshify/db/194/_/mainHP/" + mac + ":00:00/connected",json.dumps({"value":False}))
|
||||
lwtData["init"] = True
|
||||
logger.info("Connecting to MQTT Broker for LWT purposes!!!!!!!")
|
||||
lwtData["client"].connect("mq194.imistaway.net",1883, 600)
|
||||
lwtData["client"].publish("meshify/db/194/_/mainHP/" + mac + ":00:00/connected", json.dumps({"value":True}))
|
||||
except Exception as e:
|
||||
logger.error("LWT DID NOT DO THE THING")
|
||||
logger.error(e)
|
||||
|
||||
def sendData(message):
|
||||
#logger.debug(message)
|
||||
mac = __topic__.split("/")[-1] #':'.join(re.findall('..', '%012x' % uuid.getnode()))
|
||||
lwt(mac)
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault"]:
|
||||
logger.debug("Converting DINT/BOOL to STRING")
|
||||
value = convert_int(measure["name"], measure["value"])
|
||||
logger.debug("Converted {} to {}".format(measure["value"], value))
|
||||
publish(__topic__ + ":01:99/" + measure["name"], json.dumps({"value": value}), __qos__)
|
||||
else:
|
||||
publish(__topic__ + ":01:99/" + measure["name"], json.dumps({"value": measure["value"]}), __qos__)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
#publish(__topic__, json.dumps({measure["name"]: measure["value"]}), __qos__)
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from quickfaas.measure import recall
|
||||
from common.Logger import logger
|
||||
|
||||
def sync(mac,value, wizard_api):
|
||||
#get new values and send
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.info(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
topic = "meshify/db/194/_/advvfdipp/" + mac + "/" + measure["name"]
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault"]:
|
||||
payload = [{"value": convert_int(measure["name"], measure["value"])}]
|
||||
else:
|
||||
payload = [{"value": measure["value"]}]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
wizard_api.mqtt_publish(topic, json.dumps(payload))
|
||||
def writeplctag(mac, value, wizard_api):
|
||||
try:
|
||||
value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
message = {"advvfdipp":{value["tag"]: value["val"]}}
|
||||
wizard_api.write_plc_values(message)
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
|
||||
def receiveCommand(topic, payload, wizard_api):
|
||||
logger.debug(topic)
|
||||
logger.debug(json.loads(payload))
|
||||
p = json.loads(payload)[0]
|
||||
command = p["payload"]["name"].split(".")[1]
|
||||
commands = {
|
||||
"sync": sync,
|
||||
"writeplctag": writeplctag,
|
||||
}
|
||||
commands[command](p["mac"].lower(),p["payload"]["value"], wizard_api)
|
||||
#logger.debug(command)
|
||||
ack(p["msgId"], p["mac"], p["payload"]["name"].split(".")[1], p["payload"]["value"], wizard_api)
|
||||
|
||||
def ack(msgid, mac, name, value, wizard_api):
|
||||
#logger.debug(mac)
|
||||
mac = "".join(mac.split(":")[:-2])
|
||||
#logger.debug(msgid)
|
||||
#logger.debug(mac)
|
||||
#logger.debug(name)
|
||||
#logger.debug(value)
|
||||
wizard_api.mqtt_publish("meshify/responses/" + str(msgid), json.dumps([{"value": "{} Success Setting: {} To: {}".format(mac,name, value), "msgid": str(msgid)}]))
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
@@ -1,324 +0,0 @@
|
||||
import json, uuid, os
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from paho.mqtt import client
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from quickfaas.global_dict import _set_global_args
|
||||
|
||||
def reboot():
|
||||
logger.info("!" * 10 + "REBOOTING DEVICE" + "!"*10)
|
||||
r = os.popen("kill -s SIGHUP `cat /var/run/python/supervisord.pid`").read()
|
||||
logger.info(f"REBOOT : {r}")
|
||||
|
||||
def checkFileExist(filename):
|
||||
path = "/var/user/files"
|
||||
if not os.path.exists(path):
|
||||
logger.info("no folder making files folder in var/user")
|
||||
os.makedirs(path)
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
if not os.path.exists(path + "/" + filename):
|
||||
logger.info("no creds file making creds file")
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
|
||||
def convertDStoJSON(ds):
|
||||
j = dict()
|
||||
for x in ds:
|
||||
j[x["key"]] = x["value"]
|
||||
return j
|
||||
|
||||
def convertJSONtoDS(j):
|
||||
d = []
|
||||
for key in j.keys():
|
||||
d.append({"key": key, "value": j[key]})
|
||||
return d
|
||||
|
||||
def checkCredentialConfig():
|
||||
logger.info("CHECKING CONFIG")
|
||||
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
|
||||
credspath = "/var/user/files/creds.json"
|
||||
cfg = dict()
|
||||
with open(cfgpath, "r") as f:
|
||||
cfg = json.load(f)
|
||||
clouds = cfg.get("clouds")
|
||||
logger.info(clouds)
|
||||
#if not configured then try to configure from stored values
|
||||
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
logger.info("updating config with stored data")
|
||||
clouds[0]["args"]["clientId"] = creds["clientId"]
|
||||
clouds[0]["args"]["username"] = creds["userName"]
|
||||
clouds[0]["args"]["passwd"] = creds["password"]
|
||||
cfg["clouds"] = clouds
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
reboot()
|
||||
else:
|
||||
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
logger.info("updating stored file with new data")
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
if creds["clientId"] != clouds[0]["args"]["clientId"]:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
if creds["userName"] != clouds[0]["args"]["username"]:
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
if creds["password"] != clouds[0]["args"]["passwd"]:
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
else:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
with open(credspath, "w") as cw:
|
||||
json.dump(creds,cw)
|
||||
|
||||
def checkParameterConfig(cfg):
|
||||
logger.info("Checking Parameters!!!!")
|
||||
paramspath = "/var/user/files/params.json"
|
||||
cfgparams = convertDStoJSON(cfg.get("labels"))
|
||||
#check stored values
|
||||
checkFileExist("params.json")
|
||||
with open(paramspath, "r") as f:
|
||||
logger.info("Opened param storage file")
|
||||
params = json.load(f)
|
||||
if params:
|
||||
if cfgparams != params:
|
||||
#go through each param
|
||||
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
|
||||
#if key in cfg but not in params copy to params
|
||||
logger.info("equalizing params between cfg and stored")
|
||||
for key in cfgparams.keys():
|
||||
try:
|
||||
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
|
||||
params[key] = cfgparams[key]
|
||||
except:
|
||||
params[key] = cfgparams[key]
|
||||
cfg["labels"] = convertJSONtoDS(params)
|
||||
_set_global_args(convertJSONtoDS(params))
|
||||
with open(paramspath, "w") as p:
|
||||
json.dump(params, p)
|
||||
else:
|
||||
with open(paramspath, "w") as p:
|
||||
logger.info("initializing param file with params in memory")
|
||||
json.dump(convertDStoJSON(get_params()), p)
|
||||
cfg["labels"] = get_params()
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
|
||||
lwtData = {
|
||||
"init":False,
|
||||
"client": client.Client(client_id=str(uuid.uuid4()), clean_session=True, userdata=None, protocol=client.MQTTv311, transport="tcp")
|
||||
}
|
||||
def lwt(mac):
|
||||
try:
|
||||
#if not lwtData["connected"]:
|
||||
if not lwtData["init"]:
|
||||
print("INITIALIZING LWT CLIENT")
|
||||
lwtData["client"].username_pw_set(username="admin", password="columbus")
|
||||
lwtData["client"].will_set("meshify/db/194/_/mainHP/" + mac + ":00:00/connected",json.dumps([{"value":False}]))
|
||||
lwtData["client"].reconnect_delay_set(min_delay=10, max_delay=120)
|
||||
lwtData["init"] = True
|
||||
print("Connecting to MQTT Broker for LWT purposes!!!!!!!")
|
||||
lwtData["client"].connect("mq194.imistaway.net",1883, 600)
|
||||
lwtData["client"].reconnect()
|
||||
lwtData["client"].publish("meshify/db/194/_/mainHP/" + mac + ":00:00/connected", json.dumps([{"value":True}]))
|
||||
except Exception as e:
|
||||
print("LWT DID NOT DO THE THING")
|
||||
print(e)
|
||||
|
||||
def sendData(message):
|
||||
#logger.debug(message)
|
||||
mac = __topic__.split("/")[-1]
|
||||
lwt(mac)
|
||||
checkCredentialConfig()
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault"]:
|
||||
logger.debug("Converting DINT/BOOL to STRING")
|
||||
value = convert_int(measure["name"], measure["value"])
|
||||
logger.debug("Converted {} to {}".format(measure["value"], value))
|
||||
publish(__topic__ + ":01:99/" + measure["name"], json.dumps({"value": value}), __qos__)
|
||||
else:
|
||||
publish(__topic__ + ":01:99/" + measure["name"], json.dumps({"value": measure["value"]}), __qos__)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from quickfaas.measure import recall
|
||||
from common.Logger import logger
|
||||
|
||||
def sync(mac,value, wizard_api):
|
||||
#get new values and send
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.info(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
topic = "meshify/db/194/_/advvfdipp/" + mac + "/" + measure["name"]
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault"]:
|
||||
payload = [{"value": convert_int(measure["name"], measure["value"])}]
|
||||
else:
|
||||
payload = [{"value": measure["value"]}]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
wizard_api.mqtt_publish(topic, json.dumps(payload))
|
||||
def writeplctag(mac, value, wizard_api):
|
||||
try:
|
||||
value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
message = {"advvfdipp":{value["tag"]: value["val"]}}
|
||||
wizard_api.write_plc_values(message)
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
|
||||
def receiveCommand(topic, payload, wizard_api):
|
||||
logger.debug(topic)
|
||||
logger.debug(json.loads(payload))
|
||||
p = json.loads(payload)[0]
|
||||
command = p["payload"]["name"].split(".")[1]
|
||||
commands = {
|
||||
"sync": sync,
|
||||
"writeplctag": writeplctag,
|
||||
}
|
||||
commands[command](p["mac"].lower(),p["payload"]["value"], wizard_api)
|
||||
#logger.debug(command)
|
||||
ack(p["msgId"], p["mac"], command, p["payload"]["name"].split(".")[1], p["payload"]["value"], wizard_api)
|
||||
|
||||
def ack(msgid, mac, name, command, value, wizard_api):
|
||||
#logger.debug(mac)
|
||||
macsquish = "".join(mac.split(":")[:-2])
|
||||
maclower = ":".join(mac.split(":")[:-2])
|
||||
maclower = maclower.lower()
|
||||
#logger.debug(msgid)
|
||||
#logger.debug(mac)
|
||||
#logger.debug(name)
|
||||
#logger.debug(value)
|
||||
wizard_api.mqtt_publish("meshify/responses/" + str(msgid), json.dumps([{"value": "{} Success Setting: {} To: {}".format(macsquish,name, value), "msgid": str(msgid)}]))
|
||||
wizard_api.mqtt_publish("meshify/db/194/_/mainMeshify/" + maclower + ":00:00/commands", json.dumps([{"value": {"status": "success", "value": str(value), "channel": command}, "msgid": str(msgid)}]))
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
1221
Pub_Sub/advvfdipp/thingsboard/advvfdipp_tb_v5.cfg
Normal file
1221
Pub_Sub/advvfdipp/thingsboard/advvfdipp_tb_v5.cfg
Normal file
File diff suppressed because one or more lines are too long
@@ -1,194 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
import re, uuid
|
||||
from paho.mqtt import client
|
||||
|
||||
|
||||
def sendData(message):
|
||||
#logger.debug(message)
|
||||
payload = {}
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault", "flowmeter_fault"]:
|
||||
logger.debug("Converting DINT/BOOL to STRING")
|
||||
value = convert_int(measure["name"], measure["value"])
|
||||
logger.debug("Converted {} to {}".format(measure["value"], value))
|
||||
payload[measure["name"]] = value
|
||||
payload[measure["name"] + "_int"] = measure["value"]
|
||||
else:
|
||||
payload[measure["name"]] = measure["value"]
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
publish(__topic__, json.dumps(payload), __qos__)
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"flowmeter_fault": alarm_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
import time
|
||||
from quickfaas.measure import recall
|
||||
from common.Logger import logger
|
||||
|
||||
def sync(wizard_api):
|
||||
#get new values and send
|
||||
payload = {}
|
||||
topic = "v1/devices/me/telemetry"
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.info(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault", "flowmeter_fault"]:
|
||||
payload[measure["name"]] = convert_int(measure["name"], measure["value"])
|
||||
payload[measure["name"]+ "_int"] = measure["value"]
|
||||
else:
|
||||
payload[measure["name"]] = measure["value"]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
wizard_api.mqtt_publish(topic, json.dumps(payload))
|
||||
def writeplctag(value, wizard_api):
|
||||
try:
|
||||
#value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
message = {"advvfdipp":{value["measurement"]: value["value"]}}
|
||||
resp = wizard_api.write_plc_values(message)
|
||||
#logger.debug("RETURN FROM WRITE: {}".format(resp))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
return False
|
||||
|
||||
def receiveCommand(topic, payload, wizard_api):
|
||||
try:
|
||||
logger.debug(topic)
|
||||
logger.debug(json.loads(payload))
|
||||
p = json.loads(payload)
|
||||
command = p["method"]
|
||||
commands = {
|
||||
"sync": sync,
|
||||
"writeplctag": writeplctag,
|
||||
}
|
||||
if command == "setPLCTag":
|
||||
result = commands["writeplctag"](p["params"],wizard_api)
|
||||
elif command == "changeSetpoint":
|
||||
try:
|
||||
params_type = {"measurement": "pidcontrolmode", "value": p["params"]["setpointType"]}
|
||||
if params_type["value"]:
|
||||
commands["writeplctag"](params_type, wizard_api)
|
||||
time.sleep(2)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
modes = {0: "flowsetpoint", 1: "fluidlevelsetpoint", 2: "tubingpressuresetpoint", 3: "manualfrequencysetpoint"}
|
||||
params_value = {"value": p["params"]["setpointValue"]}
|
||||
if params_value["value"]:
|
||||
params_value["measurement"] = modes[getMode()]
|
||||
commands["writeplctag"](params_value, wizard_api)
|
||||
except:
|
||||
pass
|
||||
|
||||
#logger.debug(command)
|
||||
ack(topic.split("/")[-1], wizard_api)
|
||||
time.sleep(5)
|
||||
sync(wizard_api)
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
|
||||
|
||||
def ack(msgid, wizard_api):
|
||||
#logger.debug(msgid)
|
||||
#logger.debug(mac)
|
||||
#logger.debug(name)
|
||||
#logger.debug(value)
|
||||
wizard_api.mqtt_publish("v1/devices/me/rpc/response/" + str(msgid), json.dumps({"msg": {"time": time.time()}, "metadata": "", "msgType": ""}))
|
||||
|
||||
def getMode():
|
||||
try:
|
||||
data = recall()
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
if measure["name"] == "pidcontrolmode":
|
||||
return measure["value"]
|
||||
except:
|
||||
return None
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"flowmeter_fault": alarm_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
@@ -1,194 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
import re, uuid
|
||||
from paho.mqtt import client
|
||||
|
||||
|
||||
def sendData(message):
|
||||
#logger.debug(message)
|
||||
payload = {}
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault", "flowmeter_fault"]:
|
||||
logger.debug("Converting DINT/BOOL to STRING")
|
||||
value = convert_int(measure["name"], measure["value"])
|
||||
logger.debug("Converted {} to {}".format(measure["value"], value))
|
||||
payload[measure["name"]] = value
|
||||
payload[measure["name"] + "_int"] = measure["value"]
|
||||
else:
|
||||
payload[measure["name"]] = measure["value"]
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
publish(__topic__, json.dumps(payload), __qos__)
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"flowmeter_fault": alarm_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
|
||||
|
||||
@@ -1,258 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json
|
||||
import time
|
||||
from quickfaas.measure import recall
|
||||
from common.Logger import logger
|
||||
|
||||
def sync(wizard_api):
|
||||
#get new values and send
|
||||
payload = {}
|
||||
topic = "v1/devices/me/telemetry"
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.info(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault", "flowmeter_fault"]:
|
||||
payload[measure["name"]] = convert_int(measure["name"], measure["value"])
|
||||
payload[measure["name"]+ "_int"] = measure["value"]
|
||||
else:
|
||||
payload[measure["name"]] = measure["value"]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
wizard_api.mqtt_publish(topic, json.dumps(payload))
|
||||
def writeplctag(value, wizard_api):
|
||||
try:
|
||||
#value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
message = {"advvfdipp":{value["measurement"]: value["value"]}}
|
||||
resp = wizard_api.write_plc_values(message)
|
||||
#logger.debug("RETURN FROM WRITE: {}".format(resp))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
return False
|
||||
|
||||
def receiveCommand(topic, payload, wizard_api):
|
||||
try:
|
||||
logger.debug(topic)
|
||||
logger.debug(json.loads(payload))
|
||||
p = json.loads(payload)
|
||||
command = p["method"]
|
||||
commands = {
|
||||
"sync": sync,
|
||||
"writeplctag": writeplctag,
|
||||
}
|
||||
if command == "setPLCTag":
|
||||
result = commands["writeplctag"](p["params"],wizard_api)
|
||||
elif command == "changeSetpoint":
|
||||
try:
|
||||
params_type = {"measurement": "pidcontrolmode", "value": p["params"]["setpointType"]}
|
||||
if params_type["value"]:
|
||||
commands["writeplctag"](params_type, wizard_api)
|
||||
time.sleep(2)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
modes = {0: "flowsetpoint", 1: "fluidlevelsetpoint", 2: "tubingpressuresetpoint", 3: "manualfrequencysetpoint"}
|
||||
params_value = {"value": p["params"]["setpointValue"]}
|
||||
if params_value["value"]:
|
||||
params_value["measurement"] = modes[getMode()]
|
||||
commands["writeplctag"](params_value, wizard_api)
|
||||
except Exception as e:
|
||||
logger.debug("DID NOT WRITE SETPOINT")
|
||||
logger.debug(e)
|
||||
|
||||
#logger.debug(command)
|
||||
ack(topic.split("/")[-1], wizard_api)
|
||||
time.sleep(5)
|
||||
sync(wizard_api)
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
|
||||
|
||||
def ack(msgid, wizard_api):
|
||||
#logger.debug(msgid)
|
||||
#logger.debug(mac)
|
||||
#logger.debug(name)
|
||||
#logger.debug(value)
|
||||
wizard_api.mqtt_publish("v1/devices/me/rpc/response/" + str(msgid), json.dumps({"msg": {"time": time.time()}, "metadata": "", "msgType": ""}))
|
||||
|
||||
def getMode():
|
||||
try:
|
||||
data = recall()
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
if measure["name"] == "pidcontrolmode":
|
||||
return measure["value"]
|
||||
except:
|
||||
return None
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"flowmeter_fault": alarm_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
@@ -1,11 +0,0 @@
|
||||
AlarmName,ControllerName,MeasuringPointName,AlarmLevel,Condition1,Operand1,CombineMethod,Condition2,Operand2,AlarmContent,AlarmTag
|
||||
alarmflowrate,advvfdipp,alarmflowrate,5,eq,1,none,eq,,Flow Rate Alarm triggered,default
|
||||
alarmintakepressure,advvfdipp,alarmintakepressure,5,eq,1,none,eq,,Intake Pressure Alarm triggered,default
|
||||
alarmintaketemperature,advvfdipp,alarmintaketemperature,5,eq,1,none,eq,,Intake Temperature Alarm triggered,default
|
||||
alarmtubingpressure,advvfdipp,alarmtubingpressure,5,eq,1,none,eq,,Tubing Pressure Alarm triggered,default
|
||||
alarmvfd,advvfdipp,alarmvfd,5,eq,1,none,eq,,VFD Alarm triggered,default
|
||||
alarmlockout,advvfdipp,alarmlockout,5,eq,1,none,eq,,Lockout Alarm triggered,default
|
||||
alarmfluidlevel,advvfdipp,alarmfluidlevel,5,eq,1,none,eq,,Fluid Level Alarm triggered,default
|
||||
controllerfault_io,advvfdipp,controllerfault_io,5,eq,1,none,eq,,Controller IO Alarm triggered,default
|
||||
controllerfault_program,advvfdipp,controllerfault_program,5,eq,1,none,eq,,Controller Fault Alarm triggered,default
|
||||
flowmeter_fault,advvfdipp,flowmeter_fault,5,eq,1,none,eq,,Flow Meter Alarm triggered,default
|
||||
|
@@ -1,312 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json, os
|
||||
from datetime import datetime as dt
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from quickfaas.global_dict import _set_global_args
|
||||
|
||||
def reboot(reason="Rebooting for config file update"):
|
||||
#basic = Basic()
|
||||
logger.info("!" * 10 + "REBOOTING DEVICE" + "!"*10)
|
||||
logger.info(reason)
|
||||
r = os.popen("kill -s SIGHUP `cat /var/run/python/supervisord.pid`").read()
|
||||
logger.info(f"REBOOT : {r}")
|
||||
|
||||
def checkFileExist(filename):
|
||||
path = "/var/user/files"
|
||||
if not os.path.exists(path):
|
||||
logger.info("no folder making files folder in var/user")
|
||||
os.makedirs(path)
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
if not os.path.exists(path + "/" + filename):
|
||||
logger.info("no creds file making creds file")
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
|
||||
def convertDStoJSON(ds):
|
||||
j = dict()
|
||||
for x in ds:
|
||||
j[x["key"]] = x["value"]
|
||||
return j
|
||||
|
||||
def convertJSONtoDS(j):
|
||||
d = []
|
||||
for key in j.keys():
|
||||
d.append({"key": key, "value": j[key]})
|
||||
return d
|
||||
|
||||
def checkCredentialConfig():
|
||||
logger.info("CHECKING CONFIG")
|
||||
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
|
||||
credspath = "/var/user/files/creds.json"
|
||||
cfg = dict()
|
||||
with open(cfgpath, "r") as f:
|
||||
cfg = json.load(f)
|
||||
clouds = cfg.get("clouds")
|
||||
logger.info(clouds)
|
||||
#if not configured then try to configure from stored values
|
||||
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
logger.info("updating config with stored data")
|
||||
clouds[0]["args"]["clientId"] = creds["clientId"]
|
||||
clouds[0]["args"]["username"] = creds["userName"]
|
||||
clouds[0]["args"]["passwd"] = creds["password"]
|
||||
cfg["clouds"] = clouds
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
reboot()
|
||||
else:
|
||||
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
logger.info("updating stored file with new data")
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
if creds["clientId"] != clouds[0]["args"]["clientId"]:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
if creds["userName"] != clouds[0]["args"]["username"]:
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
if creds["password"] != clouds[0]["args"]["passwd"]:
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
else:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
with open(credspath, "w") as cw:
|
||||
json.dump(creds,cw)
|
||||
|
||||
def checkParameterConfig(cfg):
|
||||
logger.info("Checking Parameters!!!!")
|
||||
paramspath = "/var/user/files/params.json"
|
||||
cfgparams = convertDStoJSON(cfg.get("labels"))
|
||||
#check stored values
|
||||
checkFileExist("params.json")
|
||||
with open(paramspath, "r") as f:
|
||||
logger.info("Opened param storage file")
|
||||
params = json.load(f)
|
||||
if params:
|
||||
if cfgparams != params:
|
||||
#go through each param
|
||||
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
|
||||
#if key in cfg but not in params copy to params
|
||||
logger.info("equalizing params between cfg and stored")
|
||||
for key in cfgparams.keys():
|
||||
try:
|
||||
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
|
||||
params[key] = cfgparams[key]
|
||||
except:
|
||||
params[key] = cfgparams[key]
|
||||
cfg["labels"] = convertJSONtoDS(params)
|
||||
_set_global_args(convertJSONtoDS(params))
|
||||
with open(paramspath, "w") as p:
|
||||
json.dump(params, p)
|
||||
else:
|
||||
with open(paramspath, "w") as p:
|
||||
logger.info("initializing param file with params in memory")
|
||||
json.dump(convertDStoJSON(get_params()), p)
|
||||
cfg["labels"] = get_params()
|
||||
|
||||
return cfg
|
||||
|
||||
def sendData(message):
|
||||
#logger.debug(message)
|
||||
try:
|
||||
checkCredentialConfig()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
payload = {"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values": {}}
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
if abs(payload["ts"]/1000 - measure["timestamp"]) > 3600:
|
||||
reboot(reason="Poll timestamp and actual timestamp out of sync. Actual: {} Poll: {}".format(payload["ts"]/1000,measure["timestamp"]))
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault", "flowmeter_fault"]:
|
||||
logger.debug("Converting DINT/BOOL to STRING")
|
||||
value = convert_int(measure["name"], measure["value"])
|
||||
logger.debug("Converted {} to {}".format(measure["value"], value))
|
||||
payload["values"][measure["name"]] = value
|
||||
payload["values"][measure["name"] + "_int"] = measure["value"]
|
||||
else:
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
publish(__topic__, json.dumps(payload), __qos__)
|
||||
publish("v1/devices/me/attributes", json.dumps({"latestReportTime": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__)
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"flowmeter_fault": alarm_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
import json, time
|
||||
from quickfaas.measure import recall, write
|
||||
from quickfaas.remotebus import publish
|
||||
from common.Logger import logger
|
||||
|
||||
def sync():
|
||||
#get new values and send
|
||||
payload = {}
|
||||
topic = "v1/devices/me/telemetry"
|
||||
try:
|
||||
data = recall()#json.loads(recall().decode("utf-8"))
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
logger.debug(data)
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
#publish measure
|
||||
if measure["name"] in ["wellstatus","pidcontrolmode","downholesensorstatus","alarmflowrate","alarmintakepressure","alarmintaketemperature","alarmtubingpressure","alarmvfd","alarmlockout","alarmfluidlevel","runpermissive","startpermissive","last_vfd_fault_code","vfd_fault", "flowmeter_fault"]:
|
||||
payload[measure["name"]] = convert_int(measure["name"], measure["value"])
|
||||
payload[measure["name"]+ "_int"] = measure["value"]
|
||||
else:
|
||||
payload[measure["name"]] = measure["value"]
|
||||
logger.debug("Sending on topic: {}".format(topic))
|
||||
logger.debug("Sending value: {}".format(payload))
|
||||
publish(topic, json.dumps(payload), 1)
|
||||
def writeplctag(value):
|
||||
#value in the form {"measurement": <measurement_name>, "value": <value to write>}
|
||||
try:
|
||||
#value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
#payload format: [{"name": "advvfdipp", "measures": [{"name": "manualfrequencysetpoint", "value": 49}]}]
|
||||
message = [{"name": "advvfdipp", "measures":[{"name":value["measurement"], "value": value["value"]}]}]
|
||||
resp = write(message)
|
||||
logger.debug("RETURN FROM WRITE: {}".format(resp))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
return False
|
||||
|
||||
def receiveCommand(topic, payload):
|
||||
try:
|
||||
logger.debug(topic)
|
||||
logger.debug(json.loads(payload))
|
||||
p = json.loads(payload)
|
||||
command = p["method"]
|
||||
commands = {
|
||||
"sync": sync,
|
||||
"writeplctag": writeplctag,
|
||||
}
|
||||
if command == "setPLCTag":
|
||||
try:
|
||||
result = commands["writeplctag"](p["params"])
|
||||
logger.debug(result)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
elif command == "changeSetpoint":
|
||||
try:
|
||||
logger.debug("attempting controlpoint write")
|
||||
params_type = {"measurement": "pidcontrolmode", "value": p["params"]["setpointType"]}
|
||||
if params_type["value"]:
|
||||
commands["writeplctag"](params_type)
|
||||
time.sleep(2)
|
||||
except Exception as e:
|
||||
logger.error("DID NOT WRITE CONTROL MODE")
|
||||
logger.error(e)
|
||||
try:
|
||||
logger.debug("attempting setpoint write")
|
||||
modes = {0: "flowsetpoint", 1: "fluidlevelsetpoint", 2: "tubingpressuresetpoint", 3: "manualfrequencysetpoint"}
|
||||
params_value = {"value": p["params"]["setpointValue"]}
|
||||
if params_value["value"]:
|
||||
params_value["measurement"] = modes[getMode()]
|
||||
result = commands["writeplctag"](params_value)
|
||||
logger.debug(result)
|
||||
except Exception as e:
|
||||
logger.error("DID NOT WRITE SETPOINT")
|
||||
logger.error(e)
|
||||
#logger.debug(command)
|
||||
ack(topic.split("/")[-1])
|
||||
time.sleep(5)
|
||||
sync()
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
|
||||
|
||||
def ack(msgid):
|
||||
#logger.debug(msgid)
|
||||
#logger.debug(mac)
|
||||
#logger.debug(name)
|
||||
#logger.debug(value)
|
||||
publish("v1/devices/me/rpc/response/" + str(msgid), json.dumps({"msg": {"time": time.time()}, "metadata": "", "msgType": ""}), 1)
|
||||
|
||||
def getMode():
|
||||
try:
|
||||
data = recall()
|
||||
for controller in data:
|
||||
for measure in controller["measures"]:
|
||||
if measure["name"] == "pidcontrolmode":
|
||||
return measure["value"]
|
||||
except:
|
||||
return None
|
||||
|
||||
def convert_int(plc_tag, value):
|
||||
well_status_codes = {
|
||||
0: "Running",
|
||||
1: "Pumped Off",
|
||||
2: "Alarmed",
|
||||
3: "Locked Out",
|
||||
4: "Stopped"
|
||||
}
|
||||
|
||||
pid_control_codes = {
|
||||
0: "Flow",
|
||||
1: "Fluid Level",
|
||||
2: "Tubing Pressure",
|
||||
3: "Manual"
|
||||
}
|
||||
|
||||
downhole_codes = {
|
||||
0: "OK",
|
||||
1: "Connecting",
|
||||
2: "Open Circuit",
|
||||
3: "Shorted",
|
||||
4: "Cannot Decode"
|
||||
}
|
||||
|
||||
permissive_codes = {
|
||||
0: "OK",
|
||||
1: "Flow",
|
||||
2: "Intake Pressure",
|
||||
3: "Intake Temperature",
|
||||
4: "Tubing Pressure",
|
||||
5: "VFD",
|
||||
6: "Fluid Level",
|
||||
7: "Min. Downtime"
|
||||
}
|
||||
|
||||
alarm_codes = {
|
||||
0: "OK",
|
||||
1: "Alarm"
|
||||
}
|
||||
|
||||
alarm_vfd_codes = {
|
||||
0: "OK",
|
||||
1: "Locked Out"
|
||||
}
|
||||
|
||||
vfd_fault_codes = {
|
||||
0: "No Fault",
|
||||
2: "Auxiliary Input",
|
||||
3: "Power Loss",
|
||||
4: "UnderVoltage",
|
||||
5: "OverVoltage",
|
||||
7: "Motor Overload",
|
||||
8: "Heatsink OverTemp",
|
||||
9: "Thermister OverTemp",
|
||||
10: "Dynamic Brake OverTemp",
|
||||
12: "Hardware OverCurrent",
|
||||
13: "Ground Fault",
|
||||
14: "Ground Warning",
|
||||
15: "Load Loss",
|
||||
17: "Input Phase Loss",
|
||||
18: "Motor PTC Trip",
|
||||
19: "Task Overrun",
|
||||
20: "Torque Prove Speed Band",
|
||||
21: "Output Phase Loss",
|
||||
24: "Decel Inhibit",
|
||||
25: "OverSpeed Limit",
|
||||
26: "Brake Slipped",
|
||||
27: "Torque Prove Conflict",
|
||||
28: "TP Encls Confict",
|
||||
29: "Analog In Loss",
|
||||
33: "Auto Restarts Exhausted",
|
||||
35: "IPM OverCurrent",
|
||||
36: "SW OverCurrent",
|
||||
38: "Phase U to Ground",
|
||||
39: "Phase V to Ground",
|
||||
40: "Phase W to Ground",
|
||||
41: "Phase UV Short",
|
||||
42: "Phase VW Short",
|
||||
43: "Phase WU Short",
|
||||
44: "Phase UNeg to Ground",
|
||||
45: "Phase VNeg to Ground",
|
||||
46: "Phase WNeg to Ground",
|
||||
48: "System Defaulted",
|
||||
49: "Drive Powerup",
|
||||
51: "Clear Fault Queue",
|
||||
55: "Control Board Overtemp",
|
||||
59: "Invalid Code",
|
||||
61: "Shear Pin 1",
|
||||
62: "Shear Pin 2",
|
||||
64: "Drive Overload",
|
||||
66: "OW Torque Level",
|
||||
67: "Pump Off",
|
||||
71: "Port 1 Adapter",
|
||||
72: "Port 2 Adapter",
|
||||
73: "Port 3 Adapter",
|
||||
74: "Port 4 Adapter",
|
||||
75: "Port 5 Adapter",
|
||||
76: "Port 6 Adapter",
|
||||
77: "IR Volts Range",
|
||||
78: "FluxAmps Ref Range",
|
||||
79: "Excessive Load",
|
||||
80: "AutoTune Aborted",
|
||||
81: "Port 1 DPI Loss",
|
||||
82: "Port 2 DPI Loss",
|
||||
83: "Port 3 DPI Loss",
|
||||
84: "Port 4 DPI Loss",
|
||||
85: "Port 5 DPI Loss",
|
||||
86: "Port 6 DPI Loss",
|
||||
87: "IXo Voltage Range",
|
||||
91: "Primary Velocity Feedback Loss",
|
||||
93: "Hardware Enable Check",
|
||||
94: "Alternate Velocity Feedback Loss",
|
||||
95: "Auxiliary Velocity Feedback Loss",
|
||||
96: "Position Feedback Loss",
|
||||
97: "Auto Tach Switch",
|
||||
100: "Parameter Checksum",
|
||||
101: "Power Down NVS Blank",
|
||||
102: "NVS Not Blank",
|
||||
103: "Power Down NVS Incompatible",
|
||||
104: "Power Board Checksum",
|
||||
106: "Incompat MCB-PB",
|
||||
107: "Replaced MCB-PB",
|
||||
108: "Analog Calibration Checksum",
|
||||
110: "Invalid Power Board Data",
|
||||
111: "Power Board Invalid ID",
|
||||
112: "Power Board App Min Version",
|
||||
113: "Tracking DataError",
|
||||
115: "Power Down Table Full",
|
||||
116: "Power Down Entry Too Large",
|
||||
117: "Power Down Data Checksum",
|
||||
118: "Power Board Power Down Checksum",
|
||||
124: "App ID Changed",
|
||||
125: "Using Backup App",
|
||||
134: "Start on Power Up",
|
||||
137: "External Precharge Error",
|
||||
138: "Precharge Open",
|
||||
141: "Autotune Enc Angle",
|
||||
142: "Autotune Speed Restricted",
|
||||
143: "Autotune Current Regulator",
|
||||
144: "Autotune Inertia",
|
||||
145: "Autotune Travel",
|
||||
13035: "Net IO Timeout",
|
||||
13037: "Net IO Timeout"
|
||||
|
||||
}
|
||||
|
||||
plc_tags = {
|
||||
"wellstatus": well_status_codes.get(value, "Invalid Code"),
|
||||
"pidcontrolmode": pid_control_codes.get(value, "Invalid Code"),
|
||||
"downholesensorstatus": downhole_codes.get(value, "Invalid Code"),
|
||||
"alarmflowrate": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintakepressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmintaketemperature": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmtubingpressure": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmvfd": alarm_codes.get(value, "Invalid Code"),
|
||||
"alarmlockout": alarm_vfd_codes.get(value, "Invalid Code"),
|
||||
"alarmfluidlevel": alarm_codes.get(value, "Invalid Code"),
|
||||
"runpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"startpermissive": permissive_codes.get(value, "Invalid Code"),
|
||||
"last_vfd_fault_code": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"vfd_fault": vfd_fault_codes.get(value, "Invalid Code"),
|
||||
"flowmeter_fault": alarm_codes.get(value, "Invalid Code")
|
||||
}
|
||||
|
||||
return plc_tags.get(plc_tag, "Invalid Tag")
|
||||
@@ -1,29 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json, time
|
||||
from quickfaas.measure import recall, write
|
||||
from quickfaas.remotebus import publish
|
||||
from common.Logger import logger
|
||||
|
||||
|
||||
def writeplctag(value):
|
||||
#value in the form {"measurement": <measurement_name>, "value": <value to write>}
|
||||
try:
|
||||
#value = json.loads(value.replace("'",'"'))
|
||||
logger.debug(value)
|
||||
#payload format: [{"name": "advvfdipp", "measures": [{"name": "manualfrequencysetpoint", "value": 49}]}]
|
||||
message = [{"name": "advvfdipp", "measures":[{"name":value["measurement"], "value": value["value"]}]}]
|
||||
resp = write(message)
|
||||
logger.debug("RETURN FROM WRITE: {}".format(resp))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return False
|
||||
|
||||
def sendToPLC(message):
|
||||
logger.debug(message)
|
||||
for measure in message["measures"]:
|
||||
logger.debug(measure)
|
||||
#{'ctrlName': 'modbus_converter', 'name': 'SRU_Data[1]', 'health': 1, 'timestamp': 1664894200, 'value': 47}
|
||||
writeplctag({"measurement": measure["name"], "value": measure["value"]})
|
||||
#time.sleep(2)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import json, os
|
||||
import json, os, time
|
||||
from datetime import datetime as dt
|
||||
from common.Logger import logger
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from quickfaas.global_dict import _set_global_args
|
||||
@@ -139,4 +140,22 @@ def checkParameterConfig(cfg):
|
||||
except Exception as e:
|
||||
logger.error(f"Something went wrong in checkParameterConfig: {e}")
|
||||
os.system(f'rm {paramspath}')
|
||||
return cfg
|
||||
return cfg
|
||||
|
||||
# Helper function to split the payload into chunks
|
||||
def chunk_payload(payload, chunk_size=20):
|
||||
chunked_values = list(payload["values"].items())
|
||||
for i in range(0, len(chunked_values), chunk_size):
|
||||
yield {
|
||||
"ts": payload["ts"],
|
||||
"values": dict(chunked_values[i:i+chunk_size])
|
||||
}
|
||||
|
||||
def sendData(message):
|
||||
payload = {"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values": {}}
|
||||
|
||||
for chunk in chunk_payload(payload=payload):
|
||||
publish(__topic__, json.dumps(chunk), __qos__)
|
||||
time.sleep(2)
|
||||
|
||||
publish("v1/devices/me/attributes", json.dumps({"latestReportTime": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__)
|
||||
@@ -1,153 +0,0 @@
|
||||
import json, os
|
||||
from datetime import datetime as dt
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from mobiuspi_lib.gps import GPS
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from quickfaas.global_dict import _set_global_args
|
||||
|
||||
|
||||
def reboot():
|
||||
#basic = Basic()
|
||||
logger.info("!" * 10 + "REBOOTING DEVICE" + "!"*10)
|
||||
r = os.popen("kill -s SIGHUP `cat /var/run/python/supervisord.pid`").read()
|
||||
logger.info(f"REBOOT : {r}")
|
||||
|
||||
def checkFileExist(filename):
|
||||
path = "/var/user/files"
|
||||
if not os.path.exists(path):
|
||||
logger.info("no folder making files folder in var/user")
|
||||
os.makedirs(path)
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
if not os.path.exists(path + "/" + filename):
|
||||
logger.info("no creds file making creds file")
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
|
||||
def convertDStoJSON(ds):
|
||||
j = dict()
|
||||
for x in ds:
|
||||
j[x["key"]] = x["value"]
|
||||
return j
|
||||
|
||||
def convertJSONtoDS(j):
|
||||
d = []
|
||||
for key in j.keys():
|
||||
d.append({"key": key, "value": j[key]})
|
||||
return d
|
||||
|
||||
def checkCredentialConfig():
|
||||
logger.info("CHECKING CONFIG")
|
||||
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
|
||||
credspath = "/var/user/files/creds.json"
|
||||
cfg = dict()
|
||||
with open(cfgpath, "r") as f:
|
||||
cfg = json.load(f)
|
||||
clouds = cfg.get("clouds")
|
||||
logger.info(clouds)
|
||||
#if not configured then try to configure from stored values
|
||||
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
logger.info("updating config with stored data")
|
||||
clouds[0]["args"]["clientId"] = creds["clientId"]
|
||||
clouds[0]["args"]["username"] = creds["userName"]
|
||||
clouds[0]["args"]["passwd"] = creds["password"]
|
||||
cfg["clouds"] = clouds
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
reboot()
|
||||
else:
|
||||
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
logger.info("updating stored file with new data")
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
if creds["clientId"] != clouds[0]["args"]["clientId"]:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
if creds["userName"] != clouds[0]["args"]["username"]:
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
if creds["password"] != clouds[0]["args"]["passwd"]:
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
else:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
with open(credspath, "w") as cw:
|
||||
json.dump(creds,cw)
|
||||
|
||||
def checkParameterConfig(cfg):
|
||||
logger.info("Checking Parameters!!!!")
|
||||
paramspath = "/var/user/files/params.json"
|
||||
cfgparams = convertDStoJSON(cfg.get("labels"))
|
||||
#check stored values
|
||||
checkFileExist("params.json")
|
||||
with open(paramspath, "r") as f:
|
||||
logger.info("Opened param storage file")
|
||||
params = json.load(f)
|
||||
if params:
|
||||
if cfgparams != params:
|
||||
#go through each param
|
||||
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
|
||||
#if key in cfg but not in params copy to params
|
||||
logger.info("equalizing params between cfg and stored")
|
||||
for key in cfgparams.keys():
|
||||
try:
|
||||
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
|
||||
params[key] = cfgparams[key]
|
||||
except:
|
||||
params[key] = cfgparams[key]
|
||||
cfg["labels"] = convertJSONtoDS(params)
|
||||
_set_global_args(convertJSONtoDS(params))
|
||||
with open(paramspath, "w") as p:
|
||||
json.dump(params, p)
|
||||
else:
|
||||
with open(paramspath, "w") as p:
|
||||
logger.info("initializing param file with params in memory")
|
||||
json.dump(convertDStoJSON(get_params()), p)
|
||||
cfg["labels"] = get_params()
|
||||
|
||||
return cfg
|
||||
|
||||
def getGPS():
|
||||
# Create a gps instance
|
||||
gps = GPS()
|
||||
|
||||
# Retrieve GPS information
|
||||
position_status = gps.get_position_status()
|
||||
logger.debug("position_status: ")
|
||||
logger.debug(position_status)
|
||||
latitude = position_status["latitude"].split(" ")
|
||||
longitude = position_status["longitude"].split(" ")
|
||||
lat_dec = int(latitude[0][:-1]) + (float(latitude[1][:-1])/60)
|
||||
lon_dec = int(longitude[0][:-1]) + (float(longitude[1][:-1])/60)
|
||||
if latitude[2] == "S":
|
||||
lat_dec = lat_dec * -1
|
||||
if longitude[2] == "W":
|
||||
lon_dec = lon_dec * -1
|
||||
#lat_dec = round(lat_dec, 7)
|
||||
#lon_dec = round(lon_dec, 7)
|
||||
logger.info("HERE IS THE GPS COORDS")
|
||||
logger.info(f"LATITUDE: {lat_dec}, LONGITUDE: {lon_dec}")
|
||||
speedKnots = position_status["speed"].split(" ")
|
||||
speedMPH = float(speedKnots[0]) * 1.151
|
||||
publish(__topic__, json.dumps({"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values":{"latitude":f"{lat_dec:.8f}", "longitude":f"{lon_dec:.8f}", "speed": f"{speedMPH:.2f}"}}), __qos__)
|
||||
|
||||
def sendData(message,wizard_api):
|
||||
logger.debug(message)
|
||||
#publish(__topic__, json.dumps(message), __qos__)
|
||||
try:
|
||||
checkCredentialConfig()
|
||||
getGPS()
|
||||
except:
|
||||
logger.error("Could not get gps data!")
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import json
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from datetime import datetime as dt
|
||||
import requests
|
||||
from requests.auth import HTTPDigestAuth
|
||||
from requests.exceptions import ConnectionError
|
||||
import base64
|
||||
|
||||
|
||||
def convertJSONtoDS(j):
|
||||
d = []
|
||||
for key in j.keys():
|
||||
d.append({"key": key, "value": j[key]})
|
||||
return d
|
||||
|
||||
def getImage():
|
||||
params = convertJSONtoDS(get_params())
|
||||
camera_ip = params["camera_ip"].replace("_", ":")
|
||||
port = params["port"]
|
||||
with open('./snapshot.jpg', 'wb') as handle:
|
||||
resp = requests.get("http://" + camera_ip + ":" + port + "/cgi-bin/SnapshotJPEG?Resolution=640x360", auth=HTTPDigestAuth("ASS", "amerus@1903"), stream=True)
|
||||
for block in resp.iter_content(1024):
|
||||
if not block:
|
||||
break
|
||||
handle.write(block)
|
||||
|
||||
with open('./snapshot.jpg', 'rb') as image_file:
|
||||
encoded_string = base64.b64encode(image_file.read())
|
||||
publish(__topic__, json.dumps({"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values":{"snapshot": encoded_string.decode("UTF-8"), "camera_error": "OK"}}), __qos__)
|
||||
|
||||
|
||||
def sendSnapshot(message,wizard_api):
|
||||
logger.debug(message)
|
||||
try:
|
||||
getImage()
|
||||
except ConnectionError as ce:
|
||||
logger.error("Could not connect to Camera")
|
||||
logger.error(ce)
|
||||
publish(__topic__, json.dumps({"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values":{"camera_error": f"Could not connect to camera, check camera connection and power\n\n{ce}"}}), __qos__)
|
||||
except Exception as e:
|
||||
logger.error("Could not get image")
|
||||
logger.error(e)
|
||||
publish(__topic__, json.dumps({"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values":{"camera_error": f"Could not connect to camera, check camera connection and power\n\n{e}"}}), __qos__)
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import json, os
|
||||
from datetime import datetime as dt
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from mobiuspi_lib.gps import GPS
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from quickfaas.global_dict import _set_global_args
|
||||
|
||||
|
||||
def reboot():
|
||||
#basic = Basic()
|
||||
logger.info("!" * 10 + "REBOOTING DEVICE" + "!"*10)
|
||||
r = os.popen("kill -s SIGHUP `cat /var/run/python/supervisord.pid`").read()
|
||||
logger.info(f"REBOOT : {r}")
|
||||
|
||||
def checkFileExist(filename):
|
||||
path = "/var/user/files"
|
||||
if not os.path.exists(path):
|
||||
logger.info("no folder making files folder in var/user")
|
||||
os.makedirs(path)
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
if not os.path.exists(path + "/" + filename):
|
||||
logger.info("no creds file making creds file")
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
|
||||
def convertDStoJSON(ds):
|
||||
j = dict()
|
||||
for x in ds:
|
||||
j[x["key"]] = x["value"]
|
||||
return j
|
||||
|
||||
def convertJSONtoDS(j):
|
||||
d = []
|
||||
for key in j.keys():
|
||||
d.append({"key": key, "value": j[key]})
|
||||
return d
|
||||
|
||||
def checkCredentialConfig():
|
||||
logger.info("CHECKING CONFIG")
|
||||
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
|
||||
credspath = "/var/user/files/creds.json"
|
||||
cfg = dict()
|
||||
with open(cfgpath, "r") as f:
|
||||
cfg = json.load(f)
|
||||
clouds = cfg.get("clouds")
|
||||
logger.info(clouds)
|
||||
#if not configured then try to configure from stored values
|
||||
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
logger.info("updating config with stored data")
|
||||
clouds[0]["args"]["clientId"] = creds["clientId"]
|
||||
clouds[0]["args"]["username"] = creds["userName"]
|
||||
clouds[0]["args"]["passwd"] = creds["password"]
|
||||
cfg["clouds"] = clouds
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
reboot()
|
||||
else:
|
||||
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
logger.info("updating stored file with new data")
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
if creds["clientId"] != clouds[0]["args"]["clientId"]:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
if creds["userName"] != clouds[0]["args"]["username"]:
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
if creds["password"] != clouds[0]["args"]["passwd"]:
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
else:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
with open(credspath, "w") as cw:
|
||||
json.dump(creds,cw)
|
||||
|
||||
def checkParameterConfig(cfg):
|
||||
logger.info("Checking Parameters!!!!")
|
||||
paramspath = "/var/user/files/params.json"
|
||||
cfgparams = convertDStoJSON(cfg.get("labels"))
|
||||
#check stored values
|
||||
checkFileExist("params.json")
|
||||
with open(paramspath, "r") as f:
|
||||
logger.info("Opened param storage file")
|
||||
params = json.load(f)
|
||||
if params:
|
||||
if cfgparams != params:
|
||||
#go through each param
|
||||
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
|
||||
#if key in cfg but not in params copy to params
|
||||
logger.info("equalizing params between cfg and stored")
|
||||
for key in cfgparams.keys():
|
||||
try:
|
||||
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
|
||||
params[key] = cfgparams[key]
|
||||
except:
|
||||
params[key] = cfgparams[key]
|
||||
cfg["labels"] = convertJSONtoDS(params)
|
||||
_set_global_args(convertJSONtoDS(params))
|
||||
with open(paramspath, "w") as p:
|
||||
json.dump(params, p)
|
||||
else:
|
||||
with open(paramspath, "w") as p:
|
||||
logger.info("initializing param file with params in memory")
|
||||
json.dump(convertDStoJSON(get_params()), p)
|
||||
cfg["labels"] = get_params()
|
||||
|
||||
return cfg
|
||||
|
||||
def getGPS():
|
||||
# Create a gps instance
|
||||
gps = GPS()
|
||||
|
||||
# Retrieve GPS information
|
||||
position_status = gps.get_position_status()
|
||||
logger.debug("position_status: ")
|
||||
logger.debug(position_status)
|
||||
latitude = position_status["latitude"].split(" ")
|
||||
longitude = position_status["longitude"].split(" ")
|
||||
lat_dec = int(latitude[0][:-1]) + (float(latitude[1][:-1])/60)
|
||||
lon_dec = int(longitude[0][:-1]) + (float(longitude[1][:-1])/60)
|
||||
if latitude[2] == "S":
|
||||
lat_dec = lat_dec * -1
|
||||
if longitude[2] == "W":
|
||||
lon_dec = lon_dec * -1
|
||||
#lat_dec = round(lat_dec, 7)
|
||||
#lon_dec = round(lon_dec, 7)
|
||||
logger.info("HERE IS THE GPS COORDS")
|
||||
logger.info(f"LATITUDE: {lat_dec}, LONGITUDE: {lon_dec}")
|
||||
speedKnots = position_status["speed"].split(" ")
|
||||
speedMPH = float(speedKnots[0]) * 1.151
|
||||
publish(__topic__, json.dumps({"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values":{"latitude":f"{lat_dec:.8f}", "longitude":f"{lon_dec:.8f}", "speed": f"{speedMPH:.2f}"}}), __qos__)
|
||||
|
||||
def sendData(message,wizard_api):
|
||||
logger.debug(message)
|
||||
#publish(__topic__, json.dumps(message), __qos__)
|
||||
try:
|
||||
checkCredentialConfig()
|
||||
getGPS()
|
||||
except:
|
||||
logger.error("Could not get gps data!")
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import json, time, requests, base64
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from datetime import datetime as dt
|
||||
from requests.adapters import HTTPAdapter, Retry
|
||||
from requests.auth import HTTPDigestAuth
|
||||
from requests.exceptions import ConnectionError
|
||||
|
||||
|
||||
|
||||
def convertDStoJSON(ds):
|
||||
j = dict()
|
||||
for x in ds:
|
||||
j[x["key"]] = x["value"]
|
||||
return j
|
||||
|
||||
def getImage():
|
||||
params = convertDStoJSON(get_params())
|
||||
camera_ip = params["camera_ip"].replace("_", ".")
|
||||
port = params["port"]
|
||||
with open('./snapshot.jpg', 'wb') as handle:
|
||||
with requests.Session() as s:
|
||||
retries = Retry(total = 10, backoff_factor=0.1, status_forcelist=[404,408, 500, 502, 503, 504])
|
||||
s.mount('http://', HTTPAdapter(max_retries=retries))
|
||||
try:
|
||||
resp = s.get("http://" + camera_ip + ":" + port + "/cgi-bin/camctrl?af=on", auth=HTTPDigestAuth("ASS", "amerus@1903"),stream=True)
|
||||
except:
|
||||
logger.error("Did not Auto Focus")
|
||||
time.sleep(2)
|
||||
resp = s.get("http://" + camera_ip + ":" + port + "/cgi-bin/SnapshotJPEG?Resolution=640x360", auth=HTTPDigestAuth("ASS", "amerus@1903"), stream=True)
|
||||
for block in resp.iter_content(1024):
|
||||
if not block:
|
||||
break
|
||||
handle.write(block)
|
||||
|
||||
with open('./snapshot.jpg', 'rb') as image_file:
|
||||
encoded_string = base64.b64encode(image_file.read())
|
||||
publish(__topic__, json.dumps({"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values":{"snapshot": encoded_string.decode("UTF-8"), "camera_error": "OK"}}), __qos__)
|
||||
|
||||
|
||||
def sendSnapshot(message,wizard_api):
|
||||
logger.debug(message)
|
||||
try:
|
||||
getImage()
|
||||
except ConnectionError as ce:
|
||||
logger.error("Could not connect to Camera")
|
||||
logger.error(ce)
|
||||
publish(__topic__, json.dumps({"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values":{"camera_error": f"Could not connect to camera (ConnectionError), check camera connection and power\n\n{ce}"}}), __qos__)
|
||||
except Exception as e:
|
||||
logger.error("Could not get image")
|
||||
logger.error(e)
|
||||
publish(__topic__, json.dumps({"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values":{"camera_error": f"Could not connect to camera, check camera connection, power, IP Address\n\n{e}"}}), __qos__)
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"\n",
|
||||
"convert_config.write_code(root + \"/\" + devicetype + \"/\" + platform + \"/v\" + str(startversion) + \"/pub\" + \"/sendData.py\", convert_config.get_config_pub(root + \"/\" + devicetype + \"/\" + platform + \"/v\" + str(startversion) + \"/\" + deviceconfig))\n",
|
||||
"#convert_config.write_code(root + devicetype + \"/\" + platform + \"/v\" + str(startversion) + \"/sub\" + \"/receiveCommand.py\", convert_config.get_config_sub(root + \"/\" + devicetype + \"/\" + platform + \"/v\" + str(startversion) + \"/\" + deviceconfig))\n"
|
||||
]
|
||||
@@ -63,7 +62,6 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"\n",
|
||||
"convert_config.write_config(root + \"/\" + devicetype + \"/\" + platform + \"/v\" + str(startversion + 1) + \"/\" + devicetype + \"_\" + platform_short + \"_v\" + str(startversion + 1) + \".cfg\", \n",
|
||||
" convert_config.get_config(root + \"/\" + devicetype + \"/\" + platform + \"/v\" + str(startversion) + \"/\" + devicetype + \"_\" + platform_short + \"_v\" + str(startversion) + \".cfg\"),\n",
|
||||
" root + \"/\" + devicetype + \"/\" + platform + \"/v\" + str(startversion + 1) + \"/pub\" , \n",
|
||||
|
||||
94
Pub_Sub/config_manager_v2.ipynb
Normal file
94
Pub_Sub/config_manager_v2.ipynb
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"abbflow_tcp_tb_v3.cfg\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import convert_config\n",
|
||||
"import os\n",
|
||||
"import re\n",
|
||||
"\n",
|
||||
"def get_latest_version(root, devicetype, platform):\n",
|
||||
" platform_path = os.path.join(root, devicetype, platform)\n",
|
||||
" if not os.path.exists(platform_path):\n",
|
||||
" return 1\n",
|
||||
" version_pattern = re.compile(r'v(\\d+)')\n",
|
||||
" max_version = 0\n",
|
||||
" for file in os.listdir(platform_path):\n",
|
||||
" match = version_pattern.search(file)\n",
|
||||
" if match:\n",
|
||||
" version = int(match.group(1))\n",
|
||||
" max_version = max(max_version, version)\n",
|
||||
" return max_version + 1\n",
|
||||
"\n",
|
||||
"# Example usage\n",
|
||||
"root = \"/Users/nico/Documents/GitHub/HP_InHand_IG502/Pub_Sub\"\n",
|
||||
"devicetype = \"abbflow_tcp\"\n",
|
||||
"platform = \"thingsboard\" # or \"mistaway\"\n",
|
||||
"platform_short = \"tb\" if platform == \"thingsboard\" else \"ma\" \n",
|
||||
"startversion = get_latest_version(root, devicetype, platform)\n",
|
||||
"\n",
|
||||
"deviceconfig = f\"{devicetype}_{platform_short}_v{startversion}.cfg\"\n",
|
||||
"print(deviceconfig)\n",
|
||||
"# Rest of the code from config_manager.ipynb\n",
|
||||
"# This would include calls to convert_config.write_code and convert_config.write_config\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/Users/nico/Documents/GitHub/HP_InHand_IG502/Pub_Sub/abbflow_tcp/thingsboard\n",
|
||||
"/Users/nico/Documents/GitHub/HP_InHand_IG502/Pub_Sub/abbflow_tcp/thingsboard\n",
|
||||
"Path did not exist creating path: /Users/nico/Documents/GitHub/HP_InHand_IG502/Pub_Sub/abbflow_tcp/thingsboard/abbflow_tcp_tb_v3.cfg\n",
|
||||
"/Users/nico/Documents/GitHub/HP_InHand_IG502/Pub_Sub/abbflow_tcp/thingsboard/pub\n",
|
||||
"/Users/nico/Documents/GitHub/HP_InHand_IG502/Pub_Sub/abbflow_tcp/thingsboard/sub\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"convert_config.write_config(f\"{root}/{devicetype}/{platform}/{devicetype}_{platform_short}_v{str(startversion)}.cfg\", \n",
|
||||
" convert_config.get_config(f\"{root}/{devicetype}/{platform}/{devicetype}_{platform_short}_v{str(startversion - 1)}.cfg\"),\n",
|
||||
" root + \"/\" + devicetype + \"/\" + platform + \"/pub\" , \n",
|
||||
" root + \"/\" + devicetype + \"/\" + platform + \"/sub\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "tbDataCollector",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.5"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import json
|
||||
def get_config(path):
|
||||
checkFileExist(path)
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
|
||||
return json.load(f)
|
||||
|
||||
def get_config_pub(path):
|
||||
@@ -42,13 +41,23 @@ def write_config(path, config, pubDir, subDir):
|
||||
if pubDir:
|
||||
checkFolderExist(pubDir)
|
||||
with os.scandir(pubDir) as it:
|
||||
for ind, entry in enumerate(it):
|
||||
config["quickfaas"]["uploadFuncs"][ind]["script"] = code_to_string(entry.path)
|
||||
funcNum = 0
|
||||
for entry in it:
|
||||
#print(entry)
|
||||
#print(config["quickfaas"]["uploadFuncs"][ind])
|
||||
if not entry.name.startswith('.') and entry.is_file():
|
||||
config["quickfaas"]["uploadFuncs"][funcNum]["script"] = code_to_string(entry.path)
|
||||
funcNum += 1
|
||||
if subDir:
|
||||
checkFolderExist(subDir)
|
||||
with os.scandir(subDir) as it:
|
||||
for ind, entry in enumerate(it):
|
||||
config["quickfaas"]["downloadFuncs"][ind]["script"] = code_to_string(entry.path)
|
||||
funcNum = 0
|
||||
for entry in it:
|
||||
#print(entry)
|
||||
#print(config["quickfaas"]["downloadFuncs"][ind])
|
||||
if not entry.name.startswith('.') and entry.is_file():
|
||||
config["quickfaas"]["downloadFuncs"][funcNum]["script"] = code_to_string(entry.path)
|
||||
funcNum += 1
|
||||
config["clouds"][0]["args"]["host"] = "hp.henrypump.cloud"
|
||||
config["clouds"][0]["args"]["clientId"] = "unknown"
|
||||
config["clouds"][0]["args"]["username"] = "unknown"
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json, os
|
||||
from datetime import datetime as dt
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from quickfaas.global_dict import _set_global_args
|
||||
|
||||
def reboot():
|
||||
#basic = Basic()
|
||||
logger.info("!" * 10 + "REBOOTING DEVICE" + "!"*10)
|
||||
r = os.popen("kill -s SIGHUP `cat /var/run/python/supervisord.pid`").read()
|
||||
logger.info(f"REBOOT : {r}")
|
||||
|
||||
def checkFileExist(filename):
|
||||
path = "/var/user/files"
|
||||
if not os.path.exists(path):
|
||||
logger.info("no folder making files folder in var/user")
|
||||
os.makedirs(path)
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
if not os.path.exists(path + "/" + filename):
|
||||
logger.info("no creds file making creds file")
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
|
||||
def convertDStoJSON(ds):
|
||||
j = dict()
|
||||
for x in ds:
|
||||
j[x["key"]] = x["value"]
|
||||
return j
|
||||
|
||||
def convertJSONtoDS(j):
|
||||
d = []
|
||||
for key in j.keys():
|
||||
d.append({"key": key, "value": j[key]})
|
||||
return d
|
||||
|
||||
def checkCredentialConfig():
|
||||
logger.info("CHECKING CONFIG")
|
||||
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
|
||||
credspath = "/var/user/files/creds.json"
|
||||
cfg = dict()
|
||||
with open(cfgpath, "r") as f:
|
||||
cfg = json.load(f)
|
||||
clouds = cfg.get("clouds")
|
||||
logger.info(clouds)
|
||||
#if not configured then try to configure from stored values
|
||||
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
logger.info("updating config with stored data")
|
||||
clouds[0]["args"]["clientId"] = creds["clientId"]
|
||||
clouds[0]["args"]["username"] = creds["userName"]
|
||||
clouds[0]["args"]["passwd"] = creds["password"]
|
||||
cfg["clouds"] = clouds
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
reboot()
|
||||
else:
|
||||
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
logger.info("updating stored file with new data")
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
if creds["clientId"] != clouds[0]["args"]["clientId"]:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
if creds["userName"] != clouds[0]["args"]["username"]:
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
if creds["password"] != clouds[0]["args"]["passwd"]:
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
else:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
with open(credspath, "w") as cw:
|
||||
json.dump(creds,cw)
|
||||
|
||||
def checkParameterConfig(cfg):
|
||||
logger.info("Checking Parameters!!!!")
|
||||
paramspath = "/var/user/files/params.json"
|
||||
cfgparams = convertDStoJSON(cfg.get("labels"))
|
||||
#check stored values
|
||||
checkFileExist("params.json")
|
||||
with open(paramspath, "r") as f:
|
||||
logger.info("Opened param storage file")
|
||||
params = json.load(f)
|
||||
if params:
|
||||
if cfgparams != params:
|
||||
#go through each param
|
||||
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
|
||||
#if key in cfg but not in params copy to params
|
||||
logger.info("equalizing params between cfg and stored")
|
||||
for key in cfgparams.keys():
|
||||
try:
|
||||
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
|
||||
params[key] = cfgparams[key]
|
||||
except:
|
||||
params[key] = cfgparams[key]
|
||||
cfg["labels"] = convertJSONtoDS(params)
|
||||
_set_global_args(convertJSONtoDS(params))
|
||||
with open(paramspath, "w") as p:
|
||||
json.dump(params, p)
|
||||
else:
|
||||
with open(paramspath, "w") as p:
|
||||
logger.info("initializing param file with params in memory")
|
||||
json.dump(convertDStoJSON(get_params()), p)
|
||||
cfg["labels"] = get_params()
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
|
||||
|
||||
def sendData(message):
|
||||
payload = {}
|
||||
payload["ts"] = (round(dt.timestamp(dt.now())/600)*600)*1000
|
||||
payload["values"] = {}
|
||||
try:
|
||||
checkCredentialConfig()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
publish(__topic__, json.dumps(payload), __qos__)
|
||||
@@ -1,136 +0,0 @@
|
||||
# Enter your python code.
|
||||
import json, os
|
||||
from datetime import datetime as dt
|
||||
from common.Logger import logger
|
||||
from quickfaas.remotebus import publish
|
||||
from quickfaas.global_dict import get as get_params
|
||||
from quickfaas.global_dict import _set_global_args
|
||||
|
||||
def reboot():
|
||||
#basic = Basic()
|
||||
logger.info("!" * 10 + "REBOOTING DEVICE" + "!"*10)
|
||||
r = os.popen("kill -s SIGHUP `cat /var/run/python/supervisord.pid`").read()
|
||||
logger.info(f"REBOOT : {r}")
|
||||
|
||||
def checkFileExist(filename):
|
||||
path = "/var/user/files"
|
||||
if not os.path.exists(path):
|
||||
logger.info("no folder making files folder in var/user")
|
||||
os.makedirs(path)
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
if not os.path.exists(path + "/" + filename):
|
||||
logger.info("no creds file making creds file")
|
||||
with open(path + "/" + filename, "a") as f:
|
||||
json.dump({}, f)
|
||||
|
||||
def convertDStoJSON(ds):
|
||||
j = dict()
|
||||
for x in ds:
|
||||
j[x["key"]] = x["value"]
|
||||
return j
|
||||
|
||||
def convertJSONtoDS(j):
|
||||
d = []
|
||||
for key in j.keys():
|
||||
d.append({"key": key, "value": j[key]})
|
||||
return d
|
||||
|
||||
def checkCredentialConfig():
|
||||
logger.info("CHECKING CONFIG")
|
||||
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
|
||||
credspath = "/var/user/files/creds.json"
|
||||
cfg = dict()
|
||||
with open(cfgpath, "r") as f:
|
||||
cfg = json.load(f)
|
||||
clouds = cfg.get("clouds")
|
||||
logger.info(clouds)
|
||||
#if not configured then try to configure from stored values
|
||||
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
logger.info("updating config with stored data")
|
||||
clouds[0]["args"]["clientId"] = creds["clientId"]
|
||||
clouds[0]["args"]["username"] = creds["userName"]
|
||||
clouds[0]["args"]["passwd"] = creds["password"]
|
||||
cfg["clouds"] = clouds
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
reboot()
|
||||
else:
|
||||
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
|
||||
checkFileExist("creds.json")
|
||||
with open(credspath, "r") as c:
|
||||
logger.info("updating stored file with new data")
|
||||
cfg = checkParameterConfig(cfg)
|
||||
with open(cfgpath, "w", encoding='utf-8') as n:
|
||||
json.dump(cfg, n, indent=1, ensure_ascii=False)
|
||||
creds = json.load(c)
|
||||
if creds:
|
||||
if creds["clientId"] != clouds[0]["args"]["clientId"]:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
if creds["userName"] != clouds[0]["args"]["username"]:
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
if creds["password"] != clouds[0]["args"]["passwd"]:
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
else:
|
||||
creds["clientId"] = clouds[0]["args"]["clientId"]
|
||||
creds["userName"] = clouds[0]["args"]["username"]
|
||||
creds["password"] = clouds[0]["args"]["passwd"]
|
||||
with open(credspath, "w") as cw:
|
||||
json.dump(creds,cw)
|
||||
|
||||
def checkParameterConfig(cfg):
|
||||
logger.info("Checking Parameters!!!!")
|
||||
paramspath = "/var/user/files/params.json"
|
||||
cfgparams = convertDStoJSON(cfg.get("labels"))
|
||||
#check stored values
|
||||
checkFileExist("params.json")
|
||||
with open(paramspath, "r") as f:
|
||||
logger.info("Opened param storage file")
|
||||
params = json.load(f)
|
||||
if params:
|
||||
if cfgparams != params:
|
||||
#go through each param
|
||||
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
|
||||
#if key in cfg but not in params copy to params
|
||||
logger.info("equalizing params between cfg and stored")
|
||||
for key in cfgparams.keys():
|
||||
try:
|
||||
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
|
||||
params[key] = cfgparams[key]
|
||||
except:
|
||||
params[key] = cfgparams[key]
|
||||
cfg["labels"] = convertJSONtoDS(params)
|
||||
_set_global_args(convertJSONtoDS(params))
|
||||
with open(paramspath, "w") as p:
|
||||
json.dump(params, p)
|
||||
else:
|
||||
with open(paramspath, "w") as p:
|
||||
logger.info("initializing param file with params in memory")
|
||||
json.dump(convertDStoJSON(get_params()), p)
|
||||
cfg["labels"] = get_params()
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
|
||||
|
||||
def sendData(message):
|
||||
payload = {}
|
||||
payload["ts"] = (round(dt.timestamp(dt.now())/600)*600)*1000
|
||||
payload["values"] = {}
|
||||
try:
|
||||
checkCredentialConfig()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
for measure in message["measures"]:
|
||||
try:
|
||||
logger.debug(measure)
|
||||
payload["values"][measure["name"]] = measure["value"]
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
publish(__topic__, json.dumps(payload), __qos__)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user