Auslesen einer Variablendeklaration

Bei dem Zugriff auf die Variablendeklaration werden folgende Informationen übertragen:

Mit dem AdsSyncReadWriteReq() Aufruf wird die Information der Variablen ausgelesen. Der Name der Variable wird der Funktion im Parameter pWriteData übergeben. Nach dem Aufruf steht die angeforderte Information in der Variable pAdsSymbolEntry. In dieser Struktur sind die einzelnen Informationen der SPS-Variablen abgelegt. Die Makros PADSSYMBOLNAME, PADSSYMBOLTYPE und PADSSYMBOLCOMMENT vereinfachen das Auswerten dieser Daten. Als nächstes wird der Datentyp der Variable anhand von pAdsSymbolEntry->dataType ausgewertet.
Falls der Datentyp dem Typ UDINT oder ARRAY OF UDINT wird zusätzlich der Wert dieser Variable ausgelsen.

Download: sample14-c-ads-dll-readsinglevariabledeclaration.zip

#include <windows.h>
#include <conio.h>
#include <assert.h>
#include <string.h>
#include <iostream.h>

// ADS headers
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsApi.h"

typedef enum AdsDataTypeId
{
    ADST_VOID = VT_EMPTY,
    ADST_INT8 = VT_I1,
    ADST_UINT8 = VT_UI1,
    ADST_INT16 = VT_I2,
    ADST_UINT16 = VT_UI2,
    ADST_INT32 = VT_I4,
    ADST_UINT32 = VT_UI4,
    ADST_INT64 = VT_I8,
    ADST_UINT64 = VT_UI8,
    ADST_REAL32 = VT_R4,    
    ADST_REAL64 = VT_R8,
    ADST_STRING = VT_LPSTR,
    ADST_WSTRING = VT_LPWSTR,
    ADST_REAL80 = VT_LPWSTR+1,
    ADST_BIT = VT_LPWSTR+2,
    ADST_BIGTYPE = VT_BLOB,
    ADST_MAXTYPES = VT_STORAGE,
} ADS_DATATYPE;

typedef struct _ValueString
{
    DWORD dwValue;
    char* szLabel;
} ValueString;

ValueString AdsDatatypeString[] =

    { VT_EMPTY, "ADST_VOID", },
    { VT_I1, "ADST_INT8", },
    { VT_UI1, "ADST_UINT8", },
    { VT_I2, "ADST_INT16", },
    { VT_UI2, "ADST_UINT16", },
    { VT_I4, "ADST_INT32", },
    { VT_UI4, "ADST_UINT32", },
    { VT_I8, "ADST_INT64", },
    { VT_UI8, "ADST_UINT64", },
    { VT_R4, "ADST_REAL32", },
    { VT_R8, "ADST_REAL64", },
    { VT_LPSTR, "ADST_STRING", }, 
    { VT_LPWSTR, "ADST_WSTRING", },
    { VT_LPWSTR+2, "ADST_BIT", },
    { VT_BLOB, "ADST_BIGTYPE", },
    { VT_STORAGE, "ADST_MAXTYPES", }, 
};

void main()
{
    long nErr, nPort; 
    AmsAddr Addr; 
    PAmsAddr pAddr = &Addr; 
    char szVariable[255];
    BYTE buffer[0xFFFF];
    PAdsSymbolEntry pAdsSymbolEntry;

    // Open communication port on the ADS router
    nPort = AdsPortOpen();
    nErr = AdsGetLocalAddress(pAddr);
    if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
    
    // Select Port: TwinCAT2 PLC1 
    pAddr->port = 801;

    for(;;)
    { 
    cout << "Enter variable Name: ";
    cin >> szVariable;

    nErr = AdsSyncReadWriteReq(pAddr, ADSIGRP_SYM_INFOBYNAMEEX, 0, sizeof(buffer), buffer, strlen(szVariable)+1, szVariable);
    if (nErr) 
    {
        cerr << "Error: AdsSyncReadReq: " << nErr << '\n'; 
    }
    else
    {
        pAdsSymbolEntry = (PAdsSymbolEntry)buffer;
        cout << "Name: " << PADSSYMBOLNAME(pAdsSymbolEntry) << "\n" 
        <<"Index Group: "<< pAdsSymbolEntry->iGroup << '\n' 
        <<"Index Offset: "<< pAdsSymbolEntry->iOffs << '\n' 
        <<"Size: "<< pAdsSymbolEntry->size << '\n' 
        <<"Type: "<< (char*)PADSSYMBOLTYPE(pAdsSymbolEntry) << '\n' 
        <<"Comment: "<< (char*)PADSSYMBOLCOMMENT(pAdsSymbolEntry) << '\n'; 

        switch(pAdsSymbolEntry->dataType)
        {
        case ADST_UINT32:
        {
            int nElements = pAdsSymbolEntry->size/sizeof(unsigned long);
            unsigned long *pVal = new unsigned long[nElements];
            cout << "Datatype: ADST_UINT32" <<'\n';
            AdsSyncReadReq(pAddr, pAdsSymbolEntry->iGroup, pAdsSymbolEntry->iOffs, pAdsSymbolEntry->size, pVal); 
            if( nErr )
            {
            cerr << "Error: AdsSyncReadReq: Unable to read Value" << nErr << '\n'; 
            } 
            else
            {
            cout << "Value: ";
            for( int i=0; i<nElements; i++ ) 
            {
                cout << pVal[i] << '\t';
            }
            cout << '\n';
            }
        }
        break;
        default:
        {
            int nType = sizeof(AdsDatatypeString)/sizeof(ValueString);
            for(int i=0; i< nType; i++)
            {
            if( AdsDatatypeString[i].dwValue == pAdsSymbolEntry->dataType )
            {
                cout << "Datatype:" << AdsDatatypeString[i].szLabel <<'\n';
                break; 
            }
            }
            if( i == nType )
            cout << "Datatype:" << "Unknown datatype:" << pAdsSymbolEntry->dataType <<'\n';
        }
        break;
        } 
    } 
    cout << "Exit(y/n)" << '\n';
    cout.flush();

    if(_getch() == 'y')
        break;
    }
    // Close communication port
    nErr = AdsPortClose(); 
    if (nErr) cerr << "Fehler: AdsPortClose: " << nErr << '\n';
}
VAR_GLOBAL
    PLCVarBYTE AT %MB0: BYTE; (* PLCVarBYTE *)
    PLCVarWORD AT %MB4: WORD; (* PLCVarWORD *)
    PLCVarDWORD AT %MB8: DWORD; (* PLCVarDWORD *)
    PLCVarBOOL AT %MB12: BOOL; (* PLCVarBOOL *)
    PLCVarINT AT %MB16: INT; (* PLCVarINT *)
    PLCVarSINT AT %MB20: SINT; (* PLCVarSINT *)
    PLCVarUSINT AT %MB24: USINT; (* PLCVarUSINT *)
    PLCVarUINT AT %MB28: UINT; (* PLCVarUINT *)
    PLCVarDINT AT %MB32: DINT; (* PLCVarDINT *)
    PLCVarUDINT AT %MB34: UDINT := 1234; (* PLCVarUDINT *)
    PLCVarREAL AT %MB38: REAL; (* PLCVarREAL *)
    PLCVarLREAL AT %MB42: LREAL; (* PLCVarLREAL *)
    
    PLCVarUDINTArray :ARRAY[0..5] OF UDINT; (* PLCVarINTArray*)
END_VAR