# Sound for critical alarms

**URL:** <https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877>\
**Category:** Ignition\
**Tags:** perspective\
**Created:** [December 16, 2024, 1:00pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877 "2024-12-16T13:00:52Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andreas\_Wallevik](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/andreas_wallevik/32/64045_2.png) [@Andreas\_Wallevik](https://forum.inductiveautomation.com/u/Andreas_Wallevik)\
**Post date:** [December 16, 2024, 1:00pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/1 "2024-12-16T13:00:52Z")

</div>

Hello,

Quick question in regards to the [Audio component](https://www.docs.inductiveautomation.com/docs/8.1/appendix/components/perspective-components/perspective-display-palette/perspective-audio) in Perspective.

I wish to have a sound play when a critical alarm is triggered.

What would be the best way to achieve this?

Anyone have any experience with this?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 16, 2024, 1:05pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/2 "2024-12-16T13:05:59Z")

</div>

You cannot rely on the browser your Perspective client is using to allow auto-play of your sound, nor be sure the sound on that PC is even on. You cannot even rely on there **being** an open Perspective client to play the sound.

**Critical** audible alerts must be wired to the system, not to any client. Preferably directly to the system's PLC, but possibly to the Ignition gateway (where a gateway event can use `system.util.playSoundClip()` to play through the gateway's sound card).

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [December 16, 2024, 2:22pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/3 "2024-12-16T14:22:19Z")

</div>

If Ignition handles defining alarm priority, what is considered best practice for the alerts to be wired to a PLC? I've always wanted to ask others what they do on this. I know I could hard code in the PLC, but then that opens up discrepancies between what the HMI shows as an alarm priority and the PLC.

I usually setup an alarm listener and then send this data to the PLC by a gateway event. The alarm listener opens up the possibility to handle different priorities or even other alarm properties.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 16, 2024, 2:56pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/4 "2024-12-16T14:56:35Z")

</div>

If a PLC is going to sound or flash the alarm (literally), I don't make the logic rely on the gateway. That's the point of having the PLC do it.

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [December 16, 2024, 3:04pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/5 "2024-12-16T15:04:19Z")

</div>

Right, so how do you correlate the two (HMI \<--\> PLC)? We usually wire horns/lights to the PLC simply because that's easier to do, not because it's a "critical" function. Just curious on what others do on this, not meaning to hijack a thread or get in a needless debate.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 16, 2024, 3:08pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/6 "2024-12-16T15:08:12Z")

</div>

When there is an HMI independent of Ignition (I prefer Vision on machines...), I don't see how the priority coordination can be anything other than custom. 🤷‍♂️

When Ignition is also the HMI, I prefer that the PLC simply **generate** the alarms, with Ignition following the PLC's lead for critical alarms, and Ignition setting the priority for anything else. And Ignition handling all acknowledgements, if any.

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [December 16, 2024, 3:09pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/7 "2024-12-16T15:09:36Z")

</div>

Ok, custom is all I could think of as well.

---

<div class="post-metadata">

**Author:** ![Andreas\_Wallevik](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/andreas_wallevik/32/64045_2.png) [@Andreas\_Wallevik](https://forum.inductiveautomation.com/u/Andreas_Wallevik)\
**Post date:** [December 17, 2024, 10:38am UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/8 "2024-12-17T10:38:19Z")

</div>

Thanks for the feedback!

Here's how i solved it.

### **Views/AlarmView**

1. **Created an Audio Component**
2. **Created a Custom Property on the View**

- **Name** : `playAlarm`
- **Type** : Boolean (automatically set to `False` upon creation).

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

1. **Expression Binding on `playAlarm`**  
I set up an **Expression Binding** using `runScript()` to check for active alarms:

```python
runScript("len(system.alarm.queryStatus(priority=['Critical'], state=['ActiveUnacked'])) > 0", 2500)

```

- This checks every 2.5 seconds if there are any alarms with the following criteria:
  - **Priority** : Critical
  - **State** : ActiveUnacked (Active and Unacknowledged).

- The result (`True/False`) updates the `playAlarm` property.

1. **Binding `playAlarm` to Audio Component's `props.play`**

- I linked the `play` property of the Audio Component directly to the `playAlarm` property.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/2/822ddf9589df7af72a1f70a83a46d52d60e95f3c.png)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/d/bd30d463401d2ebf05250058fb4241db277ff182.png)

