updates 2024-07-31

This commit is contained in:
Nico Melone
2024-07-31 13:56:21 -05:00
parent 5af6c48ade
commit 79b2f149df
62 changed files with 443262 additions and 993 deletions

Binary file not shown.

View File

@@ -0,0 +1,108 @@
import json, os, time
from common.Logger import logger
from quickfaas.remotebus import publish
from datetime import datetime as dt
from mobiuspi_lib.gps import GPS
from quickfaas.global_dict import get as get_params
from quickfaas.global_dict import _set_global_args
def getGPS():
# Create a gps instance
gps = GPS()
# Retrieve GPS information
position_status = gps.get_position_status()
logger.debug("position_status: ")
logger.debug(position_status)
latitude = position_status["latitude"].split(" ")
longitude = position_status["longitude"].split(" ")
lat_dec = int(latitude[0][:-1]) + (float(latitude[1][:-1])/60)
lon_dec = int(longitude[0][:-1]) + (float(longitude[1][:-1])/60)
if latitude[2] == "S":
lat_dec = lat_dec * -1
if longitude[2] == "W":
lon_dec = lon_dec * -1
#lat_dec = round(lat_dec, 7)
#lon_dec = round(lon_dec, 7)
logger.info("HERE IS THE GPS COORDS")
logger.info(f"LATITUDE: {lat_dec}, LONGITUDE: {lon_dec}")
speedKnots = position_status["speed"].split(" ")
speedMPH = float(speedKnots[0]) * 1.151
return (f"{lat_dec:.8f}",f"{lon_dec:.8f}",f"{speedMPH:.2f}")
def chunk_payload(payload, chunk_size=20):
if "values" in payload:
# Original format: {"ts": ..., "values": {...}}
chunked_values = list(payload["values"].items())
for i in range(0, len(chunked_values), chunk_size):
yield {
"ts": payload["ts"],
"values": dict(chunked_values[i:i+chunk_size])
}
else:
# New format: {"key1": "value1", "key2": "value2"}
chunked_keys = list(payload.keys())
for i in range(0, len(chunked_keys), chunk_size):
yield {k: payload[k] for k in chunked_keys[i:i+chunk_size]}
def sendData(message):
#logger.debug(message)
payload = {"ts": (round(dt.timestamp(dt.now())/600)*600)*1000, "values": {}}
attributes_payload = {}
for measure in message["measures"]:
try:
logger.debug(measure)
if measure["health"] == 1:
if measure["name"] in ["auto_manual", "auto_control_mode", "device_status"]:
logger.debug("Converting DINT/BOOL to STRING")
payload["values"][measure["name"]] = convert_int(measure["name"], measure["value"])
payload["values"][measure["name"] + "_int"] = measure["value"]
else:
payload["values"][measure["name"]] = measure["value"]
except Exception as e:
logger.error(e)
try:
payload["values"]["latitude"], payload["values"]["longitude"], payload["values"]["speed"] = getGPS()
except:
logger.error("Could not get GPS coordinates")
for chunk in chunk_payload(payload=payload):
publish(__topic__, json.dumps(chunk), __qos__, cloud_name="ThingsBoard")
time.sleep(2)
attributes_payload["latestReportTime"] = (round(dt.timestamp(dt.now())/600)*600)*1000
for chunk in chunk_payload(payload=attributes_payload):
publish("v1/devices/me/attributes", json.dumps(chunk), __qos__, cloud_name="ThingsBoard")
time.sleep(2)
def convert_int(plc_tag, value):
auto_manual = {
0: "Manual",
1: "Auto"
}
auto_control_mode = {
0: "Pressure",
1: "Flow"
}
device_status = {
1: "Running",
64: "Idle",
128: "Overpressure",
1024: "Faulted"
}
plc_tags = {
"auto_manual": auto_manual.get(value, "Invalid Code"),
"auto_control_mode": auto_control_mode.get(value, "Invalid Code"),
"device_status": device_status.get(value, "Invalid Code"),
}
return plc_tags.get(plc_tag, "Invalid Tag")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,547 @@
{
"controllers": [
{
"protocol": "EtherNet/IP",
"name": "rigpump",
"samplePeriod": 10,
"expired": 10000,
"endpoint": "192.168.1.10:44818",
"args": {
"connectTimeOut": 2000,
"slot": 0
},
"desc": "",
"enable": 1,
"enableDebug": 0
}
],
"measures": [
{
"name": "vfd_current",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "VFD_OutCurrent",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "vfd_frequency",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "VFD_SpeedFdbk",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "discharge_pressure",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "val_DischargePressure",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "discharge_pressure_setpoint",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "cfg_PID_DischargePressureSP",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "vfd_frequency_setpoint",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "cfg_PID_ManualSP",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "flow_rate_setpoint",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "cfg_PID_FlowSP",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "auto_manual",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "BIT",
"addr": "mode_Auto",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"gain": "1.0",
"offset": "0.0",
"bitMap": 0,
"reverseBit": 0,
"storageLwTSDB": 0
},
{
"name": "device_status",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "INT",
"addr": "RigPump.State",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"gain": "1.0",
"offset": "0.0",
"enableBit": 0,
"storageLwTSDB": 0
},
{
"name": "auto_control_mode",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "INT",
"addr": "controlMode",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"gain": "1.0",
"offset": "0.0",
"enableBit": 0,
"storageLwTSDB": 0
},
{
"name": "energy_today",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "Energy_Total[0]",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "flow_rate",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "val_Flowmeter",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "energy_yesterday",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "FLOAT",
"addr": "Energy_Total[1]",
"readWrite": "ro",
"unit": "",
"desc": "",
"transformType": 0,
"decimal": 2,
"gain": "1.0",
"offset": "0.0",
"storageLwTSDB": 0
},
{
"name": "cmd_Start",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "BIT",
"addr": "cmd_Start",
"readWrite": "rw",
"unit": "",
"desc": "",
"transformType": 0,
"bitMap": 0,
"gain": "1.0",
"offset": "0.0",
"reverseBit": 0,
"storageLwTSDB": 0
},
{
"name": "cmd_Stop",
"ctrlName": "rigpump",
"group": "default",
"uploadType": "periodic",
"dataType": "BIT",
"addr": "cmd_Stop",
"readWrite": "rw",
"unit": "",
"desc": "",
"transformType": 0,
"bitMap": 0,
"gain": "1.0",
"offset": "0.0",
"reverseBit": 0,
"storageLwTSDB": 0
}
],
"alarmLables": [
"default"
],
"alarms": [],
"groups": [
{
"name": "default",
"uploadInterval": 600,
"reference": 44,
"LwTSDBSize": 1000,
"strategy": 1,
"historyDataPath": "/var/user/data/dbhome/device_supervisor/LwTSDB",
"enablePerOnchange": 0
}
],
"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"
}
],
"cachePath": "/var/user/data/dbhome/device_supervisor/offlinedata",
"cacheSize": 10000,
"debugLogPath": "/var/user/data/dbhome/device_supervisor/debugLog",
"debugLogSize": 2000
},
"clouds": [
{
"cacheSize": 10000,
"enable": 1,
"type": "Standard MQTT",
"args": {
"host": "mq194.imistaway.net",
"port": 1883,
"clientId": "rig-pump-12",
"auth": 1,
"tls": 0,
"cleanSession": 1,
"mqttVersion": "v3.1.1",
"keepalive": 120,
"key": "",
"cert": "",
"rootCA": "",
"verifyServer": 0,
"verifyClient": 0,
"username": "admin",
"passwd": "columbus",
"authType": 1,
"willQos": 0,
"willRetain": 0,
"willTopic": "",
"willPayload": "",
"tlsAuth": "caSelfSigned"
},
"name": "default",
"uploadRules": []
},
{
"cacheSize": 10000,
"enable": 1,
"name": "ThingsBoard",
"type": "Standard MQTT",
"args": {
"host": "hp.henrypump.cloud",
"port": 1883,
"clientId": "rig-pump-12",
"auth": 1,
"tls": 0,
"cleanSession": 0,
"mqttVersion": "v3.1.1",
"keepalive": 60,
"key": "",
"cert": "",
"rootCA": "",
"verifyServer": 0,
"verifyClient": 0,
"username": "7gXrx1ZD45RIx6FGMVbT",
"passwd": "",
"willQos": 0,
"willRetain": 0,
"willTopic": "",
"willPayload": ""
},
"uploadRules": []
}
],
"quickfaas": {
"genericFuncs": [],
"uploadFuncs": [
{
"name": "Send Data",
"trigger": "measure_event",
"topic": "meshify/db/194/_/rigpump/${MAC_LOWER}",
"qos": 1,
"groups": [
"default"
],
"funcName": "sendData",
"script": "# Enter your python code.\nimport json\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nimport re, uuid\nfrom paho.mqtt import client\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 for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n if measure[\"name\"] in [\"auto_manual\", \"auto_control_mode\", \"device_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 \n #publish(__topic__, json.dumps({measure[\"name\"]: measure[\"value\"]}), __qos__)\n\ndef convert_int(plc_tag, value):\n auto_manual = {\n 0: \"Manual\",\n 1: \"Auto\"\n }\n\n auto_control_mode = {\n 0: \"Pressure\",\n 1: \"Flow\"\n }\n\n device_status = {\n 1: \"Running\",\n 64: \"Idle\",\n 128: \"Overpressure\",\n 1024: \"Faulted\"\n }\n \n plc_tags = {\n \"auto_manual\": auto_manual.get(value, \"Invalid Code\"),\n \"auto_control_mode\": auto_control_mode.get(value, \"Invalid Code\"),\n \"device_status\": device_status.get(value, \"Invalid Code\"),\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n\n ",
"cloudName": "default",
"msgType": 0
},
{
"qos": 1,
"funcName": "sendData",
"script": "import json, os, time\nfrom common.Logger import logger\nfrom quickfaas.remotebus import publish\nfrom datetime import datetime as dt\nfrom mobiuspi_lib.gps import GPS\nfrom quickfaas.global_dict import get as get_params\nfrom quickfaas.global_dict import _set_global_args\n\ndef getGPS():\n # Create a gps instance\n gps = GPS()\n\n # Retrieve GPS information\n position_status = gps.get_position_status()\n logger.debug(\"position_status: \")\n logger.debug(position_status)\n latitude = position_status[\"latitude\"].split(\" \")\n longitude = position_status[\"longitude\"].split(\" \")\n lat_dec = int(latitude[0][:-1]) + (float(latitude[1][:-1])/60)\n lon_dec = int(longitude[0][:-1]) + (float(longitude[1][:-1])/60)\n if latitude[2] == \"S\":\n lat_dec = lat_dec * -1\n if longitude[2] == \"W\":\n lon_dec = lon_dec * -1\n #lat_dec = round(lat_dec, 7)\n #lon_dec = round(lon_dec, 7)\n logger.info(\"HERE IS THE GPS COORDS\")\n logger.info(f\"LATITUDE: {lat_dec}, LONGITUDE: {lon_dec}\")\n speedKnots = position_status[\"speed\"].split(\" \")\n speedMPH = float(speedKnots[0]) * 1.151\n return (f\"{lat_dec:.8f}\",f\"{lon_dec:.8f}\",f\"{speedMPH:.2f}\")\n\ndef chunk_payload(payload, chunk_size=20):\n if \"values\" in payload:\n # Original format: {\"ts\": ..., \"values\": {...}}\n chunked_values = list(payload[\"values\"].items())\n for i in range(0, len(chunked_values), chunk_size):\n yield {\n \"ts\": payload[\"ts\"],\n \"values\": dict(chunked_values[i:i+chunk_size])\n }\n else:\n # New format: {\"key1\": \"value1\", \"key2\": \"value2\"}\n chunked_keys = list(payload.keys())\n for i in range(0, len(chunked_keys), chunk_size):\n yield {k: payload[k] for k in chunked_keys[i:i+chunk_size]}\n\ndef sendData(message):\n #logger.debug(message)\n \n \n payload = {\"ts\": (round(dt.timestamp(dt.now())/600)*600)*1000, \"values\": {}}\n attributes_payload = {}\n for measure in message[\"measures\"]:\n try:\n logger.debug(measure)\n if measure[\"health\"] == 1:\n if measure[\"name\"] in [\"auto_manual\", \"auto_control_mode\", \"device_status\"]:\n logger.debug(\"Converting DINT/BOOL to STRING\")\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 except Exception as e:\n logger.error(e)\n\n try:\n payload[\"values\"][\"latitude\"], payload[\"values\"][\"longitude\"], payload[\"values\"][\"speed\"] = getGPS()\n except:\n logger.error(\"Could not get GPS coordinates\")\n\n for chunk in chunk_payload(payload=payload):\n publish(__topic__, json.dumps(chunk), __qos__, cloud_name=\"ThingsBoard\")\n time.sleep(2)\n\n attributes_payload[\"latestReportTime\"] = (round(dt.timestamp(dt.now())/600)*600)*1000\n for chunk in chunk_payload(payload=attributes_payload):\n publish(\"v1/devices/me/attributes\", json.dumps(chunk), __qos__, cloud_name=\"ThingsBoard\")\n time.sleep(2)\n \n\ndef convert_int(plc_tag, value):\n auto_manual = {\n 0: \"Manual\",\n 1: \"Auto\"\n }\n\n auto_control_mode = {\n 0: \"Pressure\",\n 1: \"Flow\"\n }\n\n device_status = {\n 1: \"Running\",\n 64: \"Idle\",\n 128: \"Overpressure\",\n 1024: \"Faulted\"\n }\n \n plc_tags = {\n \"auto_manual\": auto_manual.get(value, \"Invalid Code\"),\n \"auto_control_mode\": auto_control_mode.get(value, \"Invalid Code\"),\n \"device_status\": device_status.get(value, \"Invalid Code\"),\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")\n\n ",
"name": "sendData",
"trigger": "measure_event",
"topic": "v1/devices/me/telemetry",
"cloudName": "ThingsBoard",
"groups": [
"default"
],
"msgType": 0
}
],
"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\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 for controller in data:\n for measure in controller[\"measures\"]:\n #publish measure\n topic = \"meshify/db/194/_/rigpump/\" + mac + \"/\" + measure[\"name\"]\n if measure[\"name\"] in [\"auto_manual\", \"auto_control_mode\", \"device_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 = {\"rigpump\":{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\"], p[\"payload\"][\"name\"].split(\".\")[1], p[\"payload\"][\"value\"], wizard_api)\n\ndef ack(msgid, mac, name, value, wizard_api):\n #logger.debug(mac)\n mac = \"\".join(mac.split(\":\")[:-2])\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(mac,name, value), \"msgid\": str(msgid)}]))\n\ndef convert_int(plc_tag, value):\n auto_manual = {\n 0: \"Manual\",\n 1: \"Auto\"\n }\n\n auto_control_mode = {\n 0: \"Pressure\",\n 1: \"Flow\"\n }\n\n device_status = {\n 1: \"Running\",\n 64: \"Idle\",\n 128: \"Overpressure\",\n 1024: \"Faulted\"\n }\n\n plc_tags = {\n \"auto_manual\": auto_manual.get(value, \"Invalid Code\"),\n \"auto_control_mode\": auto_control_mode.get(value, \"Invalid Code\"),\n \"device_status\": device_status.get(value, \"Invalid Code\"),\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")",
"msgType": 0,
"trigger": "command_event",
"cloudName": "default"
},
{
"name": "receiveCommand",
"topic": "v1/devices/me/rpc/request/+",
"qos": 1,
"funcName": "receiveCommand",
"payload_type": "JSON",
"script": "import json, time\nfrom datetime import datetime as dt\nfrom quickfaas.measure import recall, write\nfrom quickfaas.remotebus import publish\nfrom common.Logger import logger\n\n# Helper function to split the payload into chunks\ndef chunk_payload(payload, chunk_size=20):\n chunked_values = list(payload[\"values\"].items())\n for i in range(0, len(chunked_values), chunk_size):\n yield {\n \"ts\": payload[\"ts\"],\n \"values\": dict(chunked_values[i:i+chunk_size])\n }\n\ndef sync():\n #get new values and send\n payload = {\"ts\": round(dt.timestamp(dt.now()))*1000, \"values\": {}}\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 [\"auto_manual\", \"auto_control_mode\", \"device_status\"]:\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 for chunk in chunk_payload(payload=payload):\n publish(topic, json.dumps(chunk), 1, cloud_name=\"ThingsBoard\")\n time.sleep(2)\ndef writeplctag(value):\n #value in the form {\"measurement\": <measurement_name>, \"value\": <value to write>}\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\": \"rigpump\", \"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(2)\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 auto_manual = {\n 0: \"Manual\",\n 1: \"Auto\"\n }\n\n auto_control_mode = {\n 0: \"Pressure\",\n 1: \"Flow\"\n }\n\n device_status = {\n 1: \"Running\",\n 64: \"Idle\",\n 128: \"Overpressure\",\n 1024: \"Faulted\"\n }\n\n plc_tags = {\n \"auto_manual\": auto_manual.get(value, \"Invalid Code\"),\n \"auto_control_mode\": auto_control_mode.get(value, \"Invalid Code\"),\n \"device_status\": device_status.get(value, \"Invalid Code\"),\n }\n\n return plc_tags.get(plc_tag, \"Invalid Tag\")",
"msgType": 0,
"cloudName": "ThingsBoard",
"trigger": "command_event"
}
]
},
"labels": [
{
"key": "SN",
"value": "GF5022210011326"
},
{
"key": "MAC",
"value": "00:18:05:1e:95:26"
},
{
"key": "MAC_UPPER",
"value": "C4:93:00:0E:E9:F0"
},
{
"key": "MAC_LOWER",
"value": "c4:93:00:0e:e9:f0"
}
],
"modbusSlave": {
"enable": 0,
"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": []
},
"iec101Server": {
"enable": 0,
"coms": "rs485",
"mode": "UnBalance",
"linkLen": 2,
"linkAddr": 1,
"asduLen": 2,
"ioaLen": 3,
"cotLen": 2,
"serverList": [
{
"asduAddr": 1
}
],
"linkTimeOut": 2000,
"timeSet": 1,
"idleTimeOut": 10000,
"byteOrder": "abcd",
"mapping_table": {
"YX": [],
"YC": [],
"YK": []
}
},
"iec104Client": {
"enable": 0,
"connectType": 2,
"serverAddr": "ipower.inhandcloud.cn",
"serverPort": 2406,
"communicationCode": "",
"protocol": 1,
"asduAddr": 1,
"tls": 1,
"verification": 1,
"mapping_table": {
"YX": [],
"YC": [],
"YK": []
}
},
"opcuaServer": {
"enable": 0,
"port": 4840,
"maximumLink": 5,
"securityMode": 0,
"identifierType": "String",
"certificate": "None",
"privateKey": "None",
"pubsub": 0,
"mapping_table": []
},
"sl651Slave": {
"enable": 0,
"centerAaddr": 1,
"remoteAddr": "",
"addrCode": "",
"password": "",
"platform_list": [],
"mapping_table": []
},
"hj212Client": {
"enable": 0,
"platform_list": [],
"block_list": [],
"mapping_table": []
},
"southMetadata": {},
"bindMetadata": {
"version": "",
"timestamp": ""
},
"bindConfig": {
"enable": 0,
"bind": {
"modelId": "",
"modelName": "",
"srcId": "",
"srcName": "",
"devId": "",
"devName": ""
},
"varGroups": [],
"variables": [],
"alerts": []
},
"templates": {},
"version": "2.7.1"
}

