Ereignisgesteuertes Lesen
Sollen in einer Bedieneroberfläche kontinuierlich Werte aus der SPS oder NC angezeigt werden, so ist das benutzen von AdsSyncReadReq() sehr aufwendig, da diese Funktion zyklisch aufgerufen werden muss. Durch das Definieren sogenannter Notifications (Meldung) kann ein TwinCAT Server dazu veranlasst werden, Werte über ADS an ein anderes ADS-Gerät zu übertragen. Hierbei wird unterschieden ob der TwinCAT Server die Werte zyklisch oder nur bei Veränderung übertragen soll.
Mit der Funktion AdsSyncAddDeviceNotificationReq() wird eine Notification gestartet. Die Callback-Funktion wird anschließend selbständig von TwinCAT aufgerufen. Mit AdsSyncDelDeviceNotificationReq() wird die Notification wieder beendet. Da die Anzahl der Notifications begrenzt ist, sollten Sie in Ihrem Programm dafür sorgen, das nicht mehr benötigte Notifications gelöscht werden. Weiter Informationen finden Sie bei der Beschreibung zur Struktur AdsNotificationAttrib.
Beispielprogramm 'Ereignisgesteuertes Lesen' entpacken: sample09.zip
- Um das *.jar Sample ausführen zu können, muss in der Konsole im korrekten Verzeichnis der Befehl 'java -classpath "Sample09.jar;[Pfad zu TcJavaToAds.jar] Main' ausgeführt werden (Beispielpfad: "C:TwinCAT\Ads Api\AdsToJava\*"). Dazu muss java in den Umgebungsvariablen eingetragen sein.
Das folgende Programm startet eine Notification auf das Merkerdoppeltwort 0 in der SPS. Bei jeder Änderung der SPS-Variablen, wird die Callback-Funktion aufgerufen. Als Parameter enthält die Callback-Funktion unter anderem eine Variable vom Typ AdsNotificationHeader(). In dieser Struktur sind alle notwendigen Informationen (Wert, Zeitstempel, ...) enthalten.
Zeitintensive Aktionen Im Callback dürfen keine zeitintensiven Aktionen ausgeführt werden. |
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());
}
}
}
Die Implementierung des 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");
}
}