1. **Audio Component's `props.source`**

- Added a test sound with the URL:

```python
https://www2.cs.uic.edu/~i101/SoundFiles/taunt.wav

```

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/e/d/ed1b7d1e071ef36984564682d68b908f9c34590d.png)

1. **Test Tag**

- Created a test tag with a **Critical** setpoint to verify the alarm functionality.

* * *

### **Behavior**

- This configuration will allow the alarm sound to play **only on this specific view** (`Views/AlarmView`).

* * *

### **Global Playback Configuration**

To enable sound playback globally, on **any view** or through a **main view** , i:

1. Used **Session Properties** for the `playAlarm` value.
2. Placed the **Audio Component** on a persistent view, `/headerview` in this case.

* * *

### **Testing**

- I tested the alarm by setting the value of the test tag to **100** (Critical setpoint), and the sound triggered successfully in the client.

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [December 17, 2024, 2:51pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/9 "2024-12-17T14:51:10Z")

</div>

You really should not be running that expression binding on a view like that. You're going to cause yourself a lot of headaches if/when you have lots of clients connected all running that query every 2.5 seconds.

Instead, run a timer script on the gateway that runs your script and just writes the either the count of alarms or a boolean value to a tag. Then you can use your binding off of that tag instead of a `runScript` expression. This guarantees it to be up to date and only running once every 2.5 seconds no matter how many clients you have.

---

<div class="post-metadata">

