ADS-Summenkommando: Holen und Freigeben von mehreren Handles

Dieses Beispiel zeigt, wie man unter Zuhilfenahme des ADS-Summenkommandos, viele Handles holen und wieder freigeben kann. Aufgebaut als AdsSyncReadWriteRequest, dient es als Behälter, in dem die Unterkommandos transportiert werden.

Systemvoraussetzungen:

Beispielprogramm 'ADS-Summenkommando: Holen und Freigeben von mehreren Handles' entpacken: sample12.zip

Handles holen

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import de.beckhoff.jni.Convert;
import de.beckhoff.jni.JNIByteBuffer;
import de.beckhoff.jni.tcads.AdsCallDllFunction;
import de.beckhoff.jni.tcads.AmsAddr;

public class Main {
    
    private static final String VAR_NAME1 = ".bVar01";
    private static final String VAR_NAME2 = ".bVar02";
    
    public static void main (String[] args) {
    long err = 0;
        
    try {
        AmsAddr addr = new AmsAddr();
        
        // Create request and response buffer
        JNIByteBuffer jniReqBuff;
        JNIByteBuffer jniResBuff = new JNIByteBuffer(new byte[24]);
        
        // Construct data objects
        RequestData req1 = new RequestData();
        req1.setIndexGroup(AdsCallDllFunction.ADSIGRP_SYM_HNDBYNAME);
        req1.setIndexOffset(0x0);
        req1.setReadLength(Integer.SIZE / Byte.SIZE);
        req1.setWriteLength(VAR_NAME1.length());
        
        RequestData req2 = new RequestData();
        req2.setIndexGroup(AdsCallDllFunction.ADSIGRP_SYM_HNDBYNAME);
        req2.setIndexOffset(0x0);
        req2.setReadLength(Integer.SIZE / Byte.SIZE);
        req2.setWriteLength(VAR_NAME2.length());      
        
         
        // Concatenate byte[] representations of RequestData objects and 
        // variable names (see picture 1)
        int reqBuffSize = RequestData.SIZE * 2 / Byte.SIZE
            + req1.getWriteLength() + req2.getWriteLength();

        ByteBuffer reqBuff = ByteBuffer.allocate(reqBuffSize);
        reqBuff.order(ByteOrder.LITTLE_ENDIAN);
        
        reqBuff.put(req1.toByteArray());
        reqBuff.put(req2.toByteArray());
        reqBuff.put(Convert.StringToByteArr(VAR_NAME1, false));
        reqBuff.put(Convert.StringToByteArr(VAR_NAME2, false));
        
        // Need to let a JNIByteBuffer wrap the byte[] to be able to send it
        jniReqBuff = new JNIByteBuffer(reqBuff.array());

Die Namen der Variablen deren Handles wir erhalten wollen, werden an das Ende des Bytearrays gehängt.

ADS-Summenkommando: Holen und Freigeben von mehreren Handles 1:

Für die Kommunikation wird ein Port geöffnet und die lokale Adresse übergeben. Kommt es zur Übertragung wird vorher der Port vom Laufzeitsystem 1 der Adresse zugewiesen.

Die Parameter für das Summenkommando bestehen aus IndexGroup (0xf082) - Aufruf des Summenkommandos, IndexOffset (0x2) - Anzahl der Unterkommandos, ReadLength (0x18) - Größenangabe der zu lesenden Daten, ReadData (pBuffRes) - Speicher, der gelesene Daten entgegen nimmt, WriteLength (cbReq) - Größenangabe der zu sendenen Daten und WriteLength (pBuffReq) - Speicher, der zu sendende Daten enthält.

        // 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!");
        } 
        
        err = AdsCallDllFunction.adsSyncReadWriteReq(
                addr, 
                0xf082,             // ADS list-read-write command
                0x2,                // number of ADS-sub commands
                jniResBuff.getUsedBytesCount(), // we expect an ADS error 
                                //  return-code for each ADS-sub command 
                jniResBuff,             // provide space for the response 
                                // containing the return codes
                jniReqBuff.getUsedBytesCount(), // send 48 bytes(IG1, 
                                // IO1, RLen1, WLen1, IG2, IO2, RLen2,
                                // WLen2, Data1, Data2)
                jniReqBuff);
        
        // Check return codes
        ByteBuffer resBuff = ByteBuffer.wrap(jniResBuff.getByteArray());
        resBuff.order(ByteOrder.LITTLE_ENDIAN);
        if (err != 0) { 
        System.out.println("Error: Get handles: 0x" 
                + Long.toHexString(err)); 
        } else {
        
        // Extract error codes from response (see picture 2)
        // Pattern is: err1, len1, .., errN, lenN, data1, .., dataN  
        int req1Err = resBuff.getInt((Integer.SIZE / Byte.SIZE) * 0);
        int req2Err = resBuff.getInt((Integer.SIZE / Byte.SIZE) * 2);
        
        if (req1Err != 0) {
            System.out.println("Error: Get handle1: 0x" 
                    + Integer.toHexString(req1Err));
        } else if (req2Err != 0) {
            System.out.println("Error: Get handle2: 0x" 
                    + Integer.toHexString(req2Err));
        } else {        
            System.out.println("Success: Get handles!");
        }
        }

Nach dem Senden des Request, erwarten wir einen ADS Fehlercode und Länge für jeden Handle den wir versuchen zu bekommen. In diesem Fall wird die Länge immer 4 Bytes betragen.

ADS-Summenkommando: Holen und Freigeben von mehreren Handles 2:

Handles freigeben

        // Extract handles from response(see picture 2)  
        int hnd1 = resBuff.getInt((Integer.SIZE / Byte.SIZE) * 4);
        int hnd2 = resBuff.getInt((Integer.SIZE / Byte.SIZE) * 5);        


        //// Release handles
        // Construct buffers
        int relBuffSize = 
            (ReleaseData.SIZE * 2 / Byte.SIZE) + (Integer.SIZE * 2 / Byte.SIZE);
        int relResBuffSize = Integer.SIZE * 2 / Byte.SIZE;

        ByteBuffer relBuff = ByteBuffer.allocate(relBuffSize);
        relBuff.order(ByteOrder.LITTLE_ENDIAN);
        JNIByteBuffer jniRelBuff = new JNIByteBuffer(relBuffSize);
        JNIByteBuffer jniRelResBuff = new JNIByteBuffer(relResBuffSize);

        // Construct data objects       
        ReleaseData rel1 = new ReleaseData();
        rel1.setIndexGroup(AdsCallDllFunction.ADSIGRP_SYM_RELEASEHND);
        rel1.setIndexOffset(0);
        rel1.setLength(Integer.SIZE / Byte.SIZE);

        ReleaseData rel2 = new ReleaseData();
        rel2.setIndexGroup(AdsCallDllFunction.ADSIGRP_SYM_RELEASEHND);
        rel2.setIndexOffset(0);
        rel2.setLength(Integer.SIZE / Byte.SIZE);
        
        // Concatenate byte[] representations of ReleaseData objects and 
        // handles (see picture 3)
        relBuff.put(rel1.toByteArray());
        relBuff.put(rel2.toByteArray());
        relBuff.putInt(hnd1);
        relBuff.putInt(hnd2);
        
        // Need to let a JNIByteBuffer wrap the byte[] to be able to send it        
        jniRelBuff.setByteArray(relBuff.array(), true);

Die zu den Kommandos zugehörigen Handles werden an das Ende des Bytearrays gehängt.

ADS-Summenkommando: Holen und Freigeben von mehreren Handles 3:

Für die Freigabe der Handles wird die bestehende Verbindung benutzt.

Die Parameter für das Summenkommando bestehen aus IndexGroup (0xf081) - Aufruf des Summenkommandos, IndexOffset (0x2) - Anzahl der Unterkommandos, ReadLength (cbRelRes) - Größenangabe der zu lesenden Daten, ReadData (pBuffRelRes) - Speicher, der gelesene Daten entgegen nimmt, WriteLength (cbRel) - Größenangabe der zu sendenen Daten und WriteLength (pBuffRel) - Speicher, der zu sendene Daten enthält.

Zum Schluss müssen die Handles freigegeben und der Port geschlossen werden.

        // Release handles - Second task cleared
        err = AdsCallDllFunction.adsSyncReadWriteReq(
                addr, 
                0xf081,         // ADS list-write command
                0x2,        // number of ADS-sub commands
                relResBuffSize,     // we expect an ADS-error-return-code for 
                        // each ADS-sub command
                jniRelResBuff,      // provide space for the response containing
                        // the return codes
                relBuffSize,    // send 32 bytes (IG1, IO1, Len1, IG2, IO2, 
                        // Len2, Data1, Data2)
                jniRelBuff);    // buffer with data     
    
        
        // Check return codes           
        if (err != 0) { 
        System.out.println("Error: Release handles: 0x" 
                + Long.toHexString(err)); 
        } else {        
        ByteBuffer relResBuff = 
            ByteBuffer.wrap(jniRelResBuff.getByteArray());
        relResBuff.order(ByteOrder.LITTLE_ENDIAN);
                    
        // Extract error codes from response (see picture 4)
        // Pattern is: err1, .., errN  
        int rel1Err = relResBuff.getInt((Integer.SIZE / Byte.SIZE) * 0);
        int rel2Err = relResBuff.getInt((Integer.SIZE / Byte.SIZE) * 1);
        
        if (rel1Err != 0) {
            System.out.println("Error: Release handle1: 0x" 
                    + Integer.toHexString(rel1Err));
        } else if (rel2Err != 0) {
            System.out.println("Error: Release handle2: 0x" 
                    + Integer.toHexString(rel2Err));
        } else {
            System.out.println("Success: Release handles!");    
        }
        }
        
        System.out.println("\nPress enter to continue..");
        System.in.read();
        
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        // Close communication
        err = AdsCallDllFunction.adsPortClose();
        
        if (err != 0) { 
        System.out.println("Error: Close communication: 0x"
            + Long.toHexString(err)); 
        } else {
        System.out.println("Success: Close communication!");
        }
    }
    }
}

Als Antwort erhalten wir einen ADS Fehlercode für jedes Handle das wir versuchen freizugeben.

ADS-Summenkommando: Holen und Freigeben von mehreren Handles 4: