WinCC v7 - GetTagMultiWait() in eine Funktion packen

RONIN

Level-3
Beiträge
2.529
Reaktionspunkte
773
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo.

Ich versuche gerade die GetTagMultiWait-Funtion aus WinCC in einen Funktionsaufruf zu verpacken so dass sich diese praktischer aufrufen lässt.
Grundsätzlich sieht GetTagMultiWait ja so aus:
Code:
BOOL bOK;
DWORD  DWORDVarValue[20];


bOK = GetTagMultiWait("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
"WinCC_VariablenName_1", &DWORDVarValue[0],
"WinCC_VariablenName_2", &DWORDVarValue[1],
"WinCC_VariablenName_3", &DWORDVarValue[2],
"WinCC_VariablenName_4", &DWORDVarValue[3],
"WinCC_VariablenName_5", &DWORDVarValue[4],
"WinCC_VariablenName_6", &DWORDVarValue[5],
"WinCC_VariablenName_7", &DWORDVarValue[6],
"WinCC_VariablenName_8", &DWORDVarValue[7],
"WinCC_VariablenName_9", &DWORDVarValue[8],
"WinCC_VariablenName_10", &DWORDVarValue[9],
"WinCC_VariablenName_11", &DWORDVarValue[10],
"WinCC_VariablenName_12", &DWORDVarValue[11],
"WinCC_VariablenName_13", &DWORDVarValue[12],
"WinCC_VariablenName_14", &DWORDVarValue[13],
"WinCC_VariablenName_15", &DWORDVarValue[14],
"WinCC_VariablenName_16", &DWORDVarValue[15],
"WinCC_VariablenName_17", &DWORDVarValue[16],
"WinCC_VariablenName_18", &DWORDVarValue[17],
"WinCC_VariablenName_19", &DWORDVarValue[18],
"WinCC_VariablenName_20", &DWORDVarValue[19]);
Die Variablennamen und den Format-String kann man zwar dynamisch erstellen...
Code:
BOOL bOK = FALSE;
int i, iVarCnt;


char GtmFormatString[255];
char VarName[20][50];
DWORD  DWORDVarValue[20];


//Variablennamen + Format-String
strcpy(GtmFormatString, "\"");
for( i = 0; i <= 20 - 1; i++)
{
    sprintf(VarName[i], "WinCC_VariablenName_%d", i);
    strcat(GtmFormatString,"%d");
}
strcat(GtmFormatString,"\"");


//Aufruf GetTagMultiWait
bOK = GetTagMultiWait(GtmFormatString,
VarName[0], &DWORDVarValue[0],
...
VarName[19], &DWORDVarValue[19]);
...ist aber immer noch verdammt viel Schreibarbeit und die Funktionen in denen man es anwendet werden unübersichtlich.



Jetzt hatte ich mir gedacht das einfach in eine Funktion zu verpacken.
Grundsätzlich nicht schwer. Den Format-String aus dem die Variablen-Namen erstellt werden ("WinCC_VariablenName_%d) und ein Array für die Ergebnisdaten übergeben.
Die tatsächlichen Variablennamen und der Format-String ("%d%d%d...") werden dann in der Funktion generiert und der GetTagMulti-Aufruf steht auch dort.

Was ich aber nicht weiß ist wie man die Parameterübergabe der GetTagMulti dynamisch gestalten könnte.
Der GetTagMulti bekommt für jede zu lesende Variable einen String-Parameter für den zu lesenden Variablen-Namen und einen Adress-Parameter wo er das Ergebnis hinschreiben soll.
Die Anzahl der Parameter ist also nicht konstant.

Ich möchte meiner Funktion gerne einen Count-Parameter übergeben.
Hätte aber keine Ahnung wie ich bei Count=5 den GetTagMulti gestalten müsste damit der 5 Strings und 5 Adressen bekommt.
Geht sowas überhaupt?

Wenn das nicht geht hatte ich mir gedacht den GetTagMulti mit einer fixen Anzahl von Parametern (z.b. für 20 Variablen) zu programmieren und dann bei Count = 5 nur die ersten 5 Strings mit Variablennamen zu füttern.
Das funktioniert auch und könnte so aussehen...
Code:
BOOL GetTagMulti_DWord20(const char *VarNameFormatString, DWORD TagData[], int Cnt, int CntStart)
{
#define VarCnt_MAX 20


BOOL bOK = FALSE;
int i, iVarCnt;


char GtmFormatString[VarCnt_MAX * 2 + 10];
char VarName[VarCnt_MAX][255];
DWORD  DWORDVarValue[VarCnt_MAX];


//Variablennamen + Format-String
strcpy(GtmFormatString, "\"");
for( i = 0; i <= Cnt - 1; i++)
{
    sprintf(VarName[i], VarNameFormatString, i + CntStart);
    strcat(GtmFormatString,"%d");
}
strcat(GtmFormatString,"\"");


//Aufruf GetTagMultiWait
bOK = GetTagMultiWait(GtmFormatString,
VarName[0], &DWORDVarValue[0],
VarName[1], &DWORDVarValue[1],
VarName[2], &DWORDVarValue[2],
VarName[3], &DWORDVarValue[3],
VarName[4], &DWORDVarValue[4],
VarName[5], &DWORDVarValue[5],
VarName[6], &DWORDVarValue[6],
VarName[7], &DWORDVarValue[7],
VarName[8], &DWORDVarValue[8],
VarName[9], &DWORDVarValue[9],
VarName[10], &DWORDVarValue[10],
VarName[11], &DWORDVarValue[11],
VarName[12], &DWORDVarValue[12],
VarName[13], &DWORDVarValue[13],
VarName[14], &DWORDVarValue[14],
VarName[15], &DWORDVarValue[15],
VarName[16], &DWORDVarValue[16],
VarName[17], &DWORDVarValue[17],
VarName[18], &DWORDVarValue[18],
VarName[19], &DWORDVarValue[19]);


printf("bOK = %d\n", bOK);


//Daten an TagData[] übergeben
if( bOK )
{
    for( i = 0; i <= Cnt - 1; i++)
    {
        TagData[i] = DWORDVarValue[i];
    }
}


return bOK;


}
... mit dem Aufruf
Code:
char VarNameFormatString[30];
DWORD VarValues[20];


strcpy( VarNameFormatString, "WinCCVariablenName_%d");
if (GetTagMulti_DWord20(VarNameFormatString, VarValues, 5, 1))
{
    //Tu was
}
Bei dem Aufruf befülle ich nur VarName[0] - VarName[5] mit eine gültigen VariablenNamen, die restlichen bleiben leer.
Ne Doku von GetTagMulti in der steht wie sich GetTagMulti in dem Fall verhält hab ich nicht gefunden.

Funtkionieren tut es tadellos.
Der GetTagMulti-Aufruf liefert keinen Fehler und die richten Werte obwohl die letzen 15 Variablen-Strings leer sind.
Es würde also gehen aber optimal gelöst ist es wohl nicht.

Gibt es die Möglichkeit die dynamische Parameter-Belegung von GetTagMulti zur Laufzeit zu erzeugen?
Oder gibt es sonst noch einen besseren Weg?

Danke.
 
Das geht nicht so einfach. Dazu müsstest du dir eine va_list mit eigenen Parametern aufbauen, die dann an die GetTagMulti übergeben wird.
Das ist nicht so einfach möglich (aber nicht unmöglich), und vor allem auch compiler-/architekturabhängig. In wie weit der C-Compiler von WinCC das überhaupt beherrscht ist die nächste Frage. Der Compiler übersetzt in P-Code der dann später interpretiert wird, und zu derem Internas wirst du wenig Informationen finden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Thomas
Ja, hatte ich mir schon gedacht dass das nicht so einfach gehen wird.
Zum Thema va_list findet sich in Google ja einiges, hat mich schon immer interessiert wie das bei Funktionen ala printf grundsätzlich funktioniert.

Ich meine ich kann auch mit der obigen Lösung ganz gut leben oder hättest du eventuell einen anderen Vorschlag.
 
Wenn deine eigene Funktion variable Parameter übernimmt, also (...), dann könntest du diese an GetTagMulti weiterreichen. Aber dann triffst du auf das "Problem" beim Aufrufen deiner eigenen Funktion.

Ich weiß ja nicht wie viele Parameter bei dir maximal vorkommen sollen... 20 Funktionsaufrufe mit switch(anzahl) sind zwar nicht sehr schön, aber funktional ;-) Sowas schreibt man ja auch nur einmal.
 
Bis zu 150... na da hätte ich ordentlich zu tippen :ROFLMAO:

Ich könnte mir eine Funktion vorstellen die per switch bis zu 20 Variablen (oder so) liest.
Dann noch eine zweite Funktion welche, bei größer 20 Variablen, die vorige Funktion mehrmals aufruft. Also 7x20 plus 1x10...
Klingt als wäre gangbarer Weg. Das switch-Kontrukt hat man mit ein wenig Copy/Paste+Excel-Magic vermutlich recht schnell beisammen... :cool:
 
Warum müssen denn so viele Variablen mit MultiWait gelesen werden?
In den meisten Fällen sind es 20, in einem 150.

Für eine Auswertung via Script bräuchte ich aus den 150 Datensätzen jeweils einen Datenpunkt. Die Datensätze sind auch alle als WinCC-Variablen angelegt.
Wenn man in den Scripten jetzt per...
Code:
for( i = 1; i <= 150; i++ )
{
    sprintf(Varname, "WinCC_Variable_%d", i);
    VarValue = GetTagDWord(VarName);
...
}
... zugreift, dann dauert das ewig wenn die Variablen grad nicht in WinCC zur Aktualisierung angemeldet sind.
Per GetTagMulti geht das eigentlich akzeptabel schnell.


Vielleicht ist da ein anderer Verbindungstyp besser geeignet, wie BSEND/BRECV, das geht ja auch in WinCC.
Kannst du mir das man näher beschreiben? :confused:

EDIT: Damit ist wohl das gemeint.
https://support.industry.siemens.com/cs/ww/de/view/37873547

Wusste nicht dass das so auch geht. So nur mal kurz drüber geschaut wäre das ebenfalls eine Überlegung wert.
Man könnte sich gleich ganze Datensätze in einen Rohdatenblock schicken. Geht das nur mit Rohdatenblöcken?
Hab aber noch nie mit den Rohdaten in WinCC gearbeitet.
Die Frage ist wie viel Aufwand es dort wäre sich die Werte wieder raus zu popeln.
 
Zuletzt bearbeitet:
Kommt drauf an was du mit den Daten machen willst. Um irgenwelche protokollierten Daten aus der SPS in eine Textdatei o.Ä. zu schreiben kann das schon ganz nützlich sein. Solche Daten werden ja nicht unbedingt in einem Prozessbild angezeigt. Wenn in den Daten nur Werte gleichen Datentyps (z.B. Int oder Real-Array) stehen, dann ist das auch recht einfach auszuwerten. Kann zudem einiges an Tags sparen.
 
Zurück
Oben