Hello everyone, I'm relatively new to Ignition and come from a low-code application development background, not industrial automation or PLC programming. I've taken on a project at my company because we currently don't have anyone else diving into these areas. It's not technically in my job title but trying to help out since we have limited resources. I could really use some guidance on setting up a Gateway Tag Change Script correctly!
Situation
I'm trying to set up a script that monitors specific tags (related to natural gas levels and temperatures) and sends this data to a webhook whenever these tags change. While I can see the tags change in real-time (they are definitely updating), the script meant to post this data isn't triggering.
Note: The webhook in my script is for testing, not our actual target, so I can play around with it and not disrupt anything. The ultimate goal is to post to a 3rd party webhook so they can help us monitor our meters -- we just need a way to get them the data, so this is what we/they came up with.
Steps Taken
1. Script Execution Location
I’ve set up my script under the Gateway Tag Change Scripts in Ignition. This is how I've configured it:
- Script Name: TagChange_v4
- Change Triggers: Value (to trigger the script when the value changes)
- Tag Path(s): I have listed all the tag paths I want to monitor. They all check out correctly when I hit the "Check Tag Paths" button.
2. Project Script Library
I created a script in the Project Library called dataPublisher
. This project is named STF_Scripting
. It does execute on the Gateway, but it doesn't post anything to the webhook or log any information.
Here’s the script I added in dataPublisher
-- it's in my Project Library:
# dataPublisher
import system
import json
from java.text.SimpleDateFormat
from java.util import Date
def postTagChangeData(event):
logger = system.util.getLogger("Losant Data Publisher")
try:
# Skip the initial change event
if event.initialChange:
logger.info("Initial change event skipped.")
return
# URL and headers for the webhook
url = 'https://ignitionlosant.free.beeceptor.com'
headers = {"Content-Type": "application/json"}
# Get the current time in the specified format
dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
current_time = dateFormat.format(Date())
# List of tag paths
tagPaths = [
"[default]NaturalGas/Hot_H2O_Tnk_1_Lvl",
"[default]NaturalGas/Hot_H2O_Tnk_1_Tmp",
"[default]NaturalGas/Hot_H2O_Tnk_2_Lvl",
"[default]NaturalGas/Hot_H2O_Tnk_2_Tmp",
"[default]NaturalGas/Cold_H2O_Tnk_3_Lvl",
"[default]NaturalGas/Cold_H2O_Tnk_3_Tmp"
]
# Read the tag values
values = system.tag.readBlocking(tagPaths)
# Construct data payload
data_payload = {}
for i, tagPath in enumerate(tagPaths):
data_payload[tagPath] = values[i].value
# Log the data payload for debugging
logger.info("Data payload: {}".format(data_payload))
# Prepare the final JSON payload
json_payload = json.dumps({
"data": data_payload,
"time": {"$date": current_time}
})
# Log the JSON payload for debugging
logger.info("JSON payload: {}".format(json_payload))
# Send the HTTP POST request
client = system.net.httpClient()
response = client.post(url, headers=headers, data=json_payload)
# Log the response from the server
if response.good:
logger.info("HTTP POST request sent to Losant. Status Code: {}, Response: {}".format(response.statusCode, response.text))
else:
logger.error("HTTP POST request failed. Status Code: {}, Response: {}".format(response.statusCode, response.text))
except Exception as e:
# Log any exceptions that occur
logger.error("Error sending data to Losant: " + str(e))
Webhook:
I have verified that the webhook I'm using for testing is fully functional. I can post to it from Ignition using the normal script module and I can post to it from Postman, so seems like it's just an issue with either a) me taking the wrong approach or b) this kind of workflow not being possible and I need to change directions/learn more about how Ignition functions?
Summary
Feel free to make me look like a complete idiot if I'm taking the wrong approach here or missing something obvious!
I haven't been able to find any direct guidance on posting from a script of this nature to a webhook. The idea was:
- Function
postTagChangeData
: Reads the values of the specified tags from theevent
object, constructs a payload, and sends it to the webhook. - Gateway Event Script: Triggers on any change in the specified tags and calls
postTagChangeData
.