**Author:** ![Andreas\_Wallevik](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/andreas_wallevik/32/64045_2.png) [@Andreas\_Wallevik](https://forum.inductiveautomation.com/u/Andreas_Wallevik)\
**Post date:** [December 17, 2024, 3:16pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/10 "2024-12-17T15:16:33Z")

</div>

Thank you so much, man.

I'm going to revise this and update the solution accordingly.

---

<div class="post-metadata">

**Author:** ![Andreas\_Wallevik](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/andreas_wallevik/32/64045_2.png) [@Andreas\_Wallevik](https://forum.inductiveautomation.com/u/Andreas_Wallevik)\
**Post date:** [December 18, 2024, 3:13pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/11 "2024-12-18T15:13:46Z")

</div>

# **Current solution:**

Any feedback is greatly appreciated 🙂

This still doesn't solve all problems, specifically in regards to issues [pturmel](https://forum.inductiveautomation.com/u/pturmel) mentioned. But hopefully this is somewhat more efficient.

### Gateway timer script

I created a gateway timer script to monitor active critical alarms and update a memory tag named CriticalAlarmCount.

```python
results = system.alarm.queryStatus(priority=["Critical"], state=["ActiveUnacked"])
critical_alarms = len(results)
system.tag.writeBlocking(["[TagProvider]TagFolder/CriticalAlarmCount"], [critical_alarms])

```

* * *

### Session property

I added a custom session property named **playAlarm** with this expression binding:

```python
try({[TagProvider]TagFolder/CriticalAlarmCount} > 0, false)

```

..triggering True when any critical alarm is active.

### View Property change script

On the View where the Audio Component is located, I created a property change script for `playAlarm`.

```python
def valueChanged(self, previousValue, currentValue, origin, missedEvents):
    if currentValue.value == True:
        self.getChild("root").getChild("Audio").props.play = True

```

...sets Audio.props.play to True when playAlarm becomes True.

### Audio component

- **Source** : URL of the audio file.
- **Play** : Controlled via the `playAlarm` logic.

If i were to use the gateway and system.util.playSoundClip for this - does anyone have any resources or tips for how to set that up?

---

<div class="post-metadata">

**Author:** ![Andreas\_Wallevik](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/andreas_wallevik/32/64045_2.png) [@Andreas\_Wallevik](https://forum.inductiveautomation.com/u/Andreas_Wallevik)\
**Post date:** [December 19, 2024, 10:05am UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/12 "2024-12-19T10:05:23Z")

</div>

Using system.util.playSoundClip("/sound/alarm.wav", 1.0, False) to trigger sound from GW (file is mounted to docker volume)

Getting an error that the file format is not supported by javax.sound.sampled API requirments

As far as i can see from the error, the requirements are these:

- **Sample rate:** 22050 Hz
- **Bit depth:** 16-bit
- **Channels:** Mono
- **Encoding:** PCM\_SIGNED

Error message:

```python
Caused by: org.python.core.PyException: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: No line matching interface Clip supporting format PCM_SIGNED 44100.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian, and buffers of 128020 to 128020 bytes is supported.

... 26 common frames omitted

Caused by: java.lang.IllegalArgumentException: No line matching interface Clip supporting format PCM_SIGNED 44100.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian, and buffers of 128020 to 128020 bytes is supported.

at java.desktop/javax.sound.sampled.AudioSystem.getLine(Unknown Source)

at com.inductiveautomation.ignition.common.script.builtin.SystemUtilities.playSoundClip(SystemUtilities.java:288)

```

I'm using a wav file with a bitrate of 705 kbps, which is a uncompressed 16-bit PCM WAV file

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

From what i can see, this audio file should work. Anyone have any thoughts?

---

<div class="post-metadata">

**Author:** ![michael.flagler](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/michael.flagler/32/26272_2.png) [@michael.flagler](https://forum.inductiveautomation.com/u/michael.flagler)\
**Post date:** [December 19, 2024, 12:25pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/13 "2024-12-19T12:25:41Z")

</div>

Your sampling rate is too high if those requirements are strict.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 19, 2024, 1:06pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/14 "2024-12-19T13:06:07Z")

</div>

> [@Andreas\_Wallevik](#):
>
> `No line matching interface`

I would not expect a docker container to emulate sound hardware, and if it did, where would the sound go?

Gateway sound generation presumes gateway hardware with a sound card.

---

<div class="post-metadata">

**Author:** ![Andreas\_Wallevik](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/andreas_wallevik/32/64045_2.png) [@Andreas\_Wallevik](https://forum.inductiveautomation.com/u/Andreas_Wallevik)\
**Post date:** [December 19, 2024, 1:43pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/16 "2024-12-19T13:43:23Z")

</div>

Okay. It seems you're right. I am still new to this and was not aware of this. But thanks for pointing that out.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 19, 2024, 1:47pm UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/17 "2024-12-19T13:47:20Z")

</div>

Consider using a VM instead of docker. Many hypervisors **do** provide sound card emulation that routes to the hypervisor's hardware.

---

<div class="post-metadata">

**Author:** ![dadmin](https://avatars.discourse-cdn.com/v4/letter/d/8baadc/32.png) [@dadmin](https://forum.inductiveautomation.com/u/dadmin)\
**Post date:** [March 19, 2025, 4:35am UTC](https://forum.inductiveautomation.com/t/sound-for-critical-alarms/99877/18 "2025-03-19T04:35:21Z")

</div>

I'm sure there is a better and more efficient way, but this is how I did it:

> [@Audible Alarms in Perspective](https://forum.inductiveautomation.com/t/audible-alarms-in-perspective/103859):
>
> I develop in a secure, air-gaped environment where it takes an act of congress to import modules. I needed a way to get audible alarms working for my remote endpoints and IA support saved the day. For windows, navigate to the following directory: C:\Program Files\Inductive Automation\Ignition\webserver\webapps\main\ Linux: /usr/local/bin/ignition/webserver/webapps/main/ Create a new directory for your .wav alarm files and add the file you want to use. Add an audio component on a header in …

Very curious about performance impacts of this query now, would appreciate any insight.
