Siemens 840dsl Alarme auslesen

Zuviel Werbung?
-> Hier kostenlos registrieren
Hab beim zweiten Paket extra den Anfang weg gelassen, da dieses ja sonst identisch zum ersten währe und damit es möglichst kurz ist.

NCK Module "SALUC" kenne ich nicht. Laut NC-Var Selektor gibt es die folgenden Alarmbereiche:

N_SALA_alarmNo 0x77
N_SALAC_alarmNo 0x54
N_SALAL_alarmNo 0x75
N_SALAP_alarmNo 0x76

Wobei da das Module 0x54 "SALAC" heißt und keine Variable für Spalte 0 vorhanden ist.


Was muss ich machen, damit WireShark mir auch die NCK Struktur anzeigt. Hab schon auf die neueste Version aktualisiert, wird jedoch nicht dargestellt.
 
Das kannst du in Wireshark nicht umstellen, ich könnte dir aber meine Entwicklungsversion zukommen lassen.

Ich weiß auch noch nicht wozu die zwei eingeschobenen Bytes sein sollen (im Screenshot werden die nicht angezeigt). Bei einer S7-SPS gibt es bei den Telegrammen für den Datenteil einen Returncode, und da steht 0xff bei Erfolg.
Bei deinen Telegrammen habe ich 3 verschiedene Kombinationen gesehen:
- 0x00, 0x12
- 0x0d, 0x11
- 0x0d, 0x12

Das habe ich zur Zeit als fixe Prüfung eingebaut damit man mal sehen kann was danach kommt. Wenn diese beiden Werte folgen, dann wird das nicht als Datenteil sondern als Parameterteil decodiert.
Das sieht mir irgendwie reingefrickelt aus, da das überhaupt nicht zu den S7-SPS Funktionen passt.
 
Ich glaube die Funktionsnamen habe ich mit freundlicher Genehmigung von Deltalogic aus einer Header-Datei von aglink entnehmen dürfen.
Wenn du da eine bessere / offizielle Siemens Dokumentation hast, dann sage ich dazu nicht nein.

Der Datensatz aus deinem letzten Anhang sieht ähnlich aus wie aus deinem ersten Anhang als Antwort auf 0x54. Da bekamst du aber mehr als eine Antwort, evtl. standen da mehr als ein Alarm an?
Die Länge ist jedoch unterschiedlich, aber so wie es aussieht sind dort auch Strings enthalten.

Aber ich denke die interessanten Sachen dürften sich aus dem Datensatz einfacher extrahieren lassen, als ein Alarm_S-System auf Basis von libnodave oder komplett neu aufzusetzen.
 
Aktuell anstehende Alarme meines Teststandes:

