376 lines
19 KiB
INI
376 lines
19 KiB
INI
{
|
|
"controllers": [
|
|
{
|
|
"enable": 1,
|
|
"protocol": "AllenBradley MicroCip",
|
|
"name": "plcfreshwater",
|
|
"samplePeriod": 10,
|
|
"desc": "",
|
|
"expired": 1000,
|
|
"args": {
|
|
"slot": 0,
|
|
"connectTimeOut": 10000
|
|
},
|
|
"enableDebug": 0,
|
|
"enablePerOnchange": 0,
|
|
"endpoint": "192.168.1.222:44818"
|
|
}
|
|
],
|
|
"measures": [
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "FLOAT",
|
|
"addr": "Scaled_Flow_Meter",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"decimal": 2,
|
|
"name": "scaled_flow_meter",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": ""
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "FLOAT",
|
|
"addr": "Scaled_Pressure_Transducer",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"decimal": 2,
|
|
"name": "scaled_pressure_transducer",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": ""
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "BIT",
|
|
"addr": "Raw_Hand_Input",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"name": "raw_hand_input",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": "",
|
|
"decimal": 2
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "BIT",
|
|
"addr": "Raw_Auto_Input",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"name": "raw_auto_input",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": "",
|
|
"decimal": 2
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "BIT",
|
|
"addr": "Raw_Run_Status",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"name": "raw_run_status",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": "",
|
|
"decimal": 2
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "BIT",
|
|
"addr": "Raw_Local_Start",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"name": "raw_local_start",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": "",
|
|
"decimal": 2
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "FLOAT",
|
|
"addr": "Lifetime_Flow_Meter_Gal",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"decimal": 2,
|
|
"name": "lifetime_flow_meter_gal",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": ""
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "BIT",
|
|
"addr": "SPT_Flow_Meter_Unit",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"name": "spt_flow_meter_unit",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": "",
|
|
"decimal": 2
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "BIT",
|
|
"addr": "Raw_Overload_Status",
|
|
"readWrite": "ro",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"name": "raw_overload_status",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": "",
|
|
"decimal": 2
|
|
},
|
|
{
|
|
"ctrlName": "plcfreshwater",
|
|
"dataType": "BIT",
|
|
"addr": "CMD_Cloud_Control",
|
|
"readWrite": "rw",
|
|
"uploadType": "periodic",
|
|
"group": "default",
|
|
"name": "CMD_Cloud_Control",
|
|
"desc": "",
|
|
"unit": "",
|
|
"transformType": 0,
|
|
"gain": "1.0",
|
|
"offset": "0.0",
|
|
"maxValue": "",
|
|
"minValue": "",
|
|
"maxScaleValue": "",
|
|
"minScaleValue": "",
|
|
"decimal": 2
|
|
}
|
|
],
|
|
"alarmLables": [
|
|
"default"
|
|
],
|
|
"alarms": [],
|
|
"groups": [
|
|
{
|
|
"name": "default",
|
|
"uploadInterval": 600,
|
|
"reference": 10
|
|
}
|
|
],
|
|
"misc": {
|
|
"maxAlarmRecordSz": 2000,
|
|
"logLvl": "INFO",
|
|
"coms": [
|
|
{
|
|
"name": "rs232",
|
|
"baud": 9600,
|
|
"bits": 8,
|
|
"stopbits": 1,
|
|
"parityChk": "n"
|
|
},
|
|
{
|
|
"name": "rs485",
|
|
"baud": 9600,
|
|
"bits": 8,
|
|
"stopbits": 1,
|
|
"parityChk": "n"
|
|
}
|
|
]
|
|
},
|
|
"clouds": [
|
|
{
|
|
"cacheSize": 100,
|
|
"enable": 1,
|
|
"name": "default",
|
|
"type": "Standard MQTT",
|
|
"args": {
|
|
"host": "mq194.imistaway.net",
|
|
"port": 1883,
|
|
"clientId": "dawn-to-terri",
|
|
"auth": 1,
|
|
"tls": 0,
|
|
"cleanSession": 0,
|
|
"mqttVersion": "v3.1.1",
|
|
"keepalive": 60,
|
|
"key": "",
|
|
"cert": "",
|
|
"rootCA": "",
|
|
"verifyServer": 0,
|
|
"verifyClient": 0,
|
|
"username": "admin",
|
|
"passwd": "columbus",
|
|
"authType": 1
|
|
}
|
|
}
|
|
],
|
|
"quickfaas": {
|
|
"genericFuncs": [],
|
|
"uploadFuncs": [
|
|
{
|
|
"name": "Send Data",
|
|
"trigger": "measure_event",
|
|
"topic": "meshify/db/194/_/plcfreshwater/${MAC_LOWER}",
|
|
"qos": 1,
|
|
"groups": [
|
|
"default"
|
|
],
|
|
"funcName": "sendData",
|
|
"script": "import json, os, uuid\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom paho.mqtt import client\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\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 print(\"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[\"client\"].reconnect_delay_set(min_delay=10, max_delay=120)\n lwtData[\"init\"] = True\n print(\"Connecting to MQTT Broker for LWT purposes!!!!!!!\")\n lwtData[\"client\"].connect(\"mq194.imistaway.net\",1883, 600)\n lwtData[\"client\"].reconnect()\n lwtData[\"client\"].publish(\"meshify/db/194/_/mainHP/\" + mac + \":00:00/connected\", json.dumps([{\"value\":True}]))\n except Exception as e:\n print(\"LWT DID NOT DO THE THING\")\n print(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 plc_ping = os.system(\"ping -c 1 192.168.1.101 > /dev/null 2>&1\")\n if plc_ping == 0:\n publish(__topic__ + \":01:99/\" + \"plc_ping\", json.dumps({\"value\": \"OK\"}), __qos__)\n else:\n publish(__topic__ + \":01:99/\" + \"plc_ping\", json.dumps({\"value\": \"Comms Error to PLC\"}), __qos__)\n for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n if measure[\"name\"] in [\"raw_hand_input\", \"raw_auto_input\", \"raw_run_status\", \"raw_local_start\",\"raw_overload_status\"]:\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 except Exception as e:\n logger.error(e)\n\ndef convert_int(plc_tag, value):\n input_codes = {\n 0: \"Off\",\n 1: \"On\"\n }\n\n run_status_codes = {\n 0: \"Stopped\",\n 1: \"Running\"\n }\n\n overload_codes = {\n 0: \"Good\",\n 1: \"Down on Overload Tripped\"\n }\n \n plc_tags = {\n \"raw_hand_input\": input_codes.get(value, \"Invalid Code\"),\n \"raw_auto_input\": input_codes.get(value, \"Invalid Code\"),\n \"raw_run_status\": run_status_codes.get(value, \"Invalid Code\"),\n \"raw_overload_status\": overload_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n\n ",
|
|
"msgType": 0,
|
|
"cloudName": "default"
|
|
}
|
|
],
|
|
"downloadFuncs": [
|
|
{
|
|
"name": "Commands",
|
|
"topic": "meshify/sets/194/${MAC_UPPER}:01:99",
|
|
"qos": 1,
|
|
"funcName": "receiveCommand",
|
|
"payload_type": "Plaintext",
|
|
"script": "# Enter your python code.\nimport json\nimport os\nfrom quickfaas.measure import recall\nfrom common.Logger import logger\n\ndef sync(mac,value, wizard_api):\n #get new values and send\n try:\n data = recall()#json.loads(recall().decode(\"utf-8\"))\n except Exception as e:\n logger.error(e)\n logger.info(data)\n plc_ping = os.system(\"ping -c 1 192.168.1.101 > /dev/null 2>&1\")\n if plc_ping == 0:\n publish(__topic__ + \":01:99/\" + \"plc_ping\", json.dumps({\"value\": \"OK\"}), __qos__)\n else:\n publish(__topic__ + \":01:99/\" + \"plc_ping\", json.dumps({\"value\": \"Comms Error to PLC\"}), __qos__)\n for controller in data:\n for measure in controller[\"measures\"]:\n #publish measure\n topic = \"meshify/db/194/_/plcfreshwater/\" + mac + \"/\" + measure[\"name\"]\n if measure[\"name\"] in [\"raw_hand_input\", \"raw_auto_input\", \"raw_run_status\", \"raw_local_start\",\"raw_overload_status\"]:\n payload = [{\"value\": convert_int(measure[\"name\"], measure[\"value\"])}]\n else:\n payload = [{\"value\": measure[\"value\"]}]\n logger.debug(\"Sending on topic: {}\".format(topic))\n logger.debug(\"Sending value: {}\".format(payload))\n wizard_api.mqtt_publish(topic, json.dumps(payload))\ndef writeplctag(mac, value, wizard_api):\n try:\n value = json.loads(value.replace(\"'\",'\"'))\n logger.debug(value)\n message = {\"plcfreshwater\":{value[\"tag\"]: value[\"val\"]}}\n wizard_api.write_plc_values(message)\n except Exception as e:\n logger.debug(e)\n \ndef receiveCommand(topic, payload, wizard_api):\n logger.debug(topic)\n logger.debug(json.loads(payload))\n p = json.loads(payload)[0]\n command = p[\"payload\"][\"name\"].split(\".\")[1]\n commands = {\n \"sync\": sync,\n \"writeplctag\": writeplctag,\n }\n commands[command](p[\"mac\"].lower(),p[\"payload\"][\"value\"], wizard_api)\n #logger.debug(command)\n ack(p[\"msgId\"], p[\"mac\"], command, p[\"payload\"][\"name\"].split(\".\")[1], p[\"payload\"][\"value\"], wizard_api)\n\ndef ack(msgid, mac, name, command, value, wizard_api):\n #logger.debug(mac)\n macsquish = \"\".join(mac.split(\":\")[:-2])\n maclower = \":\".join(mac.split(\":\")[:-2])\n maclower = maclower.lower()\n #logger.debug(msgid)\n #logger.debug(mac)\n #logger.debug(name)\n #logger.debug(value)\n wizard_api.mqtt_publish(\"meshify/responses/\" + str(msgid), json.dumps([{\"value\": \"{} Success Setting: {} To: {}\".format(macsquish,name, value), \"msgid\": str(msgid)}]))\n wizard_api.mqtt_publish(\"meshify/db/194/_/mainMeshify/\" + maclower + \":00:00/commands\", json.dumps([{\"value\": {\"status\": \"success\", \"value\": str(value), \"channel\": command}, \"msgid\": str(msgid)}]))\n\ndef convert_int(plc_tag, value):\n input_codes = {\n 0: \"Off\",\n 1: \"On\"\n }\n\n run_status_codes = {\n 0: \"Stopped\",\n 1: \"Running\"\n }\n\n overload_codes = {\n 0: \"Good\",\n 1: \"Down on Overload Tripped\"\n }\n \n plc_tags = {\n \"raw_hand_input\": input_codes.get(value, \"Invalid Code\"),\n \"raw_auto_input\": input_codes.get(value, \"Invalid Code\"),\n \"raw_run_status\": run_status_codes.get(value, \"Invalid Code\"),\n \"raw_overload_status\": overload_codes.get(value, \"Invalid Code\")\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n",
|
|
"msgType": 0,
|
|
"cloudName": "default",
|
|
"trigger": "command_event"
|
|
}
|
|
]
|
|
},
|
|
"labels": [
|
|
{
|
|
"key": "SN",
|
|
"value": "GF5022211011405"
|
|
},
|
|
{
|
|
"key": "MAC",
|
|
"value": "00:18:05:1e:ae:b8"
|
|
},
|
|
{
|
|
"key": "MAC_LOWER",
|
|
"value": "00:00:06:00:00:06"
|
|
},
|
|
{
|
|
"key": "MAC_UPPER",
|
|
"value": "00:00:06:00:00:06"
|
|
}
|
|
],
|
|
"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": 30,
|
|
"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": []
|
|
},
|
|
"southMetadata": {},
|
|
"bindMetadata": {
|
|
"version": "",
|
|
"timestamp": ""
|
|
},
|
|
"bindConfig": {
|
|
"enable": 0,
|
|
"bind": {
|
|
"modelId": "",
|
|
"modelName": "",
|
|
"srcId": "",
|
|
"srcName": "",
|
|
"devId": "",
|
|
"devName": ""
|
|
},
|
|
"varGroups": [],
|
|
"variables": [],
|
|
"alerts": []
|
|
},
|
|
"version": "2.2.1"
|
|
} |