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.

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.

Hinweis: 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(851);

     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");
}
}

Beispielprogramm 'Ereignisgesteuertes Lesen' entpacken.

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.

Voraussetzungen

Entwicklungsumgebung

Zielplattform

Einzubindende Java-Packages

TwinCAT v3.0 Build 3102, Java

PC or CX (x86)