N_SALAC_textIndex1: 0
N_SALAC_textIndex2: 0
N_SALAC_textIndex3: 0
N_SALAC_textIndex4: 0
N_SALAC_textIndex5: 0
N_SALAC_textIndex6: 0
N_SALAC_textIndex7: 0
N_SALAC_textIndex8: 0
N_SALAC_textIndex9: 0
N_SALAC_textIndex10: 0
N_SALAC_textIndex11: 0
N_SALAC_textIndex12: 0
N_SALAC_textIndex13: 0
N_SALAC_textIndex14: 0
N_SALAC_textIndex15: 0
N_SALAL_textIndex1: 8081
N_SALAL_textIndex2: 8081
N_SALAL_textIndex3: 8081
N_SALAL_textIndex4: 8081
N_SALAL_textIndex5: 8081
N_SALAL_textIndex6: 8081
N_SALAL_textIndex7: 8081
N_SALAL_textIndex8: 8081
N_SALAL_textIndex9: 8081
N_SALAL_textIndex10: 8081
N_SALAL_textIndex11: 380500
N_SALAL_textIndex12: 380500
N_SALAL_textIndex13: 25201
N_SALAL_textIndex14: 25201
N_SALAL_textIndex15: 0
N_SALAP_textIndex1: 8081
N_SALAP_textIndex2: 8081
N_SALAP_textIndex3: 8081
N_SALAP_textIndex4: 8081
N_SALAP_textIndex5: 8081
N_SALAP_textIndex6: 8081
N_SALAP_textIndex7: 8081
N_SALAP_textIndex8: 8081
N_SALAP_textIndex9: 8081
N_SALAP_textIndex10: 8081
N_SALAP_textIndex11: 380500
N_SALAP_textIndex12: 380500
N_SALAP_textIndex13: 25201
N_SALAP_textIndex14: 25201
N_SALAP_textIndex15: 0
N_SALA_textIndex1: 25201
N_SALA_textIndex2: 25201
N_SALA_textIndex3: 380500
N_SALA_textIndex4: 380500
N_SALA_textIndex5: 8081
N_SALA_textIndex6: 8081
N_SALA_textIndex7: 8081
N_SALA_textIndex8: 8081
N_SALA_textIndex9: 8081
N_SALA_textIndex10: 8081
N_SALA_textIndex11: 8081
N_SALA_textIndex12: 8081
N_SALA_textIndex13: 8081
N_SALA_textIndex14: 8081
N_SALA_textIndex15: 0


Der Alarm "410151" (von der PLC) fehlt jedoch. (Soweit war ich ja bis jetzt schon.)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dein HMI meldet sich in deinem "HMI-Hochlauf_filter" aber auch für die Alarm_S Meldungen an. Wenn es möglich wäre sich alle Meldungen über die NCK-Datensätze zu holen, dann wäre das eigentlich nicht nötig.
Wobei dein HMI sich da auch für System-Meldungen wie CPU-Stop/Start usw. anmeldet.

Ich kenne mich mit dem NCK nicht aus, inwieweit SPS und NCK da voneinander getrennt sind.
 
Ich glaube die Funktionsnamen habe ich mit freundlicher Genehmigung von Deltalogic aus einer Header-Datei von aglink entnehmen dürfen.
Wenn du da eine bessere / offizielle Siemens Dokumentation hast, dann sage ich dazu nicht nein.

Da geht´s halt Deltalogic nicht anders als der Siemens doku, die auch immer wieder falsch geschriebene Wörter(teils je nach dem welches Dokument) enthält.

Der Datensatz aus deinem letzten Anhang sieht ähnlich aus wie aus deinem ersten Anhang als Antwort auf 0x54. Da bekamst du aber mehr als eine Antwort, evtl. standen da mehr als ein Alarm an?
Die Länge ist jedoch unterschiedlich, aber so wie es aussieht sind dort auch Strings enthalten.

Aber ich denke die interessanten Sachen dürften sich aus dem Datensatz einfacher extrahieren lassen, als ein Alarm_S-System auf Basis von libnodave oder komplett neu aufzusetzen.

Das auslesen dieses Paketes erspart mir zwar das lesen jedes einzelnen Eintrags, jedoch habe ich dennoch nur die NC-Alarme und keine der PLC.
Hab mir gerade das aglink GUI angesehen. Dieses scheint das jedoch auch nicht (noch nicht) zu können. Wobei ich von IFM weiß, dass diese zusammen mit Deltalogic von einem "Alarm Server" die Daten bekommen wollen. Ob Sie es inzwischen geschafft haben weiß ich nicht.
 
Dein HMI meldet sich in deinem "HMI-Hochlauf_filter" aber auch für die Alarm_S Meldungen an. Wenn es möglich wäre sich alle Meldungen über die NCK-Datensätze zu holen, dann wäre das eigentlich nicht nötig.
Wobei dein HMI sich da auch für System-Meldungen wie CPU-Stop/Start usw. anmeldet.

Ich kenne mich mit dem NCK nicht aus, inwieweit SPS und NCK da voneinander getrennt sind.

