ADS in Java

Ads In Java


  • 依赖包
    TcJavaToAds.jar, 可以直接在TwinCAT的安装目录下找到,路径(我这里装在C盘):C:\TwinCAT\AdsApi\AdsToJava,对应的DLL(adstojava.dll)也在这个目录下,DLL不用管,只要安装了TwinCAT XAE,TcJavaToAds.jar 使用时会自己按默认路径装载这个DLL,我们只需要在Java项目中加入TcJavaToAds.jar这个外部包就行。
  • 示例
    Java中ADS通信的流程比C#中复杂些,底层机制都一样,只是C#封装的相对好一些,这里为了更清晰的说明使用方式,将分成几段进行描述;项目中,我们通常只对发布的变量进行读写,即使用了AT指定段地址和偏移地址的,此时group和offset可以直接从PLC中获取到,这里我们描述的更为通用的方式,通过变量名自动获取段地址和偏移地址,进而对变量进行读、写、监听;当然也可以通过变量名获取变量句柄,然后通过句柄对变量进行读写,但所提供的API中没有通过句柄进行变量监听的操作,要监听必须提供段地址和偏移地址。另外,这里读写监听示例主要针对单线程环境,如果需要在多线程环境下使用,需要使用相应的Ex结尾的API函数,函数名和参数均类似单线程的。
    • 建立Ads连接
    AmsAddr addr = new AmsAddr();
    AdsCallDllFunction.adsPortOpen();
    addr.setNetIdStringEx("*.*.*.*.*.*");
    addr.setPort(851);
    
    • 读取变量地址信息
    long err;
    String PLC_VAR = "MAIN.sTest";
    //JNIByteBuffer handleBuff = new JNIByteBuffer(16);
    JNIByteBuffer symbolInfoBuff = new JNIByteBuffer(BUFF_LENGTH_MAX); //BUFF_LENGTH_MAX:16
    JNIByteBuffer symbolBuff = new JNIByteBuffer(PLC_VAR.getBytes());
    err = AdsCallDllFunction.adsSyncReadWriteReq(addr, AdsCallDllFunction.ADSIGRP_SYM_INFOBYNAME, 0x0,
    			symbolInfoBuff.getUsedBytesCount(), symbolInfoBuff, symbolBuff.getUsedBytesCount(), symbolBuff);//err处理略	
    byte[] bArr = symbolInfoBuff.getByteArray();
    System.out.println(bArr.length);
    ByteBuffer wrapped = ByteBuffer.wrap(bArr);
    wrapped.order(ByteOrder.LITTLE_ENDIAN);
    int group = wrapped.getInt();
    System.out.println("group: "+group);
    int offset = wrapped.getInt();
    System.out.println("offset: "+offset);
    int len = wrapped.getInt();
    System.out.println("len: "+len);
    
    • 根据Group+Offset读取变量
      	JNIByteBuffer dataBuff = new JNIByteBuffer(BUFF_LENGTH_MAX);
      	err = AdsCallDllFunction.adsSyncReadReq(addr, group, offset, len, dataBuff);//err处理略	
      	ByteBuffer wrapped2 = ByteBuffer.wrap(dataBuff.getByteArray()); 
      	wrapped2.order(ByteOrder.LITTLE_ENDIAN);
      
      • 读取INT变量
        System.out.println("val: " + wrapped2.getShort());
        
      • 读取DINT变量
        wrapped2.getInt();
        
      • 读取LREAL变量
        wrapped2.getDouble();
        
      • 读取字符串
        new String(dataBuff.getByteArray());
        
      • 读取数组
        for(int i=0; i<len/2; i++) {
        	System.out.println("val: [" + i + "]: " + wrapped2.getShort());
        }
        
      • 读取结构体
        System.out.println(wrapped2.getShort());
        System.out.println(wrapped2.get());
        System.out.println(wrapped2.getDouble(8));
        
        其中,PLC中对应的结构体定义为:
        TYPE S_Test :
        STRUCT
        	i: INT;
        	b: BOOL;
        	q: LREAL;
        END_STRUCT
        END_TYPE
        
        注意结构体中变量的字节对齐问题
    • 根据Group+Offset写变量
      AdsCallDllFunction.adsSyncWriteReq(addr, group, offset, dataBuff.getUsedBytesCount(), dataBuff);
      
      • 写INT变量
        dataBuff.setByteArray(ByteBuffer.allocate(Short.SIZE/Byte.SIZE)
        .order(ByteOrder.LITTLE_ENDIAN).putShort((short) 99).array(), true);
        
      • 写DINT变量
        dataBuff.setByteArray(ByteBuffer.allocate(Integer.SIZE/Byte.SIZE)
        .order(ByteOrder.LITTLE_ENDIAN).putInt((short) 99).array(), true);
        
      • 写LREAL变量
        dataBuff.setByteArray(ByteBuffer.allocate(Double.SIZE/Byte.SIZE)
        .order(ByteOrder.LITTLE_ENDIAN).putDouble((short) 99).array(), true);
        
      • 写字符串
        dataBuff.setByteArray("Hi\0".getBytes(), true);
        
      • 写数组
        ByteBuffer buf = ByteBuffer.allocate(len).order(ByteOrder.LITTLE_ENDIAN);
        for(int i=1; i<=32; i++) {
        	buf.putShort((short) i);
        }
        dataBuff.setByteArray(buf.array(), true);
        
      • 写结构体
        ByteBuffer buf = ByteBuffer.allocate(len).order(ByteOrder.LITTLE_ENDIAN);
        buf.putShort((short)19);
        buf.put((byte)1);
        buf.putDouble(8, 9.99);
        dataBuff.setByteArray(buf.array(), true);
        
    • 事件触发读取变量
      • 注册变量监听

        JNILong notification = new JNILong();
        AdsNotificationAttrib attr = new AdsNotificationAttrib();
        attr.setCbLength(Short.SIZE / Byte.SIZE);
        attr.setNTransMode(AdsConstants.ADSTRANS_SERVERONCHA);
        attr.setDwChangeFilter(10000000); // 1 sec
        attr.setNMaxDelay(20000000);   // 2 sec
        
        AdsListener listener = new AdsListener();
        AdsCallbackObject callObject = new AdsCallbackObject();
        callObject.addListenerCallbackAdsState(listener);
        err = AdsCallDllFunction.adsSyncAddDeviceNotificationReq(
        	      addr,
        	      group, 
        	      offset, 
        	      attr,
        	      99,
        	      notification);
        
        
      • 监听器实现

        public class AdsListener implements CallbackListenerAdsState {
        	private final static long SPAN = 1929293939399L;
        
        	//回调函数
        	public void onEvent(AmsAddr addr, AdsNotificationHeader notification, long user) {
        		long dateInMillis = notification.getNTimeStamp();
        		Date notificationDate = new Date(dateInMillis / 10000 - SPAN);
        		System.out.println("Value: " + notification.getData());
        		System.out.println("Notification: " + notification.getHNotification());
        		System.out.println("Time: " + notificationDate.toString());
        		System.out.println("User: " + user);
        		System.out.println("ServerNetID: " + addr.getNetIdString() + "\n");
        	}
        }
        
      • 取消变量监听

        AdsCallDllFunction.adsSyncDelDeviceNotificationReq(addr, notification);
        

你可能感兴趣的:(自动化,工控)