Skip to content

Commit c518085

Browse files
authored
Merge pull request #3388 from ControlSystemStudio/alarm_infopv
Alarm `infopv` action
2 parents 523ba13 + 5751351 commit c518085

File tree

11 files changed

+352
-20
lines changed

11 files changed

+352
-20
lines changed

app/alarm/examples/infopv.db

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Example for "Info PV"
2+
# used with automated action set to "infopv:NameOfPV"
3+
#
4+
# softIoc -s -m N=NameOfPV -d infopv.db
5+
#
6+
# With Channel Access, use $(N).VAL$ to access the full text.
7+
8+
record(lsi, "$(N)")
9+
{
10+
field(SIZV, 1000)
11+
field(INP, {const:""})
12+
field(PINI, "YES")
13+
}

app/alarm/model/src/main/resources/alarm_preferences.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ automated_email_sender=Alarm Notifier <[email protected]>
101101

102102
# Comma-separated list of automated actions on which to follow up
103103
# Options include mailto:, cmd:
104-
automated_action_followup=mailto:, cmd:
104+
automated_action_followup=mailto:, cmd:, infopv:
105105

106106
# Optional heartbeat PV
107107
# When defined, alarm server will set it to 1 every heartbeat_secs

app/alarm/ui/doc/index.rst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,30 @@ Sends email with alarm detail to list of recipients.
307307
The email server is configured in the alarm preferences.
308308

309309

310+
``infopv:SomePV``:
311+
Writes the alarm detail to a PV.
312+
313+
The PV needs to hold a string, for example
314+
`mqtt://alarm/message<VString>` for an MQTT topic
315+
or
316+
`ca://NameOfPV.VAL$`
317+
for Channel Access where the PV refers to a string record::
318+
319+
# Example for "Info PV"
320+
# used with automated action set to "infopv:NameOfPV"
321+
#
322+
# softIoc -s -m N=NameOfPV -d infopv.db
323+
324+
record(lsi, "$(N)")
325+
{
326+
field(SIZV, 1000)
327+
field(INP, {const:""})
328+
field(PINI, "YES")
329+
}
330+
331+
With Channel Access, since the text usually exceeds 40 characters, use ``infopv:SomePV.VAL$``.
332+
333+
310334
``cmd:some_command arg1 arg2``:
311335
Invokes command with list of space-separated arguments.
312336
The special argument "*" will be replaced with a list of alarm PVs and their alarm severity.

