Event-driven reading (by symbol name)
Requirements:
- Delphi 5.0 or higher
- TcAdsDLL.DLL
- TcAdsDEF.pas and TcAdsAPI.pas if you wish to compile the source code yourself
Declaration files The declaration files TcAdsAPI.pas and TcAdsDEF.pas are included in the archive delphi_adsdll_api_units.zip. |
Delphi 5 program
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, TcAdsDef, TcAdsAPI,
StdCtrls, Math, ComCtrls;
const WM_ADSDEVICENOTIFICATION = WM_APP + 400;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
Memo1: TMemo;
Label1: TLabel;
Label2: TLabel;
editDelayTime: TEdit;
Label3: TLabel;
editCycleTime: TEdit;
StatusBar1: TStatusBar;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure WMAdsDeviceNotification( var Message: TMessage ); message WM_ADSDEVICENOTIFICATION;
procedure FormDestroy(Sender: TObject);
private
server : TAmsAddr;
hVar : Longword;
hNotification : Longword;
nCnt : Longword;
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
{$ALIGN OFF}
type
TNotifyData = record
netid : TAmsNetId;
port : Word;
hNotification : Longword;
dateTime : TDateTime;
cbSampleSize : Longword;
hUser : Longword;
data : Byte;
end;
PNotifyData = ^TNotifyData;
{$ALIGN ON}
var
Form1: TForm1;
DevThreadList : TThreadList;
implementation
{$R *.DFM}
Implementation of the notification callback function
////////////////////////////////////////////////////////////////////////////////////////////////
Procedure NotificationCallback( pAddr:PAmsAddr; pNotification:PAdsNotificationHeader; hUser:Longword ); stdcall;
var pItem : PNotifyData;
FileTime : _FILETIME;
SystemTime, LocalTime : _SYSTEMTIME;
TimeZoneInformation : _TIME_ZONE_INFORMATION;
begin
System.GetMem( pItem, sizeof(TNotifyData) - 1 + pNotification^.cbSampleSize );
pItem^.netId := pAddr^.netId;
pItem^.port := pAddr^.port;
pItem^.hNotification := pNotification^.hNotification;
pItem^.cbSampleSize := pNotification^.cbSampleSize;
System.Move( pNotification^.data, pItem^.data, pNotification^.cbSampleSize);
FileTime:=pNotification^.nTimeStamp;
GetTimeZoneInformation(TimeZoneInformation);
FileTimeToSystemTime(FileTime, SystemTime);
SystemTimeToTzSpecificLocalTime(@TimeZoneInformation, SystemTime, LocalTime);
pItem^.dateTime:=SystemTimeToDateTime(LocalTime);
with DevThreadList.LockList do
try
Add( pItem );
finally
DevThreadList.UnlockList;
PostMessage( HWND(hUser), WM_ADSDEVICENOTIFICATION, 0, 0);
end;
end;
Synchronization of main thread and callback thread using Windows messages
////////////////////////////////////////////////////////////////////////////////////////////////
procedure TForm1.WMAdsDeviceNotification( var Message: TMessage );
var pItem : PNotifyData;
X : integer;
sHex : String;
i : Longword;
begin
with DevThreadList.LockList do
try
Memo1.Lines.BeginUpdate();
for X := 0 to Count-1 do
begin
nCnt := nCnt + 1;
pItem := Items[X];
{convert data to hex string}
sHex := '';
if pItem^.cbSampleSize > 0 then
begin
for i:= 0 to math.Min(pItem^.cbSampleSize-1, 20) do
sHex := sHex + IntToHex( PBYTE(PAnsiChar(@pItem^.data) + i)^, 2 ) + ' ' ;
end;
{}
Memo1.Lines.Insert(0,Format( 'idx:%-4d stamp:%s, %d.%d.%d.%d.%d.%d[%d], hNot:0x%x, size:%d, data:%s',
[nCnt,TimeToStr(pItem^.dateTime), pItem^.netId.b[0], pItem^.netId.b[1], pItem^.netId.b[2],
pItem^.netId.b[3], pItem^.netId.b[4], pItem^.netId.b[5], pItem^.port,
pItem^.hNotification, pItem^.cbSampleSize, sHex]));
FreeMem( pItem, sizeof(TNotifyData) -1 + pItem^.cbSampleSize );
end;
Clear();
finally
if memo1.Lines.Count > 1000 then
memo1.Lines.Clear();
Memo1.Lines.EndUpdate();
DevThreadList.UnlockList;
end;
inherited;
end;
Establish connection to the PLC
////////////////////////////////////////////////////////////////////////////////////////////////
procedure TForm1.FormCreate(Sender: TObject);
begin
AdsPortOpen();
AdsGetLocalAddress(@server);
server.port := AMSPORT_R0_PLC_RTS1;
DevThreadList := TThreadList.Create();
StatusBar1.SimpleText := Format('Server netId: %d.%d.%d.%d.%d.%d port:%d', [server.netId.b[0], server.netId.b[1],server.netId.b[2],
server.netId.b[3], server.netId.b[4],server.netId.b[5], server.port]);
end;
Release resources, disconnect
////////////////////////////////////////////////////////////////////////////////////////////////
procedure TForm1.FormDestroy(Sender: TObject);
var X : integer;
begin
if hNotification <> 0 then
Button2Click(Sender);
with DevThreadList.LockList do
try
for X := 0 to Count -1 do
FreeMem( Items[X], sizeof(TNotifyData) + PNotifyData(Items[X])^.cbSampleSize - 1 );
Clear;
finally
DevThreadList.UnlockList;
DevThreadList.Destroy;
end;
AdsPortClose();
end;
Register notification
////////////////////////////////////////////////////////////////////////////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
var result : Longint;
adsNotificationAttrib : TAdsNotificationAttrib;
szVarName : AnsiString;
begin
Memo1.Lines.Clear;
nCnt := 0;
{ get symbol handle by symbol name }
szVarName := AnsiString(Edit1.Text);
result := AdsSyncReadWriteReq( @server, ADSIGRP_SYM_HNDBYNAME, 0,
sizeof(hVar), @hVar, Length(szVarName)+1, @szVarName[1] );
Memo1.Lines.Insert(0, Format('AdsSyncReadWriteReq(..ADSIGRP_SYM_HNDBYNAME..) result: %d [0x%x], symbol handle: 0x%x', [result, result, hVar]));
{ add notification (connect to variable)}
adsNotificationAttrib.cbLength := 20;{Should be right}
adsNotificationAttrib.nTransMode := ADSTRANS_SERVERONCHA;
adsNotificationAttrib.nMaxDelay := StrToInt(editDelayTime.Text) * 10000; //ms
adsNotificationAttrib.nCycleTime := StrToInt(editCycleTime.Text) * 10000;//ms
result := AdsSyncAddDeviceNotificationReq( @server, ADSIGRP_SYM_VALBYHND,
hVar,
@adsNotificationAttrib,
@NotificationCallback,
Handle, @hNotification );
Memo1.Lines.Insert(0, Format( 'AdsSyncAddDeviceNotificationReq(..ADSIGRP_SYM_VALBYHND..) result: %d [0x%x], notification handle: 0x%x', [result, result, hNotification] ));
Button1.Enabled := not( result = ADSERR_NOERR);
Button2.Enabled := ( result = ADSERR_NOERR);
end;
Unregister notification
////////////////////////////////////////////////////////////////////////////////////////////////
procedure TForm1.Button2Click(Sender: TObject);
var result : Longint;
begin
{ delete notification }
result := AdsSyncDelDeviceNotificationReq( @server, hNotification );
hNotification := 0;
Memo1.Lines.Insert(0, Format( 'AdsSyncDelDeviceNotificationReq() result: %d [0x%x]', [result,result] ));
{release symbol handle}
result := AdsSyncWriteReq( @server, ADSIGRP_RELEASE_SYMHND, 0,sizeof(hVar), @hVar);
Memo1.Lines.Insert(0, Format('AdsSyncReadWriteReq(..ADSIGRP_RELEASE_SYMHND..) result: %d [0x%x]', [result, result]));
Button1.Enabled := true;
Button2.Enabled := false;
end;
initialization
end.
Language / IDE | Unpack sample program |
---|---|
Delphi XE2 | |
Delphi 5 or higher (classic) |
Related documents