Hello folks,
I’m trying to access alarm events associated data without knowing what it is. In a notification pipeline script block.
A bit like I would do
for k, v in alarm.items()
with a dictionnary.
Is there any way to figure out what data is present on an alarm ?
PyAlarmEvent
implements a bunch of interfaces, including Iterable<PropertyValue>
, so even something as simple as:
for pv in alarm:
print pv.property, pv.value
Should work. No automatic unpacking, though, unfortunately.
I though I tried that…
I’ll try again, thanks Paul
Yeah so here's the issue: In the script block of the notification pipeline, it's not a PyAlarmEvent
but this pretty thing: com.inductiveautomation.ignition.alarming.pipelines.blocks.ScriptableBlock$ScriptableBlockPyAlarmEvent
So i get this error when trying to iterate through it:
com.inductiveautomation.ignition.common.script.JythonExecException: TypeError: 'com.inductiveautomation.ignition.alarming.pipelines.blocks.ScriptableBlock$ScriptableBlockPyAlarmEvent' object is not iterable
1 Like
Sure… but:

Any of these should do the trick?
for prop in alarm.properties:
print prop.name, prop.type, prop.defaultValue
print alarm.get(prop)
for prop in alarm.sourceEvent().properties:
print prop.name, prop.type, prop.defaultValue
print alarm.get(prop)
for pv in alarm.sourceEvent().values:
prop = pv.prop
print prop.name, prop.type, prop.defaultValue
print pv.value
First one resulted in an error: NoneType is not iterable
Second and third ones give me some results, but not the associated data. I’ll investigate those tomorrow, see if I can get something out of them
Ohhh, my fault.
I think you need to step from the alarm event into the active/clear/ack data:
https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.16/com/inductiveautomation/ignition/common/alarming/AlarmEvent.html#getActiveData()
Which will itself be another property set that (again, theoretically) should be directly iterable.
I’ll try this tomorrow if I can find some time between changing diapers (I’m on 4months old poop factory duty).
I do have another question though: How can I properly test pipeline scripts ? Is there some way for me to mock up a pipeline alarm event in the script console to inspect the object and play around with it ?
I did try to import a few things in the script console, but everything failed. Couldn’t figure out the right things I’d need.
I’ve been doing it directly in the pipeline, logging things and sending email notifications to output data, but that’s far from ideal…
I have a set of boolean tags with alarms configured on them, it’s much easier to just click the tags to send an alarm through the pipeline.
But it doesn’t help in inspecting the event object itself, I’d rather be able to instantiate a dummy event in the console and mess with it there.
With sufficient effort, you could generate an event on the gateway the same way the testing page does, but you won’t be able to do it from the designer - you won’t have the right classes, so you’d at best be system.util.sendMessage
-ing to the gateway to describe the event.
Eh, sendMessage
ing things to a page that would display the info actually sounds like an improvement… Would be more readable than the logs.
Is this a terrible idea ?
You’re in unsupported territory as far as creating and firing the events goes. I’d have to look at how the test page does it to know how to properly do that.
So, here’s the simplest I could do…
context = [
(str(p.property.name).lstrip("context_"), p.value)
for p in event.sourceEvent().activeData if str(p.property.name).startswith('context')
]
(I prefixed them with ‘context_’ myself so I could differentiate them, but I guess I could use the type of the property instead)
I kinda feel like there should be an easier way to get unknown associated data from an event in a pipeline script :X
This works (see below), at least in Ignition v8.1.18. Posting here for the benefit of others.
def handleAlarm(event):
# Uncomment next two lines for debug output (if needed), prints event properties to wrapper.log,
for d in dir(event): print d
for p in event.getProperties(): print"'event['{}']: {} {}".format(p, event[p], type(event[p]))
I found there are several properties not listed in available documentation.
Specifically projectName
and pipelineName
were useful to me.
Here is some sample output from the second line, modified to remove identifying details.
event['branchDepth'] <type 'int'>
event['notes'] <type 'unicode'>
event['itemPath'] <type 'unicode'>
event['activeDuration'] <type 'unicode'>
event['timeOnDelaySeconds'] <type 'float'>
event['shelvingAllowed'] <type 'bool'>
event['isActive'] <type 'bool'>
event['eventTime'] <type 'java.util.Date'>
event['source'] <type 'com.inductiveautomation.ignition.common.QualifiedPath'>
event['ackUserName'] <type 'unicode'>
event['enabled'] <type 'bool'>
event['isAcked']: <type 'instancemethod'>
event['mode'] <type 'com.inductiveautomation.ignition.common.alarming.config.AlarmMode'>
event['ackTime'] <type 'NoneType'>
event['ackUser'] <type 'NoneType'>
event['clearTime'] <type 'java.util.Date'>
event['deadband'] <type 'float'>
event['timeOffDelaySeconds'] <type 'float'>
event['state'] <type 'com.inductiveautomation.ignition.common.alarming.AlarmState'>
event['pipelineVersion'] <type 'long'>
event['displayPath'] <type 'com.inductiveautomation.ignition.common.StringPath'>
event['displayPathOrSource'] <type 'unicode'>
event['pipelineTransitionCount'] <type 'int'>
event['pipelineName'] <type 'unicode'>
event['projectName'] <type 'unicode'>
event['fullItemPath'] <type 'unicode'>
event['itemName'] <type 'unicode'>
event['label'] <type 'unicode'>
event['priority'] <type 'com.inductiveautomation.ignition.common.alarming.AlarmPriority'>
event['isJournaled'] <type 'bool'>
event['ackNotesReqd'] <type 'bool'>
event['timestampSource'] <type 'com.inductiveautomation.ignition.common.sqltags.model.types.TimestampSource'>
event['ackMode'] <type 'com.inductiveautomation.ignition.common.sqltags.model.types.AlertAckMode'>
event['eventValue'] <type 'bool'>
event['isShelved'] <bound method com.inductiveautomation.ignition.alarming.pipelines.blocks.ScriptableBlock$ScriptableBlockPyAlarmEvent.isShelved of Event[name=Alarm, source=prov:default:/tag:_Test-Tyler/TestBool:/alm:Alarm, priority=Low, desc=null]> <type 'instancemethod'>
event['ackDuration']: <type 'unicode'>
event['activeTime']: <type 'java.util.Date'>
event['isClear'] <type 'bool'>
event['eventState'] <type 'com.inductiveautomation.ignition.common.alarming.AlarmStateTransition'>
event['name']: Alarm <type 'unicode'>
event['deadbandMode'] <type 'com.inductiveautomation.ignition.common.sqltags.model.types.DeadbandMode'>
1 Like
I don't think getProperties
gets you associated data.
I found those in event.sourceEvent().activeData
1 Like
I (Ignition 8.1.42 within Alarm Pipeline script) was able to retrieve associated data via event.sourceEvent().getActiveData()
. and also event.getActiveData()
.
.. and then accessing specifics of each PropertyValue using:
myLogger = system.util.getLogger("Test_Pipeline")
activeData = event.getActiveData()
for prop in activeData:
myLogger.info("key={}, value={}".format(prop.getProperty().getName(), prop.getValue()))
Here is my latest attempt to identify and access alarm associated data from an event in an alarm notification pipeline script, without prior knowledge what alarm associated data might exist.
The basic approach here is to create a set from the properties found in in event.getActiveData().getProperties()
and then remove any matching properties that exist in the built-in CommonAlarmProperties
and AlarmModeProperties
. In theory that leaves only the alarm associated data.
def handleAlarm(event):
from com.inductiveautomation.ignition.common.alarming.config import CommonAlarmProperties, AlarmModeProperties
associatedDataProps = list(set(event.getActiveData().getProperties()).difference(AlarmModeProperties.values()).difference(CommonAlarmProperties.values()))
for prop in associatedDataProps:
print prop, event.get(prop)
Seems to work. Has anyone discovered better solutions?