app/alarm/ui/src/main/java/org/phoebus/applications/alarm/ui/tree/TitleDetailDelayTable.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018-2023 Oak Ridge National Laboratory.
2+
* Copyright (c) 2018-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -49,8 +49,16 @@
4949
@SuppressWarnings("nls")
5050
public class TitleDetailDelayTable extends BorderPane
5151
{
52-
private enum Option_d {
53-
mailto, cmd, sevrpv
52+
private enum Option_d
53+
{
54+
// Send email with alarm info
55+
mailto,
56+
// Execute external command
57+
cmd,
58+
// Update PV with severity
59+
sevrpv,
60+
// Update PV with alarm info text
61+
infopv
5462
};
5563

5664
private final ObservableList<TitleDetailDelay> items = FXCollections.observableArrayList();

core/pv-mqtt/Readme.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
MQTT PV Support
2+
===============
3+
4+
MQTT is a broker-based protocol used in the Internet-of-Things (IoT) ecosystem.
5+
See https://mqtt.org for details.
6+
The `mqtt:...` PV support allows CS-Studio tools to read and write PVs via MQTT.
7+
8+
9+
Example Broker Setup and first steps
10+
------------------------------------
11+
12+
This example uses Eclipse Mosquitto on Linux.
13+
See https://mqtt.org for links to several other MQTT brokers and clients.
14+
15+
Download: Get source release `mosquitto-....tar.gz` from https://mosquitto.org/download
16+
17+
Unpack: `tar vzxf mosquitto-....tar.gz`
18+
19+
Build: `make WITH_CJSON=no`
20+
21+
Install:
22+
23+
```
24+
export LD_LIBRARY_PATH=`pwd`/lib
25+
# Optionally, add the following to a `bin` folder that's on your $PATH
26+
# src/mosquitto, client/mosquitto_sub, client/mosquitto_pub
27+
```
28+
29+
Run broker:
30+
31+
```
32+
# Allow remote access through firewall.
33+
# Depending on Linux release, similar to this
34+
sudo firewall-cmd --add-port=1883/tcp
35+
36+
# Create configuration file that allows remote access
37+
echo "listener 1883" >> mosquitto.conf
38+
echo "allow_anonymous true" >> mosquitto.conf
39+
40+
# Start broker with that configuration file
41+
src/mosquitto -c mosquitto.conf
42+
mosquitto version ... starting
43+
Config loaded from mosquitto.conf.
44+
...
45+
Opening ipv4 listen socket on port 1883.
46+
```
47+
48+
See https://mosquitto.org/documentation/authentication-methods
49+
for a more secure configuration.
50+
51+
Subscribe to value updates: `client/mosquitto_sub -t sensors/temperature -q 1 `
52+
53+
Publish a value: `client/mosquitto_pub -t sensors/temperature -q 1 -m 42`
54+
55+
By default, the broker will not persist messages.
56+
The subscribe command shown above will receive all newly
57+
published messages. If you close the `mosquitto_sub` and then restart it,
58+
it will show nothing until a new value is published.
59+
60+
To persist data on the broker, each client that publishes or subscribes
61+
needs to connect with a unique client ID and an option to _not_ 'clean' the session,
62+
using options like `--id 8765 --disable-clean-session` for the `.._sub` and `.._pub`
63+
commands shown above.
64+
65+
66+
MQTT PV Configuration
67+
---------------------
68+
69+
By default, the MQTT PV will look for a broker on localhost
70+
and the default MQTT broker port 1883.
71+
72+
To change this, add a variant of the following to your Phoebus settings:
73+
74+
```
75+
# MQTT Broker
76+
# All "mqtt://some/tag" PVs will use this broker
77+
#org.phoebus.pv.mqtt/mqtt_broker=tcp://localhost:1883
78+
org.phoebus.pv.mqtt/mqtt_broker=tcp://my_host.site.org:1883
79+
```
80+
81+
The MQTT PV will create a unique internal ID to read persisted messages,
82+
allowing the PV to start up with the last known value of an MQTT topic
83+
without need to wait for the next update.
84+
85+
86+
MQTT PV Syntax
87+
--------------
88+
89+
To interface with the example MQTT tag shown above,
90+
use the PV `mqtt://sensors/temperature`.
91+
92+
The general format is `mqtt://` followed by the MQTT topic,
93+
for example `sensors/temperature`,
94+
and an optional `<VType>`.
95+
96+
MQTT treats all tag data as text. By default, an MQTT PV expects
97+
the text to contain a number, but the optional `<VType>` will
98+
instruct the PV to parse the text in other ways.
99+
100+
| `VType` | PV Value Parser |
101+
| ---------------- | ---------------------------------------------------------------------------- |
102+
| `<VDouble>` | This is the default, expecting the topic to parse as a floating point number |
103+
| `<VString>` | PV reads text as string |
104+
| `<VLong>` | Parse as long integer |
105+
| `<VDoubleArray>` | Parse as array of comma-separated floating point numbers |
106+
| `<VStringArray>` | Parse text as array of comma-separated strings |
107+

services/alarm-server/.classpath

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
<classpathentry combineaccessrules="false" kind="src" path="/core-util"/>
1010
<classpathentry combineaccessrules="false" kind="src" path="/core-pv"/>
1111
<classpathentry combineaccessrules="false" kind="src" path="/core-formula"/>
12-
<classpathentry combineaccessrules="false" kind="src" path="/core-vtype"/>
12+
<classpathentry combineaccessrules="false" kind="src" path="/core-pv-ca"/>
13+
<classpathentry combineaccessrules="false" kind="src" path="/core-pv-pva"/>
14+
<classpathentry combineaccessrules="false" kind="src" path="/core-pv-mqtt"/>
15+
<classpathentry combineaccessrules="false" kind="src" path="/core-vtype"/>
1316
<classpathentry combineaccessrules="false" kind="src" path="/core-email"/>
1417
<classpathentry combineaccessrules="false" kind="src" path="/app-alarm-model"/>
1518
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>

services/alarm-server/src/main/java/org/phoebus/applications/alarm/server/ServerModel.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018-2022 Oak Ridge National Laboratory.
2+
* Copyright (c) 2018-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -15,7 +15,6 @@
1515
import java.util.List;
1616
import java.util.Objects;
1717
import java.util.concurrent.ConcurrentHashMap;
18-
import java.util.concurrent.TimeUnit;
1918
import java.util.logging.Level;
2019

2120
import org.apache.kafka.clients.consumer.Consumer;
@@ -34,6 +33,7 @@
3433
import org.phoebus.applications.alarm.model.SeverityLevel;
3534
import org.phoebus.applications.alarm.model.json.JsonModelReader;
3635
import org.phoebus.applications.alarm.model.json.JsonModelWriter;
36+
import org.phoebus.applications.alarm.server.actions.InfoPVActionExecutor;
3737

3838
/** Server's model of the alarm configuration
3939
*
@@ -120,6 +120,7 @@ public void start()
120120
{
121121
thread.start();
122122
SeverityPVHandler.initialize();
123+
InfoPVActionExecutor.initialize();
123124

124125
// Alarm server startup message
125126
sendAnnunciatorMessage(root.getPathName(), SeverityLevel.OK, "* Alarm server started. Everything is going to be all right.");
@@ -603,6 +604,7 @@ private void clearActionsAndStopPVs(final AlarmTreeItem<?> node)
603604
public void shutdown()
604605
{
605606
SeverityPVHandler.stop();
607+
InfoPVActionExecutor.stop();
606608
running = false;
607609
consumer.wakeup();
608610
try

services/alarm-server/src/main/java/org/phoebus/applications/alarm/server/actions/AutomatedActionExecutor.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018-2019 Oak Ridge National Laboratory.
2+
* Copyright (c) 2018-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -27,6 +27,9 @@
2727
2828
* Sends email with alarm detail to list of recipients.
2929
*
30+
* <p>"infopv:ca://demo"<br>
31+
* Writes alarm detail to string PV.
32+
*
3033
* <p>"cmd:some_command arg1 arg2"<br>
3134
* Invokes command with list of space-separated arguments.
3235
* The special argument "*" will be replaced with a list of alarm PVs and their alarm severity.
@@ -44,18 +47,21 @@ public void accept(final AlarmTreeItem<?> item, final TitleDetailDelay action)
4447
// Perform the automated action in background thread
4548
JobManager.schedule("Automated Action", monitor ->
4649
{
47-
if (action.detail.startsWith("mailto:"))
48-
{
49-
if (AlarmLogic.getDisableNotify() == true)
50-
{
51-
return;
52-
}
53-
EmailActionExecutor.sendEmail(item, action.detail.substring(7).split(" *, *"));
54-
}
50+
final boolean mailto = action.detail.startsWith("mailto:");
51+
final boolean infopv = action.detail.startsWith("infopv:");
52+
if (mailto || infopv)
53+
{ // Are notifications disabled?
54+
if (AlarmLogic.getDisableNotify())
55+
return;
56+
if (mailto)
57+
EmailActionExecutor.sendEmail(item, action.detail.substring(7).split(" *, *"));
58+
else
59+
InfoPVActionExecutor.writeInfo(item, action.detail.substring(7).trim());
60+
}
5561
else if (action.detail.startsWith("cmd:"))
5662
CommandActionExecutor.run(item, action.detail.substring(4));
5763
else
58-
logger.log(Level.WARNING, "Automated action " + action + " lacks 'mailto:' or 'cmd:' in detail");
64+
logger.log(Level.WARNING, "Automated action " + action + " lacks 'mailto:', 'infopv:' or 'cmd:' in detail");
5965
});
6066
}
6167

services/alarm-server/src/main/java/org/phoebus/applications/alarm/server/actions/EmailActionExecutor.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2018-2020 Oak Ridge National Laboratory.
2+
* Copyright (c) 2018-2025 Oak Ridge National Laboratory.
33
* All rights reserved. This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v1.0
55
* which accompanies this distribution, and is available at
@@ -54,7 +54,11 @@ static void sendEmail(final AlarmTreeItem<?> item, final String[] addresses)
5454
}
5555
}
5656

57-
private static String createTitle(final AlarmTreeItem<?> item)
57+
/** Create title for email, also used by Info PV
58+
* @param item Item for which to create title
59+
* @return Title
60+
*/
61+
static String createTitle(final AlarmTreeItem<?> item)
5862
{
5963
final StringBuilder buf = new StringBuilder();
6064

@@ -77,7 +81,11 @@ private static String createTitle(final AlarmTreeItem<?> item)
7781
return buf.toString();
7882
}
7983

80-
private static String createBody(final AlarmTreeItem<?> item)
84+
/** Create info body for email, also used by Info PV
85+
* @param item Item for which to create info
86+
* @return Info text
87+
*/
88+
static String createBody(final AlarmTreeItem<?> item)
8189
{
8290
final StringBuilder buf = new StringBuilder();
8391

0 commit comments

Comments
 (0)