diff --git a/Pub_Sub/abbflow/.DS_Store b/Pub_Sub/abbflow/.DS_Store index cd68c8b..fe912d9 100644 Binary files a/Pub_Sub/abbflow/.DS_Store and b/Pub_Sub/abbflow/.DS_Store differ diff --git a/Pub_Sub/abbflow/thingsboard/v2/abbflowrtu_tb_v2.cfg b/Pub_Sub/abbflow/thingsboard/v2/abbflowrtu_tb_v2.cfg index a031942..91ed85a 100644 --- a/Pub_Sub/abbflow/thingsboard/v2/abbflowrtu_tb_v2.cfg +++ b/Pub_Sub/abbflow/thingsboard/v2/abbflowrtu_tb_v2.cfg @@ -238,7 +238,7 @@ "alarms": [], "misc": { "maxAlarmRecordSz": 2000, - "logLvl": "DEBUG", + "logLvl": "INFO", "coms": [ { "name": "rs232", diff --git a/Pub_Sub/abbflow/thingsboard/v2/pub/sendData.py b/Pub_Sub/abbflow/thingsboard/v2/pub/sendData.py index eb0b429..90ebb10 100644 --- a/Pub_Sub/abbflow/thingsboard/v2/pub/sendData.py +++ b/Pub_Sub/abbflow/thingsboard/v2/pub/sendData.py @@ -1,6 +1,7 @@ # Enter your python code. import json, os 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,11 +172,13 @@ 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) @@ -189,7 +193,7 @@ def sendData(message): 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"]: @@ -201,7 +205,10 @@ def sendData(message): 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"] publish(__topic__, json.dumps(payload), __qos__) publish("v1/devices/me/attributes", json.dumps({"latestReportTime": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__) diff --git a/Pub_Sub/abbflow/v2/.DS_Store b/Pub_Sub/abbflow/v2/.DS_Store index c7aae5b..d4e3577 100644 Binary files a/Pub_Sub/abbflow/v2/.DS_Store and b/Pub_Sub/abbflow/v2/.DS_Store differ diff --git a/Pub_Sub/advvfdipp/.DS_Store b/Pub_Sub/advvfdipp/.DS_Store index 4f02112..5dbc5bd 100644 Binary files a/Pub_Sub/advvfdipp/.DS_Store and b/Pub_Sub/advvfdipp/.DS_Store differ diff --git a/Pub_Sub/advvfdipp/mistaway/v4/advvfdipp_ma_v4.cfg b/Pub_Sub/advvfdipp/mistaway/v4/advvfdipp_ma_v4.cfg index 283678a..f4d7447 100644 --- a/Pub_Sub/advvfdipp/mistaway/v4/advvfdipp_ma_v4.cfg +++ b/Pub_Sub/advvfdipp/mistaway/v4/advvfdipp_ma_v4.cfg @@ -963,7 +963,7 @@ "enable": 1, "type": "Standard MQTT", "args": { - "host": "hp.henrypump.cloud", + "host": "mq194.imistaway.net", "port": 1883, "clientId": "unknown", "auth": 1, @@ -1005,7 +1005,7 @@ "default" ], "funcName": "sendData", - "script": "# Enter your python code.\nimport json, math, time, os\nfrom datetime import datetime as dt\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom quickfaas.global_dict import get as get_params\nfrom quickfaas.global_dict import _set_global_args\n\nimport re, uuid\nfrom paho.mqtt import client\n\nclass RuntimeStats:\n def __init__(self):\n self.runs = {}\n self.currentRun = 0\n self.today = \"\"\n self.todayString = \"\"\n\n def manageTime(self):\n if self.todayString != dt.strftime(dt.today(), \"%Y-%m-%d\"):\n if self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"start\"] and not self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"]:\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"] = time.mktime(dt.strptime(self.todayString + \" 23:59:59\", \"%Y-%m-%d %H:%M:%S\").timetuple())\n self.addDay()\n self.today = dt.today()\n self.todayString = dt.strftime(self.today, \"%Y-%m-%d\")\n days = list(self.runs.keys())\n days.sort()\n while (dt.strptime(days[-1],\"%Y-%m-%d\") - dt.strptime(days[0], \"%Y-%m-%d\")).days > 30:\n self.removeDay(day=days[0])\n days = list(self.runs.keys())\n days.sort()\n\n def addHertzDataPoint(self, frequency):\n if frequency > 0:\n self.manageTime()\n try:\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"frequencies\"].append(frequency)\n except:\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"frequencies\"] = [frequency]\n\n def startRun(self):\n if self.checkRunning():\n self.endRun()\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"start\"] = time.time()\n\n def endRun(self):\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"] = time.time()\n self.currentRun += 1\n self.runs[self.todayString][\"run_\" + str(self.currentRun)] = {\"start\":0, \"end\": 0, \"frequencies\":[]} \n\n def checkRunning(self):\n if self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"start\"] and not self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"]:\n return True\n return False\n\n def addDay(self):\n self.today = dt.today()\n self.todayString = dt.strftime(self.today, \"%Y-%m-%d\")\n self.currentRun = 1\n self.runs[self.todayString] = {}\n self.runs[self.todayString][\"run_\" + str(self.currentRun)] = {\"start\":0, \"end\": 0, \"frequencies\":[]}\n\n def countRunsDay(self, day=None):\n if not day:\n day = self.todayString\n return len(self.runs[day].keys())\n\n def countRunsMultiDay(self, numDays=30):\n total_runs = 0\n for day in list(self.runs.keys()):\n total_runs += self.countRunsDay(day=day)\n return total_runs\n\n def calculateAverageHertzDay(self, day=None, returnArray=False):\n dayFrequencies = []\n if not day:\n day = self.todayString\n for run in list(self.runs[day].keys()):\n try:\n dayFrequencies += self.runs[day][run][\"frequencies\"]\n except Exception as e:\n print(\"{} missing frequency data for {}\".format(day,run))\n if returnArray:\n return dayFrequencies\n return round(math.fsum(dayFrequencies)/len(dayFrequencies),2)\n\n def calculateAverageHertzMultiDay(self, numDays=30):\n self.manageTime()\n frequencies = []\n for day in list(self.runs.keys()):\n if not day == self.todayString and (dt.strptime(self.todayString, \"%Y-%m-%d\") - dt.strptime(day, \"%Y-%m-%d\")).days <= numDays:\n try:\n frequencies += self.calculateAverageHertzDay(day=day, returnArray=True)\n except Exception as e:\n print(\"{} missing frequency data\".format(day))\n if len(frequencies):\n return round(math.fsum(frequencies)/len(frequencies), 2)\n return 0\n \n def calculateRunTimeDay(self, day=None, convertToHours=True):\n total_time = 0\n if not day:\n day = self.todayString\n for run in list(self.runs[day].keys()):\n total_time = self.runs[day][run][\"end\"] - self.runs[day][run][\"start\"] + total_time\n if convertToHours:\n return self.convertSecondstoHours(total_time)\n return total_time\n\n def calculateRunTimeMultiDay(self, numDays=30, convertToHours=True):\n total_time = 0\n for day in list(self.runs.keys()):\n if not day == self.todayString and (dt.strptime(self.todayString, \"%Y-%m-%d\") - dt.strptime(day, \"%Y-%m-%d\")).days <= numDays:\n total_time += self.calculateRunTimeDay(day=day, convertToHours=False)\n if convertToHours:\n return self.convertSecondstoHours(total_time)\n return total_time\n \n def calculateRunPercentDay(self, day=None, precise=False):\n if not day:\n day = self.todayString\n if precise:\n return (self.calculateRunTimeDay(day=day)/24) * 100\n return round((self.calculateRunTimeDay(day=day)/24) * 100, 2)\n \n\n def calculateRunPercentMultiDay(self, numDays=30, precise=False):\n self.manageTime()\n if precise:\n return (self.calculateRunTimeMultiDay()/(24*numDays)) * 100\n return round((self.calculateRunTimeMultiDay()/(24*numDays)) * 100,2)\n\n def removeDay(self, day=None):\n if not day:\n raise Exception(\"Day can not be None\")\n print(\"removing day {}\".format(day))\n del self.runs[day]\n \n def convertSecondstoHours(self, seconds):\n return round(seconds / (60*60),2)\n\n def loadDataFromFile(self, filePath=\"/var/user/files/runtimestats.json\"):\n try:\n with open(filePath, \"r\") as f:\n temp = json.load(f)\n self.runs = temp[\"data\"]\n self.currentRun = temp[\"current_run\"]\n self.today = dt.strptime(temp[\"current_day\"], \"%Y-%m-%d\")\n self.todayString = temp[\"current_day\"]\n self.manageTime()\n except:\n print(\"Could not find file at {}\".format(filePath))\n print(\"creating file\")\n self.addDay()\n try:\n with open(filePath, \"w\") as f:\n d = {\n \"current_run\": self.currentRun,\n \"current_day\": self.todayString,\n \"data\": self.runs\n }\n json.dump(d, f, indent=4)\n except Exception as e:\n print(e)\n\n def saveDataToFile(self, filePath=\"/var/user/files/runtimestats.json\"):\n try:\n print(\"Saving Runs\")\n with open(filePath, \"w\") as f:\n d = {\n \"current_run\": self.currentRun,\n \"current_day\": self.todayString,\n \"data\": self.runs\n }\n json.dump(d, f, indent=4)\n except Exception as e:\n print(e)\n\nrts = RuntimeStats()\nrts.loadDataFromFile()\nrts.saveDataToFile()\n\ndef reboot(reason=\"Rebooting for config file update\"):\n #basic = Basic()\n logger.info(\"!\" * 10 + \"REBOOTING DEVICE\" + \"!\"*10)\n logger.info(reason)\n r = os.popen(\"kill -s SIGHUP `cat /var/run/python/supervisord.pid`\").read()\n logger.info(f\"REBOOT : {r}\")\n\ndef checkFileExist(filename):\n path = \"/var/user/files\"\n if not os.path.exists(path):\n logger.info(\"no folder making files folder in var/user\")\n os.makedirs(path)\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n if not os.path.exists(path + \"/\" + filename):\n logger.info(\"no creds file making creds file\")\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n\ndef convertDStoJSON(ds):\n j = dict()\n for x in ds:\n j[x[\"key\"]] = x[\"value\"]\n return j\n\ndef convertJSONtoDS(j):\n d = []\n for key in j.keys():\n d.append({\"key\": key, \"value\": j[key]})\n return d\n\ndef checkCredentialConfig():\n logger.info(\"CHECKING CONFIG\")\n cfgpath = \"/var/user/cfg/device_supervisor/device_supervisor.cfg\"\n credspath = \"/var/user/files/creds.json\"\n cfg = dict()\n with open(cfgpath, \"r\") as f:\n cfg = json.load(f)\n clouds = cfg.get(\"clouds\")\n logger.info(clouds)\n #if not configured then try to configure from stored values\n if clouds[0][\"args\"][\"clientId\"] == \"unknown\" or clouds[0][\"args\"][\"username\"] == \"unknown\" or not clouds[0][\"args\"][\"passwd\"] or clouds[0][\"args\"][\"passwd\"] == \"unknown\":\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n creds = json.load(c)\n if creds:\n logger.info(\"updating config with stored data\")\n clouds[0][\"args\"][\"clientId\"] = creds[\"clientId\"]\n clouds[0][\"args\"][\"username\"] = creds[\"userName\"]\n clouds[0][\"args\"][\"passwd\"] = creds[\"password\"]\n cfg[\"clouds\"] = clouds\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n reboot()\n else:\n #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\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n logger.info(\"updating stored file with new data\")\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n creds = json.load(c)\n if creds:\n if creds[\"clientId\"] != clouds[0][\"args\"][\"clientId\"]:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n if creds[\"userName\"] != clouds[0][\"args\"][\"username\"]:\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n if creds[\"password\"] != clouds[0][\"args\"][\"passwd\"]:\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n else:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n with open(credspath, \"w\") as cw:\n json.dump(creds,cw)\n\ndef checkParameterConfig(cfg):\n logger.info(\"Checking Parameters!!!!\")\n paramspath = \"/var/user/files/params.json\"\n cfgparams = convertDStoJSON(cfg.get(\"labels\"))\n #check stored values \n checkFileExist(\"params.json\")\n with open(paramspath, \"r\") as f:\n logger.info(\"Opened param storage file\")\n params = json.load(f)\n if params:\n if cfgparams != params:\n #go through each param\n #if not \"unknown\" and cfg and params aren't the same take from cfg likely updated manually\n #if key in cfg but not in params copy to params\n logger.info(\"equalizing params between cfg and stored\")\n for key in cfgparams.keys():\n try:\n if cfgparams[key] != params[key] and cfgparams[key] != \"unknown\":\n params[key] = cfgparams[key]\n except:\n params[key] = cfgparams[key]\n cfg[\"labels\"] = convertJSONtoDS(params)\n _set_global_args(convertJSONtoDS(params))\n with open(paramspath, \"w\") as p:\n json.dump(params, p)\n else:\n with open(paramspath, \"w\") as p:\n logger.info(\"initializing param file with params in memory\")\n json.dump(convertDStoJSON(get_params()), p)\n cfg[\"labels\"] = get_params()\n \n return cfg\n\n\n\nlwtData = {\n \"init\":False,\n \"client\": client.Client(client_id=str(uuid.uuid4()), clean_session=True, userdata=None, protocol=client.MQTTv311, transport=\"tcp\")\n}\ndef lwt(mac):\n try:\n #if not lwtData[\"connected\"]:\n if not lwtData[\"init\"]:\n logger.info(\"INITIALIZING LWT CLIENT\")\n lwtData[\"client\"].username_pw_set(username=\"admin\", password=\"columbus\")\n lwtData[\"client\"].will_set(\"meshify/db/194/_/mainHP/\" + mac + \":00:00/connected\",json.dumps({\"value\":False}))\n lwtData[\"init\"] = True\n logger.info(\"Connecting to MQTT Broker for LWT purposes!!!!!!!\")\n lwtData[\"client\"].connect(\"mq194.imistaway.net\",1883, 600)\n lwtData[\"client\"].publish(\"meshify/db/194/_/mainHP/\" + mac + \":00:00/connected\", json.dumps({\"value\":True}))\n except Exception as e:\n logger.error(\"LWT DID NOT DO THE THING\")\n logger.error(e)\n\ndef sendData(message):\n #logger.debug(message)\n mac = __topic__.split(\"/\")[-1] #':'.join(re.findall('..', '%012x' % uuid.getnode()))\n lwt(mac)\n checkCredentialConfig()\n for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n now = (round(dt.timestamp(dt.now())/600)*600)\n if abs(now - measure[\"timestamp\"]) > 7200:\n reboot(reason=\"Poll timestamp and actual timestamp out of sync. Actual: {} Poll: {}\".format(now,measure[\"timestamp\"]))\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\"]:\n logger.debug(\"Converting DINT/BOOL to STRING\")\n value = convert_int(measure[\"name\"], measure[\"value\"])\n logger.debug(\"Converted {} to {}\".format(measure[\"value\"], value))\n publish(__topic__ + \":01:99/\" + measure[\"name\"], json.dumps({\"value\": value}), __qos__)\n else:\n publish(__topic__ + \":01:99/\" + measure[\"name\"], json.dumps({\"value\": measure[\"value\"]}), __qos__)\n \n if measure[\"name\"] == \"wellstatus\":\n if measure[\"value\"] == 0 and not rts.runs[rts.todayString][\"run_\" + str(rts.currentRun)][\"start\"]:\n rts.startRun()\n rts.saveDataToFile()\n elif measure[\"value\"] > 0 and rts.runs[rts.todayString][\"run_\" + str(rts.currentRun)][\"start\"] and not rts.runs[rts.todayString][\"run_\" + str(rts.currentRun)][\"end\"]:\n rts.endRun()\n rts.saveDataToFile()\n publish(__topic__ + \":01:99/\" + \"percentRunTime30Days\", json.dumps({\"value\": rts.calculateRunPercentMultiDay()}), __qos__)\n \n if measure[\"name\"] == \"vfdfrequency\":\n if measure[\"value\"] > 0:\n rts.addHertzDataPoint(val)\n rts.saveDataToFile()\n publish(__topic__ + \":01:99/\" + \"avgFrequency30Days\", json.dumps({\"value\": rts.calculateAverageHertzMultiDay()}), __qos__)\n except Exception as e:\n logger.error(e)\n \n #publish(__topic__, json.dumps({measure[\"name\"]: measure[\"value\"]}), __qos__)\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n\n ", + "script": "# Enter your python code.\nimport json, math, time, os\nfrom datetime import datetime as dt\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom quickfaas.global_dict import get as get_params\nfrom quickfaas.global_dict import _set_global_args\n\nimport re, uuid\nfrom paho.mqtt import client\n\nclass RuntimeStats:\n def __init__(self):\n self.runs = {}\n self.currentRun = 0\n self.today = \"\"\n self.todayString = \"\"\n\n def manageTime(self):\n if self.todayString != dt.strftime(dt.today(), \"%Y-%m-%d\"):\n if self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"start\"] and not self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"]:\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"] = time.mktime(dt.strptime(self.todayString + \" 23:59:59\", \"%Y-%m-%d %H:%M:%S\").timetuple())\n self.addDay()\n self.today = dt.today()\n self.todayString = dt.strftime(self.today, \"%Y-%m-%d\")\n days = list(self.runs.keys())\n days.sort()\n while (dt.strptime(days[-1],\"%Y-%m-%d\") - dt.strptime(days[0], \"%Y-%m-%d\")).days > 30:\n self.removeDay(day=days[0])\n days = list(self.runs.keys())\n days.sort()\n\n def addHertzDataPoint(self, frequency):\n if frequency > 0:\n self.manageTime()\n try:\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"frequencies\"].append(frequency)\n except:\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"frequencies\"] = [frequency]\n\n def startRun(self):\n if self.checkRunning():\n self.endRun()\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"start\"] = time.time()\n\n def endRun(self):\n self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"] = time.time()\n self.currentRun += 1\n self.runs[self.todayString][\"run_\" + str(self.currentRun)] = {\"start\":0, \"end\": 0, \"frequencies\":[]} \n\n def checkRunning(self):\n if self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"start\"] and not self.runs[self.todayString][\"run_\" + str(self.currentRun)][\"end\"]:\n return True\n return False\n\n def addDay(self):\n self.today = dt.today()\n self.todayString = dt.strftime(self.today, \"%Y-%m-%d\")\n self.currentRun = 1\n self.runs[self.todayString] = {}\n self.runs[self.todayString][\"run_\" + str(self.currentRun)] = {\"start\":0, \"end\": 0, \"frequencies\":[]}\n\n def countRunsDay(self, day=None):\n if not day:\n day = self.todayString\n return len(self.runs[day].keys())\n\n def countRunsMultiDay(self, numDays=30):\n total_runs = 0\n for day in list(self.runs.keys()):\n total_runs += self.countRunsDay(day=day)\n return total_runs\n\n def calculateAverageHertzDay(self, day=None, returnArray=False):\n dayFrequencies = []\n if not day:\n day = self.todayString\n for run in list(self.runs[day].keys()):\n try:\n dayFrequencies += self.runs[day][run][\"frequencies\"]\n except Exception as e:\n print(\"{} missing frequency data for {}\".format(day,run))\n if returnArray:\n return dayFrequencies\n return round(math.fsum(dayFrequencies)/len(dayFrequencies),2)\n\n def calculateAverageHertzMultiDay(self, numDays=30):\n self.manageTime()\n frequencies = []\n for day in list(self.runs.keys()):\n if not day == self.todayString and (dt.strptime(self.todayString, \"%Y-%m-%d\") - dt.strptime(day, \"%Y-%m-%d\")).days <= numDays:\n try:\n frequencies += self.calculateAverageHertzDay(day=day, returnArray=True)\n except Exception as e:\n print(\"{} missing frequency data\".format(day))\n if len(frequencies):\n return round(math.fsum(frequencies)/len(frequencies), 2)\n return 0\n \n def calculateRunTimeDay(self, day=None, convertToHours=True):\n total_time = 0\n if not day:\n day = self.todayString\n for run in list(self.runs[day].keys()):\n total_time = self.runs[day][run][\"end\"] - self.runs[day][run][\"start\"] + total_time\n if convertToHours:\n return self.convertSecondstoHours(total_time)\n return total_time\n\n def calculateRunTimeMultiDay(self, numDays=30, convertToHours=True):\n total_time = 0\n for day in list(self.runs.keys()):\n if not day == self.todayString and (dt.strptime(self.todayString, \"%Y-%m-%d\") - dt.strptime(day, \"%Y-%m-%d\")).days <= numDays:\n total_time += self.calculateRunTimeDay(day=day, convertToHours=False)\n if convertToHours:\n return self.convertSecondstoHours(total_time)\n return total_time\n \n def calculateRunPercentDay(self, day=None, precise=False):\n if not day:\n day = self.todayString\n if precise:\n return (self.calculateRunTimeDay(day=day)/24) * 100\n return round((self.calculateRunTimeDay(day=day)/24) * 100, 2)\n \n\n def calculateRunPercentMultiDay(self, numDays=30, precise=False):\n self.manageTime()\n if precise:\n return (self.calculateRunTimeMultiDay()/(24*numDays)) * 100\n return round((self.calculateRunTimeMultiDay()/(24*numDays)) * 100,2)\n\n def removeDay(self, day=None):\n if not day:\n raise Exception(\"Day can not be None\")\n print(\"removing day {}\".format(day))\n del self.runs[day]\n \n def convertSecondstoHours(self, seconds):\n return round(seconds / (60*60),2)\n\n def loadDataFromFile(self, filePath=\"/var/user/files/runtimestats.json\"):\n try:\n with open(filePath, \"r\") as f:\n temp = json.load(f)\n self.runs = temp[\"data\"]\n self.currentRun = temp[\"current_run\"]\n self.today = dt.strptime(temp[\"current_day\"], \"%Y-%m-%d\")\n self.todayString = temp[\"current_day\"]\n self.manageTime()\n except:\n print(\"Could not find file at {}\".format(filePath))\n print(\"creating file\")\n self.addDay()\n try:\n with open(filePath, \"w\") as f:\n d = {\n \"current_run\": self.currentRun,\n \"current_day\": self.todayString,\n \"data\": self.runs\n }\n json.dump(d, f, indent=4)\n except Exception as e:\n print(e)\n\n def saveDataToFile(self, filePath=\"/var/user/files/runtimestats.json\"):\n try:\n print(\"Saving Runs\")\n with open(filePath, \"w\") as f:\n d = {\n \"current_run\": self.currentRun,\n \"current_day\": self.todayString,\n \"data\": self.runs\n }\n json.dump(d, f, indent=4)\n except Exception as e:\n print(e)\n\nrts = RuntimeStats()\nrts.loadDataFromFile()\nrts.saveDataToFile()\n\ndef reboot(reason=\"Rebooting for config file update\"):\n #basic = Basic()\n logger.info(\"!\" * 10 + \"REBOOTING DEVICE\" + \"!\"*10)\n logger.info(reason)\n r = os.popen(\"kill -s SIGHUP `cat /var/run/python/supervisord.pid`\").read()\n logger.info(f\"REBOOT : {r}\")\n\ndef checkFileExist(filename):\n path = \"/var/user/files\"\n if not os.path.exists(path):\n logger.info(\"no folder making files folder in var/user\")\n os.makedirs(path)\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n if not os.path.exists(path + \"/\" + filename):\n logger.info(\"no creds file making creds file\")\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n\ndef convertDStoJSON(ds):\n j = dict()\n for x in ds:\n j[x[\"key\"]] = x[\"value\"]\n return j\n\ndef convertJSONtoDS(j):\n d = []\n for key in j.keys():\n d.append({\"key\": key, \"value\": j[key]})\n return d\n\ndef checkCredentialConfig():\n logger.info(\"CHECKING CONFIG\")\n cfgpath = \"/var/user/cfg/device_supervisor/device_supervisor.cfg\"\n credspath = \"/var/user/files/creds.json\"\n cfg = dict()\n with open(cfgpath, \"r\") as f:\n cfg = json.load(f)\n clouds = cfg.get(\"clouds\")\n logger.info(clouds)\n #if not configured then try to configure from stored values\n if clouds[0][\"args\"][\"clientId\"] == \"unknown\" or clouds[0][\"args\"][\"username\"] == \"unknown\" or not clouds[0][\"args\"][\"passwd\"] or clouds[0][\"args\"][\"passwd\"] == \"unknown\":\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n creds = json.load(c)\n if creds:\n logger.info(\"updating config with stored data\")\n clouds[0][\"args\"][\"clientId\"] = creds[\"clientId\"]\n clouds[0][\"args\"][\"username\"] = creds[\"userName\"]\n clouds[0][\"args\"][\"passwd\"] = creds[\"password\"]\n cfg[\"clouds\"] = clouds\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n reboot()\n else:\n #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\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n logger.info(\"updating stored file with new data\")\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n creds = json.load(c)\n if creds:\n if creds[\"clientId\"] != clouds[0][\"args\"][\"clientId\"]:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n if creds[\"userName\"] != clouds[0][\"args\"][\"username\"]:\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n if creds[\"password\"] != clouds[0][\"args\"][\"passwd\"]:\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n else:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n with open(credspath, \"w\") as cw:\n json.dump(creds,cw)\n\ndef checkParameterConfig(cfg):\n logger.info(\"Checking Parameters!!!!\")\n paramspath = \"/var/user/files/params.json\"\n cfgparams = convertDStoJSON(cfg.get(\"labels\"))\n #check stored values \n checkFileExist(\"params.json\")\n with open(paramspath, \"r\") as f:\n logger.info(\"Opened param storage file\")\n params = json.load(f)\n if params:\n if cfgparams != params:\n #go through each param\n #if not \"unknown\" and cfg and params aren't the same take from cfg likely updated manually\n #if key in cfg but not in params copy to params\n logger.info(\"equalizing params between cfg and stored\")\n for key in cfgparams.keys():\n try:\n if cfgparams[key] != params[key] and cfgparams[key] != \"unknown\":\n params[key] = cfgparams[key]\n except:\n params[key] = cfgparams[key]\n cfg[\"labels\"] = convertJSONtoDS(params)\n _set_global_args(convertJSONtoDS(params))\n with open(paramspath, \"w\") as p:\n json.dump(params, p)\n else:\n with open(paramspath, \"w\") as p:\n logger.info(\"initializing param file with params in memory\")\n json.dump(convertDStoJSON(get_params()), p)\n cfg[\"labels\"] = get_params()\n \n return cfg\n\n\n\nlwtData = {\n \"init\":False,\n \"client\": client.Client(client_id=str(uuid.uuid4()), clean_session=True, userdata=None, protocol=client.MQTTv311, transport=\"tcp\")\n}\ndef lwt(mac):\n try:\n #if not lwtData[\"connected\"]:\n if not lwtData[\"init\"]:\n logger.info(\"INITIALIZING LWT CLIENT\")\n lwtData[\"client\"].username_pw_set(username=\"admin\", password=\"columbus\")\n lwtData[\"client\"].will_set(\"meshify/db/194/_/mainHP/\" + mac + \":00:00/connected\",json.dumps({\"value\":False}))\n lwtData[\"init\"] = True\n logger.info(\"Connecting to MQTT Broker for LWT purposes!!!!!!!\")\n lwtData[\"client\"].connect(\"mq194.imistaway.net\",1883, 600)\n lwtData[\"client\"].publish(\"meshify/db/194/_/mainHP/\" + mac + \":00:00/connected\", json.dumps({\"value\":True}))\n except Exception as e:\n logger.error(\"LWT DID NOT DO THE THING\")\n logger.error(e)\n\ndef sendData(message):\n #logger.debug(message)\n mac = __topic__.split(\"/\")[-1] #':'.join(re.findall('..', '%012x' % uuid.getnode()))\n lwt(mac)\n checkCredentialConfig()\n for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n now = (round(dt.timestamp(dt.now())/600)*600)\n if abs(now - measure[\"timestamp\"]) > 7200:\n reboot(reason=\"Poll timestamp and actual timestamp out of sync. Actual: {} Poll: {}\".format(now,measure[\"timestamp\"]))\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\"]:\n logger.debug(\"Converting DINT/BOOL to STRING\")\n value = convert_int(measure[\"name\"], measure[\"value\"])\n logger.debug(\"Converted {} to {}\".format(measure[\"value\"], value))\n publish(__topic__ + \":01:99/\" + measure[\"name\"], json.dumps({\"value\": value}), __qos__)\n else:\n publish(__topic__ + \":01:99/\" + measure[\"name\"], json.dumps({\"value\": measure[\"value\"]}), __qos__)\n \n if measure[\"name\"] == \"wellstatus\":\n if measure[\"value\"] == 0 and not rts.runs[rts.todayString][\"run_\" + str(rts.currentRun)][\"start\"]:\n rts.startRun()\n rts.saveDataToFile()\n elif measure[\"value\"] > 0 and rts.runs[rts.todayString][\"run_\" + str(rts.currentRun)][\"start\"] and not rts.runs[rts.todayString][\"run_\" + str(rts.currentRun)][\"end\"]:\n rts.endRun()\n rts.saveDataToFile()\n publish(__topic__ + \":01:99/\" + \"percentRunTime30Days\", json.dumps({\"value\": rts.calculateRunPercentMultiDay()}), __qos__)\n \n if measure[\"name\"] == \"vfdfrequency\":\n if measure[\"value\"] > 0:\n rts.addHertzDataPoint(measure[\"value\"])\n rts.saveDataToFile()\n publish(__topic__ + \":01:99/\" + \"avgFrequency30Days\", json.dumps({\"value\": rts.calculateAverageHertzMultiDay()}), __qos__)\n except Exception as e:\n logger.error(e)\n \n #publish(__topic__, json.dumps({measure[\"name\"]: measure[\"value\"]}), __qos__)\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n\n ", "msgType": 0, "cloudName": "default" } diff --git a/Pub_Sub/advvfdipp/mistaway/v4/pub/sendData.py b/Pub_Sub/advvfdipp/mistaway/v4/pub/sendData.py index a80ee5c..cdf1e90 100644 --- a/Pub_Sub/advvfdipp/mistaway/v4/pub/sendData.py +++ b/Pub_Sub/advvfdipp/mistaway/v4/pub/sendData.py @@ -342,7 +342,7 @@ def sendData(message): if measure["name"] == "vfdfrequency": if measure["value"] > 0: - rts.addHertzDataPoint(val) + rts.addHertzDataPoint(measure["value"]) rts.saveDataToFile() publish(__topic__ + ":01:99/" + "avgFrequency30Days", json.dumps({"value": rts.calculateAverageHertzMultiDay()}), __qos__) except Exception as e: diff --git a/Pub_Sub/advvfdipp/thingsboard/v3/advvfdipp_tb_v3.cfg b/Pub_Sub/advvfdipp/thingsboard/v3/advvfdipp_tb_v3.cfg index 21aaede..d2e0fa6 100644 --- a/Pub_Sub/advvfdipp/thingsboard/v3/advvfdipp_tb_v3.cfg +++ b/Pub_Sub/advvfdipp/thingsboard/v3/advvfdipp_tb_v3.cfg @@ -697,66 +697,6 @@ "gain": "", "offset": "" }, - { - "name": "hartnettotal", - "ctrlName": "advvfdipp", - "group": "default", - "uploadType": "periodic", - "dataType": "FLOAT", - "addr": "in_HART_Flowmeter_Net", - "decimal": 2, - "len": 1, - "readWrite": "ro", - "unit": "", - "desc": "", - "transformType": 0, - "maxValue": "", - "minValue": "", - "maxScaleValue": "", - "minScaleValue": "", - "gain": "", - "offset": "" - }, - { - "name": "hartfwdtotal", - "ctrlName": "advvfdipp", - "group": "default", - "uploadType": "periodic", - "dataType": "FLOAT", - "addr": "in_HART_Flowmeter_Fwd", - "decimal": 2, - "len": 1, - "readWrite": "ro", - "unit": "", - "desc": "", - "transformType": 0, - "maxValue": "", - "minValue": "", - "maxScaleValue": "", - "minScaleValue": "", - "gain": "", - "offset": "" - }, - { - "name": "hartrevtotal", - "ctrlName": "advvfdipp", - "group": "default", - "uploadType": "periodic", - "dataType": "FLOAT", - "addr": "in_HART_Flowmeter_Rev", - "decimal": 2, - "len": 1, - "readWrite": "ro", - "unit": "", - "desc": "", - "transformType": 0, - "maxValue": "", - "minValue": "", - "maxScaleValue": "", - "minScaleValue": "", - "gain": "", - "offset": "" - }, { "ctrlName": "advvfdipp", "dataType": "BIT", @@ -948,7 +888,176 @@ "decimal": 2 } ], - "alarms": [], + "alarms": [{ + "name": "alarmflowrate", + "ctrlName": "advvfdipp", + "measureName": "alarmflowrate", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Flow Rate Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmintakepressure", + "ctrlName": "advvfdipp", + "measureName": "alarmintakepressure", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Intake Pressure Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmintaketemperature", + "ctrlName": "advvfdipp", + "measureName": "alarmintaketemperature", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Intake Temperature Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmtubingpressure", + "ctrlName": "advvfdipp", + "measureName": "alarmtubingpressure", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Tubing Pressure Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmvfd", + "ctrlName": "advvfdipp", + "measureName": "alarmvfd", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "VFD Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmlockout", + "ctrlName": "advvfdipp", + "measureName": "alarmlockout", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Lockout Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmfluidlevel", + "ctrlName": "advvfdipp", + "measureName": "alarmfluidlevel", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Fluid Level Alarm triggered", + "alarmLable": "default" + }, + { + "name": "controllerfault_io", + "ctrlName": "advvfdipp", + "measureName": "controllerfault_io", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Controller IO Alarm triggered", + "alarmLable": "default" + }, + { + "name": "controllerfault_program", + "ctrlName": "advvfdipp", + "measureName": "controllerfault_program", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Controller Fault Alarm triggered", + "alarmLable": "default" + }, + { + "name": "flowmeter_fault", + "ctrlName": "advvfdipp", + "measureName": "flowmeter_fault", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Flow Meter Alarm triggered", + "alarmLable": "default" + }], "misc": { "maxAlarmRecordSz": 2000, "logLvl": "INFO", @@ -1020,7 +1129,20 @@ "script": "# Enter your python code.\nimport json, os\nfrom datetime import datetime as dt\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom quickfaas.global_dict import get as get_params\nfrom quickfaas.global_dict import _set_global_args\n\ndef reboot():\n #basic = Basic()\n logger.info(\"!\" * 10 + \"REBOOTING DEVICE\" + \"!\"*10)\n r = os.popen(\"kill -s SIGHUP `cat /var/run/python/supervisord.pid`\").read()\n logger.info(f\"REBOOT : {r}\")\n\ndef checkFileExist(filename):\n path = \"/var/user/files\"\n if not os.path.exists(path):\n logger.info(\"no folder making files folder in var/user\")\n os.makedirs(path)\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n if not os.path.exists(path + \"/\" + filename):\n logger.info(\"no creds file making creds file\")\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n\ndef convertDStoJSON(ds):\n j = dict()\n for x in ds:\n j[x[\"key\"]] = x[\"value\"]\n return j\n\ndef convertJSONtoDS(j):\n d = []\n for key in j.keys():\n d.append({\"key\": key, \"value\": j[key]})\n return d\n\ndef checkCredentialConfig():\n logger.info(\"CHECKING CONFIG\")\n cfgpath = \"/var/user/cfg/device_supervisor/device_supervisor.cfg\"\n credspath = \"/var/user/files/creds.json\"\n cfg = dict()\n with open(cfgpath, \"r\") as f:\n cfg = json.load(f)\n clouds = cfg.get(\"clouds\")\n logger.info(clouds)\n #if not configured then try to configure from stored values\n if clouds[0][\"args\"][\"clientId\"] == \"unknown\" or clouds[0][\"args\"][\"username\"] == \"unknown\" or not clouds[0][\"args\"][\"passwd\"] or clouds[0][\"args\"][\"passwd\"] == \"unknown\":\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n creds = json.load(c)\n if creds:\n logger.info(\"updating config with stored data\")\n clouds[0][\"args\"][\"clientId\"] = creds[\"clientId\"]\n clouds[0][\"args\"][\"username\"] = creds[\"userName\"]\n clouds[0][\"args\"][\"passwd\"] = creds[\"password\"]\n cfg[\"clouds\"] = clouds\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n reboot()\n else:\n #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\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n logger.info(\"updating stored file with new data\")\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n creds = json.load(c)\n if creds:\n if creds[\"clientId\"] != clouds[0][\"args\"][\"clientId\"]:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n if creds[\"userName\"] != clouds[0][\"args\"][\"username\"]:\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n if creds[\"password\"] != clouds[0][\"args\"][\"passwd\"]:\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n else:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n with open(credspath, \"w\") as cw:\n json.dump(creds,cw)\n\ndef checkParameterConfig(cfg):\n logger.info(\"Checking Parameters!!!!\")\n paramspath = \"/var/user/files/params.json\"\n cfgparams = convertDStoJSON(cfg.get(\"labels\"))\n #check stored values \n checkFileExist(\"params.json\")\n with open(paramspath, \"r\") as f:\n logger.info(\"Opened param storage file\")\n params = json.load(f)\n if params:\n if cfgparams != params:\n #go through each param\n #if not \"unknown\" and cfg and params aren't the same take from cfg likely updated manually\n #if key in cfg but not in params copy to params\n logger.info(\"equalizing params between cfg and stored\")\n for key in cfgparams.keys():\n try:\n if cfgparams[key] != params[key] and cfgparams[key] != \"unknown\":\n params[key] = cfgparams[key]\n except:\n params[key] = cfgparams[key]\n cfg[\"labels\"] = convertJSONtoDS(params)\n _set_global_args(convertJSONtoDS(params))\n with open(paramspath, \"w\") as p:\n json.dump(params, p)\n else:\n with open(paramspath, \"w\") as p:\n logger.info(\"initializing param file with params in memory\")\n json.dump(convertDStoJSON(get_params()), p)\n cfg[\"labels\"] = get_params()\n \n return cfg\n\ndef sendData(message):\n #logger.debug(message)\n try:\n checkCredentialConfig()\n except Exception as e:\n logger.error(e)\n payload = {\"ts\": (round(dt.timestamp(dt.now())/600)*600)*1000, \"values\": {}}\n for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n if payload[\"ts\"]/1000 - measure[\"timestamp\"] > 86400:\n reboot()\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\", \"flowmeter_fault\"]:\n logger.debug(\"Converting DINT/BOOL to STRING\")\n value = convert_int(measure[\"name\"], measure[\"value\"])\n logger.debug(\"Converted {} to {}\".format(measure[\"value\"], value))\n payload[\"values\"][measure[\"name\"]] = value\n payload[\"values\"][measure[\"name\"] + \"_int\"] = measure[\"value\"]\n else:\n payload[\"values\"][measure[\"name\"]] = measure[\"value\"] \n except Exception as e:\n logger.error(e)\n \n publish(__topic__, json.dumps(payload), __qos__)\n publish(\"v1/devices/me/attributes\", json.dumps({\"latestReportTime\": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__)\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"flowmeter_fault\": alarm_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n\n ", "msgType": 0, "cloudName": "default" - } + }, + { + "name": "sendAlarm", + "trigger": "warning_event", + "topic": "v1/devices/me/telemetry", + "qos": 1, + "funcName": "sendAlarm", + "script": "# Enter your python code.\nimport json, time\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\n\n\ndef sendAlarm(message):\n logger.info(message)\n payload = {}\n payload[\"ts\"] = time.time()*1000\n payload[\"values\"] = {message[\"measureName\"]: message[\"value\"]}\n publish(__topic__, json.dumps(payload), __qos__)", + "alarms": [ + "default" + ], + "msgType": 0, + "cloudName": "default" + } ], "downloadFuncs": [ { diff --git a/Pub_Sub/advvfdipp/thingsboard/v3/pub/sendData.py b/Pub_Sub/advvfdipp/thingsboard/v3/pub/sendData.py index 817bfca..b6d38cc 100644 --- a/Pub_Sub/advvfdipp/thingsboard/v3/pub/sendData.py +++ b/Pub_Sub/advvfdipp/thingsboard/v3/pub/sendData.py @@ -127,7 +127,7 @@ def sendData(message): for measure in message["measures"]: try: logger.debug(measure) - 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 ["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") diff --git a/Pub_Sub/advvfdipp/thingsboard/v4/advvfdipp_tb_v4.cfg b/Pub_Sub/advvfdipp/thingsboard/v4/advvfdipp_tb_v4.cfg new file mode 100644 index 0000000..54b338c --- /dev/null +++ b/Pub_Sub/advvfdipp/thingsboard/v4/advvfdipp_tb_v4.cfg @@ -0,0 +1,1221 @@ +{ + "controllers": [ + { + "protocol": "EtherNet/IP", + "name": "advvfdipp", + "args": {}, + "samplePeriod": 2, + "expired": 10000, + "endpoint": "192.168.1.10:44818" + } + ], + "groups": [ + { + "name": "default", + "uploadInterval": 600, + "reference": 45 + } + ], + "measures": [ + { + "name": "flowrate", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_Flowmeter", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "fluidlevel", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_FluidLevel", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "intakepressure", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_IntakePressure", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "intaketemperature", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_IntakeTemperature", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "tubingpressure", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_TubingPressure", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "wellstatus", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "Device_Status_INT", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "vfdfrequency", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "VFD_SpeedFdbk", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "flowtotal", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Flow_Total[0]", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "energytotal", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Energy_Total[0]", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "vfdcurrent", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "VFD_OutCurrent", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "downholesensorstatus", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "Downhole_Sensor_Status_INT", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "fluidspecificgravity", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "cfg_FluidSpecificGravity", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "flowtotalyesterday", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Flow_Total[1]", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "energytotalyesterday", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Energy_Total[1]", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmflowrate", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_Flowmeter", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmintakepressure", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_IntakePressure", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmintaketemperature", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_IntakeTemperature", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmtubingpressure", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_TubingPressure", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmvfd", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_VFD", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmlockout", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_Lockout", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "runpermissive", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "Run_Permissive_INT", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "startpermissive", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "Start_Permissive_INT", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmfluidlevel", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_FluidLevel", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "pressureshutdownlimit", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "AIn_IntakePressure.Val_LoLim", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "pressurestartuplimit", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "AIn_IntakePressure.Val_HiLim", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "temperatureshutdownlimit", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "AIn_IntakeTemperature.Val_HiLim", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "temperaturestartuplimit", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "AIn_IntakeTemperature.Val_LoLim", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "sensorheight", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "cfg_DHSensorDistToIntake", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "last_vfd_fault_code", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "PowerFlex755.Val_LastFaultCode", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "vfd_fault", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "sts_CurrentVFDFaultCode", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "controllerfault_io", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "ControllerFault_IO", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "controllerfault_program", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "ControllerFault_Program", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "minvfdfrequency", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "PowerFlex755.Cfg_MinSpdRef", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "maxvfdfrequency", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "PowerFlex755.Cfg_MaxSpdRef", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "ctrlName": "advvfdipp", + "dataType": "BIT", + "addr": "cmd_Start", + "readWrite": "rw", + "uploadType": "periodic", + "group": "default", + "name": "startcommand", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "decimal": 2 + }, + { + "ctrlName": "advvfdipp", + "dataType": "BIT", + "addr": "cmd_Stop", + "readWrite": "rw", + "uploadType": "periodic", + "group": "default", + "name": "stopcommand", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "decimal": 2 + }, + { + "ctrlName": "advvfdipp", + "dataType": "INT", + "addr": "sts_PID_Control", + "readWrite": "rw", + "uploadType": "periodic", + "group": "default", + "name": "pidcontrolmode", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "decimal": 2 + }, + { + "ctrlName": "advvfdipp", + "dataType": "FLOAT", + "addr": "cfg_PID_FlowSP", + "readWrite": "rw", + "uploadType": "periodic", + "group": "default", + "decimal": 2, + "name": "flowsetpoint", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "" + }, + { + "ctrlName": "advvfdipp", + "dataType": "FLOAT", + "addr": "cfg_PID_TubingPressureSP", + "readWrite": "rw", + "uploadType": "periodic", + "group": "default", + "decimal": 2, + "name": "tubingpressuresetpoint", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "" + }, + { + "ctrlName": "advvfdipp", + "dataType": "FLOAT", + "addr": "cfg_PID_FluidLevelSP", + "readWrite": "rw", + "uploadType": "periodic", + "group": "default", + "decimal": 2, + "name": "fluidlevelsetpoint", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "" + }, + { + "ctrlName": "advvfdipp", + "dataType": "FLOAT", + "addr": "cfg_PID_ManualSP", + "readWrite": "rw", + "uploadType": "periodic", + "group": "default", + "decimal": 2, + "name": "manualfrequencysetpoint", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "" + }, + { + "ctrlName": "advvfdipp", + "dataType": "BIT", + "addr": "cmd_ResetAlarms", + "readWrite": "rw", + "uploadType": "periodic", + "group": "default", + "name": "resetalarms", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "decimal": 2 + }, + { + "ctrlName": "advvfdipp", + "dataType": "FLOAT", + "addr": "val_Flowmeter_BarrelsPerMinute", + "readWrite": "ro", + "uploadType": "periodic", + "group": "default", + "decimal": 2, + "name": "flowrate_gpm", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "" + }, + { + "ctrlName": "advvfdipp", + "dataType": "BIT", + "addr": "PROMAG_300:I1.Connection_Fault", + "readWrite": "ro", + "uploadType": "periodic", + "group": "default", + "name": "flowmeter_fault", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "decimal": 2 + } + ], + "alarms": [ + { + "name": "alarmflowrate", + "ctrlName": "advvfdipp", + "measureName": "alarmflowrate", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Flow Rate Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmintakepressure", + "ctrlName": "advvfdipp", + "measureName": "alarmintakepressure", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Intake Pressure Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmintaketemperature", + "ctrlName": "advvfdipp", + "measureName": "alarmintaketemperature", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Intake Temperature Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmtubingpressure", + "ctrlName": "advvfdipp", + "measureName": "alarmtubingpressure", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Tubing Pressure Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmvfd", + "ctrlName": "advvfdipp", + "measureName": "alarmvfd", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "VFD Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmlockout", + "ctrlName": "advvfdipp", + "measureName": "alarmlockout", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Lockout Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmfluidlevel", + "ctrlName": "advvfdipp", + "measureName": "alarmfluidlevel", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Fluid Level Alarm triggered", + "alarmLable": "default" + }, + { + "name": "controllerfault_io", + "ctrlName": "advvfdipp", + "measureName": "controllerfault_io", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Controller IO Alarm triggered", + "alarmLable": "default" + }, + { + "name": "controllerfault_program", + "ctrlName": "advvfdipp", + "measureName": "controllerfault_program", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Controller Fault Alarm triggered", + "alarmLable": "default" + }, + { + "name": "flowmeter_fault", + "ctrlName": "advvfdipp", + "measureName": "flowmeter_fault", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Flow Meter Alarm triggered", + "alarmLable": "default" + } + ], + "misc": { + "maxAlarmRecordSz": 2000, + "logLvl": "INFO", + "coms": [ + { + "name": "rs232", + "baud": 9600, + "bits": 8, + "stopbits": 1, + "parityChk": "n" + }, + { + "name": "rs485", + "baud": 19200, + "bits": 8, + "stopbits": 1, + "parityChk": "n" + } + ] + }, + "clouds": [ + { + "cacheSize": 100, + "enable": 1, + "type": "Standard MQTT", + "args": { + "host": "hp.henrypump.cloud", + "port": 1883, + "clientId": "unknown", + "auth": 1, + "tls": 0, + "cleanSession": 1, + "mqttVersion": "v3.1.1", + "keepalive": 120, + "key": "", + "cert": "", + "rootCA": "", + "verifyServer": 0, + "verifyClient": 0, + "username": "unknown", + "passwd": "unknown", + "authType": 1 + }, + "name": "default" + } + ], + "labels": [ + { + "key": "SN", + "value": "GF5022210011339" + }, + { + "key": "MAC", + "value": "00:18:05:1e:95:0f" + } + ], + "quickfaas": { + "genericFuncs": [], + "uploadFuncs": [ + { + "name": "Send Data", + "trigger": "measure_event", + "topic": "v1/devices/me/telemetry", + "qos": 1, + "groups": [ + "default" + ], + "funcName": "sendData", + "script": "# Enter your python code.\nimport json, os\nfrom datetime import datetime as dt\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom quickfaas.global_dict import get as get_params\nfrom quickfaas.global_dict import _set_global_args\n\ndef reboot(reason=\"Rebooting for config file update\"):\n #basic = Basic()\n logger.info(\"!\" * 10 + \"REBOOTING DEVICE\" + \"!\"*10)\n logger.info(reason)\n r = os.popen(\"kill -s SIGHUP `cat /var/run/python/supervisord.pid`\").read()\n logger.info(f\"REBOOT : {r}\")\n\ndef checkFileExist(filename):\n path = \"/var/user/files\"\n if not os.path.exists(path):\n logger.debug(\"no folder making files folder in var/user\")\n os.makedirs(path)\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n if not os.path.exists(path + \"/\" + filename):\n logger.debug(\"no creds file making creds file\")\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n\ndef convertDStoJSON(ds):\n j = dict()\n for x in ds:\n j[x[\"key\"]] = x[\"value\"]\n return j\n\ndef convertJSONtoDS(j):\n d = []\n for key in j.keys():\n d.append({\"key\": key, \"value\": j[key]})\n return d\n\ndef checkCredentialConfig():\n logger.debug(\"CHECKING CONFIG\")\n cfgpath = \"/var/user/cfg/device_supervisor/device_supervisor.cfg\"\n credspath = \"/var/user/files/creds.json\"\n cfg = dict()\n with open(cfgpath, \"r\") as f:\n cfg = json.load(f)\n clouds = cfg.get(\"clouds\")\n logger.debug(clouds)\n #if not configured then try to configure from stored values\n if clouds[0][\"args\"][\"clientId\"] == \"unknown\" or clouds[0][\"args\"][\"username\"] == \"unknown\" or not clouds[0][\"args\"][\"passwd\"] or clouds[0][\"args\"][\"passwd\"] == \"unknown\":\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n creds = json.load(c)\n if creds:\n logger.debug(\"updating config with stored data\")\n clouds[0][\"args\"][\"clientId\"] = creds[\"clientId\"]\n clouds[0][\"args\"][\"username\"] = creds[\"userName\"]\n clouds[0][\"args\"][\"passwd\"] = creds[\"password\"]\n cfg[\"clouds\"] = clouds\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n reboot()\n else:\n #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\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n logger.debug(\"updating stored file with new data\")\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n creds = json.load(c)\n if creds:\n if creds[\"clientId\"] != clouds[0][\"args\"][\"clientId\"]:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n if creds[\"userName\"] != clouds[0][\"args\"][\"username\"]:\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n if creds[\"password\"] != clouds[0][\"args\"][\"passwd\"]:\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n else:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n with open(credspath, \"w\") as cw:\n json.dump(creds,cw)\n\ndef checkParameterConfig(cfg):\n logger.debug(\"Checking Parameters!!!!\")\n paramspath = \"/var/user/files/params.json\"\n cfgparams = convertDStoJSON(cfg.get(\"labels\"))\n #check stored values \n checkFileExist(\"params.json\")\n with open(paramspath, \"r\") as f:\n logger.debug(\"Opened param storage file\")\n params = json.load(f)\n if params:\n if cfgparams != params:\n #go through each param\n #if not \"unknown\" and cfg and params aren't the same take from cfg likely updated manually\n #if key in cfg but not in params copy to params\n logger.debug(\"equalizing params between cfg and stored\")\n for key in cfgparams.keys():\n try:\n if cfgparams[key] != params[key] and cfgparams[key] != \"unknown\":\n params[key] = cfgparams[key]\n except:\n params[key] = cfgparams[key]\n cfg[\"labels\"] = convertJSONtoDS(params)\n _set_global_args(convertJSONtoDS(params))\n with open(paramspath, \"w\") as p:\n json.dump(params, p)\n else:\n with open(paramspath, \"w\") as p:\n logger.debug(\"initializing param file with params in memory\")\n json.dump(convertDStoJSON(get_params()), p)\n cfg[\"labels\"] = get_params()\n \n return cfg\n\ndef sendData(message):\n #logger.debug(message)\n try:\n checkCredentialConfig()\n except Exception as e:\n logger.error(e)\n payload = {\"ts\": (round(dt.timestamp(dt.now())/600)*600)*1000, \"values\": {}}\n for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n if abs(payload[\"ts\"]/1000 - measure[\"timestamp\"]) > 3600:\n reboot(reason=\"Poll timestamp and actual timestamp out of sync. Actual: {} Poll: {}\".format(payload[\"ts\"]/1000,measure[\"timestamp\"]))\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\", \"flowmeter_fault\"]:\n logger.debug(\"Converting DINT/BOOL to STRING\")\n value = convert_int(measure[\"name\"], measure[\"value\"])\n logger.debug(\"Converted {} to {}\".format(measure[\"value\"], value))\n payload[\"values\"][measure[\"name\"]] = value\n payload[\"values\"][measure[\"name\"] + \"_int\"] = measure[\"value\"]\n else:\n payload[\"values\"][measure[\"name\"]] = measure[\"value\"] \n except Exception as e:\n logger.error(e)\n \n publish(__topic__, json.dumps(payload), __qos__)\n publish(\"v1/devices/me/attributes\", json.dumps({\"latestReportTime\": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__)\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"flowmeter_fault\": alarm_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n\n ", + "msgType": 0, + "cloudName": "default" + }, + { + "name": "sendAlarm", + "trigger": "warning_event", + "topic": "v1/devices/me/telemetry", + "qos": 1, + "funcName": "sendAlarm", + "script": "# Enter your python code.\nimport json, time\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom quickfaas.measure import recall\n\n\ndef sendAlarm(message):\n logger.info(message)\n payload = {}\n payload[\"ts\"] = time.time()*1000\n payload[\"values\"] = {message[\"measureName\"]: message[\"value\"]}\n publish(__topic__, json.dumps(payload), __qos__)\n sync()\n\ndef sync():\n #get new values and send\n payload = {\"ts\": time.time()*1000, \"values\": {}}\n try:\n data = recall()#json.loads(recall().decode(\"utf-8\"))\n except Exception as e:\n logger.error(e)\n logger.debug(data)\n for controller in data:\n for measure in controller[\"measures\"]:\n #publish measure\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\", \"flowmeter_fault\"]:\n payload[\"values\"][measure[\"name\"]] = convert_int(measure[\"name\"], measure[\"value\"])\n payload[\"values\"][measure[\"name\"]+ \"_int\"] = measure[\"value\"]\n else:\n payload[\"values\"][measure[\"name\"]] = measure[\"value\"]\n logger.debug(\"Sending on topic: {}\".format(__topic__))\n logger.debug(\"Sending value: {}\".format(payload))\n publish(__topic__, json.dumps(payload), 1)\n\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"flowmeter_fault\": alarm_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n", + "alarms": [ + "default" + ], + "msgType": 0, + "cloudName": "default" + } + ], + "downloadFuncs": [ + { + "name": "Commands", + "topic": "v1/devices/me/rpc/request/+", + "qos": 1, + "funcName": "receiveCommand", + "payload_type": "JSON", + "script": "import json, time\nfrom quickfaas.measure import recall, write\nfrom quickfaas.remotebus import publish\nfrom common.Logger import logger\n\ndef sync():\n #get new values and send\n payload = {}\n topic = \"v1/devices/me/telemetry\"\n try:\n data = recall()#json.loads(recall().decode(\"utf-8\"))\n except Exception as e:\n logger.error(e)\n logger.debug(data)\n for controller in data:\n for measure in controller[\"measures\"]:\n #publish measure\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\", \"flowmeter_fault\"]:\n payload[measure[\"name\"]] = convert_int(measure[\"name\"], measure[\"value\"])\n payload[measure[\"name\"]+ \"_int\"] = measure[\"value\"]\n else:\n payload[measure[\"name\"]] = measure[\"value\"]\n logger.debug(\"Sending on topic: {}\".format(topic))\n logger.debug(\"Sending value: {}\".format(payload))\n publish(topic, json.dumps(payload), 1)\ndef writeplctag(value):\n #value in the form {\"measurement\": , \"value\": }\n try:\n #value = json.loads(value.replace(\"'\",'\"'))\n logger.debug(value)\n #payload format: [{\"name\": \"advvfdipp\", \"measures\": [{\"name\": \"manualfrequencysetpoint\", \"value\": 49}]}]\n message = [{\"name\": \"advvfdipp\", \"measures\":[{\"name\":value[\"measurement\"], \"value\": value[\"value\"]}]}]\n resp = write(message) \n logger.debug(\"RETURN FROM WRITE: {}\".format(resp))\n return True\n except Exception as e:\n logger.debug(e)\n return False\n \ndef receiveCommand(topic, payload):\n try:\n logger.debug(topic)\n logger.debug(json.loads(payload))\n p = json.loads(payload)\n command = p[\"method\"]\n commands = {\n \"sync\": sync,\n \"writeplctag\": writeplctag,\n } \n if command == \"setPLCTag\":\n try:\n result = commands[\"writeplctag\"](p[\"params\"])\n logger.debug(result)\n except Exception as e:\n logger.error(e)\n elif command == \"changeSetpoint\":\n try:\n logger.debug(\"attempting controlpoint write\")\n params_type = {\"measurement\": \"pidcontrolmode\", \"value\": p[\"params\"][\"setpointType\"]}\n if params_type[\"value\"]:\n commands[\"writeplctag\"](params_type)\n time.sleep(2)\n except Exception as e:\n logger.error(\"DID NOT WRITE CONTROL MODE\")\n logger.error(e)\n try:\n logger.debug(\"attempting setpoint write\")\n modes = {0: \"flowsetpoint\", 1: \"fluidlevelsetpoint\", 2: \"tubingpressuresetpoint\", 3: \"manualfrequencysetpoint\"}\n params_value = {\"value\": p[\"params\"][\"setpointValue\"]}\n if params_value[\"value\"]:\n params_value[\"measurement\"] = modes[getMode()]\n result = commands[\"writeplctag\"](params_value)\n logger.debug(result)\n except Exception as e:\n logger.error(\"DID NOT WRITE SETPOINT\")\n logger.error(e)\n #logger.debug(command)\n ack(topic.split(\"/\")[-1])\n time.sleep(5)\n sync()\n except Exception as e:\n logger.debug(e)\n \n\ndef ack(msgid):\n #logger.debug(msgid)\n #logger.debug(mac)\n #logger.debug(name)\n #logger.debug(value)\n publish(\"v1/devices/me/rpc/response/\" + str(msgid), json.dumps({\"msg\": {\"time\": time.time()}, \"metadata\": \"\", \"msgType\": \"\"}), 1)\n\ndef getMode():\n try:\n data = recall()\n for controller in data:\n for measure in controller[\"measures\"]:\n if measure[\"name\"] == \"pidcontrolmode\":\n return measure[\"value\"]\n except:\n return None\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"flowmeter_fault\": alarm_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n", + "msgType": 0, + "trigger": "command_event", + "cloudName": "default" + } + ] + }, + "modbusSlave": { + "enable": 0, + "protocol": "Modbus-TCP", + "port": 502, + "slaveAddr": 1, + "int16Ord": "ab", + "int32Ord": "abcd", + "float32Ord": "abcd", + "maxConnection": 5, + "mapping_table": [] + }, + "iec104Server": { + "enable": 0, + "cotSize": 2, + "port": 2404, + "serverList": [ + { + "asduAddr": 1 + } + ], + "kValue": 12, + "wValue": 8, + "t0": 15, + "t1": 15, + "t2": 10, + "t3": 20, + "maximumLink": 5, + "timeSet": 1, + "byteOrder": "abcd", + "mapping_table": [] + }, + "opcuaServer": { + "enable": 0, + "port": 4840, + "maximumLink": 5, + "securityMode": 0, + "identifierType": "String", + "mapping_table": [] + }, + "bindConfig": { + "enable": 0, + "bind": { + "modelId": "", + "modelName": "", + "srcId": "", + "srcName": "", + "devId": "", + "devName": "" + }, + "varGroups": [], + "variables": [], + "alerts": [] + }, + "southMetadata": {}, + "bindMetadata": { + "version": "", + "timestamp": "" + } +} \ No newline at end of file diff --git a/Pub_Sub/advvfdipp/thingsboard/v4/pub/sendAlarms.py b/Pub_Sub/advvfdipp/thingsboard/v4/pub/sendAlarms.py new file mode 100644 index 0000000..c5039e9 --- /dev/null +++ b/Pub_Sub/advvfdipp/thingsboard/v4/pub/sendAlarms.py @@ -0,0 +1,201 @@ +# Enter your python code. +import json, time +from common.Logger import logger +from quickfaas.remotebus import publish +from quickfaas.measure import recall + + +def sendAlarm(message): + logger.info(message) + payload = {} + payload["ts"] = time.time()*1000 + payload["values"] = {message["measureName"]: message["value"]} + publish(__topic__, json.dumps(payload), __qos__) + sync() + +def sync(): + #get new values and send + payload = {"ts": time.time()*1000, "values": {}} + 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["values"][measure["name"]] = convert_int(measure["name"], measure["value"]) + payload["values"][measure["name"]+ "_int"] = measure["value"] + else: + payload["values"][measure["name"]] = measure["value"] + logger.debug("Sending on topic: {}".format(__topic__)) + logger.debug("Sending value: {}".format(payload)) + publish(__topic__, json.dumps(payload), 1) + + +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") diff --git a/Pub_Sub/advvfdipp/thingsboard/v4/pub/sendData.py b/Pub_Sub/advvfdipp/thingsboard/v4/pub/sendData.py new file mode 100644 index 0000000..b1d19d5 --- /dev/null +++ b/Pub_Sub/advvfdipp/thingsboard/v4/pub/sendData.py @@ -0,0 +1,312 @@ +# 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.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.debug("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.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.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.debug("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.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) + 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.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.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.debug("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.debug("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") + + \ No newline at end of file diff --git a/Pub_Sub/advvfdipp/thingsboard/v4/sub/receiveCommand.py b/Pub_Sub/advvfdipp/thingsboard/v4/sub/receiveCommand.py new file mode 100644 index 0000000..5610b34 --- /dev/null +++ b/Pub_Sub/advvfdipp/thingsboard/v4/sub/receiveCommand.py @@ -0,0 +1,266 @@ +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") diff --git a/Pub_Sub/advvfdipp_sru/thingsboard/v1/advvfdipp_tb_v1.cfg b/Pub_Sub/advvfdipp_sru/thingsboard/v1/advvfdipp_sru_tb_v1.cfg similarity index 93% rename from Pub_Sub/advvfdipp_sru/thingsboard/v1/advvfdipp_tb_v1.cfg rename to Pub_Sub/advvfdipp_sru/thingsboard/v1/advvfdipp_sru_tb_v1.cfg index 807e012..fe27780 100644 --- a/Pub_Sub/advvfdipp_sru/thingsboard/v1/advvfdipp_tb_v1.cfg +++ b/Pub_Sub/advvfdipp_sru/thingsboard/v1/advvfdipp_sru_tb_v1.cfg @@ -1614,7 +1614,176 @@ "addr": "30017" } ], - "alarms": [], + "alarms": [{ + "name": "alarmflowrate", + "ctrlName": "advvfdipp", + "measureName": "alarmflowrate", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Flow Rate Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmintakepressure", + "ctrlName": "advvfdipp", + "measureName": "alarmintakepressure", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Intake Pressure Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmintaketemperature", + "ctrlName": "advvfdipp", + "measureName": "alarmintaketemperature", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Intake Temperature Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmtubingpressure", + "ctrlName": "advvfdipp", + "measureName": "alarmtubingpressure", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Tubing Pressure Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmvfd", + "ctrlName": "advvfdipp", + "measureName": "alarmvfd", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "VFD Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmlockout", + "ctrlName": "advvfdipp", + "measureName": "alarmlockout", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Lockout Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmfluidlevel", + "ctrlName": "advvfdipp", + "measureName": "alarmfluidlevel", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Fluid Level Alarm triggered", + "alarmLable": "default" + }, + { + "name": "controllerfault_io", + "ctrlName": "advvfdipp", + "measureName": "controllerfault_io", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Controller IO Alarm triggered", + "alarmLable": "default" + }, + { + "name": "controllerfault_program", + "ctrlName": "advvfdipp", + "measureName": "controllerfault_program", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Controller Fault Alarm triggered", + "alarmLable": "default" + }, + { + "name": "flowmeter_fault", + "ctrlName": "advvfdipp", + "measureName": "flowmeter_fault", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Flow Meter Alarm triggered", + "alarmLable": "default" + }], "misc": { "maxAlarmRecordSz": 2000, "logLvl": "INFO", @@ -1699,6 +1868,19 @@ "script": "# Enter your python code.\nimport json, time\nfrom quickfaas.measure import recall, write\nfrom quickfaas.remotebus import publish\nfrom common.Logger import logger\n\n\ndef writeplctag(value):\n #value in the form {\"measurement\": , \"value\": }\n try:\n #value = json.loads(value.replace(\"'\",'\"'))\n logger.info(value)\n #payload format: [{\"name\": \"advvfdipp\", \"measures\": [{\"name\": \"manualfrequencysetpoint\", \"value\": 49}]}]\n message = [{\"name\": \"advvfdipp\", \"measures\":[{\"name\":value[\"measurement\"], \"value\": value[\"value\"]}]}]\n resp = write(message) \n logger.info(\"RETURN FROM WRITE: {}\".format(resp))\n return True\n except Exception as e:\n logger.info(e)\n return False\n\ndef sendToPLC(message):\n logger.info(message)\n for measure in message[\"measures\"]:\n logger.info(measure)\n #{'ctrlName': 'modbus_converter', 'name': 'SRU_Data[1]', 'health': 1, 'timestamp': 1664894200, 'value': 47}\n writeplctag({\"measurement\": measure[\"name\"], \"value\": measure[\"value\"]})\n #time.sleep(2)\n ", "msgType": 0, "cloudName": "default" + }, + { + "name": "sendAlarm", + "trigger": "warning_event", + "topic": "v1/devices/me/telemetry", + "qos": 1, + "funcName": "sendAlarm", + "script": "# Enter your python code.\nimport json, time\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\n\n\ndef sendAlarm(message):\n logger.info(message)\n payload = {}\n payload[\"ts\"] = time.time()*1000\n payload[\"values\"] = {message[\"measureName\"]: message[\"value\"]}\n publish(__topic__, json.dumps(payload), __qos__)", + "alarms": [ + "default" + ], + "msgType": 0, + "cloudName": "default" } ], "downloadFuncs": [ diff --git a/Pub_Sub/advvfdipp_sru/thingsboard/v1/pub/sendToPLC.py b/Pub_Sub/advvfdipp_sru/thingsboard/v1/pub/sendToPLC.py index 300736d..afdc889 100644 --- a/Pub_Sub/advvfdipp_sru/thingsboard/v1/pub/sendToPLC.py +++ b/Pub_Sub/advvfdipp_sru/thingsboard/v1/pub/sendToPLC.py @@ -9,20 +9,20 @@ def writeplctag(value): #value in the form {"measurement": , "value": } try: #value = json.loads(value.replace("'",'"')) - logger.info(value) + 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.info("RETURN FROM WRITE: {}".format(resp)) + logger.debug("RETURN FROM WRITE: {}".format(resp)) return True except Exception as e: - logger.info(e) + logger.error(e) return False def sendToPLC(message): - logger.info(message) + logger.debug(message) for measure in message["measures"]: - logger.info(measure) + 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) diff --git a/Pub_Sub/advvfdipp_sru/thingsboard/v2/advvfdipp_sru_tb_v2.cfg b/Pub_Sub/advvfdipp_sru/thingsboard/v2/advvfdipp_sru_tb_v2.cfg new file mode 100644 index 0000000..42623d3 --- /dev/null +++ b/Pub_Sub/advvfdipp_sru/thingsboard/v2/advvfdipp_sru_tb_v2.cfg @@ -0,0 +1,1960 @@ +{ + "controllers": [ + { + "protocol": "EtherNet/IP", + "name": "advvfdipp", + "args": {}, + "samplePeriod": 2, + "expired": 10000, + "endpoint": "192.168.1.10:44818" + }, + { + "protocol": "Modbus-RTU", + "name": "SRU", + "args": { + "slaveAddr": 234, + "int16Ord": "ab", + "int32Ord": "abcd", + "float32Ord": "abcd", + "continuousAcquisition": 1, + "maxContinuousNumber": 64 + }, + "endpoint": "rs485", + "samplePeriod": 10, + "expired": 10000 + } + ], + "groups": [ + { + "name": "default", + "uploadInterval": 600, + "reference": 45 + }, + { + "name": "converter", + "uploadInterval": 10 + }, + { + "name": "null", + "uploadInterval": 3600 + } + ], + "measures": [ + { + "name": "SRU_Data[0]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30001", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30001", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[1]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30002", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30002", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[2]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30003", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30003", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[3]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30004", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30004", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[4]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30005", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30005", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[5]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30006", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30006", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[6]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30007", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30007", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[7]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30008", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30008", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[8]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30009", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30009", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[9]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30010", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30010", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[10]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30011", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30011", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[11]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30012", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30012", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[12]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30013", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30013", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[13]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30014", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30014", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[14]", + "ctrlName": "SRU", + "group": "converter", + "uploadType": "periodic", + "dataType": "INT", + "addr": "30015", + "decimal": "", + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "regAddr": "30015", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "flowrate", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_Flowmeter", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "fluidlevel", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_FluidLevel", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "intakepressure", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_IntakePressure", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "intaketemperature", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_IntakeTemperature", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "tubingpressure", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_TubingPressure", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "wellstatus", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "Device_Status_INT", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "vfdfrequency", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "VFD_SpeedFdbk", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "flowtotal", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Flow_Total[0]", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "energytotal", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Energy_Total[0]", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "vfdcurrent", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "VFD_OutCurrent", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "downholesensorstatus", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "Downhole_Sensor_Status_INT", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "fluidspecificgravity", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "cfg_FluidSpecificGravity", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "flowtotalyesterday", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Flow_Total[1]", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "energytotalyesterday", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Energy_Total[1]", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmflowrate", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_Flowmeter", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmintakepressure", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_IntakePressure", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmintaketemperature", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_IntakeTemperature", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmtubingpressure", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_TubingPressure", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmvfd", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_VFD", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmlockout", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_Lockout", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "runpermissive", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "Run_Permissive_INT", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "startpermissive", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "Start_Permissive_INT", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "alarmfluidlevel", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "alarm_FluidLevel", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "pressureshutdownlimit", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "AIn_IntakePressure.Val_LoLim", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "pressurestartuplimit", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "AIn_IntakePressure.Val_HiLim", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "temperatureshutdownlimit", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "AIn_IntakeTemperature.Val_HiLim", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "temperaturestartuplimit", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "AIn_IntakeTemperature.Val_LoLim", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "sensorheight", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "cfg_DHSensorDistToIntake", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "last_vfd_fault_code", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "PowerFlex755.Val_LastFaultCode", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "vfd_fault", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "INT", + "addr": "sts_CurrentVFDFaultCode", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "controllerfault_io", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "ControllerFault_IO", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "controllerfault_program", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "ControllerFault_Program", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "minvfdfrequency", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "PowerFlex755.Cfg_MinSpdRef", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "maxvfdfrequency", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "PowerFlex755.Cfg_MaxSpdRef", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "startcommand", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "cmd_Start", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "stopcommand", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "cmd_Stop", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "pidcontrolmode", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "DINT", + "addr": "sts_PID_Control", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "flowsetpoint", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "cfg_PID_FlowSP", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "tubingpressuresetpoint", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "cfg_PID_TubingPressureSP", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "fluidlevelsetpoint", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "cfg_PID_FluidLevelSP", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "manualfrequencysetpoint", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "cfg_PID_ManualSP", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "resetalarms", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "cmd_ResetAlarms", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "flowrate_gpm", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "val_Flowmeter_BarrelsPerMinute", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "flowmeter_fault", + "ctrlName": "advvfdipp", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "PROMAG_300:I1.Connection_Fault", + "decimal": 2, + "len": 1, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[0]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[0]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[1]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[1]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[2]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[2]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[3]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[3]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[4]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[4]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[5]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[5]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[6]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[6]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[7]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[7]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[8]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[8]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[9]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[9]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[10]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[10]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[11]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[11]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[12]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[12]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[13]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[13]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[14]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[14]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[15]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[15]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "name": "SRU_Data[16]", + "ctrlName": "advvfdipp", + "group": "null", + "uploadType": "periodic", + "dataType": "INT", + "addr": "SRU_Data[16]", + "decimal": 2, + "len": 1, + "readWrite": "rw", + "unit": "", + "desc": "", + "transformType": 0, + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "gain": "", + "offset": "" + }, + { + "ctrlName": "SRU", + "dataType": "INT", + "readWrite": "ro", + "uploadType": "periodic", + "group": "converter", + "name": "SRU_Data[15]", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "regAddr": "30016", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "addr": "30016" + }, + { + "ctrlName": "SRU", + "dataType": "INT", + "readWrite": "ro", + "uploadType": "periodic", + "group": "converter", + "name": "SRU_Data[16]", + "desc": "", + "unit": "", + "transformType": 0, + "gain": "1.0", + "offset": "0.0", + "regAddr": "30017", + "maxValue": "", + "minValue": "", + "maxScaleValue": "", + "minScaleValue": "", + "addr": "30017" + } + ], + "alarms": [ + { + "name": "alarmflowrate", + "ctrlName": "advvfdipp", + "measureName": "alarmflowrate", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Flow Rate Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmintakepressure", + "ctrlName": "advvfdipp", + "measureName": "alarmintakepressure", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Intake Pressure Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmintaketemperature", + "ctrlName": "advvfdipp", + "measureName": "alarmintaketemperature", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Intake Temperature Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmtubingpressure", + "ctrlName": "advvfdipp", + "measureName": "alarmtubingpressure", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Tubing Pressure Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmvfd", + "ctrlName": "advvfdipp", + "measureName": "alarmvfd", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "VFD Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmlockout", + "ctrlName": "advvfdipp", + "measureName": "alarmlockout", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Lockout Alarm triggered", + "alarmLable": "default" + }, + { + "name": "alarmfluidlevel", + "ctrlName": "advvfdipp", + "measureName": "alarmfluidlevel", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Fluid Level Alarm triggered", + "alarmLable": "default" + }, + { + "name": "controllerfault_io", + "ctrlName": "advvfdipp", + "measureName": "controllerfault_io", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Controller IO Alarm triggered", + "alarmLable": "default" + }, + { + "name": "controllerfault_program", + "ctrlName": "advvfdipp", + "measureName": "controllerfault_program", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Controller Fault Alarm triggered", + "alarmLable": "default" + }, + { + "name": "flowmeter_fault", + "ctrlName": "advvfdipp", + "measureName": "flowmeter_fault", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Flow Meter Alarm triggered", + "alarmLable": "default" + } + ], + "misc": { + "maxAlarmRecordSz": 2000, + "logLvl": "INFO", + "coms": [ + { + "name": "rs232", + "baud": 9600, + "bits": 8, + "stopbits": 1, + "parityChk": "n" + }, + { + "name": "rs485", + "baud": 38400, + "bits": 8, + "stopbits": 1, + "parityChk": "n" + } + ] + }, + "clouds": [ + { + "cacheSize": 100, + "enable": 1, + "type": "Standard MQTT", + "args": { + "host": "hp.henrypump.cloud", + "port": 1883, + "clientId": "unknown", + "auth": 1, + "tls": 0, + "cleanSession": 1, + "mqttVersion": "v3.1.1", + "keepalive": 120, + "key": "", + "cert": "", + "rootCA": "", + "verifyServer": 0, + "verifyClient": 0, + "username": "unknown", + "passwd": "unknown", + "authType": 1 + }, + "name": "default" + } + ], + "labels": [ + { + "key": "SN", + "value": "GF5022215013085" + }, + { + "key": "MAC", + "value": "00:18:05:1f:8d:43" + } + ], + "quickfaas": { + "genericFuncs": [], + "uploadFuncs": [ + { + "name": "Send Data", + "trigger": "measure_event", + "topic": "v1/devices/me/telemetry", + "qos": 1, + "groups": [ + "default" + ], + "funcName": "sendData", + "script": "# Enter your python code.\nimport json, os\nfrom datetime import datetime as dt\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom quickfaas.global_dict import get as get_params\nfrom quickfaas.global_dict import _set_global_args\n\ndef reboot(reason=\"Rebooting for config file update\"):\n #basic = Basic()\n logger.info(\"!\" * 10 + \"REBOOTING DEVICE\" + \"!\"*10)\n logger.info(reason)\n r = os.popen(\"kill -s SIGHUP `cat /var/run/python/supervisord.pid`\").read()\n logger.info(f\"REBOOT : {r}\")\n\ndef checkFileExist(filename):\n path = \"/var/user/files\"\n if not os.path.exists(path):\n logger.debug(\"no folder making files folder in var/user\")\n os.makedirs(path)\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n if not os.path.exists(path + \"/\" + filename):\n logger.debug(\"no creds file making creds file\")\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n\ndef convertDStoJSON(ds):\n j = dict()\n for x in ds:\n j[x[\"key\"]] = x[\"value\"]\n return j\n\ndef convertJSONtoDS(j):\n d = []\n for key in j.keys():\n d.append({\"key\": key, \"value\": j[key]})\n return d\n\ndef checkCredentialConfig():\n logger.debug(\"CHECKING CONFIG\")\n cfgpath = \"/var/user/cfg/device_supervisor/device_supervisor.cfg\"\n credspath = \"/var/user/files/creds.json\"\n cfg = dict()\n with open(cfgpath, \"r\") as f:\n cfg = json.load(f)\n clouds = cfg.get(\"clouds\")\n logger.debug(clouds)\n #if not configured then try to configure from stored values\n if clouds[0][\"args\"][\"clientId\"] == \"unknown\" or clouds[0][\"args\"][\"username\"] == \"unknown\" or not clouds[0][\"args\"][\"passwd\"] or clouds[0][\"args\"][\"passwd\"] == \"unknown\":\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n creds = json.load(c)\n if creds:\n logger.debug(\"updating config with stored data\")\n clouds[0][\"args\"][\"clientId\"] = creds[\"clientId\"]\n clouds[0][\"args\"][\"username\"] = creds[\"userName\"]\n clouds[0][\"args\"][\"passwd\"] = creds[\"password\"]\n cfg[\"clouds\"] = clouds\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n reboot()\n else:\n #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\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n logger.debug(\"updating stored file with new data\")\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n creds = json.load(c)\n if creds:\n if creds[\"clientId\"] != clouds[0][\"args\"][\"clientId\"]:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n if creds[\"userName\"] != clouds[0][\"args\"][\"username\"]:\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n if creds[\"password\"] != clouds[0][\"args\"][\"passwd\"]:\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n else:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n with open(credspath, \"w\") as cw:\n json.dump(creds,cw)\n\ndef checkParameterConfig(cfg):\n logger.debug(\"Checking Parameters!!!!\")\n paramspath = \"/var/user/files/params.json\"\n cfgparams = convertDStoJSON(cfg.get(\"labels\"))\n #check stored values \n checkFileExist(\"params.json\")\n with open(paramspath, \"r\") as f:\n logger.debug(\"Opened param storage file\")\n params = json.load(f)\n if params:\n if cfgparams != params:\n #go through each param\n #if not \"unknown\" and cfg and params aren't the same take from cfg likely updated manually\n #if key in cfg but not in params copy to params\n logger.debug(\"equalizing params between cfg and stored\")\n for key in cfgparams.keys():\n try:\n if cfgparams[key] != params[key] and cfgparams[key] != \"unknown\":\n params[key] = cfgparams[key]\n except:\n params[key] = cfgparams[key]\n cfg[\"labels\"] = convertJSONtoDS(params)\n _set_global_args(convertJSONtoDS(params))\n with open(paramspath, \"w\") as p:\n json.dump(params, p)\n else:\n with open(paramspath, \"w\") as p:\n logger.debug(\"initializing param file with params in memory\")\n json.dump(convertDStoJSON(get_params()), p)\n cfg[\"labels\"] = get_params()\n \n return cfg\n\ndef sendData(message):\n #logger.debug(message)\n try:\n checkCredentialConfig()\n except Exception as e:\n logger.error(e)\n payload = {\"ts\": (round(dt.timestamp(dt.now())/600)*600)*1000, \"values\": {}}\n for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n if abs(payload[\"ts\"]/1000 - measure[\"timestamp\"]) > 3600:\n reboot(reason=\"Poll timestamp and actual timestamp out of sync. Actual: {} Poll: {}\".format(payload[\"ts\"]/1000,measure[\"timestamp\"]))\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\", \"flowmeter_fault\"]:\n logger.debug(\"Converting DINT/BOOL to STRING\")\n value = convert_int(measure[\"name\"], measure[\"value\"])\n logger.debug(\"Converted {} to {}\".format(measure[\"value\"], value))\n payload[\"values\"][measure[\"name\"]] = value\n payload[\"values\"][measure[\"name\"] + \"_int\"] = measure[\"value\"]\n else:\n payload[\"values\"][measure[\"name\"]] = measure[\"value\"] \n except Exception as e:\n logger.error(e)\n \n publish(__topic__, json.dumps(payload), __qos__)\n publish(\"v1/devices/me/attributes\", json.dumps({\"latestReportTime\": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__)\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"flowmeter_fault\": alarm_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n\n ", + "msgType": 0, + "cloudName": "default" + }, + { + "name": "sendToPLC", + "trigger": "measure_event", + "topic": "v1", + "qos": 1, + "groups": [ + "converter" + ], + "funcName": "sendToPLC", + "script": "# Enter your python code.\nimport json, time\nfrom quickfaas.measure import recall, write\nfrom quickfaas.remotebus import publish\nfrom common.Logger import logger\n\n\ndef writeplctag(value):\n #value in the form {\"measurement\": , \"value\": }\n try:\n #value = json.loads(value.replace(\"'\",'\"'))\n logger.debug(value)\n #payload format: [{\"name\": \"advvfdipp\", \"measures\": [{\"name\": \"manualfrequencysetpoint\", \"value\": 49}]}]\n message = [{\"name\": \"advvfdipp\", \"measures\":[{\"name\":value[\"measurement\"], \"value\": value[\"value\"]}]}]\n resp = write(message) \n logger.debug(\"RETURN FROM WRITE: {}\".format(resp))\n return True\n except Exception as e:\n logger.error(e)\n return False\n\ndef sendToPLC(message):\n logger.debug(message)\n for measure in message[\"measures\"]:\n logger.debug(measure)\n #{'ctrlName': 'modbus_converter', 'name': 'SRU_Data[1]', 'health': 1, 'timestamp': 1664894200, 'value': 47}\n writeplctag({\"measurement\": measure[\"name\"], \"value\": measure[\"value\"]})\n #time.sleep(2)\n ", + "msgType": 0, + "cloudName": "default" + }, + { + "name": "sendAlarm", + "trigger": "warning_event", + "topic": "v1/devices/me/telemetry", + "qos": 1, + "funcName": "sendAlarm", + "script": "# Enter your python code.\nimport json, time\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom quickfaas.measure import recall\n\n\ndef sendAlarm(message):\n logger.info(message)\n payload = {}\n payload[\"ts\"] = time.time()*1000\n payload[\"values\"] = {message[\"measureName\"]: message[\"value\"]}\n publish(__topic__, json.dumps(payload), __qos__)\n sync()\n\ndef sync():\n #get new values and send\n payload = {\"ts\": time.time()*1000, \"values\": {}}\n try:\n data = recall()#json.loads(recall().decode(\"utf-8\"))\n except Exception as e:\n logger.error(e)\n logger.debug(data)\n for controller in data:\n for measure in controller[\"measures\"]:\n #publish measure\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\", \"flowmeter_fault\"]:\n payload[\"values\"][measure[\"name\"]] = convert_int(measure[\"name\"], measure[\"value\"])\n payload[\"values\"][measure[\"name\"]+ \"_int\"] = measure[\"value\"]\n else:\n payload[\"values\"][measure[\"name\"]] = measure[\"value\"]\n logger.debug(\"Sending on topic: {}\".format(__topic__))\n logger.debug(\"Sending value: {}\".format(payload))\n publish(__topic__, json.dumps(payload), 1)\n\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"flowmeter_fault\": alarm_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n", + "alarms": [ + "default" + ], + "msgType": 0, + "cloudName": "default" + } + ], + "downloadFuncs": [ + { + "name": "Commands", + "topic": "v1/devices/me/rpc/request/+", + "qos": 1, + "funcName": "receiveCommand", + "payload_type": "JSON", + "script": "import json, time\nfrom quickfaas.measure import recall, write\nfrom quickfaas.remotebus import publish\nfrom common.Logger import logger\n\ndef sync():\n #get new values and send\n payload = {}\n topic = \"v1/devices/me/telemetry\"\n try:\n data = recall()#json.loads(recall().decode(\"utf-8\"))\n except Exception as e:\n logger.error(e)\n logger.debug(data)\n for controller in data:\n for measure in controller[\"measures\"]:\n #publish measure\n if measure[\"name\"] in [\"wellstatus\",\"pidcontrolmode\",\"downholesensorstatus\",\"alarmflowrate\",\"alarmintakepressure\",\"alarmintaketemperature\",\"alarmtubingpressure\",\"alarmvfd\",\"alarmlockout\",\"alarmfluidlevel\",\"runpermissive\",\"startpermissive\",\"last_vfd_fault_code\",\"vfd_fault\", \"flowmeter_fault\"]:\n payload[measure[\"name\"]] = convert_int(measure[\"name\"], measure[\"value\"])\n payload[measure[\"name\"]+ \"_int\"] = measure[\"value\"]\n else:\n payload[measure[\"name\"]] = measure[\"value\"]\n logger.debug(\"Sending on topic: {}\".format(topic))\n logger.debug(\"Sending value: {}\".format(payload))\n publish(topic, json.dumps(payload), 1)\ndef writeplctag(value):\n #value in the form {\"measurement\": , \"value\": }\n try:\n #value = json.loads(value.replace(\"'\",'\"'))\n logger.debug(value)\n #payload format: [{\"name\": \"advvfdipp\", \"measures\": [{\"name\": \"manualfrequencysetpoint\", \"value\": 49}]}]\n message = [{\"name\": \"advvfdipp\", \"measures\":[{\"name\":value[\"measurement\"], \"value\": value[\"value\"]}]}]\n resp = write(message) \n logger.debug(\"RETURN FROM WRITE: {}\".format(resp))\n return True\n except Exception as e:\n logger.debug(e)\n return False\n \ndef receiveCommand(topic, payload):\n try:\n logger.debug(topic)\n logger.debug(json.loads(payload))\n p = json.loads(payload)\n command = p[\"method\"]\n commands = {\n \"sync\": sync,\n \"writeplctag\": writeplctag,\n } \n if command == \"setPLCTag\":\n try:\n result = commands[\"writeplctag\"](p[\"params\"])\n logger.debug(result)\n except Exception as e:\n logger.error(e)\n elif command == \"changeSetpoint\":\n try:\n logger.debug(\"attempting controlpoint write\")\n params_type = {\"measurement\": \"pidcontrolmode\", \"value\": p[\"params\"][\"setpointType\"]}\n if params_type[\"value\"]:\n commands[\"writeplctag\"](params_type)\n time.sleep(2)\n except Exception as e:\n logger.error(\"DID NOT WRITE CONTROL MODE\")\n logger.error(e)\n try:\n logger.debug(\"attempting setpoint write\")\n modes = {0: \"flowsetpoint\", 1: \"fluidlevelsetpoint\", 2: \"tubingpressuresetpoint\", 3: \"manualfrequencysetpoint\"}\n params_value = {\"value\": p[\"params\"][\"setpointValue\"]}\n if params_value[\"value\"]:\n params_value[\"measurement\"] = modes[getMode()]\n result = commands[\"writeplctag\"](params_value)\n logger.debug(result)\n except Exception as e:\n logger.error(\"DID NOT WRITE SETPOINT\")\n logger.error(e)\n #logger.debug(command)\n ack(topic.split(\"/\")[-1])\n time.sleep(5)\n sync()\n except Exception as e:\n logger.debug(e)\n \n\ndef ack(msgid):\n #logger.debug(msgid)\n #logger.debug(mac)\n #logger.debug(name)\n #logger.debug(value)\n publish(\"v1/devices/me/rpc/response/\" + str(msgid), json.dumps({\"msg\": {\"time\": time.time()}, \"metadata\": \"\", \"msgType\": \"\"}), 1)\n\ndef getMode():\n try:\n data = recall()\n for controller in data:\n for measure in controller[\"measures\"]:\n if measure[\"name\"] == \"pidcontrolmode\":\n return measure[\"value\"]\n except:\n return None\n\ndef convert_int(plc_tag, value):\n well_status_codes = {\n 0: \"Running\",\n 1: \"Pumped Off\",\n 2: \"Alarmed\",\n 3: \"Locked Out\",\n 4: \"Stopped\"\n }\n\n pid_control_codes = {\n 0: \"Flow\",\n 1: \"Fluid Level\",\n 2: \"Tubing Pressure\",\n 3: \"Manual\"\n }\n\n downhole_codes = {\n 0: \"OK\",\n 1: \"Connecting\",\n 2: \"Open Circuit\",\n 3: \"Shorted\",\n 4: \"Cannot Decode\"\n }\n\n permissive_codes = {\n 0: \"OK\",\n 1: \"Flow\",\n 2: \"Intake Pressure\",\n 3: \"Intake Temperature\",\n 4: \"Tubing Pressure\",\n 5: \"VFD\",\n 6: \"Fluid Level\",\n 7: \"Min. Downtime\"\n }\n\n alarm_codes = {\n 0: \"OK\",\n 1: \"Alarm\"\n }\n\n alarm_vfd_codes = {\n 0: \"OK\",\n 1: \"Locked Out\"\n }\n\n vfd_fault_codes = {\n 0: \"No Fault\",\n 2: \"Auxiliary Input\",\n 3: \"Power Loss\",\n 4: \"UnderVoltage\",\n 5: \"OverVoltage\",\n 7: \"Motor Overload\",\n 8: \"Heatsink OverTemp\",\n 9: \"Thermister OverTemp\",\n 10: \"Dynamic Brake OverTemp\",\n 12: \"Hardware OverCurrent\",\n 13: \"Ground Fault\",\n 14: \"Ground Warning\",\n 15: \"Load Loss\",\n 17: \"Input Phase Loss\",\n 18: \"Motor PTC Trip\",\n 19: \"Task Overrun\",\n 20: \"Torque Prove Speed Band\",\n 21: \"Output Phase Loss\",\n 24: \"Decel Inhibit\",\n 25: \"OverSpeed Limit\",\n 26: \"Brake Slipped\",\n 27: \"Torque Prove Conflict\",\n 28: \"TP Encls Confict\",\n 29: \"Analog In Loss\",\n 33: \"Auto Restarts Exhausted\",\n 35: \"IPM OverCurrent\",\n 36: \"SW OverCurrent\",\n 38: \"Phase U to Ground\",\n 39: \"Phase V to Ground\",\n 40: \"Phase W to Ground\",\n 41: \"Phase UV Short\",\n 42: \"Phase VW Short\",\n 43: \"Phase WU Short\",\n 44: \"Phase UNeg to Ground\",\n 45: \"Phase VNeg to Ground\",\n 46: \"Phase WNeg to Ground\",\n 48: \"System Defaulted\",\n 49: \"Drive Powerup\",\n 51: \"Clear Fault Queue\",\n 55: \"Control Board Overtemp\",\n 59: \"Invalid Code\",\n 61: \"Shear Pin 1\",\n 62: \"Shear Pin 2\",\n 64: \"Drive Overload\",\n 66: \"OW Torque Level\",\n 67: \"Pump Off\",\n 71: \"Port 1 Adapter\",\n 72: \"Port 2 Adapter\",\n 73: \"Port 3 Adapter\",\n 74: \"Port 4 Adapter\",\n 75: \"Port 5 Adapter\",\n 76: \"Port 6 Adapter\",\n 77: \"IR Volts Range\",\n 78: \"FluxAmps Ref Range\",\n 79: \"Excessive Load\",\n 80: \"AutoTune Aborted\",\n 81: \"Port 1 DPI Loss\",\n 82: \"Port 2 DPI Loss\",\n 83: \"Port 3 DPI Loss\",\n 84: \"Port 4 DPI Loss\",\n 85: \"Port 5 DPI Loss\",\n 86: \"Port 6 DPI Loss\",\n 87: \"IXo Voltage Range\",\n 91: \"Primary Velocity Feedback Loss\",\n 93: \"Hardware Enable Check\",\n 94: \"Alternate Velocity Feedback Loss\",\n 95: \"Auxiliary Velocity Feedback Loss\",\n 96: \"Position Feedback Loss\",\n 97: \"Auto Tach Switch\",\n 100: \"Parameter Checksum\",\n 101: \"Power Down NVS Blank\",\n 102: \"NVS Not Blank\",\n 103: \"Power Down NVS Incompatible\",\n 104: \"Power Board Checksum\",\n 106: \"Incompat MCB-PB\",\n 107: \"Replaced MCB-PB\",\n 108: \"Analog Calibration Checksum\",\n 110: \"Invalid Power Board Data\",\n 111: \"Power Board Invalid ID\",\n 112: \"Power Board App Min Version\",\n 113: \"Tracking DataError\",\n 115: \"Power Down Table Full\",\n 116: \"Power Down Entry Too Large\",\n 117: \"Power Down Data Checksum\",\n 118: \"Power Board Power Down Checksum\",\n 124: \"App ID Changed\",\n 125: \"Using Backup App\",\n 134: \"Start on Power Up\",\n 137: \"External Precharge Error\",\n 138: \"Precharge Open\",\n 141: \"Autotune Enc Angle\",\n 142: \"Autotune Speed Restricted\",\n 143: \"Autotune Current Regulator\",\n 144: \"Autotune Inertia\",\n 145: \"Autotune Travel\",\n 13035: \"Net IO Timeout\",\n 13037: \"Net IO Timeout\"\n\n }\n\n plc_tags = {\n \"wellstatus\": well_status_codes.get(value, \"Invalid Code\"),\n \"pidcontrolmode\": pid_control_codes.get(value, \"Invalid Code\"),\n \"downholesensorstatus\": downhole_codes.get(value, \"Invalid Code\"),\n \"alarmflowrate\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintakepressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmintaketemperature\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmtubingpressure\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmvfd\": alarm_codes.get(value, \"Invalid Code\"),\n \"alarmlockout\": alarm_vfd_codes.get(value, \"Invalid Code\"),\n \"alarmfluidlevel\": alarm_codes.get(value, \"Invalid Code\"),\n \"runpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"startpermissive\": permissive_codes.get(value, \"Invalid Code\"),\n \"last_vfd_fault_code\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"vfd_fault\": vfd_fault_codes.get(value, \"Invalid Code\"),\n \"flowmeter_fault\": alarm_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n", + "msgType": 0, + "trigger": "command_event", + "cloudName": "default" + } + ] + }, + "modbusSlave": { + "enable": 0, + "protocol": "Modbus-TCP", + "port": 502, + "slaveAddr": 1, + "int16Ord": "ab", + "int32Ord": "abcd", + "float32Ord": "abcd", + "maxConnection": 5, + "mapping_table": [] + }, + "iec104Server": { + "enable": 0, + "cotSize": 2, + "port": 2404, + "serverList": [ + { + "asduAddr": 1 + } + ], + "kValue": 12, + "wValue": 8, + "t0": 15, + "t1": 15, + "t2": 10, + "t3": 20, + "maximumLink": 5, + "timeSet": 1, + "byteOrder": "abcd", + "mapping_table": [] + }, + "opcuaServer": { + "enable": 0, + "port": 4840, + "maximumLink": 5, + "securityMode": 0, + "identifierType": "String", + "mapping_table": [] + }, + "bindConfig": { + "enable": 0, + "bind": { + "modelId": "", + "modelName": "", + "srcId": "", + "srcName": "", + "devId": "", + "devName": "" + }, + "varGroups": [], + "variables": [], + "alerts": [] + }, + "southMetadata": {}, + "bindMetadata": { + "version": "", + "timestamp": "" + } +} \ No newline at end of file diff --git a/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendAlarms.py b/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendAlarms.py new file mode 100644 index 0000000..c5039e9 --- /dev/null +++ b/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendAlarms.py @@ -0,0 +1,201 @@ +# Enter your python code. +import json, time +from common.Logger import logger +from quickfaas.remotebus import publish +from quickfaas.measure import recall + + +def sendAlarm(message): + logger.info(message) + payload = {} + payload["ts"] = time.time()*1000 + payload["values"] = {message["measureName"]: message["value"]} + publish(__topic__, json.dumps(payload), __qos__) + sync() + +def sync(): + #get new values and send + payload = {"ts": time.time()*1000, "values": {}} + 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["values"][measure["name"]] = convert_int(measure["name"], measure["value"]) + payload["values"][measure["name"]+ "_int"] = measure["value"] + else: + payload["values"][measure["name"]] = measure["value"] + logger.debug("Sending on topic: {}".format(__topic__)) + logger.debug("Sending value: {}".format(payload)) + publish(__topic__, json.dumps(payload), 1) + + +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") diff --git a/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendData.py b/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendData.py new file mode 100644 index 0000000..b1d19d5 --- /dev/null +++ b/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendData.py @@ -0,0 +1,312 @@ +# 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.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.debug("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.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.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.debug("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.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) + 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.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.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.debug("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.debug("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") + + \ No newline at end of file diff --git a/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendToPLC.py b/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendToPLC.py new file mode 100644 index 0000000..afdc889 --- /dev/null +++ b/Pub_Sub/advvfdipp_sru/thingsboard/v2/pub/sendToPLC.py @@ -0,0 +1,29 @@ +# 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": , "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.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) + \ No newline at end of file diff --git a/Pub_Sub/advvfdipp_sru/thingsboard/v2/sub/receiveCommand.py b/Pub_Sub/advvfdipp_sru/thingsboard/v2/sub/receiveCommand.py new file mode 100644 index 0000000..5610b34 --- /dev/null +++ b/Pub_Sub/advvfdipp_sru/thingsboard/v2/sub/receiveCommand.py @@ -0,0 +1,266 @@ +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") diff --git a/Pub_Sub/hrtankbattery/thingsboard/hrtankbattery_tb_v1.cfg b/Pub_Sub/hrtankbattery/thingsboard/v1/hrtankbattery_tb_v1.cfg similarity index 96% rename from Pub_Sub/hrtankbattery/thingsboard/hrtankbattery_tb_v1.cfg rename to Pub_Sub/hrtankbattery/thingsboard/v1/hrtankbattery_tb_v1.cfg index c6ae390..6a436e5 100644 --- a/Pub_Sub/hrtankbattery/thingsboard/hrtankbattery_tb_v1.cfg +++ b/Pub_Sub/hrtankbattery/thingsboard/v1/hrtankbattery_tb_v1.cfg @@ -995,6 +995,97 @@ "desc": "", "transformType": 0 }, + { + "name": "water_09_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_9.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_9.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_9.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_9.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_9.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_9.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_9.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, { "name": "oil_run_tank", "ctrlName": "hrtankbattery", @@ -2742,6 +2833,57 @@ "content": "Water Tank 8 transmission error", "alarmLable": "default" }, + { + "name": "water_09_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_09_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 9 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_09_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_09_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 9 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_09_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_09_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 9 transmission error", + "alarmLable": "default" + }, { "name": "oil_01_hihi_alm", "ctrlName": "hrtankbattery", diff --git a/Pub_Sub/hrtankbattery/thingsboard/pub/sendAlarms.py b/Pub_Sub/hrtankbattery/thingsboard/v1/pub/sendAlarms.py similarity index 100% rename from Pub_Sub/hrtankbattery/thingsboard/pub/sendAlarms.py rename to Pub_Sub/hrtankbattery/thingsboard/v1/pub/sendAlarms.py diff --git a/Pub_Sub/hrtankbattery/thingsboard/pub/sendData.py b/Pub_Sub/hrtankbattery/thingsboard/v1/pub/sendData.py similarity index 100% rename from Pub_Sub/hrtankbattery/thingsboard/pub/sendData.py rename to Pub_Sub/hrtankbattery/thingsboard/v1/pub/sendData.py diff --git a/Pub_Sub/hrtankbattery/thingsboard/sub/receiveCommand.py b/Pub_Sub/hrtankbattery/thingsboard/v1/sub/receiveCommand.py similarity index 100% rename from Pub_Sub/hrtankbattery/thingsboard/sub/receiveCommand.py rename to Pub_Sub/hrtankbattery/thingsboard/v1/sub/receiveCommand.py diff --git a/Pub_Sub/hrtankbattery/thingsboard/v2/hrtankbattery_tb_v2.cfg b/Pub_Sub/hrtankbattery/thingsboard/v2/hrtankbattery_tb_v2.cfg new file mode 100644 index 0000000..0e3ea98 --- /dev/null +++ b/Pub_Sub/hrtankbattery/thingsboard/v2/hrtankbattery_tb_v2.cfg @@ -0,0 +1,3739 @@ +{ + "controllers": [ + { + "protocol": "EtherNet/IP", + "name": "hrtankbattery", + "args": { + "slot": 0 + }, + "samplePeriod": 10, + "expired": 10000, + "endpoint": "192.168.1.10:44818", + "enablePerOnchange": 0 + } + ], + "measures": [ + { + "name": "plc_io_fault_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "IO_Fault_Alarm", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "plc_fault", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "PLC_FAULT", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "analog_01_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Fault_Analog_Mod_01", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "analog_02_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Fault_Analog_Mod_02", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "analog_03_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Fault_Analog_Mod_03", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "analog_04_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Fault_Analog_Mod_04", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "analog_05_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Fault_Analog_Mod_05", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "analog_06_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Fault_Analog_Mod_06", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "ac_power_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Alm_AC_Pwr.Alm_TgtDisagree", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "ups_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Alm_UPS.Alm_TgtDisagree", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "dc_power_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "DC_Power_OK.Alm_TgtDisagree", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "three_phase_pwr_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Three_Phase_Power_Alarm.Alm_TgtDisagree", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "count_oil_tanks", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "DINT", + "addr": "NUMBER_OF_OIL_TANKS", + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "count_water_tanks", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "DINT", + "addr": "NUMBER_OF_WTR_TANKS", + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "count_flow_meters", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "DINT", + "addr": "NUMBER_OF_FLOWMETERS", + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "count_transfer_pumps", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "DINT", + "addr": "NUMBER_OF_TRANSFER_PUMPS", + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "count_lacts", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "DINT", + "addr": "NUMBER_OF_LACTS", + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_run_tank", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "DINT", + "addr": "WT_Selector", + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_01_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_1.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_run_tank_volume", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Curent_Water_Tank_Volume", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_gauge_off_volume", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Gauge_Off_Water_Tank_Volume", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_01_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_1.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_01_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_1.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_01_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_1.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_01_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_1.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_01_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_1.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_01_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_1.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_02_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_2.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_02_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_2.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_02_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_2.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_02_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_2.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_02_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_2.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_02_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_2.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_02_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_2.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_03_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_3.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_03_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_3.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_03_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_3.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_03_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_3.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_03_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_3.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_03_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_3.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_03_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_3.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_04_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_4.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_04_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_4.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_04_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_4.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_04_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_4.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_04_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_4.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_04_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_4.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_04_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_4.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_05_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_5.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_05_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_5.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_05_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_5.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_05_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_5.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_05_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_5.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_05_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_5.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_05_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_5.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_06_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_6.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_06_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_6.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_06_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_6.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_06_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_6.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_06_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_6.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_06_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_6.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_06_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_6.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_07_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_7.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_07_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_7.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_07_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_7.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_07_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_7.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_07_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_7.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_07_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_7.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_07_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_7.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_08_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_8.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_08_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_8.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_08_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_8.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_08_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_8.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_08_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_8.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_08_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_8.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_08_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_8.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_9.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_9.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_9.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "WT_9.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_9.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_9.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "water_09_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "WT_9.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_run_tank", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "DINT", + "addr": "OT_Selector", + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_run_tank_volume", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Current_Oil_Tank_Volume", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_gauge_off_volume", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Gauge_Off_Oil_Tank_Volume", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_01_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_1.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_01_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_1.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_01_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_1.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_01_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_1.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_01_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_1.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_01_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_1.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_01_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_1.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_02_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_2.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_02_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_2.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_02_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_2.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_02_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_2.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_02_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_2.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_02_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_2.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_02_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_2.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_03_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_3.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_03_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_3.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_03_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_3.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_03_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_3.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_03_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_3.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_03_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_3.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_03_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_3.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_04_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_4.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_04_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_4.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_04_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_4.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_04_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_4.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_04_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_4.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_04_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_4.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_04_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_4.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_05_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_5.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_05_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_5.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_05_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_5.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_05_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_5.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_05_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_5.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_05_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_5.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_05_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_5.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_06_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_6.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_06_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_6.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_06_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_6.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_06_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_6.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_06_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_6.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_06_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_6.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_06_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_6.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_07_level", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_7.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_07_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_7.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_07_hi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_7.Alm_Hi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_07_tx_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "OT_7.Alm_Fail", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_07_hihi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_7.PSet_HiHiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_07_hi_spt", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_7.PSet_HiLim", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "oil_07_max_height", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "OT_7.Cfg_PVEUMax", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_sts", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XFER_PUMP_Motor_01.Sts_Running", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XFER_PUMP_Motor_01.Alm_FailToStart", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_discharge", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "XferPump_01_Dis_PSI.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_discharge_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XferPump_01_Dis_PSI.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_discharge_lolo_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XferPump_01_Dis_PSI.Alm_LoLo", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_flow_rate", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "XferPump_01_FlowRate.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_flow_rate_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XferPump_01_FlowRate.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_flow_rate_lolo_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XferPump_01_FlowRate.Alm_LoLo", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_01_3_phase_pwr_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Transfer_Pump_3_Phase_Power_Alarm.Alm_TgtDisagree", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_02_sts", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XFER_PUMP_Motor_02.Sts_Running", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_02_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XFER_PUMP_Motor_02.Alm_FailToStart", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_02_discharge", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "XferPump_02_Dis_PSI.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_02_discharge_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XferPump_02_Dis_PSI.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_02_discharge_lolo_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XferPump_02_Dis_PSI.Alm_LoLo", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_02_flow_rate", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "XferPump_02_FlowRate.Val", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_02_flow_rate_hihi_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XferPump_02_FlowRate.Alm_HiHi", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "transfer_02_flow_rate_lolo_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "XferPump_02_FlowRate.Alm_LoLo", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_01_permissive", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "LACT_01_Permissive", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_01_sts", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "LACT_01_Run_Status", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_01_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "LACT_01_Failure", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_01_oil_shutdown", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "LACT_01_Bad_Oil_Shutdown", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_01_flow_rate", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Lact_01_Realtime_Flow_Rate", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_01_bs_w", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Lact_01_BS_and_W_Reading", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_01_daily_volume", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Lact_01_Current_Daily_Ind_Volume_Total", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_01_prev_day", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Lact_01_History.Previous_Day_1", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_02_permissive", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "LACT_02_Permissive", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_02_sts", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "LACT_02_Run_Status", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_02_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "LACT_02_Failure", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_02_oil_shutdown", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "LACT_02_Bad_Oil_Shutdown", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_02_flow_rate", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Lact_02_Realtime_Flow_Rate", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_02_bs_w", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Lact_02_BS_and_W_Reading", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_02_daily_volume", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Lact_02_Current_Daily_Ind_Volume_Total", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "lact_02_prev_day", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "FLOAT", + "addr": "Lact_02_History.Previous_Day_1", + "decimal": 2, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "containment_high_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "Contain_Hi_Level.Alm_TgtDisagree", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + }, + { + "name": "h2s_alm", + "ctrlName": "hrtankbattery", + "group": "default", + "uploadType": "periodic", + "dataType": "BIT", + "addr": "H2s_Alarm.Alm_TgtDisagree", + "bitMap": 0, + "readWrite": "ro", + "unit": "", + "desc": "", + "transformType": 0 + } + ], + "alarmLables": [ + "default" + ], + "alarms": [ + { + "name": "plc_io_fault_alm", + "ctrlName": "hrtankbattery", + "measureName": "plc_io_fault_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "PLC IO has faulted", + "alarmLable": "default" + }, + { + "name": "plc_fault", + "ctrlName": "hrtankbattery", + "measureName": "plc_fault", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "PLC has faulted", + "alarmLable": "default" + }, + { + "name": "analog_01_alm", + "ctrlName": "hrtankbattery", + "measureName": "analog_01_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Analog Module 1 has faulted", + "alarmLable": "default" + }, + { + "name": "analog_02_alm", + "ctrlName": "hrtankbattery", + "measureName": "analog_02_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Analog Module 2 has faulted", + "alarmLable": "default" + }, + { + "name": "analog_03_alm", + "ctrlName": "hrtankbattery", + "measureName": "analog_03_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Analog Module 3 has faulted", + "alarmLable": "default" + }, + { + "name": "analog_04_alm", + "ctrlName": "hrtankbattery", + "measureName": "analog_04_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Analog Module 4 has faulted", + "alarmLable": "default" + }, + { + "name": "analog_05_alm", + "ctrlName": "hrtankbattery", + "measureName": "analog_05_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Analog Module 5 has faulted", + "alarmLable": "default" + }, + { + "name": "analog_06_alm", + "ctrlName": "hrtankbattery", + "measureName": "analog_06_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Analog Module 6 has faulted", + "alarmLable": "default" + }, + { + "name": "ac_power_alm", + "ctrlName": "hrtankbattery", + "measureName": "ac_power_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "AC Power Fault", + "alarmLable": "default" + }, + { + "name": "ups_alm", + "ctrlName": "hrtankbattery", + "measureName": "ups_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "UPS Fault", + "alarmLable": "default" + }, + { + "name": "dc_power_alm", + "ctrlName": "hrtankbattery", + "measureName": "dc_power_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "DC Power Fault", + "alarmLable": "default" + }, + { + "name": "three_phase_pwr_alm", + "ctrlName": "hrtankbattery", + "measureName": "three_phase_pwr_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Three Phase Power Fault", + "alarmLable": "default" + }, + { + "name": "water_01_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_01_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 1 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_01_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_01_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 1 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_01_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_01_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 1 transmission error", + "alarmLable": "default" + }, + { + "name": "water_02_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_02_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 2 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_02_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_02_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 2 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_02_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_02_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 2 transmission error", + "alarmLable": "default" + }, + { + "name": "water_03_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_03_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 3 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_03_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_03_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 3 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_03_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_03_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 3 transmission error", + "alarmLable": "default" + }, + { + "name": "water_04_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_04_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 4 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_04_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_04_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 4 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_04_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_04_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 4 transmission error", + "alarmLable": "default" + }, + { + "name": "water_05_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_05_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 5 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_05_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_05_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 5 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_05_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_05_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 5 transmission error", + "alarmLable": "default" + }, + { + "name": "water_06_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_06_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 6 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_06_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_06_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 6 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_06_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_06_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 6 transmission error", + "alarmLable": "default" + }, + { + "name": "water_07_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_07_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 7 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_07_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_07_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 7 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_07_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_07_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 7 transmission error", + "alarmLable": "default" + }, + { + "name": "water_08_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_08_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 8 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_08_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_08_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 8 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_08_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_08_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 8 transmission error", + "alarmLable": "default" + }, + { + "name": "water_09_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_09_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 9 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "water_09_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_09_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 9 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "water_09_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "water_09_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Water Tank 9 transmission error", + "alarmLable": "default" + }, + { + "name": "oil_01_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_01_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 1 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "oil_01_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_01_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 1 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "oil_01_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_01_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 1 transmission error", + "alarmLable": "default" + }, + { + "name": "oil_02_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_02_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 2 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "oil_02_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_02_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 2 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "oil_02_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_02_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 2 transmission error", + "alarmLable": "default" + }, + { + "name": "oil_03_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_03_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 3 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "oil_03_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_03_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 3 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "oil_03_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_03_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 3 transmission error", + "alarmLable": "default" + }, + { + "name": "oil_04_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_04_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 4 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "oil_04_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_04_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 4 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "oil_04_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_04_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 4 transmission error", + "alarmLable": "default" + }, + { + "name": "oil_05_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_05_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 5 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "oil_05_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_05_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 5 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "oil_05_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_05_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 5 transmission error", + "alarmLable": "default" + }, + { + "name": "oil_06_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_06_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 6 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "oil_06_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_06_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 6 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "oil_06_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_06_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 6 transmission error", + "alarmLable": "default" + }, + { + "name": "oil_07_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_07_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 7 crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "oil_07_hi_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_07_hi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 7 crossed Hi threshold", + "alarmLable": "default" + }, + { + "name": "oil_07_tx_alm", + "ctrlName": "hrtankbattery", + "measureName": "oil_07_tx_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Oil Tank 7 transmission error", + "alarmLable": "default" + }, + { + "name": "transfer_01_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_01_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 1 Faulted", + "alarmLable": "default" + }, + { + "name": "transfer_01_discharge_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_01_discharge_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 1 Discharge crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "transfer_01_discharge_lolo_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_01_discharge_lolo_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 1 Discharge crossed LoLo threshold", + "alarmLable": "default" + }, + { + "name": "transfer_01_flow_rate_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_01_flow_rate_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 1 Flow Rate crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "transfer_01_flow_rate_lolo_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_01_flow_rate_lolo_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 1 Flow Rate crossed LoLo threshold", + "alarmLable": "default" + }, + { + "name": "transfer_01_3_phase_pwr_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_01_3_phase_pwr_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 1 3 Phase Power Failure", + "alarmLable": "default" + }, + { + "name": "transfer_02_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_02_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 2 Faulted", + "alarmLable": "default" + }, + { + "name": "transfer_02_discharge_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_02_discharge_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 2 Discharge crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "transfer_02_discharge_lolo_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_02_discharge_lolo_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 2 Discharge crossed LoLo threshold", + "alarmLable": "default" + }, + { + "name": "transfer_02_flow_rate_hihi_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_02_flow_rate_hihi_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 2 Flow Rate crossed HiHi threshold", + "alarmLable": "default" + }, + { + "name": "transfer_02_flow_rate_lolo_alm", + "ctrlName": "hrtankbattery", + "measureName": "transfer_02_flow_rate_lolo_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Transfer 2 Flow Rate crossed LoLo threshold", + "alarmLable": "default" + }, + { + "name": "lact_01_alm", + "ctrlName": "hrtankbattery", + "measureName": "lact_01_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "LACT 1 Meter Failure", + "alarmLable": "default" + }, + { + "name": "lact_01_oil_shutdown", + "ctrlName": "hrtankbattery", + "measureName": "lact_01_oil_shutdown", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "LACT 1 Bad Oil", + "alarmLable": "default" + }, + { + "name": "lact_02_alm", + "ctrlName": "hrtankbattery", + "measureName": "lact_02_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "LACT 2 Meter Failure", + "alarmLable": "default" + }, + { + "name": "lact_02_oil_shutdown", + "ctrlName": "hrtankbattery", + "measureName": "lact_02_oil_shutdown", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "LACT 2 Bad Oil", + "alarmLable": "default" + }, + { + "name": "containment_high_alm", + "ctrlName": "hrtankbattery", + "measureName": "containment_high_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "Containment Level has crossed the Hi threshold.", + "alarmLable": "default" + }, + { + "name": "h2s_alm", + "ctrlName": "hrtankbattery", + "measureName": "h2s_alm", + "alarmLevel": 5, + "cond1": { + "op": "eq", + "value": "1.0" + }, + "condOp": "none", + "cond2": { + "op": "eq", + "value": "" + }, + "content": "H2S Detected", + "alarmLable": "default" + } + ], + "groups": [ + { + "name": "default", + "uploadInterval": 600, + "reference": 45 + }, + { + "name": "converter", + "uploadInterval": 10 + }, + { + "name": "null", + "uploadInterval": 3600 + } + ], + "misc": { + "maxAlarmRecordSz": 2000, + "logLvl": "INFO", + "coms": [ + { + "name": "rs232", + "baud": 9600, + "bits": 8, + "stopbits": 1, + "parityChk": "n" + }, + { + "name": "rs485", + "baud": 38400, + "bits": 8, + "stopbits": 1, + "parityChk": "n" + } + ] + }, + "clouds": [ + { + "cacheSize": 10000, + "enable": 1, + "type": "Standard MQTT", + "args": { + "host": "hp.henrypump.cloud", + "port": 1883, + "clientId": "unknown", + "auth": 1, + "tls": 0, + "cleanSession": 1, + "mqttVersion": "v3.1.1", + "keepalive": 120, + "key": "", + "cert": "", + "rootCA": "", + "verifyServer": 0, + "verifyClient": 0, + "username": "unknown", + "passwd": "unknown", + "authType": 1, + "willQos": 0, + "willRetain": 0, + "willTopic": "", + "willPayload": "" + }, + "name": "default" + } + ], + "quickfaas": { + "genericFuncs": [], + "uploadFuncs": [ + { + "name": "Send Data", + "trigger": "measure_event", + "topic": "v1/devices/me/telemetry", + "qos": 1, + "groups": [ + "default" + ], + "funcName": "sendData", + "script": "# Enter your python code.\nimport json, os\nfrom datetime import datetime as dt\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom quickfaas.global_dict import get as get_params\nfrom quickfaas.global_dict import _set_global_args\n\ndef reboot(reason=\"Rebooting for config file update\"):\n #basic = Basic()\n logger.info(\"!\" * 10 + \"REBOOTING DEVICE\" + \"!\"*10)\n logger.info(reason)\n r = os.popen(\"kill -s SIGHUP `cat /var/run/python/supervisord.pid`\").read()\n logger.info(f\"REBOOT : {r}\")\n\ndef checkFileExist(filename):\n path = \"/var/user/files\"\n if not os.path.exists(path):\n logger.info(\"no folder making files folder in var/user\")\n os.makedirs(path)\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n if not os.path.exists(path + \"/\" + filename):\n logger.info(\"no creds file making creds file\")\n with open(path + \"/\" + filename, \"a\") as f:\n json.dump({}, f)\n\ndef convertDStoJSON(ds):\n j = dict()\n for x in ds:\n j[x[\"key\"]] = x[\"value\"]\n return j\n\ndef convertJSONtoDS(j):\n d = []\n for key in j.keys():\n d.append({\"key\": key, \"value\": j[key]})\n return d\n\ndef checkCredentialConfig():\n logger.debug(\"CHECKING CONFIG\")\n cfgpath = \"/var/user/cfg/device_supervisor/device_supervisor.cfg\"\n credspath = \"/var/user/files/creds.json\"\n cfg = dict()\n with open(cfgpath, \"r\") as f:\n cfg = json.load(f)\n clouds = cfg.get(\"clouds\")\n logger.debug(clouds)\n #if not configured then try to configure from stored values\n if clouds[0][\"args\"][\"clientId\"] == \"unknown\" or clouds[0][\"args\"][\"username\"] == \"unknown\" or not clouds[0][\"args\"][\"passwd\"] or clouds[0][\"args\"][\"passwd\"] == \"unknown\":\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n creds = json.load(c)\n if creds:\n logger.debug(\"updating config with stored data\")\n clouds[0][\"args\"][\"clientId\"] = creds[\"clientId\"]\n clouds[0][\"args\"][\"username\"] = creds[\"userName\"]\n clouds[0][\"args\"][\"passwd\"] = creds[\"password\"]\n cfg[\"clouds\"] = clouds\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n reboot()\n else:\n #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\n checkFileExist(\"creds.json\")\n with open(credspath, \"r\") as c:\n logger.debug(\"updating stored file with new data\")\n cfg = checkParameterConfig(cfg)\n with open(cfgpath, \"w\", encoding='utf-8') as n:\n json.dump(cfg, n, indent=1, ensure_ascii=False)\n creds = json.load(c)\n if creds:\n if creds[\"clientId\"] != clouds[0][\"args\"][\"clientId\"]:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n if creds[\"userName\"] != clouds[0][\"args\"][\"username\"]:\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n if creds[\"password\"] != clouds[0][\"args\"][\"passwd\"]:\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n else:\n creds[\"clientId\"] = clouds[0][\"args\"][\"clientId\"]\n creds[\"userName\"] = clouds[0][\"args\"][\"username\"]\n creds[\"password\"] = clouds[0][\"args\"][\"passwd\"]\n with open(credspath, \"w\") as cw:\n json.dump(creds,cw)\n\ndef checkParameterConfig(cfg):\n logger.debug(\"Checking Parameters!!!!\")\n paramspath = \"/var/user/files/params.json\"\n cfgparams = convertDStoJSON(cfg.get(\"labels\"))\n #check stored values \n checkFileExist(\"params.json\")\n with open(paramspath, \"r\") as f:\n logger.debug(\"Opened param storage file\")\n params = json.load(f)\n if params:\n if cfgparams != params:\n #go through each param\n #if not \"unknown\" and cfg and params aren't the same take from cfg likely updated manually\n #if key in cfg but not in params copy to params\n logger.debug(\"equalizing params between cfg and stored\")\n for key in cfgparams.keys():\n try:\n if cfgparams[key] != params[key] and cfgparams[key] != \"unknown\":\n params[key] = cfgparams[key]\n except:\n params[key] = cfgparams[key]\n cfg[\"labels\"] = convertJSONtoDS(params)\n _set_global_args(convertJSONtoDS(params))\n with open(paramspath, \"w\") as p:\n json.dump(params, p)\n else:\n with open(paramspath, \"w\") as p:\n logger.debug(\"initializing param file with params in memory\")\n json.dump(convertDStoJSON(get_params()), p)\n cfg[\"labels\"] = get_params()\n \n return cfg\n\ndef sendData(message):\n #logger.debug(message)\n try:\n checkCredentialConfig()\n except Exception as e:\n logger.error(e)\n payload = {\"ts\": (round(dt.timestamp(dt.now())/600)*600)*1000, \"values\": {}}\n for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n if abs(payload[\"ts\"]/1000 - measure[\"timestamp\"]) > 3600:\n reboot(reason=\"Poll timestamp and actual timestamp out of sync. Actual: {} Poll: {}\".format(payload[\"ts\"]/1000,measure[\"timestamp\"]))\n payload[\"values\"][measure[\"name\"]] = measure[\"value\"] \n except Exception as e:\n logger.error(e)\n \n publish(__topic__, json.dumps(payload), __qos__)\n publish(\"v1/devices/me/attributes\", json.dumps({\"latestReportTime\": (round(dt.timestamp(dt.now())/600)*600)*1000}), __qos__)\n\n", + "msgType": 0, + "cloudName": "default" + }, + { + "name": "sendAlarm", + "trigger": "warning_event", + "topic": "v1/devices/me/telemetry", + "qos": 1, + "funcName": "sendAlarm", + "script": "# Enter your python code.\nimport json, time\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\n\n\ndef sendAlarm(message):\n logger.info(message)\n payload = {}\n payload[\"ts\"] = time.time()*1000\n payload[\"values\"] = {message[\"measureName\"]: message[\"value\"]}\n publish(__topic__, json.dumps(payload), __qos__)", + "alarms": [ + "default" + ], + "msgType": 0, + "cloudName": "default" + } + ], + "downloadFuncs": [ + { + "name": "Commands", + "topic": "v1/devices/me/rpc/request/+", + "qos": 1, + "funcName": "receiveCommand", + "payload_type": "JSON", + "script": "import json, time\nfrom quickfaas.measure import recall, write\nfrom quickfaas.remotebus import publish\nfrom common.Logger import logger\n\ndef sync():\n #get new values and send\n payload = {}\n topic = \"v1/devices/me/telemetry\"\n try:\n data = recall()#json.loads(recall().decode(\"utf-8\"))\n except Exception as e:\n logger.error(e)\n logger.debug(data)\n for controller in data:\n for measure in controller[\"measures\"]:\n #publish measure\n payload[measure[\"name\"]] = measure[\"value\"]\n logger.debug(\"Sending on topic: {}\".format(topic))\n logger.debug(\"Sending value: {}\".format(payload))\n publish(topic, json.dumps(payload), 1)\ndef writeplctag(value):\n #value in the form {\"measurement\": , \"value\": }\n try:\n #value = json.loads(value.replace(\"'\",'\"'))\n logger.debug(value)\n #payload format: [{\"name\": \"advvfdipp\", \"measures\": [{\"name\": \"manualfrequencysetpoint\", \"value\": 49}]}]\n message = [{\"name\": \"hrtankbattery\", \"measures\":[{\"name\":value[\"measurement\"], \"value\": value[\"value\"]}]}]\n resp = write(message) \n logger.debug(\"RETURN FROM WRITE: {}\".format(resp))\n return True\n except Exception as e:\n logger.debug(e)\n return False\n \ndef receiveCommand(topic, payload):\n try:\n logger.debug(topic)\n logger.debug(json.loads(payload))\n p = json.loads(payload)\n command = p[\"method\"]\n commands = {\n \"sync\": sync,\n \"writeplctag\": writeplctag,\n } \n if command == \"setPLCTag\":\n try:\n result = commands[\"writeplctag\"](p[\"params\"])\n logger.debug(result)\n except Exception as e:\n logger.error(e)\n #logger.debug(command)\n ack(topic.split(\"/\")[-1])\n time.sleep(5)\n sync()\n except Exception as e:\n logger.debug(e)\n \n\ndef ack(msgid):\n #logger.debug(msgid)\n #logger.debug(mac)\n #logger.debug(name)\n #logger.debug(value)\n publish(\"v1/devices/me/rpc/response/\" + str(msgid), json.dumps({\"msg\": {\"time\": time.time()}, \"metadata\": \"\", \"msgType\": \"\"}), 1)\n\n", + "msgType": 0, + "trigger": "command_event", + "cloudName": "default" + } + ] + }, + "labels": [ + { + "key": "SN", + "value": "GF5022228018984" + }, + { + "key": "MAC", + "value": "00:18:05:22:9d:3d" + } + ], + "modbusSlave": { + "enable": 1, + "protocol": "Modbus-TCP", + "port": 502, + "slaveAddr": 1, + "int16Ord": "ab", + "int32Ord": "abcd", + "float32Ord": "abcd", + "maxConnection": 5, + "mapping_table": [] + }, + "modbusRTUSlave": { + "enable": 0, + "protocol": "Modbus-RTU", + "coms": "rs485", + "slaveAddr": 1, + "int16Ord": "ab", + "int32Ord": "abcd", + "float32Ord": "abcd", + "mapping_table": [] + }, + "iec104Server": { + "enable": 0, + "cotSize": 2, + "port": 2404, + "serverList": [ + { + "asduAddr": 1 + } + ], + "kValue": 12, + "wValue": 8, + "t0": 15, + "t1": 15, + "t2": 10, + "t3": 20, + "maximumLink": 5, + "timeSet": 1, + "byteOrder": "abcd", + "mapping_table": [] + }, + "iec104Client": { + "enable": 0, + "connectType": 2, + "serverAddr": "ipower.inhandcloud.cn", + "serverPort": 2404, + "communicationCode": "", + "protocol": 1, + "asduAddr": 1, + "tls": 0, + "mapping_table": { + "YX": [], + "YC": [], + "YK": [] + } + }, + "opcuaServer": { + "enable": 0, + "port": 4840, + "maximumLink": 5, + "securityMode": 0, + "identifierType": "String", + "certificate": "None", + "privateKey": "None", + "mapping_table": [] + }, + "southMetadata": {}, + "bindMetadata": { + "version": "", + "timestamp": "" + }, + "bindConfig": { + "enable": 0, + "bind": { + "modelId": "", + "modelName": "", + "srcId": "", + "srcName": "", + "devId": "", + "devName": "" + }, + "varGroups": [], + "variables": [], + "alerts": [] + }, + "version": "2.4.0" +} \ No newline at end of file diff --git a/Pub_Sub/hrtankbattery/thingsboard/v2/pub/sendAlarms.py b/Pub_Sub/hrtankbattery/thingsboard/v2/pub/sendAlarms.py new file mode 100644 index 0000000..58497ef --- /dev/null +++ b/Pub_Sub/hrtankbattery/thingsboard/v2/pub/sendAlarms.py @@ -0,0 +1,12 @@ +# Enter your python code. +import json, time +from common.Logger import logger +from quickfaas.remotebus import publish + + +def sendAlarm(message): + logger.info(message) + payload = {} + payload["ts"] = time.time()*1000 + payload["values"] = {message["measureName"]: message["value"]} + publish(__topic__, json.dumps(payload), __qos__) \ No newline at end of file diff --git a/Pub_Sub/hrtankbattery/thingsboard/v2/pub/sendData.py b/Pub_Sub/hrtankbattery/thingsboard/v2/pub/sendData.py new file mode 100644 index 0000000..08c83f3 --- /dev/null +++ b/Pub_Sub/hrtankbattery/thingsboard/v2/pub/sendData.py @@ -0,0 +1,138 @@ +# 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.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.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.debug("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.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) + 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.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.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.debug("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.debug("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"])) + 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__) + diff --git a/Pub_Sub/hrtankbattery/thingsboard/v2/sub/receiveCommand.py b/Pub_Sub/hrtankbattery/thingsboard/v2/sub/receiveCommand.py new file mode 100644 index 0000000..3b7993b --- /dev/null +++ b/Pub_Sub/hrtankbattery/thingsboard/v2/sub/receiveCommand.py @@ -0,0 +1,66 @@ +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 + 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": "hrtankbattery", "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) + #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) +