Nach meiner bereits mehrjährigen Erfahrung mit der 840dsl würde ich sagen, Siemens hat einfach ne "normale" SPS (meistens 317) und ne CPU für nen NC-Kern auf eine Platine gesetzt. Damit diese dann mit einander Arbeiten können wurden so Bausteine wie der FB1 (unter anderem Parametrieren der NC-Kommunikation und behandeln von M, H, ... Funktionen), FB15(Schnittstelle nach draußen z.B zur NC) programmiert.

Die HMI scheint nun die Alarme der NC und der "normalen" SPS einzusammeln und anzuzeigen. Somit komme ich wohl um die Alarm_S nicht herum.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
So "schwer" ist das mit dem Alarm Server nun auch nicht, den Aufbau der Datensätze habe ich in Wireshark vollständig für Alarm_S, Alarm_SQ, Alarm_8 und Notify. Aber wenn du so was mal anfängst, dann sollte es auch den ganzen Zoo von Meldungstypen unterstützen. Und mit dem Testen der verschiedenen Varianten in allen Ausprägungen ist das dann doch etwas Aufwand, der sich bei einem kommerziellen Produkt auch irgendwann rechnen muss.

Ich muss aber sagen, dass ich selbst bei der SPS-Programmierung die Bausteinmeldungen nur im Zusammenhang mit PCS7 verwende. Ich habe darum weder berufliches noch persönliches Interesse an so einem Alarm-Server. Ich könnte da höchstens mit dem was ich weiß unterstützen wenn das jemand umsetzen will.
 
Beim Testen und einfachen Debuggen sehe ich kein Problem, da der Zeitdruck noch eher gering ist.

