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

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.

Ereignisgesteuertes Lesen 1:

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