Multiinstanzalarme
Voraussetzungen / Verhalten:
Der Treiber muss eine eindeutige AlertId generieren und sie auch wieder in sinnvolle Peripheriedaten umwandeln können, damit die jeweilige Alarminstanz in der SPS eindeutig ansprechbar ist.
Die Alarmkennung ist für jede Alarminstanz (KAM/GING) eindeutig. Ein Alarmpaar besteht aus zwei Alarminstanzen.
Das Mapping der SPS Alarmart auf WinCC OA Alarmklassen ist frei und obliegt dem Anwender/Treiberprogrammierer.
Die Alarmzeit kommt idealerweise von der Peripherie und wird an den Event verschickt. Falls die Peripherie keine Zeit liefert, wird ersatzweise die Zeit durch den Treiber eingefügt. Der Event bekommt immer eine (Alarm-)Zeit vom Treiber. Der Event sorgt für die Eindeutigkeit dieser Zeit durch Setzen des Counters.
Der ComDrv stellt die Möglichkeit des Mappings zwischen der SPS Alarmkennung (_alert_id) und dem Alarmpaar (zwei AlertIdentifier) seitens WinCC OA zur Verfügung.
Datenpunktelemente, die Ziel eines Alarms sein können, werden durch ein Attribut im _address-Config gekennzeichnet (_mode = AM_Alarm). Eine detaillierte Zuordnung kann im Adressstring hinterlegt werden.
Die für einen Alarm gewählte Alarmklasse spiegelt das Verhalten in der Peripherie wider (Alarm Handling State Machine).
Bei Alarmadressen wird der Subindex des _address-Configs nicht ausgewertet.
Die Alarmbehandlung im Treiber verläuft parallel zur Datenbehandlung. Das bedeutet, dass keine Glättung, Umrechnung und Low Level Alt/Neu Vergleiche für dieses Datenpunktelement möglich sind (Konfigs im Treiber, die auf dem "Datenpfad“ liegen).
Eventuell mitgegebene Werte werden auf den Datenpunktelementtyp gecastet und einfach gesetzt. Werden auf einem Datenpunktelement Alarme von mehreren Quellen abgebildet, so ist der Treiber für ein sinnvolles Setzen der Werte verantwortlich.
Das bisher verwendete Verhalten von direktem Setzen von Alarmen bleibt von dieser Implementierung unbeeinflusst, weil zur Unterscheidung das AM_Alarm Mode Bit des Peripherieadressen-Configs herangezogen wird.
Alarmklassen verfügbar machen
Ein Datenpunkt vom Typ _DriverCommon hat einen Knoten für Alarmbehandlung (AL). Dieser beinhaltet das Datenpunktelement AClasses als dyn_string. Dieses Element enthält die zur Verfügung stehenden Alarmklassen. Die Namen entsprechen den Datenpunkten, welche das _alert_class-Config tragen. Es liegt in der Verantwortung des Parametrierers, hier richtige Namen einzutragen.
Der Treiber liest den Inhalt dieses Elements und baut sich intern eine Liste der Einträge mit Name, DpIdentifier und Priorität auf. Kann die Priorität zu einem Eintrag nicht ermittelt werden (falscher Name oder keine Alarmklasse am DPE), so wird der Eintrag ignoriert (-> Warnung in der Logdatei).
Durch Ändern des DPE wird die Liste zur Laufzeit neu aufgebaut.
Bei jedem Setzen eines neuen Alarms (KAM) muss eine Alarmklasse (der Name) mitgegeben werden. Die Auflösung Namen -> DpId erfolgt im ComDrv. Wird keine passende Alarmklasse gefunden, so wird der Alarm nicht gesetzt (-> Fehler in der Logdatei).
DPE zuordnen
Das _address-Config bietet den Modus AM_Alarm. Dieser dient der Kennzeichnung einer Alarm-Peripherieadresse. Der Rest der Attribute ist für die Alarmbehandlung nicht relevant (Polling, Subindex, Transformation, etc.) und wird im Zuge der Alarmbehandlung ignoriert. Er hat daher auch keinen Einfluss auf die Daten, welche im Zuge eines alertSet() Aufrufs an das DPE übermittelt werden.
Statt dpConnect verwendet der ComDrv zur Anmeldung für _alert_hdl-Konfigs ein alertConnectRetVisible auf den jeweiligen DpIdentifier und die Attribute _alert_id, _add_values, _ack_state, _ackable sowie _visible. Die HL Messages werden verwendet, um den ACK-Aufruf Richtung Peripherie zu generieren, sowie um die lokale Map AlertId <-> AlertIdentifier aktuell zu halten. Eine Callback-Funktion für den Treiber bietet die Möglichkeit, einen Alarm nach erfolgreichem Setzen im Event an die Peripherie zu bestätigen.
AlertId Map
Die Peripherie liefert eine eindeutige Kennung pro Alarm. Kommen und Gehen des Alarms werden mit unterschiedlicher AlertId gemeldet. Seitens WinCC OA wird ein Alarmpaar angelegt. Der ComDrv verwaltet Alarminstanzen als eigene Einträge. Über die AlertId Map bestimmt der ComDrv die AlertIdentifier zu den übergebenen AlertIds und umgekehrt. Neben dem AlertIdentifier wird auch der _ack Zustand gespeichert.
Die Map wird rein durch HL Messages aktualisiert. Nur so wird im Fall der Redundanz garantiert, dass die Maps der beiden redundanten Treiber die gleichen AlertIdentifier-Einträge halten. Wenn das _visible-Attribut eines Alarms auf FALSE gesetzt ist, wird der entsprechende Eintrag aus der Map entfernt. Über eine Callback-Funktion wird der Treiber über Änderungen in der Map informiert. So kann er eine eventuell gewünschte Bestätigung des Alarmeingangs an die Peripherie generieren.
Redundanzbetrachtung:
Beim Anlegen eines Alarms wird die Alarmzeit vom Treiber generiert, der Count in der Alarmzeit wird auf (-1) gesetzt. Der Event ersetzt diesen Count durch einen Passenden, welcher die eindeutige Zuordnung garantiert. Solange kein HL vom Event empfangen wurde, steht dieser Count lokal auf (-1). Im Falle einer Redundanzumschaltung muss der nun aktiv gewordene Treiber alle neuen Alarme mit Count (-1) nochmals an den Event schicken, weil man davon ausgeht, dass unbestätigte Anforderungen nicht (mehr) vom Event bearbeitet wurden. Beim Empfang einer HL Message wird anhand der eindeutigen AlertId der entsprechende Eintrag in der AlertId Map gesucht und der Count Parameter abgeglichen.
Die anstehenden Alarme werden als AlertObjects lokal gespeichert. Folgende Attribute werden für Updates angemeldet:
_alert_id
_add_values
_ack_state
_ack_possible
_visible
_direction
Kann ein Alarm nicht angelegt werden (Fehler vom Event), so wird eine entsprechende Meldung ausgegeben und das AlertObject wieder aus der lokalen Liste entfernt. Alle gepufferten Folgeaufträge (ACK oder WENT oder MODIFY) gehen damit auch verloren.
Neuen Alarm generieren (KAM)
Zum Anlegen eines neuen Alarms wird lokal im ComDrv ein AlertObject generiert. Die Zeit dieses AlertObjects kommt immer vom Treiber (wenn die Peripherie die Zeit mitliefert, wird diese eingesetzt, sonst die lokale Zeit).
Das _event Attribut wird auf DPATTR_ALERTEVENT_CAME gesetzt. Die Alarmklasse wird als String übergeben. Der Name muss im Treiber-Datenpunkt parametriert sein. _alert_id und _add_values werden gemäß der Peripherieinformation befüllt. Danach wird mit dem Aufruf von alertSet() die Message an den Event generiert. Eine spezielle Zuordnung, zu welchem DPE der Alarm geschickt werden soll, wird durch die Peripherieadresse bestimmt. Ein HWObject trägt hier die Information und kann treiberspezifisch zur Aufschlüsselung der Peripherieadresse in Hardware-Adresskomponenten benutzt werden.
Bei der Auswahl der Alarmklasse ist davon auszugehen, dass die gewählte Klasse in ihrem Verhalten jenes der Peripherie-Statemachine widerspiegelt.
Das AlertObject Objekt hat auch ein optionales Variablenelement. Ist dieses gesetzt (!= 0), so wird die Variable auf den entsprechenden DPE-Typ gewandelt und mit der Alarm-Message an das DPE geschickt. Der Treiber ist für die sinnhafte Verwendung der Multiinstanzalarm-Erweiterung verantwortlich (Setzen von Werten, wenn Alarme verschiedener Quellen an einem DPE hängen).
Empfängt der ComDrv einen weiteren Auftrag für eine AlertId, welche noch nicht in der Alarmliste steht, so muss überprüft werden, ob ein entsprechender Auftrag bereits an den Event weitergeleitet wurde. Falls ja, wird der neue Auftrag verzögert und nach Event HL ausgeführt, falls nein -> Fehlermeldung!
Beim Einfügen einzelner Begleitwerte werden die Variablen in eine anytype-Variable gekapselt, falls sie nicht vom Typ anytype sind.
Alarm geht (GING)
Wenn eine "GING“-Meldung von der Peripherie kommt, wird ein AlertObject generiert und das _event Attribut auf DPATTR_ALERTEVENT_WENT gesetzt. Die neue AlertId sowie die neuen Begleitwerte werden im AlertObject initialisiert. Des Weiteren muss die KAM-AlertId übergeben werden. Diese muss vom Treiber rekonstruiert werden. Eine eventuell übergebene Alarmklasse wird ignoriert, ein eventuell übergebener Wert wird wie im KAM-Fall an das DPE geschickt.
Danach wird mit alertSet() die Meldung an den Event geschickt.
Alarm wird quittiert ( WinCC OA )
Wird ein Alarm in WinCC OA quittiert, so wird dies dem Treiber durch das Setzen der DPEs AL.AckDps und AL.AckData am treiberinternen Datenpunkt mitgeteilt. Der ComDrv ruft für jeden Eintrag die Funktion ackAlertInHW() auf, wobei jeweils das entsprechende HWObject (Peripherieadresse) und AlertObject (AlertId) übergeben werden. Diese Funktion ist dafür gedacht, dass eine Message an die Peripherie mit dem Auftrag zur Quittierung eines Alarms verschickt wird. Die tatsächliche Quittierung in WinCC OA muss durch ein Antworttelegramm von der Peripherie ausgelöst werden.
Wenn ein _ack-Event auf einen treiberbehandelten Datenpunkt über den regulären HL-Weg empfangen wird, wird dies im ComDrv ignoriert, d.h. der lokale Status des AlertObjects wird auf aktuellen Stand gebracht, es erfolgt aber keine Sendung eines Quittiertelegramms in Richtung Peripherie.
Alarm wird quittiert (SPS)
Wird der Alarm auf der Hardware quittiert (durch eine Message seitens WinCC OA oder durch lokale Interaktion), so wird dies dem Treiber mitgeteilt. Dieser ruft dann die ackAlertInPVSS() Funktion auf, wobei die passende AlertId (im AlertObject) und PeriphAddr (im HWObject) übergeben werden. Das _event Attribut wird auf DPATTR_ALERTEVENT_SINGLE_ACK gesetzt und an den Event geschickt.
Alarm wird ungültig
Wenn das _visible Attribut für beide AlertIdentifier eines Alarmpaares auf FALSE steht, kann dieser Eintrag aus der AlertId Map entfernt werden. Der Alarm ist dann nicht länger im Treiber verwaltet. Vor Löschung des Alarms wird eine Callback-Funktion für den speziellen Treiber aufgerufen, in der die jeweilige AlertID übergeben wird.
Weitere Informationen
Das Overload (OV) Element am internen Treiberdatenpunkt wird zur Anzeige der Treiberüberlastung herangezogen. Im Moment wird hier nur der Modus "Wert durch aktuellen überschreiben“ in der Wertebehandlungs-Queue dargestellt. Zukünftig wird auch das Verschicken von Alarmen über eine Queue kontrolliert. Diese hat 2 Parameter: wie viele AlertVCs dürfen ausständig sein (werden über Hotlinks zurückgemeldet) und wie lang darf die AlertQueue maximal werden, bevor Alerts nicht mehr geschickt werden. Im zweiten Fall wird ebenfalls das Overload Element gesetzt. Die beiden Werte werden in der Config-Datei festgelegt.
maxAlertQueueSize, Default: 10000
maxOpenAlertMsg, Default: 30
Die AlertQueue wird regelmäßig in der DrvManager workProc gecheckt und anstehende Messages verschickt, solange die nicht bestätigte Anzahl kleiner als die gegebene Grenze ist.
Beim Hochlauf werden alle (laut Event) anstehenden Alarme in die Alarmliste eingetragen (kein Aufruf der Callback-Funktion!). Der spezielle Treiber kann dann später mit einem Iterator durch diese Liste gehen und den Abgleich mit der SPS durchführen. Dieser Abgleich obliegt der Verantwortung des Treibers.
Im Falle einer Redundazumschaltung wird davon ausgegangen, dass alle ausstehenden Meldungen zwischen Treiber und Event als verloren anzusehen sind. Der Zähler für offene Messages wird daher bei jeder Umschaltung zurückgesetzt. Da er nicht kleiner als 0 werden kann, werden zusätzlich empfangene Antworten einfach ignoriert.
Für die Pufferung von Aufträgen auf noch nicht angelegte Alarme ist auf einen Auftrag pro Typ beschränkt (WENT, ACK, MODIFY). Die Aufgabe eines neuen Auftrags desselben Typs überschreibt den vorherigen. Das Eintreffen eines Hotlinks für einen bestimmten Typ (z.B. ACK) löscht den anstehenden Auftrag, egal ob der Hotlink aufgrund des lokalen Telegramms oder eines anderen Telegramms empfangen wurde (es soll der Zustand des Alarms abgebildet bzw. erreicht werden, und das erfolgt unabhängig vom Sender).
Im Falle einer Redundanzumschaltung werden die ausstehenden Alarminstanzen vom jetzt aktiven Treiber noch einmal zum Event verschickt. Bei positiver Bestätigung erfolgt das erneute Senden der zusätzlich gepufferten Aufträge. Diese werden erst nach erfolgter Änderung (und zwar erst wenn als HL empfangen) gelöscht.
Empfehlungen
Erster Eintrag (alert_hdl..add_value_1) sollte der auslösende Wert sein.
Zweiter Eintrag (alert_hdl..add_value_2) sollte den von Gerät gelieferten Alarmtext beinhalten.
Dritter Eintrag (alert_hdl..add_value_3) beinhaltet die vom Gerät kommende Priorität.
Vierter Eintrag (alert_hdl..add_value_4) beinhaltet einen Quality Code.
Für diese Einträge wurden im AlertService Konstanten definiert, damit man auf die einzelnen vordefinierten Plätze mit Konstanten zugreifen kann.