# Alarming directly from a module

**URL:** <https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098>\
**Category:** Module Development\
**Created:** [December 14, 2021, 1:54pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098 "2021-12-14T13:54:40Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![jtdfan](https://avatars.discourse-cdn.com/v4/letter/j/a88e4f/32.png) [@jtdfan](https://forum.inductiveautomation.com/u/jtdfan)\
**Post date:** [December 14, 2021, 1:54pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/1 "2021-12-14T13:54:40Z")

</div>

Can someone provide an example on how to use alarming within a module?

[https://docs.inductiveautomation.com/display/SE/Working+with+Platform+Services](https://docs.inductiveautomation.com/display/SE/Working+with+Platform+Services)

We want to be able to set an active alarm when a function call fails without having to create and/or update a tag every time there is an alarm.

Any help would be appreciated

Josh

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 14, 2021, 1:58pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/2 "2021-12-14T13:58:49Z")

</div>

Seems like you were most of the way there in this thread:

> [@Alarming from within a module](https://forum.inductiveautomation.com/t/alarming-from-within-a-module/51748/6):
>
> Still trying to work through this based on the SDK Programmer Guide and the JavaDocs, but struggling with a few things. The SDK guide says Most alarms in Ignition are defined on tags. However, it is possible for modules to generate their own alarms. All alarm evaluation is handled by the AlarmManager, you simply give it the definition of an alarm through AlarmManager.registerAlarm(…), and it provides you with an AlarmEvaluator that you update from time to time with the current value. Howeve…

What happened? Where did you get stuck?

---

<div class="post-metadata">

**Author:** ![jtdfan](https://avatars.discourse-cdn.com/v4/letter/j/a88e4f/32.png) [@jtdfan](https://forum.inductiveautomation.com/u/jtdfan)\
**Post date:** [December 14, 2021, 2:02pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/3 "2021-12-14T14:02:26Z")

</div>

Thanks Kevin,

I can’t get the alarm to show as active and unacknowledged specifically through the [System]Gateway/Alarming/Active and Acked tag or through the Alarm Log.

So I can put it in the Journal as Active, but it doesn’t show it as an active alarm. I have been trying to get an answer on this for a while and since there was no activity on my original post I made a new one.

Josh

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 14, 2021, 2:04pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/4 "2021-12-14T14:04:05Z")

</div>

Can you post the current code you have?

---

<div class="post-metadata">

**Author:** ![jtdfan](https://avatars.discourse-cdn.com/v4/letter/j/a88e4f/32.png) [@jtdfan](https://forum.inductiveautomation.com/u/jtdfan)\
**Post date:** [December 14, 2021, 2:07pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/5 "2021-12-14T14:07:52Z")

</div>

Here is a collection of code I have tried to use. LIFT is the name of our product we are developing. The liftGatewayContext is the gatewayContext object for our gateway part of the module. It is probable that this is a combination of things and it won’t work in its current state. This is currently not being used in our project and hasn’t really been looked at in a few weeks.

```auto
public void createAlarm() {
        try {

            // Qualified Path
            var addr = InetAddress.getLocalHost();
            String hostname = addr.getHostName();
            QualifiedPath.Builder qualifiedPathBuilder = new QualifiedPath.Builder();
            qualifiedPathBuilder.setAlarm("Test Alarm");
            qualifiedPathBuilder.setMachine(hostname);
            qualifiedPathBuilder.setProvider("LIFT");
            qualifiedPathBuilder.setEvent("1");
            //qualifiedPathBuilder.setSource(source);
            //qualifiedPathBuilder.setUser(user);
            //qualifiedPathBuilder.setTag("testAlarm");
            QualifiedPath qualifiedPath = qualifiedPathBuilder.build();
            logger.info("Qualified Path " + qualifiedPath.toString());

            BasicPropertySet bsp = new BasicPropertySet();
            EventData eventData = new EventData();
            eventData.set(CommonAlarmProperties.Label, "LIFT Alarm Test");
            eventData.set(AlarmModeProperties.Mode, AlarmMode.Equality);
            eventData.set(AlarmModeProperties.SetpointA, 1.0);
            eventData.set(CommonAlarmProperties.IsSystemEvent, true);
            eventData.set(CommonAlarmProperties.EventValue, 1.0);
            BasicAlarmEvent alarmEvent = new BasicAlarmEvent(qualifiedPath, "LIFT", AlarmPriority.Low);
            alarmEvent.active(eventData);
            liftGatewayContext.getAlarmManager().getJournalManager().storeEvent(alarmEvent, AlarmStateTransition.Active);

            alarmEvent.acknowledge(eventData);
            liftGatewayContext.getAlarmManager().getJournalManager().storeEvent(alarmEvent, AlarmStateTransition.Ack);
            eventData.set(CommonAlarmProperties.EventValue, 0.0);
            alarmEvent.clear(eventData);
            liftGatewayContext.getAlarmManager().getJournalManager().storeEvent(alarmEvent, AlarmStateTransition.Clear);

            // Parent Properties
            BasicPropertySet basicPropertySet = new BasicPropertySet();

            // Alarm Definition
            BasicAlarmDefinition alarmDefinition = new BasicAlarmDefinition();
            alarmDefinition.set(CommonAlarmProperties.DisplayPath,"LIFT/Alarms");
            alarmDefinition.set(CommonAlarmProperties.Enabled, true);
            alarmDefinition.set(CommonAlarmProperties.IsSystemEvent, true);
            alarmDefinition.set(CommonAlarmProperties.Label, "Test");
            alarmDefinition.set(CommonAlarmProperties.Name, "LIFT Alarm Test");
            alarmDefinition.set(CommonAlarmProperties.Priority, AlarmPriority.Low);
            alarmDefinition.set(CommonAlarmProperties.Source, qualifiedPath);
            alarmDefinition.set(AlarmModeProperties.Mode, AlarmMode.Equality);
            alarmDefinition.set(AlarmModeProperties.SetpointA, 1.0);
            logger.info("Alarm Definition " + alarmDefinition.getName() + " " + alarmDefinition.getRawValueMap().toString());

            // Alarm Configuration
            BasicAlarmConfiguration alarmConfiguration = new BasicAlarmConfiguration();
            alarmConfiguration.add(alarmDefinition);
            logger.info("Alarm Configuration " + alarmConfiguration.get("LIFT Alarm Test").getProperties());

            // Expression Context
            ExpressionContext expressionContext = null;

            AlarmEvaluator alarmEvaluator = LiftGatewayContext.get().getGatewayContext().getAlarmManager().registerAlarm(qualifiedPath, basicPropertySet, alarmConfiguration, null);
            logger.info("Alarm Evaluator " + alarmEvaluator.getState().getEvaluationStatus().toString());

            // Evaluate
            BasicQualifiedValue basicQualifiedValue = new BasicQualifiedValue();
            basicQualifiedValue.setValue(1.0);
            basicQualifiedValue.setQuality(QualityCode.Good);
            basicQualifiedValue.setTimestamp(DateTime.now().toDate());

            alarmEvaluator.evaluate(basicQualifiedValue);
            logger.info("Alarm Evaluator " + alarmEvaluator.getState().getEvaluationStatus().toString());
            alarmEvaluator.release();
        }
        catch (Exception ex) {
            logger.error("Create Alarm Failed", ex);
        }
    }

```

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 14, 2021, 2:14pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/6 "2021-12-14T14:14:57Z")

</div>

Not sure what all that event creation and manual storing in the journal is for. I don't think that would be needed if the Alarm is properly created and then triggered/evaluated by Ignition.

@eric.hollering had it right in the original thread - all you should really need is to register an alarm via `AlarmManager::registerAlarm` with a configuration that would always cause the alarm to trip and then whenever you want to fire it just call `AlarmEvaluator::evaluate` with some value.

> [@jtdfan](#):
>
> but it doesn’t show it as an active alarm

Do you mean that an alarm triggered by the method mentioned previously doesn't show up in the alarm status table?

---

<div class="post-metadata">

**Author:** ![jtdfan](https://avatars.discourse-cdn.com/v4/letter/j/a88e4f/32.png) [@jtdfan](https://forum.inductiveautomation.com/u/jtdfan)\
**Post date:** [December 14, 2021, 2:50pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/7 "2021-12-14T14:50:03Z")

</div>

Kevin,

When doing the above code examples, I can get the alarm in the journal, but not in the alarm status table and it doesn’t impact the System\Gateway\Alarming tags which we are using for some UI elements.

I think we are struggling with what needs to go into the registerAlarm.

An example of setting up a  
QualifiedPath  
PropertyValueSource  
AlarmConfiguration  
ExpressionParseContext  
etc

The documentation doesn’t provide much in the way of an example for how to use registerAlarm.

1. We have a class in our module
2. We have functions in that class
3. We would like to register an alarm for the class
4. When an exception or error occurs, we would like to trigger an alarm.

That’s primarily what we are looking for.

Does that make sense?

Josh

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 14, 2021, 2:52pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/8 "2021-12-14T14:52:43Z")

</div>

I have confirmed the following example code works.

Create an AlarmDefinition:

```java
private static class TestAlarmDefinition extends BasicAlarmDefinition {

    public TestAlarmDefinition() {
        UUID id = UUID.randomUUID();
        setName("MyAlarm/" + id);
        set(AlarmModeProperties.Mode, AlarmMode.AnyChange);
        set(AlarmModeProperties.OnEachEvaluation, Boolean.TRUE);
        set(CommonAlarmProperties.NotifyInitialEvent, Boolean.TRUE);
        set(CommonAlarmProperties.DisplayPath, id.toString());
        set(CommonAlarmProperties.Priority, AlarmPriority.High);
    }

}

```

Create the evaluator and trigger the alarm:

```java
QualifiedPath path = QualifiedPath.of(
    WellKnownPathTypes.Source, "MyModule",
    WellKnownPathTypes.Alarm, "MyAlarm"
);
var definition = new TestAlarmDefinition();
var configuration = new BasicAlarmConfiguration(Collections.singletonList(definition));

AlarmEvaluator evaluator = getContext().getAlarmManager().registerAlarm(
    path,
    null,
    configuration,
    null
);

getContext().getScheduledExecutorService().scheduleAtFixedRate(
    () -> {
        LoggerFactory.getLogger("AlarmTest").info("Evaluating alarm...");

        evaluator.evaluate(new BasicQualifiedValue(Boolean.TRUE));
    },
    10, 10, TimeUnit.SECONDS
);

```

These show up in the alarm status table and the alarm system tags. Because it uses an “any change” alarm the event is always cleared, not active, but it _is_ unacknowledged.

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [December 14, 2021, 4:06pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/9 "2021-12-14T16:06:28Z")

</div>

Thanks @Kevin.Herron, we appreciate the example and are excited to give this a shot. I know it might seem a little obscure, but being able to leverage alarming decoupled from the tag structure has some pretty important implications for certain customer scenarios, and keeping it within the existing platform toolset will be a good win for us.

---

<div class="post-metadata">

**Author:** ![eric.hollering](https://avatars.discourse-cdn.com/v4/letter/e/ad7895/32.png) [@eric.hollering](https://forum.inductiveautomation.com/u/eric.hollering)\
**Post date:** [December 14, 2021, 8:42pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/10 "2021-12-14T20:42:22Z")

</div>

We have successfully implemented this after reviewing the example.

Thanks again.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [December 14, 2021, 8:57pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/11 "2021-12-14T20:57:35Z")

</div>

Make sure that you release the evaluator during your module shutdown or when you are otherwise done generating alarms, not immediately like in the previous code samples you provided.

---

<div class="post-metadata">

**Author:** ![jtdfan](https://avatars.discourse-cdn.com/v4/letter/j/a88e4f/32.png) [@jtdfan](https://forum.inductiveautomation.com/u/jtdfan)\
**Post date:** [January 19, 2022, 9:32pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/12 "2022-01-19T21:32:24Z")

</div>

We are very close, but noticed an odd problem. Can I get someone else’s thoughts?

The Alarm Log looks correct in regards to DisplayPath and Label

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/6/761348ef53bb7ba012c1b09873f8feb48903bdc7.png)

However, that is not translating to the Alarm Journal

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/1/01de8a3fa94e8891f15d0875f2a34dd2cf0e997f.png)

Any input would be appreciated.

```auto
public void raiseAlarm(String code, String message, AlarmPriority priority, String displayPath, String label, String notes) {
        var alarmDefinition = new BasicAlarmDefinition();
        UUID id = UUID.randomUUID();
        alarmDefinition.setName(code + "/" + id);
        // AnyChange means this will fire whenever the evaluator's evaluate method is called.
        // Because there's no value source to evaluate against, the state will always be cleared.
        // If, in the future, we want to set an Active alarm state rather than cleared, we can use AlarmMode.Equality
        // or similar with a setpoint property, and the active state can be driven by the value passed into the evaluate function.

        // For now, we've kept this simple, with the thinking that the alarm state would be cleared in these cases,
        // since the driving event (a code exception / processing error condition) will be fired and require a manual intervention.

        // It might be especially interesting to consider using the active state in a case where a failure may be able to
        // be resolved through automation. For example, a failed message to do an inventory move could allow for automated retries,
        // and in the event that a retry succeeds, the alarm could clear.

        // Here's an example of an equality config, looking for a 1 as SetpointA
        alarmDefinition.set(AlarmModeProperties.Mode, AlarmMode.Equality);
        alarmDefinition.set(AlarmModeProperties.SetpointA, 1d);

        //alarmDefinition.set(AlarmModeProperties.Mode, AlarmMode.AnyChange);
        //alarmDefinition.set(AlarmModeProperties.OnEachEvaluation, Boolean.TRUE);
        alarmDefinition.set(CommonAlarmProperties.NotifyInitialEvent, Boolean.TRUE);
        alarmDefinition.set(CommonAlarmProperties.EventId, id);
        alarmDefinition.set(CommonAlarmProperties.Label, label);
        alarmDefinition.set(CommonAlarmProperties.DisplayPath, displayPath);
        alarmDefinition.set(CommonAlarmProperties.Priority, priority);
        alarmDefinition.set(CommonAlarmProperties.Notes, notes);

        QualifiedPath path = QualifiedPath.of(
                WellKnownPathTypes.Source, "LIFT Module",
                WellKnownPathTypes.Alarm, code
        );

        var configuration = new BasicAlarmConfiguration(Collections.singletonList(alarmDefinition));

        var evaluator = this.getGatewayContext().getAlarmManager().registerAlarm(
                path,
                null,
                configuration,
                null
        );

        evaluator.setAlarmObserver(this);

        evaluators.put(id, evaluator);

        evaluator.evaluate(new BasicQualifiedValue(Boolean.TRUE));
    }

```

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [January 19, 2022, 10:11pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/13 "2022-01-19T22:11:18Z")

</div>

You seem to be creating a new definition and registering a new evaluator every time you call `raiseAlarm`, which I assume is every time you want to generate an alarm, and that seems problematic to me and may be the cause of your issue.

Note that my example creates one definition and one evaluator and then re-uses it each time it generates a new alarm event using the evaluator.

---

<div class="post-metadata">

**Author:** ![jtdfan](https://avatars.discourse-cdn.com/v4/letter/j/a88e4f/32.png) [@jtdfan](https://forum.inductiveautomation.com/u/jtdfan)\
**Post date:** [January 20, 2022, 2:43pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/14 "2022-01-20T14:43:56Z")

</div>

Currently, that is true, but we are also releasing the evaluator on acknowledge as we are clearing the alarm as well. Does that still make this an issue?

```auto
/**
     * LIFT Alarm Transitioned State
     * @param alarmEvent - Alarm Event that occurred
     * @param alarmStateTransition - Current Alarm State
     */
    @Override
    public void alarmTransitioned(AlarmEvent alarmEvent, AlarmStateTransition alarmStateTransition) {
        if (alarmStateTransition == AlarmStateTransition.Ack) {
            logger.debug("Alarm (" + alarmEvent.getName() + ") Acknowledged");
            alarmEvent.clear(alarmEvent.getAckData());
            logger.debug("Alarm (" + alarmEvent.getName() + ") Cleared");
            // Get evaluator and remove from map
            UUID id = UUID.fromString(alarmEvent.getName());
            evaluators.get(id).release();
            evaluators.remove(id);
        }
    }

```

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [January 20, 2022, 2:56pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/15 "2022-01-20T14:56:14Z")

</div>

Make the changes and find out. You shouldn’t be releasing on ack either - release when your module shuts down or you are otherwise done ever firing that alarm. Each time you create a new definition you are defining a new alarm with a new UUID and I’m wondering if the journal doesn’t work because by the time it’s there viewing it you’ve unregistered and moved onto a new UUID.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 20, 2022, 4:14pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/16 "2022-01-20T16:14:31Z")

</div>

Also, your additional config is probably showing up as “static” config to the alarm journal system, and therefore not being logged to the journal unless you specifically configured your alarm journal to do so.

---

<div class="post-metadata">

**Author:** ![jtdfan](https://avatars.discourse-cdn.com/v4/letter/j/a88e4f/32.png) [@jtdfan](https://forum.inductiveautomation.com/u/jtdfan)\
**Post date:** [January 21, 2022, 6:39pm UTC](https://forum.inductiveautomation.com/t/alarming-directly-from-a-module/54098/17 "2022-01-21T18:39:10Z")

</div>

So, after what Paul said, we enabled Static Config to be stored in the journal

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/7/2/724ca4940711bde62b75f9269b76f21e4fcc7474.png)

We also changed the alarmTransitioned code to reevaluate the alarm before releasing it.

```auto
/**
     * LIFT Alarm Transitioned State
     * @param alarmEvent - Alarm Event that occurred
     * @param alarmStateTransition - Current Alarm State
     */
    @Override
    public void alarmTransitioned(AlarmEvent alarmEvent, AlarmStateTransition alarmStateTransition) {
        if (alarmStateTransition == AlarmStateTransition.Ack) {
            logger.debug("Alarm (" + alarmEvent.getName() + ") Acknowledged");
            //alarmEvent.clear(alarmEvent.getAckData());

            // Get evaluator and remove from map
            UUID id = UUID.fromString(alarmEvent.getName());
            evaluators.get(id).evaluate(new BasicQualifiedValue(Boolean.FALSE));
            logger.debug("Alarm (" + alarmEvent.getName() + ") Cleared");
            evaluators.get(id).release();
            logger.debug("Alarm (" + alarmEvent.getName() + ") Evaluator Released");
            evaluators.remove(id);
        }
    }

```

This is what the journal looks like now and it looks how I would expect it. Is there a better way to do this?

 ![AlarmJournal](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/4/34c70dd6e62c1240b9c4aa7fab2b2f304a6ee8fc.png)