View File

@@ -0,0 +1,117 @@
import json, time
from datetime import datetime as dt
from quickfaas.measure import recall, write
from quickfaas.remotebus import publish
from common.Logger import logger
# Helper function to split the payload into chunks
def chunk_payload(payload, chunk_size=20):
chunked_values = list(payload["values"].items())
for i in range(0, len(chunked_values), chunk_size):
yield {
"ts": payload["ts"],
"values": dict(chunked_values[i:i+chunk_size])
}
def sync():
#get new values and send
payload = {"ts": round(dt.timestamp(dt.now()))*1000, "values": {}}
topic = "v1/devices/me/telemetry"
try:
data = recall()#json.loads(recall().decode("utf-8"))
except Exception as e:
logger.error(e)
logger.debug(data)
for controller in data:
for measure in controller["measures"]:
#publish measure
if measure["name"] in ["auto_manual", "auto_control_mode", "device_status"]:
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))
for chunk in chunk_payload(payload=payload):
publish(topic, json.dumps(chunk), 1, cloud_name="ThingsBoard")
time.sleep(2)
def writeplctag(value):
#value in the form {"measurement": <measurement_name>, "value": <value to write>}
try:
#value = json.loads(value.replace("'",'"'))
logger.debug(value)
#payload format: [{"name": "advvfdipp", "measures": [{"name": "manualfrequencysetpoint", "value": 49}]}]
message = [{"name": "rigpump", "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(2)
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):
auto_manual = {
0: "Manual",
1: "Auto"
}
auto_control_mode = {
0: "Pressure",
1: "Flow"
}
device_status = {
1: "Running",
64: "Idle",
128: "Overpressure",
1024: "Faulted"
}
plc_tags = {
"auto_manual": auto_manual.get(value, "Invalid Code"),
"auto_control_mode": auto_control_mode.get(value, "Invalid Code"),
"device_status": device_status.get(value, "Invalid Code"),
}
return plc_tags.get(plc_tag, "Invalid Tag")