Write Values to an Modbus/TCP Slave Device
Description
This script sets a value inside a Modbus/TCP slave device.
This is used if you want to link the form system back into your control or information systems to advise that that a job - such as an isolation - has been completed.
In turn, you could use this to indicate isolation in SCADA, route around the isolated equipment in your plant logic, or simply keep a history of events in your historian product without having to add additional data sources.
In the example below, the target Modbus address to be set is a property of the asset. We read the target address from the ARDI API before we set it.
We also set a fixed value (in this case, 1) to the address. Alternatively, you could set timestamps, strings etc.
Full Script
import requests import pymodbus from datetime import datetime import os import sys import traceback import warnings from pymodbus.client.sync import ModbusTcpClient #Set default details #The ARDI server to query server="localhost/s/bm" #The ARDI property containing the Modbus address mbaddressid=47 #Modbus connection details ipaddress="localhost" unit=1 port=502 register=0 offset=0 #The value to write valuetoset=1 asset = "Unknown Asset" checklist = "Unknown Checklist" user = "Unknown User" assetid = "1" tm = datetime.now().strftime("%Y/%m/%d %H:%M:%S") #Get submission details from environment variables try: asset = os.environ["assetname"] except: print "No Asset Provided" sys.exit(0) try: assetid = os.environ["assetid"] except: print "No Asset ID Provided" sys.exit(0) try: checklist = os.environ["checklist"] except: print "No Checklist Provided" sys.exit(0) try: user = os.environ["user"] except: print "No User Provided" sys.exit(0) def Sub(st,ass,chk,usr,dt): return st.replace("{checklist}",chk).replace("{asset}",ass).replace("{user}",usr).replace("{date}",dt) #Get isolation modbus address from server (assumes a Guest Mode server, otherwise we need to authenticate!) url = "http://" + server + "/api/asset/property?id=" + str(assetid) + "&property=" + str(mbaddressid) resp = requests.get(url) data = resp.content #Read the address from ARDI ind = data.find("<text>") if ind > 0: indx = data.find("</text>") totaloffset = ind + 6 value = data[totaloffset:indx] #Adjust the value based on the type of I/O point we are talking about. if len(value) > 3: if value[0] == '1': register = 1 offset = 1000 if len(value) > 4: offset = 10000 if value[0] == '3': register = 3 offset = 3000 if len(value) > 4: offset = 30000 if value[0] == '4': register = 4 offset = 4000 if len(value) > 4: offset = 40000 #Connect to modbus device client=ModbusTcpClient(ipaddress,port=port) client.connect() address = int(value)-offset #Write data at correct location... if register == 3: client.write_input_register(address,int(valuetoset),unit=unit) if register == 4: client.write_register(address,int(valuetoset),unit=unit) if register == 1: if valuetoset == 1: valuetoset = True else: valuetoset = False client.write_discrete_input(address,valuetoset,unit=unit) if register == 0: if valuetoset == 1: valuetoset = True else: valuetoset = False client.write_coil(address,valuetoset,unit=unit) #If everything worked out, send the word 'OK'. print 'OK'