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": , "value": } 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")