Event-driven detection of changes to the symbol table
ADS devices that support symbol names (PLC, NC, ...) store those names in an internal table. A handle is assigned here to each symbol. The symbol handle is necessary in order to be able to access the variables (see also Sample 9). If the symbol table changes because, for instance, a new PLC program is written into the controller, the handles must be ascertained once again. The following sample illustrates how changes to the symbol table can be detected.
Download: sample12-c-ads-dll-detectsymbolchanges.zip
#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <winbase.h>
// ADS headers
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsApi.h"
void __stdcall SymbolChanged(AmsAddr*, AdsNotificationHeader*, unsigned long);
void main()
{
long nErr;
AmsAddr Addr;
PAmsAddr pAddr = &Addr;
ULONG hNotification;
AdsNotificationAttrib adsNotificationAttrib;
// Open communication port on the ADS router
AdsPortOpen();
nErr = AdsGetLocalAddress(pAddr);
if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
// Select Port: TwinCAT2 PLC1
pAddr->port = 801;
// Specify attributes of the notification
adsNotificationAttrib.cbLength = 1;
adsNotificationAttrib.nTransMode = ADSTRANS_SERVERONCHA;
adsNotificationAttrib.nMaxDelay = 5000000; // 500ms
adsNotificationAttrib.nCycleTime = 5000000; // 500ms
// Start notification for changes to the symbol table
nErr = AdsSyncAddDeviceNotificationReq(pAddr, ADSIGRP_SYM_VERSION, 0, &adsNotificationAttrib, SymbolChanged, NULL, &hNotification);
if (nErr) cerr << "Error: AdsSyncAddDeviceNotificationReq: " << nErr << '\n';
// Wait for a key-press from the user
_getch();
// Stop notification
nErr = AdsSyncDelDeviceNotificationReq(pAddr, hNotification);
if (nErr) cerr << "Error: AdsSyncDelDeviceNotificationReq: " << nErr << '\n';
// Close communication port
nErr = AdsPortClose();
if (nErr) cerr << "Error: AdsPortClose: " << nErr << '\n';
}
// Callback function
void __stdcall SymbolChanged(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser)
{
cout << "Symboltabelle hat sich geändert!\n";
cout.flush();
}