Event driven reading
If values from a PLC or NC are to be displayed continuously on a user interface, then it is very inefficient to use AdsSyncReadReq(), since this function must be called cyclically. By defining so-called notifications, a TwinCAT server can be caused to transfer values via ADS to another ADS device. A distinction is drawn between whether the TwinCAT server is to transmit the values cyclically, or only when the values change.
A notification is begun with the AdsSyncAddDeviceNotificationReq() function. After this, the callback function is automatically invoked by TwinCAT. AdsSyncDelDeviceNotificationReq() is used to halt the notification again. Since the number of notifications is limited, you should ensure the notifications no longer required by your program are deleted. You will find further information under the description of the AdsNotificationAttrib structure.
Unpack the sample program 'Event driven reading': sample09.zip
- To execute the *.jar sample, the command 'java -classpath "Sample09.jar;[path to TcJavaToAds.jar] Main' must be executed in the console in the correct directory (example path: "C:TwinCAT\Ads Api\AdsToJava\*"). For this, java must be entered in the environment variables.
The following program starts a notification on flag double word 0 in the PLC. Each time the PLC variable changes, the callback function is invoked. The callback function receives a variable of type AdsNotificationHeader() as one of its parameters. This structure contains all the necessary information (value, timestamp, ...).
Time intensive actions No time-intensive actions may be executed in the callback. |
import de.beckhoff.jni.AdsConstants;
import de.beckhoff.jni.JNILong;
import de.beckhoff.jni.tcads.AdsCallDllFunction;
import de.beckhoff.jni.tcads.AdsNotificationAttrib;
import de.beckhoff.jni.tcads.AdsCallbackObject;
import de.beckhoff.jni.tcads.AmsAddr;
public class Main {
public static void main(String[] args) {
try {
long err;
AmsAddr addr = new AmsAddr();
JNILong notification = new JNILong();
// Open communication
AdsCallDllFunction.adsPortOpen();
err = AdsCallDllFunction.getLocalAddress(addr);
addr.setPort(AdsCallDllFunction.AMSPORT_R0_PLC_RTS1);
if (err != 0) {
System.out.println("Error: Open communication: 0x"
+ Long.toHexString(err));
} else {
System.out.println("Success: Open communication!");
}
// Specify attributes of the notificationRequest
AdsNotificationAttrib attr = new AdsNotificationAttrib();
attr.setCbLength(Integer.SIZE / Byte.SIZE);
attr.setNTransMode(AdsConstants.ADSTRANS_SERVERONCHA);
attr.setDwChangeFilter(10000000); // 1 sec
attr.setNMaxDelay(20000000); // 2 sec
// Create and add listener
AdsListener listener = new AdsListener();
AdsCallbackObject callObject = new AdsCallbackObject();
callObject.addListenerCallbackAdsState(listener);
// Create notificationHandle
err = AdsCallDllFunction.adsSyncAddDeviceNotificationReq(
addr,
0x4020, // IndexGroup
0x0, // IndexOffset
attr, // The defined AdsNotificationAttrib object
42, // Choose arbitrary number
notification);
if(err!=0) {
System.out.println("Error: Add notification: 0x"
+ Long.toHexString(err));
}
// Read as long as user does not press return
System.out.println("Press enter to continue..");
System.in.read();
// Delete notificationHandle
err = AdsCallDllFunction.adsSyncDelDeviceNotificationReq(
addr,
notification);
if(err!=0) {
System.out.println("Error: Remove notification: 0x"
+ Long.toHexString(err));
}
// Delete listener
callObject.removeListenerCallbackAdsState(listener);
//Close communication
err = AdsCallDllFunction.adsPortClose();
if(err!=0) {
System.out.println("Error: Close Communication: 0x"
+ Long.toHexString(err));
}
} catch(Exception ex) {
System.out.println(ex.getMessage());
}
}
}
The implementation of the CallbackListenerAdsState interface:
import de.beckhoff.jni.Convert;
import de.beckhoff.jni.tcads.AdsNotificationHeader;
import de.beckhoff.jni.tcads.AmsAddr;
import de.beckhoff.jni.tcads.CallbackListenerAdsState;
import java.util.Date;
public class AdsListener implements CallbackListenerAdsState {
private final static long SPAN = 11644473600000L;
// Callback function
public void onEvent(AmsAddr addr,
AdsNotificationHeader notification,
long user) {
// The PLC timestamp is coded in Windows FILETIME.
// Nano secs since 01.01.1601.
long dateInMillis = notification.getNTimeStamp();
// Date accepts millisecs since 01.01.1970.
// Convert to millisecs and substract span.
Date notificationDate = new Date(dateInMillis / 10000 - SPAN);
System.out.println("Value:\t\t"
+ Convert.ByteArrToInt(notification.getData()));
System.out.println("Notification:\t" + notification.getHNotification());
System.out.println("Time:\t\t" + notificationDate.toString());
System.out.println("User:\t\t" + user);
System.out.println("ServerNetID:\t" + addr.getNetIdString() + "\n");
}
}