Doch da bekommt man bei Unified Panels zusätzlich das Problem, dass dazu der Benutzer-Kontext beachtet werden muss.
In dem Fall tatsächlich nicht direkt.
Die Bedienung der Meldeanzeige und darüber das Triggern der Quittierung ist Client-spezifisch.
Das Meldesystem an sich ist wieder serverseitig für alle Clients einheitlich.
Quittierst du auf einem Client, wird die betreffende Meldung auch bei allen anderen Clients auf "quittiert" gesetzt.
Wenn ich grade so drüber nachdenke ist es vllt. möglich über den Aufgabenplaner direkt auf die Alarmobjekte zuzugreifen...
So aktualisiere ich z.B. den Zähler meines Meldeindikators.
Also Aufgabe mit Variablentrigger => Quittierscript auslösen.
Für das Durchzählen der Alarme benutze ich folgendes Script:
Javascript:
export async function UpdatePendingAlarmsInfo(errorCode, systemName, alarmResultArray, state) {
/*
Dieses Script ist für den Aufruf im Aufgabenplaner gedacht.
Für jeden Meldungszustand muss eine eigene Aufgabe angelegt werden.
Darüber erfolgt dann die Unterscheidung welches Ereignis in den Alarmen aufgetreten ist.
Das von der Aufgabe generierte "alarmResultArray" enthält nur die geänderten Meldungen, während GetActiveAlarms() alle aktiven Alarme ausgibt.
*/
//"Enumeration" zur Unterscheidung des Triggerevents im Aufgabenplaner
const stateG = 1; //Meldung_Gekommen
const stateGQ = 2; //Meldung_GekommenQuittiert
const stateGG = 3; //Meldung_GekommenGegangen
const stateGQG = 4; //Meldung_GekommenQuittiertGegangen
const stateGGQ = 5; //Meldung_GekommenGegangenQuittiert
const stateSYS = 6; //Meldung_SystembedingtEntfernt
const stateN = 7; //Meldung_Normal
//Sonstige Variablen
let countOfpendingAlarms = -1;
try {
const currentLCID = 127; //127 = invariant culture, da im Aufgabenplaner ein Zugriff auf die localMachine nicht möglich ist.
let promiseGetActiveAlarms = HMIRuntime.Alarming.GetActiveAlarms(currentLCID)
.then((hmiAlarmResult) => {
//Anzahl aller anstehenden Alarme aktualisieren
countOfpendingAlarms = hmiAlarmResult.length;
})
.catch((ex) => {
countOfpendingAlarms = 0; //Wenn keine Alarme aktiv sind, wird der .catch() ausgelöst
HMIRuntime.Trace("SystemName: " + systemName + "\n" +
"Parameter errorCode: " + errorCode + "\n" +
"Fehler bei GetActiveAlarms. Promise-Handler .catch wurde ausgelöst.\n" +
"Fehlercode: " + ex + "\n" +
"Fehlerbeschreibung: " + HMIRuntime.GetDetailedErrorDescription(ex),
HMIRuntime.Trace.Enums.hmiSeverity.Error);
});
await Promise.all([promiseGetActiveAlarms]);
//Anzahl der gezählten Alarme ausgeben
Tags("AlarmsCntAll").Write(countOfpendingAlarms, Tags.Enums.hmiWriteType.hmiWriteNoWait);
//Event-Bit invertieren => kann für nachfolgende Reaktionen genutzt werden
let hmiTagChangeEventBit = Tags("AlarmsUpdate");
hmiTagChangeEventBit.Write(!hmiTagChangeEventBit.Read(Tags.Enums.hmiReadType.hmiReadCache), Tags.Enums.hmiWriteType.hmiWriteNoWait);
} catch (ex) {
HMIRuntime.Trace("SystemName: " + systemName + "\n" +
"Parameter errorCode: " + errorCode + "\n" +
"ALlgemeiner Fehler beim Auswerten des Ereignisses.\n" +
"Fehler: " + ex,
HMIRuntime.Trace.Enums.hmiSeverity.Error);
};
}
In meinem Fall rufe ich dieses Script bei jeder Änderung eines Alarmzustandes über den Aufgabenplaner aus, etwa so:
(Die doppelte Deklaration der State-Konstanten ist nur notwendig, da ich keine globalen Enums anlegen kann)

Für jeden Meldezustand einzeln eine Aufgabe anzulegen ist für mich nur notwendig, da ich teilweise unterschiedlich auf Zustandsänderungen reagiere.
Hier beim Gekommen-Ereignis beispielsweise mit dem Zustandswechsel einer Triggervariable, die dann wiederum Client-seitig per Subscription ein Popup öffnet.
@REBSNB du könntest das "UpdatePendingAlarmsInfo"-Script etwas erweitern um, je nach Meldezustand, das Alarmobjekt über dessen Acknowledge()-Methode zu quittieren.
Damit liesen sich alle Meldungen gleichzeitig bearbeiten, ohne extra Quittierbits anlegen zu müssen.
=> Funktioniert dann auch für Meldesysteme ohne Bit-Alarm