Das größere Problem sehe ich für mich eher in der Programmierung in C (programmiere normalerweise SPS, NC oder C#) und vor allem den richtigen Netzwerkpaketen.
 
Ich denke auch, dass es sinnvoll sein könnte so einen Alarmserver völlig losgelöst von anderen Bibliotheken zu programmieren. Es benötigt dann ggf. eine Verbindungsressource auf der CPU mehr.
Von Snap7 gibt es eine native C#-Portierung, wobei da die Trennung der verschiedenen Protokollebenen fehlt die in der C++ Version vorhanden sind. Wenn es nur für dich selber ist, dann kannst du sowas auch komplett in C# programmieren. Für eine Bibliothek würde ich sowas immer in C oder C++ machen, das ist einfach universell, und schnell.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn ich mir den Wireshark Log von CPU Melden so anschaue sieht es doch grundsätzlich aus wie beim File Upload von der NC.

Hier wird halt das SubscribedEvents ALM gesetzt. Dann kommt die Bestätigung von der SPS. Anschließend wird das Alarm query empfangen und quittiert, bis "Last" == True kommt. Damit hab ich ja dann alle anstehenden Alarme.
 
Bis dahin ist auch alles noch normal, nach Anfrage / Antwort.
Aber nachdem du dich bei der SPS für den Empfang von Alarmen angemeldet hast, sendet diese dir bei auftreten eines Alarms einfach so eine Nachricht zu. Und das ist was, das in libnodave überhaupt nicht vorgesehen ist. D.h. du musst ein Event generieren (z.B. muss ein Callback angemeldet werden), das deine Client-Anwendung implementiert wenn so eine Nachricht eintrifft. Und es können auch mehrere Meldungen gleichzeitig eintreffen.
Und dann sollte sich dieser Server auch automatisch wiederverbinden nach einer Netzwerkstörung, und sich auch ordnungsgemäß bei der SPS abmelden.

Du kannst es natürlich auch so machen, dass du z.B. alle 10s nur die Meldungen von der SPS abfragst und danach alles wieder abbaust. Dann sollte das recht einfach zu lösen sein, wenn du dich rein auf Alarm_S konzentrierst.
Dann geht dir der Vorteil des Bausteinmeldeverfahrens, nämlich der geringen Netzwerklast, aber abhanden. Bei Alarm_S ist das insofern auch kein Problem, als dass du auch bei Alarmen die du nicht "online" mitbekommen hast noch den Zeitstempel abfragen kannst. Bei Alarm_8 ist das z.B. nicht möglich. Deine Client-Anwendung muss das natürlich alles kombinieren können.

Beim Bausteinmeldeverfahren kommt selbst WinCC gelegentlich ins straucheln, nicht ohne Grund gibt es in der WinCC Alarmanzeige ein "Notquittieren" mit der man gelegentlich hängende Meldungen wegbekommt.
 
Im ersten Schritt hab ich auf jeden Fall an zweiteres gedacht. Mir geht es zunächst nur darum, welche Alarme gerade anstehen. Ob ich die Alarme nun pollent abhole oder nur einmal wenn der Fehler Merker der PLC gesetzt wird weiß ich noch nicht. Ich brauch auch durch den Fehler keine Reaktion auslösen.

Kannst du mir bei der "einfachen" Lösung in C (libNoDave) helfen? Kann ja, wenn ich´s verstanden habe, versuchen den Listener selber in C# zu programmieren.
 
Zuletzt bearbeitet:
Mit der zweiten Lösung kann es aber vorkommen, dass dir ein Alarm durch die Lappen geht wenn jemand diesen schnell genug an einem anderen HMI quittiert. Achso, ein Quittieren der Meldungen ist natürlich prinzipiell auch möglich. Ist die Frage ob du das benötigst?

Da ich Alarm_S auch bei mir zu Hause verfügbar habe könnte ich das mal probieren. Ich würde den Nachrichten-Datensatz für den Client aber trotzdem schonmal so aufbohren wollen, dass er auch für die anderen Nachrichtentypen funktioniert, man weiß ja nie.
Ich müsste aber auch erst mal nachsehen, wie man Funktionszeiger durch die .Net Abstraktionsebene durchbekommt.
 
Mit der folgenden Funktion lassen sich bei einer S7-300 alle anstehenden ALARM_S Meldungen abfragen:
Code:
int DECL2 alarmQueryAlarm_S(daveConnection *dc, void *buffer, int buflen, int *number_of_alarms){
    int res, len, cpylen;
    int pa7;
    PDU p2;

    uc pa[] = { 0x00, 0x01, 0x12, 0x04, 0x11, 0x44, 0x13, 0x00};                          /* Parameter 1. Anfrage */
    uc da[] = { 0x00, 0x01, 0x12, 0x08, 0x1a, 0x00, 0x01, 0x34, 0x00, 0x00, 0x00, 0x04 }; /* Datenteil 1. Anfrage */
    uc pa2[]= { 0x00, 0x01, 0x12, 0x08, 0x12, 0x44, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00 }; /* Parameter weitere Anfragen */

    *number_of_alarms = 0;

    res = daveBuildAndSendPDU(dc, &p2,pa, sizeof(pa), da, sizeof(da));
    if (res != daveResOK) return res;

    len = 0;
    pa7 = p2.param[7];              /* Sequence number für weitere Abfragen */

    if (p2.udlen < 2) return daveEmptyResultError;
    /* Aufbau des 1. Antworttelegramms ist anders und besitzt noch einen 6 Byte Header */
    if (p2.udlen > 6 && p2.udata[1] == 1 && p2.udata[2] == 0xff) {
        *number_of_alarms += 1;
        cpylen = p2.udlen - 6;
        if (buffer != NULL) {
            if (len + cpylen > buflen) cpylen = buflen - len;
            if (cpylen > 0) memcpy((uc *)buffer+len, &(p2.udata[6]), cpylen);
            len += cpylen;
        }
    }
    
    if (p2.param[9] != 0) {
        pa2[7] = pa7;
        res = daveBuildAndSendPDU(dc, &p2, pa2, sizeof(pa2), NULL, 1);
        if (res != daveResOK) return res;
        
        while (p2.param[9] != 0) {      /* Last Data unit 0=Yes*/
            if (p2.udlen > 2) {
                *number_of_alarms += 1;
                cpylen = p2.udlen;
                if (buffer != NULL) {
                    if (len + cpylen > buflen) cpylen = buflen - len;
                    if (cpylen > 0) memcpy((uc *)buffer+len, p2.udata, cpylen);
                    len += cpylen;
                }
            }
            dc->resultPointer = p2.udata;
            dc->_resultPointer = p2.udata;
            pa2[7] = pa7;
            res = daveBuildAndSendPDU(dc, &p2, pa2, sizeof(pa2), NULL, 1);
            if (res != daveResOK) return res;
        }
    }

    dc->AnswLen = len;
    return res;
}
Die reinen Nachrichten-Objekte werden so wie du sie auch in Wireshark sehen kannst in den Buffer kopiert.

Die Nachrichten-Objekte können aufgrund der möglichen Begleitwerte unterschiedliche Längen besitzen. Zum Durchgehen der Objekte musst du darum nach jedem Objekt den Zeiger auf den Buffer um die Längenangabe + 2 weitersetzen. Der Buffer muss also auch entsprechend groß gewählt werden, bei der S7-300 lässt sich in den Systemdaten ablesen wie viele Alarm_S Meldungen gleichzeitig anstehen können, bei der IM151-8 PN/DP CPU sind das z.B 300. Wegen den Begleitwerten muss dieser dann entsprechend groß gewählt werden. Oder wir müssten die Funktion aufteilen, sodass nicht alle Meldungen in einem Rutsch in den Buffer kopiert werden, sondern mit zwei Einzelfunktionen. Aber Speicher ist auf einem PC ja nicht das Problem, da kannst du problemlos einen buffer[32767] angeben.

Evtl. habe ich da in meiner Wireshark Dekodierung noch etwas nicht ganz richtig, denn dort gebe ich die Längenangabe "Length of dataset" des Message-Objects mit nur einem Byte an. Das müssten aber eigentlich 2 Bytes sein, da es ansonsten mit der Gesamtlänge nicht zusammenpasst. Allerdings gäbe es dann hier eine andere Endianess, muss ich mir nochmal ansehen wie das aussieht wenn ich einen entsprechend großen Begleitwert übermittle.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke!!!

Alarme werden gemeldet.

Kann ich bei dem Message Objekt davon ausgehen, dass die Struktur immer gleich ist? Länge ist noch abhängig von der Associated value(s).
 
Bis zum ersten Begleitwert ist der Aufbau immer gleich. Um an den "gehenden Zeitstempel" zu kommen musst du auf jeden Fall die Begleitwerte korrekt verarbeiten. Wenn du nur EventID und alles bis zu "kommender Zeitstempel" benötigst, dann könntest du das auch überspringen.

Ich habe mal geguckt wie Siemens das macht. Prodave unterstützt keine Bausteinmeldungen, aber über Sapi-S7 ist das wohl möglich. Das gibt dir über die entsprechenden Funktionen auch eine Struktur mit den Message-Objekt-Daten zurück. Zwar nicht ganz so roh wie ich es mache, aber der Unterschied ist nicht mehr groß als dass es viel Arbeit ersparen würde.
 
Hab mir jetzt mal ne Struktur gebastelt, die bis zum kommenden Zeitstempel geht und kopiere den Buffer darüber. Funktioniert auch recht gut.

Was bedeutet der EventState sowie AckState going/coming?

Den gehenden Zeitstempel bekomme ich sowie so nur wenn ich laufend die Alarme auslese. (Was ich nicht vor habe.)

Anderer seits muss ich jetzt mal schauen, wann ich die Alarme abhole. Entweder per Störungsmerker der SPS oder doch einen Listener programmieren.
 
Zurück
Oben