New file |
| | |
| | | package com.zy.gateway; |
| | | |
| | | import com.zy.gateway.core.domain.OperateResult; |
| | | import com.zy.gateway.core.domain.OperateResultExOne; |
| | | import com.zy.gateway.core.domain.siemens.SiemensPLCS; |
| | | import com.zy.gateway.core.net.siemens.SiemensS7Net; |
| | | |
| | | /** |
| | | * Created by vincent on 2020-06-04 |
| | | */ |
| | | public class Test { |
| | | |
| | | public static void main(String[] args) throws InterruptedException { |
| | | SiemesTest(); |
| | | try { |
| | | |
| | | SiemensS7Net siemensS7Net = new SiemensS7Net(SiemensPLCS.S1200,"192.168.1.102"); |
| | | OperateResult write = siemensS7Net.Write("M200",(short)200); |
| | | |
| | | if(!write.IsSuccess){ |
| | | System.out.println("Write failed:"+write.Message); |
| | | } |
| | | |
| | | OperateResultExOne<Short> read = siemensS7Net.ReadInt16("M200"); |
| | | if(read.IsSuccess){ |
| | | System.out.println("Value:"+read.Content.toString()); |
| | | } |
| | | else { |
| | | System.out.println("Read failed:"+read.Message); |
| | | } |
| | | } |
| | | catch (Exception ex){ |
| | | System.out.println(ex.getMessage()); |
| | | } |
| | | Thread.sleep(1000); |
| | | } |
| | | |
| | | private static void SiemesTest(){ |
| | | SiemensS7Net siemens_net = new SiemensS7Net(SiemensPLCS.S1200,"192.168.1.102"); |
| | | OperateResult connect = siemens_net.ConnectServer(); |
| | | if(connect.IsSuccess){ |
| | | System.out.println("connect success!"); |
| | | } |
| | | else { |
| | | System.out.println("failed:"+connect.Message); |
| | | } |
| | | siemens_net.ConnectClose(); |
| | | |
| | | // 上面是初始化 |
| | | System.out.println(siemens_net.ReadByte("M100").Content); |
| | | |
| | | byte m100_byte = siemens_net.ReadByte("M100").Content; |
| | | short m100_short = siemens_net.ReadInt16("M100").Content; |
| | | int m100_int = siemens_net.ReadInt32("M100").Content; |
| | | long m100_long = siemens_net.ReadInt64("M100").Content; |
| | | float m100_float = siemens_net.ReadFloat("M100").Content; |
| | | double m100_double = siemens_net.ReadDouble("M100").Content; |
| | | String m100_string = siemens_net.ReadString("M100",(short) 10).Content; |
| | | |
| | | siemens_net.Write("M100",(byte) 123); |
| | | siemens_net.Write("M100",(short) 123); |
| | | siemens_net.Write("M100",(int) 123); |
| | | siemens_net.Write("M100",(long) 123); |
| | | siemens_net.Write("M100", 123.456f); |
| | | siemens_net.Write("M100", 123.456d); |
| | | siemens_net.Write("M100","1234567890"); |
| | | |
| | | OperateResultExOne<byte[]> read = siemens_net.Read( "M100", (short) 10 ); |
| | | { |
| | | if(read.IsSuccess) |
| | | { |
| | | byte m100 = read.Content[0]; |
| | | byte m101 = read.Content[1]; |
| | | byte m102 = read.Content[2]; |
| | | byte m103 = read.Content[3]; |
| | | byte m104 = read.Content[4]; |
| | | byte m105 = read.Content[5]; |
| | | byte m106 = read.Content[6]; |
| | | byte m107 = read.Content[7]; |
| | | byte m108 = read.Content[8]; |
| | | byte m109 = read.Content[9]; |
| | | } |
| | | else |
| | | { |
| | | // 发生了异常 |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core; |
| | | |
| | | import com.zy.gateway.core.domain.IDataTransfer; |
| | | import com.zy.gateway.core.domain.OperateResult; |
| | | import com.zy.gateway.core.domain.OperateResultExOne; |
| | | |
| | | /** |
| | | * 所有设备交互类的统一的读写接口 |
| | | */ |
| | | public interface IReadWriteNet { |
| | | |
| | | /** |
| | | * 批量读取底层的数据信息,需要指定地址和长度,具体的结果取决于实现 |
| | | * @param address 地址信息 |
| | | * @param length 数据长度 |
| | | * @return 带有成功标识的byte[]数组 |
| | | */ |
| | | OperateResultExOne<byte[]> Read(String address, short length); |
| | | |
| | | /** |
| | | * 读取16位的有符号整型 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的short数据 |
| | | */ |
| | | OperateResultExOne<Short> ReadInt16(String address); |
| | | |
| | | /** |
| | | * 读取16位的有符号整型数组 |
| | | * @param address 起始地址 |
| | | * @param length 读取的数组长度 |
| | | * @return 带有成功标识的short数组 |
| | | */ |
| | | OperateResultExOne<short []> ReadInt16(String address, short length); |
| | | |
| | | /** |
| | | * 读取32位的有符号整型 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的int数据 |
| | | */ |
| | | OperateResultExOne<Integer> ReadInt32(String address); |
| | | |
| | | /** |
| | | * 读取32位有符号整型的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | OperateResultExOne<int[]> ReadInt32(String address, short length); |
| | | |
| | | /** |
| | | * 读取64位的有符号整型 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的long数据 |
| | | */ |
| | | OperateResultExOne<Long> ReadInt64(String address); |
| | | |
| | | /** |
| | | * 读取64位的有符号整型数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | OperateResultExOne<long[]> ReadInt64(String address, short length); |
| | | |
| | | /** |
| | | * 读取单浮点精度的数据 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的float数据 |
| | | */ |
| | | OperateResultExOne<Float> ReadFloat(String address); |
| | | |
| | | /** |
| | | * 读取单浮点精度的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | OperateResultExOne<float[]> ReadFloat(String address, short length); |
| | | |
| | | /** |
| | | * 读取双浮点精度的数据 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的double数据 |
| | | */ |
| | | OperateResultExOne<Double> ReadDouble(String address); |
| | | |
| | | |
| | | /** |
| | | * 读取双浮点精度的数据的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | OperateResultExOne<double[]> ReadDouble(String address, short length); |
| | | |
| | | /** |
| | | * 读取字符串数据 |
| | | * @param address 起始地址 |
| | | * @param length 数据长度 |
| | | * @return 带有成功标识的string数据 |
| | | */ |
| | | OperateResultExOne<String> ReadString(String address, short length); |
| | | |
| | | |
| | | /** |
| | | * 读取自定义的数据类型,需要继承自IDataTransfer接口 |
| | | * @param address 起始地址 |
| | | * @param <T> 自定义的类型 |
| | | * @return 带有成功标识的自定义类型数据 |
| | | */ |
| | | <T extends IDataTransfer> OperateResultExOne<T> ReadCustomer(String address, Class<T> tClass); |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 写入short数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, short value); |
| | | |
| | | /** |
| | | * 写入short数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, short[] values); |
| | | |
| | | /** |
| | | * 写入int数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, int value); |
| | | |
| | | /** |
| | | * 写入int[]数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, int[] values); |
| | | |
| | | /** |
| | | * 写入long数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, long value); |
| | | |
| | | /** |
| | | * 写入long数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, long[] values); |
| | | |
| | | /** |
| | | * 写入float数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, float value); |
| | | |
| | | /** |
| | | * 写入float数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, float[] values); |
| | | |
| | | /** |
| | | * 写入double数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, double value); |
| | | |
| | | /** |
| | | * 写入double数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, double[] values); |
| | | |
| | | /** |
| | | * 写入字符串信息,编码为ASCII |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, String value); |
| | | |
| | | |
| | | /** |
| | | * 写入字符串信息,编码为ASCII |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @param length 写入的字符串的长度 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, String value, int length); |
| | | |
| | | /** |
| | | * 写入自定义类型的数据,该类型必须继承自IDataTransfer接口 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @param <T> 类型对象 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | <T extends IDataTransfer> OperateResult WriteCustomer(String address, T value); |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core; |
| | | |
| | | import com.zy.gateway.core.language.DefaultLanguage; |
| | | import com.zy.gateway.core.language.English; |
| | | |
| | | import java.util.Locale; |
| | | |
| | | public class StringResources { |
| | | |
| | | static |
| | | { |
| | | Locale locale = Locale.getDefault(); |
| | | if (locale.getLanguage().startsWith( "zh" )) |
| | | { |
| | | SetLanguageChinese( ); |
| | | } |
| | | else |
| | | { |
| | | SeteLanguageEnglish( ); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取或设置系统的语言选项 -> |
| | | * Gets or sets the language options for the system |
| | | */ |
| | | public static DefaultLanguage Language = new DefaultLanguage( ); |
| | | |
| | | /** |
| | | * 将语言设置为中文 -> |
| | | * Set the language to Chinese |
| | | */ |
| | | public static void SetLanguageChinese( ) |
| | | { |
| | | Language = new DefaultLanguage( ); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将语言设置为英文 -> |
| | | * Set the language to English |
| | | */ |
| | | public static void SeteLanguageEnglish( ) |
| | | { |
| | | Language = new English( ); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.base; |
| | | |
| | | public class HslSecurity { |
| | | |
| | | /// <summary> |
| | | /// 加密方法,只对当前的程序集开放 |
| | | /// </summary> |
| | | /// <param name="enBytes">等待加密的数据</param> |
| | | /// <returns>加密后的数据</returns> |
| | | public static byte[] ByteEncrypt(byte[] enBytes) { |
| | | if (enBytes == null) return null; |
| | | byte[] result = new byte[enBytes.length]; |
| | | for (int i = 0; i < enBytes.length; i++) { |
| | | result[i] = (byte) (enBytes[i] ^ 0xB5); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 解密方法,只对当前的程序集开放 |
| | | /// </summary> |
| | | /// <param name="deBytes">等待解密的数据</param> |
| | | /// <returns>解密后的数据</returns> |
| | | public static byte[] ByteDecrypt(byte[] deBytes) { |
| | | return ByteEncrypt(deBytes); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.base; |
| | | |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.IOException; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.lang.reflect.Array; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Random; |
| | | import java.util.UUID; |
| | | |
| | | |
| | | public class SoftBasic { |
| | | |
| | | |
| | | /** |
| | | * 根据大小获取文本描述信息 |
| | | * @param size 数据大小 |
| | | * @return 字符串文本 |
| | | */ |
| | | public static String GetSizeDescription(long size) { |
| | | if (size < 1000) { |
| | | return size + " B"; |
| | | } else if (size < 1000 * 1000) { |
| | | float data = (float) size / 1024; |
| | | return String.format("%.2f", data) + " Kb"; |
| | | } else if (size < 1000 * 1000 * 1000) { |
| | | float data = (float) size / 1024 / 1024; |
| | | return String.format("%.2f", data) + " Mb"; |
| | | } else { |
| | | float data = (float) size / 1024 / 1024 / 1024; |
| | | return String.format("%.2f", data) + " Gb"; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 判断两个字节数组是否是一致的,可以指定中间的某个区域 |
| | | * @param b1 第一个字节数组 |
| | | * @param start1 起始字节 |
| | | * @param b2 第二个字节数组 |
| | | * @param start2 起始字节 |
| | | * @param length 对比数据的长度 |
| | | * @return 是否一致 |
| | | */ |
| | | public static boolean IsTwoBytesEquel(byte[] b1, int start1, byte[] b2, int start2, int length) |
| | | { |
| | | if (b1 == null || b2 == null) return false; |
| | | for (int i = 0; i < length; i++) |
| | | { |
| | | if (b1[i + start1] != b2[i + start2]) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将byte数组的长度扩充到指定长度 |
| | | * @param data 原先的数据长度 |
| | | * @param length 扩充或是缩短后的长度 |
| | | * @return 新的扩充后的数据对象 |
| | | */ |
| | | public static byte[] ArrayExpandToLength(byte[] data,int length){ |
| | | if (data == null) return new byte[0]; |
| | | byte[] buffer = new byte[length]; |
| | | System.arraycopy( data,0, buffer,0, Math.min( data.length, buffer.length ) ); |
| | | return buffer; |
| | | } |
| | | |
| | | /** |
| | | * 将byte数组的长度扩充到偶数长度 |
| | | * @param data 原先的数据长度 |
| | | * @return 新的扩充后的数据对象 |
| | | */ |
| | | public static byte[] ArrayExpandToLengthEven( byte[] data ) |
| | | { |
| | | if (data == null) data = new byte[0]; |
| | | if (data.length % 2 == 1) |
| | | { |
| | | return ArrayExpandToLength(data, data.length + 1 ); |
| | | } |
| | | else |
| | | { |
| | | return data; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将一个数组进行扩充到偶数长度 |
| | | * @param data 原先数据的数据 |
| | | * @param <T> 数组的类型 |
| | | * @return 新数组长度信息 |
| | | */ |
| | | public static <T> T[] ArrayExpandToLengthEven(Class<T> tClass, T[] data ) |
| | | { |
| | | if (data == null) data = (T[]) new Object[0]; |
| | | |
| | | if (data.length % 2 == 1) |
| | | { |
| | | return ArrayExpandToLength(tClass, data, data.length + 1 ); |
| | | } |
| | | else |
| | | { |
| | | return data; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 将一个数组进行扩充到指定长度,或是缩短到指定长度 |
| | | * @param data 原先数据的数据 |
| | | * @param length 新数组的长度 |
| | | * @param <T> 数组的类型 |
| | | * @return 新数组长度信息 |
| | | */ |
| | | public static <T> T[] ArrayExpandToLength(Class<T> tClass, T[] data, int length ) |
| | | { |
| | | if (data == null) return (T[]) Array.newInstance(tClass,0); |
| | | |
| | | if (data.length == length) return data; |
| | | |
| | | T[] buffer = (T[]) Array.newInstance(tClass,length); |
| | | |
| | | System.arraycopy( data,0, buffer,0, Math.min( data.length, buffer.length ) ); |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 获取一串唯一的随机字符串,长度为20,由Guid码和4位数的随机数组成,保证字符串的唯一性 |
| | | * @return 随机字符串数据 |
| | | */ |
| | | public static String GetUniqueStringByGuidAndRandom() |
| | | { |
| | | Random random = new Random(); |
| | | return UUID.randomUUID().toString() + (random.nextInt(9000)+1000); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 字节数据转化成16进制表示的字符串 |
| | | * @param InBytes 字节数组 |
| | | * @return 返回的字符串 |
| | | */ |
| | | public static String ByteToHexString(byte[] InBytes) |
| | | { |
| | | return ByteToHexString(InBytes, (char)0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 字节数据转化成16进制表示的字符串 |
| | | * @param InBytes 字节数组 |
| | | * @param segment 分割符 |
| | | * @return 返回的字符串 |
| | | */ |
| | | public static String ByteToHexString(byte[] InBytes, char segment) |
| | | { |
| | | |
| | | StringBuilder stringBuilder = new StringBuilder(""); |
| | | if (InBytes == null || InBytes.length <= 0) { |
| | | return null; |
| | | } |
| | | for (int i = 0; i < InBytes.length; i++) { |
| | | int v = InBytes[i] & 0xFF; |
| | | String hv = Integer.toHexString(v); |
| | | if (hv.length() < 2) { |
| | | stringBuilder.append(0); |
| | | } |
| | | stringBuilder.append(hv); |
| | | stringBuilder.append(segment); |
| | | } |
| | | return stringBuilder.toString(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | *将bool数组转换到byte数组 |
| | | * @param array bool数组 |
| | | * @return 字节数组 |
| | | */ |
| | | public static byte[] BoolArrayToByte(boolean[] array) |
| | | { |
| | | if (array == null) return null; |
| | | |
| | | int length = array.length % 8 == 0 ? array.length / 8 : array.length / 8 + 1; |
| | | byte[] buffer = new byte[length]; |
| | | |
| | | for (int i = 0; i < array.length; i++) |
| | | { |
| | | int index = i / 8; |
| | | int offect = i % 8; |
| | | |
| | | byte temp = 0; |
| | | switch (offect) |
| | | { |
| | | case 0: temp = 0x01; break; |
| | | case 1: temp = 0x02; break; |
| | | case 2: temp = 0x04; break; |
| | | case 3: temp = 0x08; break; |
| | | case 4: temp = 0x10; break; |
| | | case 5: temp = 0x20; break; |
| | | case 6: temp = 0x40; break; |
| | | case 7: temp = (byte) 0x80; break; |
| | | default: break; |
| | | } |
| | | |
| | | if (array[i]) buffer[index] += temp; |
| | | } |
| | | |
| | | return buffer; |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从Byte数组中提取位数组 |
| | | * @param InBytes 原先的字节数组 |
| | | * @param length 想要转换的长度,如果超出自动会缩小到数组最大长度 |
| | | * @return 结果对象 |
| | | */ |
| | | public static boolean[] ByteToBoolArray(byte[] InBytes, int length) |
| | | { |
| | | if (InBytes == null) return null; |
| | | |
| | | if (length > InBytes.length * 8) length = InBytes.length * 8; |
| | | boolean[] buffer = new boolean[length]; |
| | | |
| | | for (int i = 0; i < length; i++) |
| | | { |
| | | int index = i / 8; |
| | | int offect = i % 8; |
| | | |
| | | byte temp = 0; |
| | | switch (offect) |
| | | { |
| | | case 0: temp = 0x01; break; |
| | | case 1: temp = 0x02; break; |
| | | case 2: temp = 0x04; break; |
| | | case 3: temp = 0x08; break; |
| | | case 4: temp = 0x10; break; |
| | | case 5: temp = 0x20; break; |
| | | case 6: temp = 0x40; break; |
| | | case 7: temp = (byte) 0x80; break; |
| | | default: break; |
| | | } |
| | | |
| | | if ((InBytes[index] & temp) == temp) |
| | | { |
| | | buffer[i] = true; |
| | | } |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 字符串数据转化成16进制表示的字符串 |
| | | * @param InString 输入的字符串数据 |
| | | * @return 返回的字符串 |
| | | * @throws UnsupportedEncodingException |
| | | */ |
| | | public static String ByteToHexString(String InString) throws UnsupportedEncodingException |
| | | { |
| | | return ByteToHexString(InString.getBytes("unicode")); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 实际的字符串列表 |
| | | */ |
| | | private static List<Character> hexCharList = Arrays.asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'); |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将16进制的字符串转化成Byte数据,将检测每2个字符转化,也就是说,中间可以是任意字符 |
| | | * @param hex 16进制表示的字符串数据 |
| | | * @return 字节数组 |
| | | */ |
| | | public static byte[] HexStringToBytes(String hex) |
| | | { |
| | | hex = hex.toUpperCase(); |
| | | |
| | | ByteArrayOutputStream ms = new ByteArrayOutputStream (); |
| | | |
| | | for (int i = 0; i < hex.length(); i++) |
| | | { |
| | | if ((i + 1) < hex.length()) |
| | | { |
| | | if (hexCharList.contains(hex.charAt(i)) && hexCharList.contains(hex.charAt(i+1))) |
| | | { |
| | | // 这是一个合格的字节数据 |
| | | ms.write((byte)(hexCharList.indexOf(hex.charAt(i)) * 16 +hexCharList.indexOf(hex.charAt(i+1)))); |
| | | i++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | byte[] result = ms.toByteArray(); |
| | | try { |
| | | ms.close(); |
| | | } |
| | | catch (IOException ex) |
| | | { |
| | | |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 拼接2个字节数组的数据 |
| | | * @param bytes1 数组一 |
| | | * @param bytes2 数组二 |
| | | * @return 拼接后的数组 |
| | | */ |
| | | public static byte[] SpliceTwoByteArray( byte[] bytes1, byte[] bytes2 ) |
| | | { |
| | | if (bytes1 == null && bytes2 == null) return null; |
| | | if (bytes1 == null) return bytes2; |
| | | if (bytes2 == null) return bytes1; |
| | | |
| | | byte[] buffer = new byte[bytes1.length + bytes2.length]; |
| | | System.arraycopy(bytes1,0,buffer,0,bytes1.length); |
| | | System.arraycopy(bytes2,0,buffer,bytes1.length,bytes2.length); |
| | | return buffer; |
| | | } |
| | | |
| | | /** |
| | | * 将一个byte数组的前面指定位数移除,返回新的一个数组 |
| | | * @param value 字节数组 |
| | | * @param length 等待移除的长度 |
| | | * @return 新的数据 |
| | | */ |
| | | public static byte[] BytesArrayRemoveBegin( byte[] value, int length ) |
| | | { |
| | | return BytesArrayRemoveDouble( value, length, 0 ); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将一个byte数组的后面指定位数移除,返回新的一个数组 |
| | | * @param value 字节数组 |
| | | * @param length 等待移除的长度 |
| | | * @return 新的数据 |
| | | */ |
| | | public static byte[] BytesArrayRemoveLast( byte[] value, int length ) |
| | | { |
| | | return BytesArrayRemoveDouble( value, 0, length ); |
| | | } |
| | | |
| | | /** |
| | | * 将一个byte数组的前后移除指定位数,返回新的一个数组 |
| | | * @param value 字节数组 |
| | | * @param leftLength 前面的位数 |
| | | * @param rightLength 后面的位数 |
| | | * @return 新的数据 |
| | | */ |
| | | public static byte[] BytesArrayRemoveDouble( byte[] value, int leftLength, int rightLength ) |
| | | { |
| | | if (value == null) return null; |
| | | if (value.length <= (leftLength + rightLength)) return new byte[0]; |
| | | |
| | | byte[] buffer = new byte[value.length - leftLength - rightLength]; |
| | | System.arraycopy( value, leftLength, buffer, 0, buffer.length ); |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.zy.gateway.core.base; |
| | | |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.util.zip.GZIPInputStream; |
| | | import java.util.zip.GZIPOutputStream; |
| | | |
| | | public class SoftZipped { |
| | | |
| | | public static byte[] CompressBytes(byte[] data) { |
| | | byte[] b = null; |
| | | try { |
| | | ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| | | GZIPOutputStream gzip = new GZIPOutputStream(bos); |
| | | gzip.write(data); |
| | | gzip.finish(); |
| | | gzip.close(); |
| | | b = bos.toByteArray(); |
| | | bos.close(); |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | } |
| | | return b; |
| | | } |
| | | |
| | | |
| | | |
| | | public static byte[] Decompress(byte[] data) { |
| | | byte[] b = null; |
| | | try { |
| | | ByteArrayInputStream bis = new ByteArrayInputStream(data); |
| | | GZIPInputStream gzip = new GZIPInputStream(bis); |
| | | byte[] buf = new byte[1024]; |
| | | int num = -1; |
| | | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| | | while ((num = gzip.read(buf, 0, buf.length)) != -1) { |
| | | baos.write(buf, 0, num); |
| | | } |
| | | b = baos.toByteArray(); |
| | | baos.flush(); |
| | | baos.close(); |
| | | gzip.close(); |
| | | bis.close(); |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | } |
| | | return b; |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | /** |
| | | * 空操作的类 |
| | | */ |
| | | public class ActionOperate |
| | | { |
| | | /** |
| | | * 空操作 |
| | | */ |
| | | public void Action(){ |
| | | |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | /** |
| | | * 带一个参数对象的操作类 |
| | | * @param <T> |
| | | */ |
| | | public class ActionOperateExOne<T> |
| | | { |
| | | /** |
| | | * 带一个参数对象的空操作 |
| | | * @param content 类型对象 |
| | | */ |
| | | public void Action(T content) |
| | | { |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | /** |
| | | * 带三个参数的类型对象 |
| | | * @param <T1> 类型一 |
| | | * @param <T2> 类型二 |
| | | * @param <T3> 类型三 |
| | | */ |
| | | public class ActionOperateExThree<T1,T2,T3> |
| | | { |
| | | /** |
| | | * 实际的操作方法,需要继承重写 |
| | | * @param content1 类型一对象 |
| | | * @param content2 类型二对象 |
| | | * @param content3 类型三对象 |
| | | */ |
| | | public void Action(T1 content1,T2 content2,T3 content3){ |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | /** |
| | | * 带二个参数对象的操作类 |
| | | * @param <T1> 类型一 |
| | | * @param <T2> 类型二 |
| | | */ |
| | | public class ActionOperateExTwo <T1,T2> |
| | | { |
| | | /** |
| | | * 实际的操作方法,应该重写 |
| | | * @param content1 类型一对象 |
| | | * @param content2 类型二对象 |
| | | */ |
| | | public void Action(T1 content1,T2 content2) |
| | | { |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | public class FunctionOperate<R> |
| | | { |
| | | public R Action(){ |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | public class FunctionOperateExOne<T,R> |
| | | { |
| | | public R Action(T content){ |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | import java.net.Socket; |
| | | import java.util.Date; |
| | | |
| | | public class HslTimeOut { |
| | | |
| | | |
| | | /** |
| | | * 默认的无参构造函数 |
| | | */ |
| | | public HslTimeOut() |
| | | { |
| | | StartTime = new Date(); |
| | | IsSuccessful = false; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 操作的开始时间 |
| | | */ |
| | | public Date StartTime = null; |
| | | |
| | | |
| | | /** |
| | | * 操作是否成功 |
| | | */ |
| | | public boolean IsSuccessful = false; |
| | | |
| | | |
| | | /** |
| | | * 延时的时间,单位:毫秒 |
| | | */ |
| | | public int DelayTime = 5000; |
| | | |
| | | |
| | | /** |
| | | * 当前的网络通讯的核心 |
| | | */ |
| | | public Socket WorkSocket = null; |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | /** |
| | | * 用于PLC通讯及Modbus自定义数据类型的读写操作 |
| | | */ |
| | | public interface IDataTransfer { |
| | | |
| | | /** |
| | | * 读取的数据长度,对于西门子,等同于字节数,对于三菱和Modbus为字节数的一半 |
| | | * @return |
| | | */ |
| | | short getReadCount(); |
| | | |
| | | |
| | | /** |
| | | * 从字节数组进行解析实际的对象 |
| | | * @param Content 实际的内容 |
| | | */ |
| | | void ParseSource(byte[] Content); |
| | | |
| | | /** |
| | | * 将对象生成字符源,写入PLC中 |
| | | * @return 写入PLC中 |
| | | */ |
| | | byte[] ToSource(); |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | import com.zy.gateway.core.StringResources; |
| | | |
| | | /** |
| | | * 一个结果操作类的基类 |
| | | */ |
| | | public class OperateResult { |
| | | |
| | | |
| | | /** |
| | | * 默认的无参构造方法 |
| | | */ |
| | | public OperateResult(){ |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的消息实例化默认的对象 |
| | | * @param msg 错误的消息 |
| | | */ |
| | | public OperateResult(String msg){ |
| | | this.Message = msg; |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的错误号和消息实例化默认的对象 |
| | | * @param err 错误码 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResult(int err, String msg){ |
| | | this.ErrorCode = err; |
| | | this.Message = msg; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 指示本次访问是否成功 |
| | | */ |
| | | public boolean IsSuccess = false; |
| | | |
| | | |
| | | /** |
| | | * 具体的错误描述 |
| | | */ |
| | | public String Message = StringResources.Language.UnknownError(); |
| | | |
| | | |
| | | /** |
| | | * 具体的错误代码 |
| | | */ |
| | | public int ErrorCode = 10000; |
| | | |
| | | |
| | | /** |
| | | * @return 获取错误代号及文本描述 |
| | | */ |
| | | public String ToMessageShowString() { |
| | | return "错误代码:" + ErrorCode + "\r\n错误信息:" + Message; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从另一个结果类中拷贝错误信息 |
| | | * |
| | | * @param result 支持结果类及派生类 |
| | | */ |
| | | public void CopyErrorFromOther(OperateResult result) { |
| | | if (result != null) { |
| | | ErrorCode = result.ErrorCode; |
| | | Message = result.Message; |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 创建一个成功的结果类对象 |
| | | * |
| | | * @return 结果类对象 |
| | | */ |
| | | public static OperateResult CreateSuccessResult() { |
| | | OperateResult result = new OperateResult(); |
| | | result.IsSuccess = true; |
| | | result.Message = "success"; |
| | | return result; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | /** |
| | | * 带三个参数的泛型类对象 |
| | | * @param <T1> 参数一 |
| | | * @param <T2> 参数二 |
| | | * @param <T3> 参数三 |
| | | * @param <T4> 参数四 |
| | | */ |
| | | public class OperateResultExFour<T1,T2,T3,T4> extends OperateResult |
| | | { |
| | | /** |
| | | * 默认的无参构造方法 |
| | | */ |
| | | public OperateResultExFour(){ |
| | | super(); |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的消息实例化默认的对象 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResultExFour(String msg){ |
| | | super(msg); |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的错误号和消息实例化默认的对象 |
| | | * @param err 错误码 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResultExFour(int err,String msg){ |
| | | super(err,msg); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 泛型对象1 |
| | | */ |
| | | public T1 Content1 = null; |
| | | |
| | | |
| | | /** |
| | | * 泛型对象二 |
| | | */ |
| | | public T2 Content2 = null; |
| | | |
| | | |
| | | /** |
| | | * 泛型对象三 |
| | | */ |
| | | public T3 Content3 = null; |
| | | |
| | | /** |
| | | * 泛型对象四 |
| | | */ |
| | | public T4 Content4 = null; |
| | | |
| | | |
| | | /** |
| | | * 创建一个成功的泛型类结果对象 |
| | | * @param content1 内容一 |
| | | * @param content2 内容二 |
| | | * @param content3 内容三 |
| | | * @param content4 内容四 |
| | | * @param <T1> 类型一 |
| | | * @param <T2> 类型二 |
| | | * @param <T3> 类型三 |
| | | * @param <T4> 类型四 |
| | | * @return 结果类对象 |
| | | */ |
| | | public static <T1,T2,T3,T4> OperateResultExFour<T1,T2,T3,T4> CreateSuccessResult(T1 content1,T2 content2,T3 content3,T4 content4){ |
| | | OperateResultExFour<T1,T2,T3,T4> result = new OperateResultExFour<>(); |
| | | result.IsSuccess = true; |
| | | result.Content1 = content1; |
| | | result.Content2 = content2; |
| | | result.Content3 = content3; |
| | | result.Content4 = content4; |
| | | result.Message = "success"; |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 创建一个失败的泛型类结果对象 |
| | | * @param result 复制的结果对象 |
| | | * @param <T1> 类型一 |
| | | * @param <T2> 类型二 |
| | | * @param <T3> 类型三 |
| | | * @param <T4> 类型四 |
| | | * @return 结果类对象 |
| | | */ |
| | | public static <T1,T2,T3,T4> OperateResultExFour<T1,T2,T3,T4> CreateFailedResult(OperateResult result){ |
| | | OperateResultExFour resultExFour = new OperateResultExFour(); |
| | | resultExFour.CopyErrorFromOther(result); |
| | | return resultExFour; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | /** |
| | | * 带一个参数的结果类对象 |
| | | * @param <T> |
| | | */ |
| | | public class OperateResultExOne<T> extends OperateResult { |
| | | |
| | | /** |
| | | * 默认的无参构造方法 |
| | | */ |
| | | public OperateResultExOne(){ |
| | | super(); |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的消息实例化默认的对象 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResultExOne(String msg){ |
| | | super(msg); |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的错误号和消息实例化默认的对象 |
| | | * @param err 错误码 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResultExOne(int err, String msg){ |
| | | super(err,msg); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 泛型参数对象 |
| | | */ |
| | | public T Content = null; |
| | | |
| | | |
| | | /** |
| | | * 创建一个失败的对象 |
| | | * @param result 失败的结果 |
| | | * @param <T> 类型参数 |
| | | * @return 结果类对象 |
| | | */ |
| | | public static <T> OperateResultExOne<T> CreateFailedResult(OperateResult result){ |
| | | OperateResultExOne<T> resultExOne = new OperateResultExOne<T>(); |
| | | resultExOne.CopyErrorFromOther(result); |
| | | return resultExOne; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 创建一个成功的泛型类结果对象 |
| | | * @param content 内容 |
| | | * @param <T> 类型 |
| | | * @return 结果类对象 |
| | | */ |
| | | public static <T> OperateResultExOne<T> CreateSuccessResult(T content){ |
| | | OperateResultExOne<T> result = new OperateResultExOne<T>(); |
| | | result.IsSuccess = true; |
| | | result.Content = content; |
| | | result.Message = "success"; |
| | | return result; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | |
| | | /** |
| | | * 带三个参数的泛型类对象 |
| | | * @param <T1> 参数一 |
| | | * @param <T2> 参数二 |
| | | * @param <T3> 参数三 |
| | | */ |
| | | public class OperateResultExThree<T1,T2,T3> extends OperateResult |
| | | { |
| | | |
| | | |
| | | /** |
| | | * 默认的无参构造方法 |
| | | */ |
| | | public OperateResultExThree(){ |
| | | super(); |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的消息实例化默认的对象 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResultExThree(String msg){ |
| | | super(msg); |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的错误号和消息实例化默认的对象 |
| | | * @param err 错误码 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResultExThree(int err,String msg){ |
| | | super(err,msg); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 泛型对象1 |
| | | */ |
| | | public T1 Content1 = null; |
| | | |
| | | |
| | | /** |
| | | * 泛型对象二 |
| | | */ |
| | | public T2 Content2 = null; |
| | | |
| | | |
| | | /** |
| | | * 泛型对象三 |
| | | */ |
| | | public T3 Content3 = null; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 创建一个成功的泛型类结果对象 |
| | | * @param content1 内容一 |
| | | * @param content2 内容二 |
| | | * @param content3 内容三 |
| | | * @param <T1> 类型一 |
| | | * @param <T2> 类型二 |
| | | * @param <T3> 类型三 |
| | | * @return 结果类对象 |
| | | */ |
| | | public static <T1,T2,T3> OperateResultExThree<T1,T2,T3> CreateSuccessResult(T1 content1,T2 content2,T3 content3){ |
| | | OperateResultExThree<T1,T2,T3> result = new OperateResultExThree<>(); |
| | | result.IsSuccess = true; |
| | | result.Content1 = content1; |
| | | result.Content2 = content2; |
| | | result.Content3 = content3; |
| | | result.Message = "success"; |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 创建一个失败的泛型类结果对象 |
| | | * @param result 复制的结果对象 |
| | | * @param <T1> 类型一 |
| | | * @param <T2> 类型二 |
| | | * @param <T3> 类型三 |
| | | * @return 结果类对象 |
| | | */ |
| | | public static <T1,T2,T3> OperateResultExThree<T1,T2,T3> CreateFailedResult(OperateResult result){ |
| | | OperateResultExThree resultExThree = new OperateResultExThree(); |
| | | resultExThree.CopyErrorFromOther(result); |
| | | return resultExThree; |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain; |
| | | |
| | | /** |
| | | * 带2个参数的结果类 |
| | | * @param <T1> 第一个参数类型 |
| | | * @param <T2> 第二个参数类型 |
| | | */ |
| | | public class OperateResultExTwo<T1,T2> extends OperateResult |
| | | { |
| | | |
| | | /** |
| | | * 默认的无参构造方法 |
| | | */ |
| | | public OperateResultExTwo(){ |
| | | super(); |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的消息实例化默认的对象 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResultExTwo(String msg){ |
| | | super(msg); |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的错误号和消息实例化默认的对象 |
| | | * @param err 错误码 |
| | | * @param msg 错误消息 |
| | | */ |
| | | public OperateResultExTwo(int err,String msg){ |
| | | super(err,msg); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 泛型对象1 |
| | | */ |
| | | public T1 Content1 = null; |
| | | |
| | | |
| | | /** |
| | | * 泛型对象二 |
| | | */ |
| | | public T2 Content2 = null; |
| | | |
| | | /** |
| | | * 创建一个成功的泛型类结果对象 |
| | | * @param content1 内容一 |
| | | * @param content2 内容二 |
| | | * @param <T1> 类型一 |
| | | * @param <T2> 类型二 |
| | | * @return 结果类对象 |
| | | */ |
| | | public static <T1,T2> OperateResultExTwo<T1,T2> CreateSuccessResult(T1 content1,T2 content2){ |
| | | OperateResultExTwo<T1,T2> result = new OperateResultExTwo<T1,T2>(); |
| | | result.IsSuccess = true; |
| | | result.Content1 = content1; |
| | | result.Content2 = content2; |
| | | result.Message = "success"; |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 创建一个失败的泛型类结果对象 |
| | | * @param result 复制的结果对象 |
| | | * @param <T1> 类型一 |
| | | * @param <T2> 类型二 |
| | | * @return 结果类对象 |
| | | */ |
| | | public static <T1,T2> OperateResultExTwo<T1,T2> CreateFailedResult(OperateResult result){ |
| | | OperateResultExTwo resultExTwo = new OperateResultExTwo(); |
| | | resultExTwo.CopyErrorFromOther(result); |
| | | return resultExTwo; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain.siemens; |
| | | |
| | | /** |
| | | * 本系统的消息类,包含了各种解析规则,数据信息提取规则 |
| | | */ |
| | | public interface INetMessage { |
| | | |
| | | /** |
| | | * 消息头的指令长度 |
| | | */ |
| | | int ProtocolHeadBytesLength(); |
| | | |
| | | |
| | | /** |
| | | * 从当前的头子节文件中提取出接下来需要接收的数据长度 |
| | | * @return 返回接下来的数据内容长度 |
| | | */ |
| | | int GetContentLengthByHeadBytes(); |
| | | |
| | | |
| | | /** |
| | | * 检查头子节的合法性 |
| | | * @param token 特殊的令牌,有些特殊消息的验证 |
| | | * @return 是否合法的验证 |
| | | */ |
| | | boolean CheckHeadBytesLegal(byte[] token); |
| | | |
| | | |
| | | /** |
| | | * 获取头子节里的消息标识 |
| | | * @return |
| | | */ |
| | | int GetHeadBytesIdentity(); |
| | | |
| | | |
| | | /** |
| | | * 设置消息头子节 |
| | | * @param headBytes 字节数据 |
| | | */ |
| | | void setHeadBytes(byte[] headBytes); |
| | | |
| | | /** |
| | | * 获取消息头字节 |
| | | * @return |
| | | */ |
| | | byte[] getHeadBytes(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * 获取消息内容字节 |
| | | * @return |
| | | */ |
| | | byte[] getContentBytes(); |
| | | |
| | | /** |
| | | * 设置消息内容字节 |
| | | * @param contentBytes 内容字节 |
| | | */ |
| | | void setContentBytes(byte[] contentBytes); |
| | | |
| | | |
| | | /** |
| | | * 获取发送的消息 |
| | | * @return |
| | | */ |
| | | byte[] getSendBytes(); |
| | | |
| | | /** |
| | | * 设置发送的字节信息 |
| | | * @param sendBytes 发送的字节信息 |
| | | */ |
| | | void setSendBytes(byte[] sendBytes); |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain.siemens; |
| | | |
| | | public class S7Message implements INetMessage { |
| | | |
| | | // 头字节 |
| | | private byte[] HeadBytes = null; |
| | | |
| | | // 消息内容字节 |
| | | private byte[] ContentBytes = null; |
| | | |
| | | // 发送的消息 |
| | | private byte[] SendBytes = null; |
| | | |
| | | /** |
| | | * 消息头的指令长度 |
| | | */ |
| | | public int ProtocolHeadBytesLength(){ |
| | | return 4; |
| | | } |
| | | |
| | | /** |
| | | * 从当前的头子节文件中提取出接下来需要接收的数据长度 |
| | | * @return 返回接下来的数据内容长度 |
| | | */ |
| | | public int GetContentLengthByHeadBytes(){ |
| | | if(HeadBytes == null) return 0; |
| | | return (HeadBytes[2] & 0xff) * 256 + (HeadBytes[3] & 0xff) - 4; |
| | | } |
| | | |
| | | /** |
| | | * 检查头子节的合法性 |
| | | * @param token 特殊的令牌,有些特殊消息的验证 |
| | | * @return 是否合法的验证 |
| | | */ |
| | | public boolean CheckHeadBytesLegal(byte[] token) { |
| | | if(HeadBytes == null) return false; |
| | | return HeadBytes[0] == 0x03 && HeadBytes[1] == 0x00; |
| | | } |
| | | |
| | | /** |
| | | * 获取头子节里的消息标识 |
| | | */ |
| | | public int GetHeadBytesIdentity(){ |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public byte[] getHeadBytes() { |
| | | return HeadBytes; |
| | | } |
| | | |
| | | @Override |
| | | public byte[] getContentBytes() { |
| | | return ContentBytes; |
| | | } |
| | | |
| | | @Override |
| | | public byte[] getSendBytes() { |
| | | return SendBytes; |
| | | } |
| | | |
| | | public void setHeadBytes(byte[] headBytes){ |
| | | HeadBytes = headBytes; |
| | | } |
| | | |
| | | public void setContentBytes(byte[] contentBytes){ |
| | | ContentBytes = contentBytes; |
| | | } |
| | | |
| | | public void setSendBytes(byte[] sendBytes){ |
| | | SendBytes = sendBytes; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.domain.siemens; |
| | | |
| | | /** |
| | | * 西门子的PLC类型,目前支持的访问类型 |
| | | */ |
| | | public enum SiemensPLCS { |
| | | |
| | | /** |
| | | * 1200系列 |
| | | */ |
| | | S1200, |
| | | |
| | | /** |
| | | * 300系列 |
| | | */ |
| | | S300, |
| | | |
| | | /** |
| | | * 1500系列 |
| | | */ |
| | | S1500, |
| | | |
| | | /** |
| | | * S200Smart系列 |
| | | */ |
| | | S200Smart, |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.language; |
| | | |
| | | /** |
| | | * 系统的语言基类,默认也即是中文版本 |
| | | */ |
| | | public class DefaultLanguage |
| | | { |
| | | /*********************************************************************************** |
| | | * |
| | | * 一般的错误信息 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | public String ConnectedFailed (){ return "连接失败:"; } |
| | | public String UnknownError (){ return "未知错误"; } |
| | | public String ErrorCode (){ return "错误代号"; } |
| | | public String TextDescription (){ return "文本描述"; } |
| | | public String ExceptionMessage (){ return "错误信息:"; } |
| | | public String ExceptionSourse (){ return "错误源:"; } |
| | | public String ExceptionType (){ return "错误类型:"; } |
| | | public String ExceptionStackTrace (){ return "错误堆栈:"; } |
| | | public String ExceptopnTargetSite (){ return "错误方法:"; } |
| | | public String ExceprionCustomer (){ return "用户自定义方法出错:"; } |
| | | public String SuccessText (){ return "成功"; } |
| | | public String TwoParametersLengthIsNotSame (){ return "两个参数的个数不一致"; } |
| | | public String NotSupportedDataType (){ return "输入的类型不支持,请重新输入"; } |
| | | public String DataLengthIsNotEnough (){ return "接收的数据长度不足,应该值:{0},实际值:{1}"; } |
| | | public String ReceiveDataTimeout (){ return "接收数据超时:"; } |
| | | public String ReceiveDataLengthTooShort (){ return "接收的数据长度太短:"; } |
| | | public String MessageTip (){ return "消息提示:"; } |
| | | public String Close (){ return "关闭"; } |
| | | public String Time (){ return "时间:"; } |
| | | public String SoftWare (){ return "软件:"; } |
| | | public String BugSubmit (){ return "Bug提交"; } |
| | | public String MailServerCenter (){ return "邮件发送系统"; } |
| | | public String MailSendTail (){ return "邮件服务系统自动发出,请勿回复!"; } |
| | | public String IpAddresError (){ return "Ip地址输入异常,格式不正确"; } |
| | | public String Send (){ return "发送";} |
| | | public String Receive(){ return "接收";} |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * 系统相关的错误信息 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | public String SystemInstallOperater (){ return "安装新系统:IP为"; } |
| | | public String SystemUpdateOperater (){ return "更新新系统:IP为"; } |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * 套接字相关的信息描述 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | public String SocketIOException (){ return "套接字传送数据异常:"; } |
| | | public String SocketSendException (){ return "同步数据发送异常:"; } |
| | | public String SocketHeadReceiveException (){ return "指令头接收异常:"; } |
| | | public String SocketContentReceiveException (){ return "内容数据接收异常:"; } |
| | | public String SocketContentRemoteReceiveException (){ return "对方内容数据接收异常:"; } |
| | | public String SocketAcceptCallbackException (){ return "异步接受传入的连接尝试"; } |
| | | public String SocketReAcceptCallbackException (){ return "重新异步接受传入的连接尝试"; } |
| | | public String SocketSendAsyncException (){ return "异步数据发送出错:"; } |
| | | public String SocketEndSendException (){ return "异步数据结束挂起发送出错"; } |
| | | public String SocketReceiveException (){ return "异步数据发送出错:"; } |
| | | public String SocketEndReceiveException (){ return "异步数据结束接收指令头出错"; } |
| | | public String SocketRemoteCloseException (){ return "远程主机强迫关闭了一个现有的连接"; } |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * 文件相关的信息 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | |
| | | public String FileDownloadSuccess (){ return "文件下载成功"; } |
| | | public String FileDownloadFailed (){ return "文件下载异常"; } |
| | | public String FileUploadFailed (){ return "文件上传异常"; } |
| | | public String FileUploadSuccess (){ return "文件上传成功"; } |
| | | public String FileDeleteFailed (){ return "文件删除异常"; } |
| | | public String FileDeleteSuccess (){ return "文件删除成功"; } |
| | | public String FileReceiveFailed (){ return "确认文件接收异常"; } |
| | | public String FileNotExist (){ return "文件不存在"; } |
| | | public String FileSaveFailed (){ return "文件存储失败"; } |
| | | public String FileLoadFailed (){ return "文件加载失败"; } |
| | | public String FileSendClientFailed (){ return "文件发送的时候发生了异常"; } |
| | | public String FileWriteToNetFailed (){ return "文件写入网络异常"; } |
| | | public String FileReadFromNetFailed (){ return "从网络读取文件异常"; } |
| | | public String FilePathCreateFailed (){ return "文件夹路径创建失败:"; } |
| | | public String FileRemoteNotExist (){ return "对方文件不存在,无法接收!"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * 服务器的引擎相关数据 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | public String TokenCheckFailed (){ return "接收验证令牌不一致"; } |
| | | public String TokenCheckTimeout (){ return "接收验证超时:"; } |
| | | public String CommandHeadCodeCheckFailed (){ return "命令头校验失败"; } |
| | | public String CommandLengthCheckFailed (){ return "命令长度检查失败"; } |
| | | public String NetClientAliasFailed (){ return "客户端的别名接收失败:"; } |
| | | public String NetEngineStart (){ return "启动引擎"; } |
| | | public String NetEngineClose (){ return "关闭引擎"; } |
| | | public String NetClientOnline (){ return "上线"; } |
| | | public String NetClientOffline (){ return "下线"; } |
| | | public String NetClientBreak (){ return "异常掉线"; } |
| | | public String NetClientFull (){ return "服务器承载上限,收到超出的请求连接。"; } |
| | | public String NetClientLoginFailed (){ return "客户端登录中错误:"; } |
| | | public String NetHeartCheckFailed (){ return "心跳验证异常:"; } |
| | | public String NetHeartCheckTimeout (){ return "心跳验证超时,强制下线:"; } |
| | | public String DataSourseFormatError (){ return "数据源格式不正确"; } |
| | | public String ServerFileCheckFailed (){ return "服务器确认文件失败,请重新上传"; } |
| | | public String ClientOnlineInfo (){ return "客户端 [ {0} ] 上线"; } |
| | | public String ClientOfflineInfo (){ return "客户端 [ {0} ] 下线"; } |
| | | public String ClientDisableLogin (){ return "客户端 [ {0} ] 不被信任,禁止登录"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Client 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | public String ReConnectServerSuccess (){ return "重连服务器成功"; } |
| | | public String ReConnectServerAfterTenSeconds (){ return "在10秒后重新连接服务器"; } |
| | | public String KeyIsNotAllowedNull (){ return "关键字不允许为空"; } |
| | | public String KeyIsExistAlready (){ return "当前的关键字已经存在"; } |
| | | public String KeyIsNotExist (){ return "当前订阅的关键字不存在"; } |
| | | public String ConnectingServer (){ return "正在连接服务器..."; } |
| | | public String ConnectFailedAndWait (){ return "连接断开,等待{0}秒后重新连接"; } |
| | | public String AttemptConnectServer (){ return "正在尝试第{0}次连接服务器"; } |
| | | public String ConnectServerSuccess (){ return "连接服务器成功"; } |
| | | public String GetClientIpaddressFailed (){ return "客户端IP地址获取失败"; } |
| | | public String ConnectionIsNotAvailable (){ return "当前的连接不可用"; } |
| | | public String DeviceCurrentIsLoginRepeat (){ return "当前设备的id重复登录"; } |
| | | public String DeviceCurrentIsLoginForbidden (){ return "当前设备的id禁止登录"; } |
| | | public String PasswordCheckFailed (){ return "密码验证失败"; } |
| | | public String DataTransformError (){ return "数据转换失败,源数据:"; } |
| | | public String RemoteClosedConnection (){ return "远程关闭了连接"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * 日志 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | public String LogNetDebug (){ return "调试"; } |
| | | public String LogNetInfo (){ return "信息"; } |
| | | public String LogNetWarn (){ return "警告"; } |
| | | public String LogNetError (){ return "错误"; } |
| | | public String LogNetFatal (){ return "致命"; } |
| | | public String LogNetAbandon (){ return "放弃"; } |
| | | public String LogNetAll (){ return "全部"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Modbus相关 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | public String ModbusTcpFunctionCodeNotSupport (){ return "不支持的功能码"; } |
| | | public String ModbusTcpFunctionCodeOverBound (){ return "读取的数据越界"; } |
| | | public String ModbusTcpFunctionCodeQuantityOver (){ return "读取长度超过最大值"; } |
| | | public String ModbusTcpFunctionCodeReadWriteException (){ return "读写异常"; } |
| | | public String ModbusTcpReadCoilException (){ return "读取线圈异常"; } |
| | | public String ModbusTcpWriteCoilException (){ return "写入线圈异常"; } |
| | | public String ModbusTcpReadRegisterException (){ return "读取寄存器异常"; } |
| | | public String ModbusTcpWriteRegisterException (){ return "写入寄存器异常"; } |
| | | public String ModbusAddressMustMoreThanOne (){ return "地址值在起始地址为1的情况下,必须大于1"; } |
| | | public String ModbusAsciiFormatCheckFailed (){ return "Modbus的ascii指令检查失败,不是modbus-ascii报文"; } |
| | | public String ModbusCRCCheckFailed (){ return "Modbus的CRC校验检查失败"; } |
| | | public String ModbusLRCCheckFailed (){ return "Modbus的LRC校验检查失败"; } |
| | | public String ModbusMatchFailed (){ return "不是标准的modbus协议"; } |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Melsec PLC 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | public String MelsecPleaseReferToManulDocument (){ return "请查看三菱的通讯手册来查看报警的具体信息"; } |
| | | public String MelsecReadBitInfo (){ return "读取位变量数组只能针对位软元件,如果读取字软元件,请调用Read方法"; } |
| | | public String MelsecCurrentTypeNotSupportedWordOperate (){ return "当前的类型不支持字读写"; } |
| | | public String MelsecCurrentTypeNotSupportedBitOperate (){ return "当前的类型不支持位读写"; } |
| | | public String MelsecFxReceiveZore (){ return "接收的数据长度为0"; } |
| | | public String MelsecFxAckNagative (){ return "PLC反馈的数据无效"; } |
| | | public String MelsecFxAckWrong (){ return "PLC反馈信号错误:"; } |
| | | public String MelsecFxCrcCheckFailed (){ return "PLC反馈报文的和校验失败!"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Siemens PLC 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | public String SiemensDBAddressNotAllowedLargerThan255 (){ return "DB块数据无法大于255"; } |
| | | public String SiemensReadLengthMustBeEvenNumber (){ return "读取的数据长度必须为偶数"; } |
| | | public String SiemensWriteError (){ return "写入数据异常,代号为:"; } |
| | | public String SiemensReadLengthCannotLargerThan19 (){ return "读取的数组数量不允许大于19"; } |
| | | public String SiemensDataLengthCheckFailed (){ return "数据块长度校验失败,请检查是否开启put/get以及关闭db块优化"; } |
| | | public String SiemensFWError (){ return "发生了异常,具体信息查找Fetch/Write协议文档"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Omron PLC 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | public String OmronAddressMustBeZeroToFiveteen (){ return "输入的位地址只能在0-15之间"; } |
| | | public String OmronReceiveDataError (){ return "数据接收异常"; } |
| | | public String OmronStatus0 (){ return "通讯正常"; } |
| | | public String OmronStatus1 (){ return "消息头不是FINS"; } |
| | | public String OmronStatus2 (){ return "数据长度太长"; } |
| | | public String OmronStatus3 (){ return "该命令不支持"; } |
| | | public String OmronStatus20 (){ return "超过连接上限"; } |
| | | public String OmronStatus21 (){ return "指定的节点已经处于连接中"; } |
| | | public String OmronStatus22 (){ return "尝试去连接一个受保护的网络节点,该节点还未配置到PLC中"; } |
| | | public String OmronStatus23 (){ return "当前客户端的网络节点超过正常范围"; } |
| | | public String OmronStatus24 (){ return "当前客户端的网络节点已经被使用"; } |
| | | public String OmronStatus25 (){ return "所有的网络节点已经被使用"; } |
| | | |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * AB PLC 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | |
| | | public String AllenBradley04 (){ return "它没有正确生成或匹配标记不存在。"; } |
| | | public String AllenBradley05 (){ return "引用的特定项(通常是实例)无法找到。"; } |
| | | public String AllenBradley06 (){ return "请求的数据量不适合响应缓冲区。 发生了部分数据传输。"; } |
| | | public String AllenBradley0A (){ return "尝试处理其中一个属性时发生错误。"; } |
| | | public String AllenBradley13 (){ return "命令中没有提供足够的命令数据/参数来执行所请求的服务。"; } |
| | | public String AllenBradley1C (){ return "与属性计数相比,提供的属性数量不足。"; } |
| | | public String AllenBradley1E (){ return "此服务中的服务请求出错。"; } |
| | | public String AllenBradley26 (){ return "IOI字长与处理的IOI数量不匹配。"; } |
| | | |
| | | public String AllenBradleySessionStatus00 (){ return "成功"; } |
| | | public String AllenBradleySessionStatus01 (){ return "发件人发出无效或不受支持的封装命令。"; } |
| | | public String AllenBradleySessionStatus02 (){ return "接收器中的内存资源不足以处理命令。 这不是一个应用程序错误。 相反,只有在封装层无法获得所需内存资源的情况下才会导致此问题。"; } |
| | | public String AllenBradleySessionStatus03 (){ return "封装消息的数据部分中的数据形成不良或不正确。"; } |
| | | public String AllenBradleySessionStatus64 (){ return "向目标发送封装消息时,始发者使用了无效的会话句柄。"; } |
| | | public String AllenBradleySessionStatus65 (){ return "目标收到一个无效长度的信息。"; } |
| | | public String AllenBradleySessionStatus69 (){ return "不支持的封装协议修订。"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Panasonic PLC 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | public String PanasonicReceiveLengthMustLargerThan9 (){ return "接收数据长度必须大于9"; } |
| | | public String PanasonicAddressParameterCannotBeNull (){ return "地址参数不允许为空"; } |
| | | public String PanasonicMewStatus20 (){ return "错误未知"; } |
| | | public String PanasonicMewStatus21 (){ return "NACK错误,远程单元无法被正确识别,或者发生了数据错误。"; } |
| | | public String PanasonicMewStatus22 (){ return "WACK 错误:用于远程单元的接收缓冲区已满。"; } |
| | | public String PanasonicMewStatus23 (){ return "多重端口错误:远程单元编号(01 至 16)设置与本地单元重复。"; } |
| | | public String PanasonicMewStatus24 (){ return "传输格式错误:试图发送不符合传输格式的数据,或者某一帧数据溢出或发生了数据错误。"; } |
| | | public String PanasonicMewStatus25 (){ return "硬件错误:传输系统硬件停止操作。"; } |
| | | public String PanasonicMewStatus26 (){ return "单元号错误:远程单元的编号设置超出 01 至 63 的范围。"; } |
| | | public String PanasonicMewStatus27 (){ return "不支持错误:接收方数据帧溢出. 试图在不同的模块之间发送不同帧长度的数据。"; } |
| | | public String PanasonicMewStatus28 (){ return "无应答错误:远程单元不存在. (超时)。"; } |
| | | public String PanasonicMewStatus29 (){ return "缓冲区关闭错误:试图发送或接收处于关闭状态的缓冲区。"; } |
| | | public String PanasonicMewStatus30 (){ return "超时错误:持续处于传输禁止状态。"; } |
| | | public String PanasonicMewStatus40 (){ return "BCC 错误:在指令数据中发生传输错误。"; } |
| | | public String PanasonicMewStatus41 (){ return "格式错误:所发送的指令信息不符合传输格式。"; } |
| | | public String PanasonicMewStatus42 (){ return "不支持错误:发送了一个未被支持的指令。向未被支持的目标站发送了指令。"; } |
| | | public String PanasonicMewStatus43 (){ return "处理步骤错误:在处于传输请求信息挂起时,发送了其他指令。"; } |
| | | public String PanasonicMewStatus50 (){ return "链接设置错误:设置了实际不存在的链接编号。"; } |
| | | public String PanasonicMewStatus51 (){ return "同时操作错误:当向其他单元发出指令时,本地单元的传输缓冲区已满。"; } |
| | | public String PanasonicMewStatus52 (){ return "传输禁止错误:无法向其他单元传输。"; } |
| | | public String PanasonicMewStatus53 (){ return "忙错误:在接收到指令时,正在处理其他指令。"; } |
| | | public String PanasonicMewStatus60 (){ return "参数错误:在指令中包含有无法使用的代码,或者代码没有附带区域指定参数(X, Y, D), 等以外。"; } |
| | | public String PanasonicMewStatus61 (){ return "数据错误:触点编号,区域编号,数据代码格式(BCD,hex,等)上溢出, 下溢出以及区域指定错误。"; } |
| | | public String PanasonicMewStatus62 (){ return "寄存器错误:过多记录数据在未记录状态下的操作(监控记录、跟踪记录等。)。"; } |
| | | public String PanasonicMewStatus63 (){ return "PLC 模式错误:当一条指令发出时,运行模式不能够对指令进行处理。"; } |
| | | public String PanasonicMewStatus65 (){ return "保护错误:在存储保护状态下执行写操作到程序区域或系统寄存器。"; } |
| | | public String PanasonicMewStatus66 (){ return "地址错误:地址(程序地址、绝对地址等)数据编码形式(BCD、hex 等)、上溢、下溢或指定范围错误。"; } |
| | | public String PanasonicMewStatus67 (){ return "丢失数据错误:要读的数据不存在。(读取没有写入注释寄存区的数据。。"; } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.language; |
| | | |
| | | /** |
| | | * English Version Text |
| | | */ |
| | | public class English extends DefaultLanguage { |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Normal Info |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | @Override |
| | | public String ConnectedFailed (){ return "Connected Failed: "; } |
| | | @Override |
| | | public String UnknownError (){ return "Unknown Error"; } |
| | | @Override |
| | | public String ErrorCode (){ return "Error Code: "; } |
| | | @Override |
| | | public String TextDescription (){ return "Description: "; } |
| | | @Override |
| | | public String ExceptionMessage (){ return "Exception Info: "; } |
| | | @Override |
| | | public String ExceptionSourse (){ return "Exception Sourse:"; } |
| | | @Override |
| | | public String ExceptionType (){ return "Exception Type:"; } |
| | | @Override |
| | | public String ExceptionStackTrace (){ return "Exception Stack: "; } |
| | | @Override |
| | | public String ExceptopnTargetSite (){ return "Exception Method: "; } |
| | | @Override |
| | | public String ExceprionCustomer (){ return "Error in user-defined method: "; } |
| | | @Override |
| | | public String SuccessText (){ return "Success"; } |
| | | @Override |
| | | public String TwoParametersLengthIsNotSame (){ return "Two Parameter Length is not same"; } |
| | | @Override |
| | | public String NotSupportedDataType (){ return "Unsupported DataType, input again"; } |
| | | @Override |
| | | public String DataLengthIsNotEnough (){ return "Receive length is not enough,Should:{0},Actual:{1}"; } |
| | | @Override |
| | | public String ReceiveDataTimeout (){ return "Receive timeout: "; } |
| | | @Override |
| | | public String ReceiveDataLengthTooShort (){ return "Receive length is too short: "; } |
| | | @Override |
| | | public String MessageTip (){ return "Message prompt:"; } |
| | | @Override |
| | | public String Close (){ return "Close"; } |
| | | @Override |
| | | public String Time (){ return "Time:"; } |
| | | @Override |
| | | public String SoftWare (){ return "Software:"; } |
| | | @Override |
| | | public String BugSubmit (){ return "Bug submit"; } |
| | | @Override |
| | | public String MailServerCenter (){ return "Mail Center System"; } |
| | | @Override |
| | | public String MailSendTail (){ return "Mail Service system issued automatically, do not reply"; } |
| | | @Override |
| | | public String IpAddresError (){ return "IP address input exception, format is incorrect"; } |
| | | @Override |
| | | public String Send (){ return "Send";} |
| | | @Override |
| | | public String Receive(){ return "Receive";} |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * System about |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | @Override |
| | | public String SystemInstallOperater (){ return "Install new software: ip address is"; } |
| | | @Override |
| | | public String SystemUpdateOperater (){ return "Update software: ip address is"; } |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Socket-related Information description |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | @Override |
| | | public String SocketIOException (){ return "Socket transport error: "; } |
| | | @Override |
| | | public String SocketSendException (){ return "Synchronous Data Send exception: "; } |
| | | @Override |
| | | public String SocketHeadReceiveException (){ return "Command header receive exception: "; } |
| | | @Override |
| | | public String SocketContentReceiveException (){ return "Content Data Receive exception: "; } |
| | | @Override |
| | | public String SocketContentRemoteReceiveException (){ return "Recipient content Data Receive exception: "; } |
| | | @Override |
| | | public String SocketAcceptCallbackException (){ return "Asynchronously accepts an incoming connection attempt: "; } |
| | | @Override |
| | | public String SocketReAcceptCallbackException (){ return "To re-accept incoming connection attempts asynchronously"; } |
| | | @Override |
| | | public String SocketSendAsyncException (){ return "Asynchronous Data send Error: "; } |
| | | @Override |
| | | public String SocketEndSendException (){ return "Asynchronous data end callback send Error"; } |
| | | @Override |
| | | public String SocketReceiveException (){ return "Asynchronous Data send Error: "; } |
| | | @Override |
| | | public String SocketEndReceiveException (){ return "Asynchronous data end receive instruction header error"; } |
| | | @Override |
| | | public String SocketRemoteCloseException (){ return "An existing connection was forcibly closed by the remote host"; } |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * File related information |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | |
| | | @Override |
| | | public String FileDownloadSuccess (){ return "File Download Successful"; } |
| | | @Override |
| | | public String FileDownloadFailed (){ return "File Download exception"; } |
| | | @Override |
| | | public String FileUploadFailed (){ return "File Upload exception"; } |
| | | @Override |
| | | public String FileUploadSuccess (){ return "File Upload Successful"; } |
| | | @Override |
| | | public String FileDeleteFailed (){ return "File Delete exception"; } |
| | | @Override |
| | | public String FileDeleteSuccess (){ return "File deletion succeeded"; } |
| | | @Override |
| | | public String FileReceiveFailed (){ return "Confirm File Receive exception"; } |
| | | @Override |
| | | public String FileNotExist (){ return "File does not exist"; } |
| | | @Override |
| | | public String FileSaveFailed (){ return "File Store failed"; } |
| | | @Override |
| | | public String FileLoadFailed (){ return "File load failed"; } |
| | | @Override |
| | | public String FileSendClientFailed (){ return "An exception occurred when the file was sent"; } |
| | | @Override |
| | | public String FileWriteToNetFailed (){ return "File Write Network exception"; } |
| | | @Override |
| | | public String FileReadFromNetFailed (){ return "Read file exceptions from the network"; } |
| | | @Override |
| | | public String FilePathCreateFailed (){ return "Folder path creation failed: "; } |
| | | @Override |
| | | public String FileRemoteNotExist (){ return "The other file does not exist, cannot receive!"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Engine-related data for the server |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | @Override |
| | | public String TokenCheckFailed (){ return "Receive authentication token inconsistency"; } |
| | | @Override |
| | | public String TokenCheckTimeout (){ return "Receive authentication timeout: "; } |
| | | @Override |
| | | public String CommandHeadCodeCheckFailed (){ return "Command header check failed"; } |
| | | @Override |
| | | public String CommandLengthCheckFailed (){ return "Command length check failed"; } |
| | | @Override |
| | | public String NetClientAliasFailed (){ return "Client's alias receive failed: "; } |
| | | @Override |
| | | public String NetEngineStart (){ return "Start engine"; } |
| | | @Override |
| | | public String NetEngineClose (){ return "Shutting down the engine"; } |
| | | @Override |
| | | public String NetClientOnline (){ return "Online"; } |
| | | @Override |
| | | public String NetClientOffline (){ return "Offline"; } |
| | | @Override |
| | | public String NetClientBreak (){ return "Abnormal offline"; } |
| | | @Override |
| | | public String NetClientFull (){ return "The server hosts the upper limit and receives an exceeded request connection."; } |
| | | @Override |
| | | public String NetClientLoginFailed (){ return "Error in Client logon: "; } |
| | | @Override |
| | | public String NetHeartCheckFailed (){ return "Heartbeat Validation exception: "; } |
| | | @Override |
| | | public String NetHeartCheckTimeout (){ return "Heartbeat verification timeout, force offline: "; } |
| | | @Override |
| | | public String DataSourseFormatError (){ return "Data source format is incorrect"; } |
| | | @Override |
| | | public String ServerFileCheckFailed (){ return "Server confirmed file failed, please re-upload"; } |
| | | @Override |
| | | public String ClientOnlineInfo (){ return "Client [ {0} ] Online"; } |
| | | @Override |
| | | public String ClientOfflineInfo (){ return "Client [ {0} ] Offline"; } |
| | | @Override |
| | | public String ClientDisableLogin (){ return "Client [ {0} ] is not trusted, login forbidden"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Client related |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | @Override |
| | | public String ReConnectServerSuccess (){ return "Re-connect server succeeded"; } |
| | | @Override |
| | | public String ReConnectServerAfterTenSeconds (){ return "Reconnect the server after 10 seconds"; } |
| | | @Override |
| | | public String KeyIsNotAllowedNull (){ return "The keyword is not allowed to be empty"; } |
| | | @Override |
| | | public String KeyIsExistAlready (){ return "The current keyword already exists"; } |
| | | @Override |
| | | public String KeyIsNotExist (){ return "The keyword for the current subscription does not exist"; } |
| | | @Override |
| | | public String ConnectingServer (){ return "Connecting to Server..."; } |
| | | @Override |
| | | public String ConnectFailedAndWait (){ return "Connection disconnected, wait {0} seconds to reconnect"; } |
| | | @Override |
| | | public String AttemptConnectServer (){ return "Attempting to connect server {0} times"; } |
| | | @Override |
| | | public String ConnectServerSuccess (){ return "Connection Server succeeded"; } |
| | | @Override |
| | | public String GetClientIpaddressFailed (){ return "Client IP Address acquisition failed"; } |
| | | @Override |
| | | public String ConnectionIsNotAvailable (){ return "The current connection is not available"; } |
| | | @Override |
| | | public String DeviceCurrentIsLoginRepeat (){ return "ID of the current device duplicate login"; } |
| | | @Override |
| | | public String DeviceCurrentIsLoginForbidden (){ return "The ID of the current device prohibits login"; } |
| | | @Override |
| | | public String PasswordCheckFailed (){ return "Password validation failed"; } |
| | | @Override |
| | | public String DataTransformError (){ return "Data conversion failed, source data: "; } |
| | | @Override |
| | | public String RemoteClosedConnection (){ return "Remote shutdown of connection"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Log related |
| | | * |
| | | ************************************************************************************/ |
| | | @Override |
| | | public String LogNetDebug (){ return "Debug"; } |
| | | @Override |
| | | public String LogNetInfo (){ return "Info"; } |
| | | @Override |
| | | public String LogNetWarn (){ return "Warn"; } |
| | | @Override |
| | | public String LogNetError (){ return "Error"; } |
| | | @Override |
| | | public String LogNetFatal (){ return "Fatal"; } |
| | | @Override |
| | | public String LogNetAbandon (){ return "Abandon"; } |
| | | @Override |
| | | public String LogNetAll (){ return "All"; } |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Modbus related |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | @Override |
| | | public String ModbusTcpFunctionCodeNotSupport (){ return "Unsupported function code"; } |
| | | @Override |
| | | public String ModbusTcpFunctionCodeOverBound (){ return "Data read out of bounds"; } |
| | | @Override |
| | | public String ModbusTcpFunctionCodeQuantityOver (){ return "Read length exceeds maximum value"; } |
| | | @Override |
| | | public String ModbusTcpFunctionCodeReadWriteException (){ return "Read and Write exceptions"; } |
| | | @Override |
| | | public String ModbusTcpReadCoilException (){ return "Read Coil anomalies"; } |
| | | @Override |
| | | public String ModbusTcpWriteCoilException (){ return "Write Coil exception"; } |
| | | @Override |
| | | public String ModbusTcpReadRegisterException (){ return "Read Register exception"; } |
| | | @Override |
| | | public String ModbusTcpWriteRegisterException (){ return "Write Register exception"; } |
| | | @Override |
| | | public String ModbusAddressMustMoreThanOne (){ return "The address value must be greater than 1 in the case where the start address is 1"; } |
| | | @Override |
| | | public String ModbusAsciiFormatCheckFailed (){ return "Modbus ASCII command check failed, not MODBUS-ASCII message"; } |
| | | @Override |
| | | public String ModbusCRCCheckFailed (){ return "The CRC checksum check failed for Modbus"; } |
| | | @Override |
| | | public String ModbusLRCCheckFailed (){ return "The LRC checksum check failed for Modbus"; } |
| | | @Override |
| | | public String ModbusMatchFailed (){ return "Not the standard Modbus protocol"; } |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Melsec PLC related |
| | | * |
| | | ************************************************************************************/ |
| | | @Override |
| | | public String MelsecPleaseReferToManulDocument (){ return "Please check Mitsubishi's communication manual for details of the alarm."; } |
| | | @Override |
| | | public String MelsecReadBitInfo (){ return "The read bit variable array can only be used for bit soft elements, if you read the word soft component, call the Read method"; } |
| | | @Override |
| | | public String MelsecCurrentTypeNotSupportedWordOperate (){ return "The current type does not support word read and write"; } |
| | | @Override |
| | | public String MelsecCurrentTypeNotSupportedBitOperate (){ return "The current type does not support bit read and write"; } |
| | | @Override |
| | | public String MelsecFxReceiveZore (){ return "The received data length is 0"; } |
| | | @Override |
| | | public String MelsecFxAckNagative (){ return "Invalid data from PLC feedback"; } |
| | | @Override |
| | | public String MelsecFxAckWrong (){ return "PLC Feedback Signal Error: "; } |
| | | @Override |
| | | public String MelsecFxCrcCheckFailed (){ return "PLC Feedback message and check failed!"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Siemens PLC related |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | @Override |
| | | public String SiemensDBAddressNotAllowedLargerThan255 (){ return "DB block data cannot be greater than 255"; } |
| | | @Override |
| | | public String SiemensReadLengthMustBeEvenNumber (){ return "The length of the data read must be an even number"; } |
| | | @Override |
| | | public String SiemensWriteError (){ return "Writes the data exception, the code name is: "; } |
| | | @Override |
| | | public String SiemensReadLengthCannotLargerThan19 (){ return "The number of arrays read does not allow greater than 19"; } |
| | | @Override |
| | | public String SiemensDataLengthCheckFailed (){ return "Block length checksum failed, please check if Put/get is turned on and DB block optimization is turned off"; } |
| | | @Override |
| | | public String SiemensFWError (){ return "An exception occurred, the specific information to find the Fetch/write protocol document"; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Omron PLC related |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | @Override |
| | | public String OmronAddressMustBeZeroToFiveteen (){ return "The bit address entered can only be between 0-15"; } |
| | | @Override |
| | | public String OmronReceiveDataError (){ return "Data Receive exception"; } |
| | | @Override |
| | | public String OmronStatus0 (){ return "Communication is normal."; } |
| | | @Override |
| | | public String OmronStatus1 (){ return "The message header is not fins"; } |
| | | @Override |
| | | public String OmronStatus2 (){ return "Data length too long"; } |
| | | @Override |
| | | public String OmronStatus3 (){ return "This command does not support"; } |
| | | @Override |
| | | public String OmronStatus20 (){ return "Exceeding connection limit"; } |
| | | @Override |
| | | public String OmronStatus21 (){ return "The specified node is already in the connection"; } |
| | | @Override |
| | | public String OmronStatus22 (){ return "Attempt to connect to a protected network node that is not yet configured in the PLC"; } |
| | | @Override |
| | | public String OmronStatus23 (){ return "The current client's network node exceeds the normal range"; } |
| | | @Override |
| | | public String OmronStatus24 (){ return "The current client's network node is already in use"; } |
| | | @Override |
| | | public String OmronStatus25 (){ return "All network nodes are already in use"; } |
| | | |
| | | |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * AB PLC 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | |
| | | |
| | | @Override |
| | | public String AllenBradley04 (){ return "The IOI could not be deciphered. Either it was not formed correctly or the match tag does not exist."; } |
| | | @Override |
| | | public String AllenBradley05 (){ return "The particular item referenced (usually instance) could not be found."; } |
| | | @Override |
| | | public String AllenBradley06 (){ return "The amount of data requested would not fit into the response buffer. Partial data transfer has occurred."; } |
| | | @Override |
| | | public String AllenBradley0A (){ return "An error has occurred trying to process one of the attributes."; } |
| | | @Override |
| | | public String AllenBradley13 (){ return "Not enough command data / parameters were supplied in the command to execute the service requested."; } |
| | | @Override |
| | | public String AllenBradley1C (){ return "An insufficient number of attributes were provided compared to the attribute count."; } |
| | | @Override |
| | | public String AllenBradley1E (){ return "A service request in this service went wrong."; } |
| | | @Override |
| | | public String AllenBradley26 (){ return "The IOI word length did not match the amount of IOI which was processed."; } |
| | | |
| | | @Override |
| | | public String AllenBradleySessionStatus00 (){ return "success"; } |
| | | @Override |
| | | public String AllenBradleySessionStatus01 (){ return "The sender issued an invalid or unsupported encapsulation command."; } |
| | | @Override |
| | | public String AllenBradleySessionStatus02 (){ return "Insufficient memory resources in the receiver to handle the command. This is not an application error. Instead, it only results if the encapsulation layer cannot obtain memory resources that it need."; } |
| | | @Override |
| | | public String AllenBradleySessionStatus03 (){ return "Poorly formed or incorrect data in the data portion of the encapsulation message."; } |
| | | @Override |
| | | public String AllenBradleySessionStatus64 (){ return "An originator used an invalid session handle when sending an encapsulation message."; } |
| | | @Override |
| | | public String AllenBradleySessionStatus65 (){ return "The target received a message of invalid length."; } |
| | | @Override |
| | | public String AllenBradleySessionStatus69 (){ return "Unsupported encapsulation protocol revision."; } |
| | | |
| | | /*********************************************************************************** |
| | | * |
| | | * Panasonic PLC 相关 |
| | | * |
| | | ************************************************************************************/ |
| | | @Override |
| | | public String PanasonicReceiveLengthMustLargerThan9 (){ return "The received data length must be greater than 9"; } |
| | | @Override |
| | | public String PanasonicAddressParameterCannotBeNull (){ return "Address parameter is not allowed to be empty"; } |
| | | @Override |
| | | public String PanasonicMewStatus20 (){ return "Error unknown"; } |
| | | @Override |
| | | public String PanasonicMewStatus21 (){ return "Nack error, the remote unit could not be correctly identified, or a data error occurred."; } |
| | | @Override |
| | | public String PanasonicMewStatus22 (){ return "WACK Error: The receive buffer for the remote unit is full."; } |
| | | @Override |
| | | public String PanasonicMewStatus23 (){ return "Multiple port error: The remote unit number (01 to 16) is set to repeat with the local unit."; } |
| | | @Override |
| | | public String PanasonicMewStatus24 (){ return "Transport format error: An attempt was made to send data that does not conform to the transport format, or a frame data overflow or a data error occurred."; } |
| | | @Override |
| | | public String PanasonicMewStatus25 (){ return "Hardware error: Transport system hardware stopped operation."; } |
| | | @Override |
| | | public String PanasonicMewStatus26 (){ return "Unit Number error: The remote unit's numbering setting exceeds the range of 01 to 63."; } |
| | | @Override |
| | | public String PanasonicMewStatus27 (){ return "Error not supported: Receiver data frame overflow. An attempt was made to send data of different frame lengths between different modules."; } |
| | | @Override |
| | | public String PanasonicMewStatus28 (){ return "No answer error: The remote unit does not exist. (timeout)."; } |
| | | @Override |
| | | public String PanasonicMewStatus29 (){ return "Buffer Close error: An attempt was made to send or receive a buffer that is in a closed state."; } |
| | | @Override |
| | | public String PanasonicMewStatus30 (){ return "Timeout error: Persisted in transport forbidden State."; } |
| | | @Override |
| | | public String PanasonicMewStatus40 (){ return "BCC Error: A transmission error occurred in the instruction data."; } |
| | | @Override |
| | | public String PanasonicMewStatus41 (){ return "Malformed: The sent instruction information does not conform to the transmission format."; } |
| | | @Override |
| | | public String PanasonicMewStatus42 (){ return "Error not supported: An unsupported instruction was sent. An instruction was sent to a target station that was not supported."; } |
| | | @Override |
| | | public String PanasonicMewStatus43 (){ return "Processing Step Error: Additional instructions were sent when the transfer request information was suspended."; } |
| | | @Override |
| | | public String PanasonicMewStatus50 (){ return "Link Settings Error: A link number that does not actually exist is set."; } |
| | | @Override |
| | | public String PanasonicMewStatus51 (){ return "Simultaneous operation error: When issuing instructions to other units, the transmit buffer for the local unit is full."; } |
| | | @Override |
| | | public String PanasonicMewStatus52 (){ return "Transport suppression Error: Unable to transfer to other units."; } |
| | | @Override |
| | | public String PanasonicMewStatus53 (){ return "Busy error: Other instructions are being processed when the command is received."; } |
| | | @Override |
| | | public String PanasonicMewStatus60 (){ return "Parameter error: Contains code that cannot be used in the directive, or the code does not have a zone specified parameter (X, Y, D), and so on."; } |
| | | @Override |
| | | public String PanasonicMewStatus61 (){ return "Data error: Contact number, area number, Data code format (BCD,HEX, etc.) overflow, overflow, and area specified error."; } |
| | | @Override |
| | | public String PanasonicMewStatus62 (){ return "Register ERROR: Excessive logging of data in an unregistered state of operations (Monitoring records, tracking records, etc.). )。"; } |
| | | @Override |
| | | public String PanasonicMewStatus63 (){ return "PLC mode error: When an instruction is issued, the run mode is not able to process the instruction."; } |
| | | @Override |
| | | public String PanasonicMewStatus65 (){ return "Protection Error: Performs a write operation to the program area or system register in the storage protection state."; } |
| | | @Override |
| | | public String PanasonicMewStatus66 (){ return "Address Error: Address (program address, absolute address, etc.) Data encoding form (BCD, hex, etc.), overflow, underflow, or specified range error."; } |
| | | @Override |
| | | public String PanasonicMewStatus67 (){ return "Missing data error: The data to be read does not exist. (reads data that is not written to the comment register.)"; } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.log; |
| | | |
| | | /** |
| | | * 日志的存储等级 |
| | | */ |
| | | public enum HslMessageDegree { |
| | | /** |
| | | * 一条消息都不记录 |
| | | */ |
| | | None, |
| | | /** |
| | | * 记录致命等级及以上日志的消息 |
| | | */ |
| | | FATAL, |
| | | /** |
| | | * 记录异常等级及以上日志的消息 |
| | | */ |
| | | ERROR, |
| | | /** |
| | | * 记录警告等级及以上日志的消息 |
| | | */ |
| | | WARN, |
| | | /** |
| | | * 记录信息等级及以上日志的消息 |
| | | */ |
| | | INFO, |
| | | /** |
| | | * 记录调试等级及以上日志的信息 |
| | | */ |
| | | DEBUG |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.log; |
| | | |
| | | /** |
| | | * 日志的存储对象 |
| | | */ |
| | | public interface ILogNet { |
| | | |
| | | /** |
| | | * 文件存储模式,1:单文件,2:根据大小,3:根据时间 |
| | | * @return |
| | | */ |
| | | int LogSaveMode(); |
| | | |
| | | |
| | | /** |
| | | * 自定义的消息存储方法 |
| | | * @param degree |
| | | * @param keyWord |
| | | * @param text |
| | | */ |
| | | void RecordMessage(HslMessageDegree degree, String keyWord, String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一条调试的日志 |
| | | * @param text |
| | | */ |
| | | void WriteDebug(String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一条调试的日志 |
| | | * @param keyWord |
| | | * @param text |
| | | */ |
| | | void WriteDebug(String keyWord, String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一条解释性的信息 |
| | | * @param description |
| | | */ |
| | | void WriteDescrition(String description); |
| | | |
| | | |
| | | /** |
| | | * 写入一条错误信息 |
| | | * @param text |
| | | */ |
| | | void WriteError(String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一条错误信息 |
| | | * @param keyWord |
| | | * @param text |
| | | */ |
| | | void WriteError(String keyWord, String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一条异常的信息 |
| | | * @param keyWord |
| | | * @param ex |
| | | */ |
| | | void WriteException(String keyWord, Exception ex); |
| | | |
| | | /** |
| | | * 写入一条异常的信息 |
| | | * @param keyWord |
| | | * @param text |
| | | * @param ex |
| | | */ |
| | | void WriteException(String keyWord, String text, Exception ex); |
| | | |
| | | |
| | | /** |
| | | * 写入一条致命的信息 |
| | | * @param text |
| | | */ |
| | | void WriteFatal(String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一条致命的信息 |
| | | * @param keyWord |
| | | * @param text |
| | | */ |
| | | void WriteFatal(String keyWord, String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一条普通的信息 |
| | | * @param text |
| | | */ |
| | | void WriteInfo(String text); |
| | | |
| | | /** |
| | | * 写入一条普通的信息 |
| | | * @param keyWord |
| | | * @param text |
| | | */ |
| | | void WriteInfo(String keyWord, String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一个空行 |
| | | */ |
| | | void WriteNewLine(); |
| | | |
| | | |
| | | /** |
| | | * 写入一条警告信息 |
| | | * @param text |
| | | */ |
| | | void WriteWarn(String text); |
| | | |
| | | |
| | | /** |
| | | * 写入一条警告信息 |
| | | * @param keyWord |
| | | * @param text |
| | | */ |
| | | void WriteWarn(String keyWord, String text); |
| | | |
| | | |
| | | /** |
| | | * 设置日志的存储等级,高于该等级的才会被存储 |
| | | * @param degree |
| | | */ |
| | | void SetMessageDegree(HslMessageDegree degree); |
| | | |
| | | |
| | | /** |
| | | * 过滤掉指定的关键字的日志,该信息不存储,但仍然触发BeforeSaveToFile事件 |
| | | * @param keyword |
| | | */ |
| | | void FiltrateKeyword(String keyword); |
| | | |
| | | |
| | | /** |
| | | * 获取已存在的日志文件名称 |
| | | * @return |
| | | */ |
| | | String[] GetExistLogFileNames(); |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.net; |
| | | |
| | | import com.zy.gateway.core.base.HslSecurity; |
| | | import com.zy.gateway.core.base.SoftZipped; |
| | | import com.zy.gateway.core.utils.Utilities; |
| | | |
| | | import java.util.UUID; |
| | | |
| | | public class HslProtocol |
| | | { |
| | | |
| | | /** |
| | | * 规定所有的网络传输的指令头长度 |
| | | */ |
| | | public static final int HeadByteLength = 32; |
| | | |
| | | /** |
| | | * 所有网络通信中的缓冲池的数据信息 |
| | | */ |
| | | public static final int ProtocolBufferSize = 1024; |
| | | |
| | | /** |
| | | * 用于心跳程序的暗号信息 |
| | | */ |
| | | public static final int ProtocolCheckSecends = 1; |
| | | |
| | | /** |
| | | * 客户端退出的消息 |
| | | */ |
| | | public static final int ProtocolClientQuit = 2; |
| | | |
| | | /** |
| | | * 因为客户端达到上限而拒绝登录 |
| | | */ |
| | | public static final int ProtocolClientRefuseLogin = 3; |
| | | |
| | | /** |
| | | * 允许客户端登录到服务器 |
| | | */ |
| | | public static final int ProtocolClientAllowLogin = 4; |
| | | |
| | | /** |
| | | * 说明发送的信息是文本数据 |
| | | */ |
| | | public static final int ProtocolUserString = 1001; |
| | | |
| | | /** |
| | | * 说明发送的信息是字节数组数据 |
| | | */ |
| | | public static final int ProtocolUserBytes = 1002; |
| | | |
| | | /** |
| | | * 发送的数据是普通的图片数据 |
| | | */ |
| | | public static final int ProtocolUserBitmap = 1003; |
| | | |
| | | /** |
| | | * 发送的数据是一条异常的数据,字符串为异常消息 |
| | | */ |
| | | public static final int ProtocolUserException = 1004; |
| | | |
| | | /** |
| | | * 请求文件下载的暗号 |
| | | */ |
| | | public static final int ProtocolFileDownload = 2001; |
| | | |
| | | /** |
| | | * 请求文件上传的暗号 |
| | | */ |
| | | public static final int ProtocolFileUpload = 2002; |
| | | |
| | | /** |
| | | * 请求删除文件的暗号 |
| | | */ |
| | | public static final int ProtocolFileDelete = 2003; |
| | | |
| | | /** |
| | | * 文件校验成功 |
| | | */ |
| | | public static final int ProtocolFileCheckRight = 2004; |
| | | |
| | | /** |
| | | * 文件校验失败 |
| | | */ |
| | | public static final int ProtocolFileCheckError = 2005; |
| | | |
| | | /** |
| | | * 文件保存失败 |
| | | */ |
| | | public static final int ProtocolFileSaveError = 2006; |
| | | |
| | | /** |
| | | * 请求文件的列表的暗号 |
| | | */ |
| | | public static final int ProtocolFileDirectoryFiles = 2007; |
| | | |
| | | /** |
| | | * 请求子文件的列表暗号 |
| | | */ |
| | | public static final int ProtocolFileDirectories = 2008; |
| | | |
| | | /** |
| | | * 进度返回暗号 |
| | | */ |
| | | public static final int ProtocolProgressReport = 2009; |
| | | |
| | | |
| | | /** |
| | | * 不压缩字节数据 |
| | | */ |
| | | public static final int ProtocolNoZipped = 3001; |
| | | |
| | | /** |
| | | * 压缩字节数据 |
| | | */ |
| | | public static final int ProtocolZipped = 3002; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 生成终极传送指令的方法,所有的数据均通过该方法出来 |
| | | * @param command 命令头 |
| | | * @param customer 自用自定义 |
| | | * @param token 令牌 |
| | | * @param data 字节数据 |
| | | * @return 发送的消息数据 |
| | | */ |
| | | public static byte[] CommandBytes(int command, int customer, UUID token, byte[] data ) |
| | | { |
| | | byte[] _temp = null; |
| | | int _zipped = ProtocolNoZipped; |
| | | int _sendLength = 0; |
| | | if (data == null) |
| | | { |
| | | _temp = new byte[HeadByteLength]; |
| | | } |
| | | else |
| | | { |
| | | // 加密 |
| | | data = HslSecurity.ByteEncrypt(data); |
| | | if (data.length > 10240) |
| | | { |
| | | // 10K以上的数据,进行数据压缩 |
| | | data = SoftZipped.CompressBytes(data); |
| | | _zipped = ProtocolZipped; |
| | | } |
| | | _temp = new byte[HeadByteLength + data.length]; |
| | | _sendLength = data.length; |
| | | } |
| | | |
| | | Utilities.getBytes(command); |
| | | |
| | | System.arraycopy(Utilities.getBytes(command),0,_temp,0,4); |
| | | System.arraycopy(Utilities.getBytes(customer),0,_temp,4,4); |
| | | System.arraycopy(Utilities.getBytes(_zipped),0,_temp,8,4); |
| | | System.arraycopy(Utilities.UUID2Byte(token),0,_temp,12,16); |
| | | System.arraycopy(Utilities.getBytes(_sendLength),0,_temp,28,4); |
| | | if (_sendLength > 0) |
| | | { |
| | | System.arraycopy(data,0,_temp,32,_sendLength); |
| | | } |
| | | return _temp; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 解析接收到数据,先解压缩后进行解密 |
| | | * @param head |
| | | * @param content |
| | | * @return |
| | | */ |
| | | public static byte[] CommandAnalysis( byte[] head, byte[] content ) |
| | | { |
| | | if (content != null) |
| | | { |
| | | byte[] buffer = new byte[4]; |
| | | buffer[0] = head[8]; |
| | | buffer[1] = head[9]; |
| | | buffer[2] = head[10]; |
| | | buffer[3] = head[11]; |
| | | |
| | | // 获取是否压缩的情况 |
| | | int _zipped = Utilities.getInt(buffer,0); |
| | | |
| | | |
| | | // 先进行解压 |
| | | if (_zipped == ProtocolZipped) |
| | | { |
| | | content = SoftZipped.Decompress( content ); |
| | | } |
| | | // 进行解密 |
| | | return HslSecurity.ByteDecrypt( content ); |
| | | } |
| | | else |
| | | { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 获取发送字节数据的实际数据,带指令头 |
| | | * @param customer |
| | | * @param token |
| | | * @param data |
| | | * @return |
| | | */ |
| | | public static byte[] CommandBytes( int customer, UUID token, byte[] data ) |
| | | { |
| | | return CommandBytes( ProtocolUserBytes, customer, token, data ); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取发送字节数据的实际数据,带指令头 |
| | | * @param customer |
| | | * @param token |
| | | * @param data |
| | | * @return |
| | | */ |
| | | public static byte[] CommandBytes( int customer, UUID token, String data ) |
| | | { |
| | | if (data == null) return CommandBytes( ProtocolUserString, customer, token, null ); |
| | | else return CommandBytes( ProtocolUserString, customer, token, Utilities.string2Byte(data) ); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.net; |
| | | |
| | | import com.zy.gateway.core.domain.IDataTransfer; |
| | | import com.zy.gateway.core.domain.OperateResult; |
| | | import com.zy.gateway.core.domain.OperateResultExOne; |
| | | |
| | | /** |
| | | * 所有设备交互类的统一的读写接口 |
| | | */ |
| | | public interface IReadWriteNet { |
| | | |
| | | /** |
| | | * 批量读取底层的数据信息,需要指定地址和长度,具体的结果取决于实现 |
| | | * @param address 地址信息 |
| | | * @param length 数据长度 |
| | | * @return 带有成功标识的byte[]数组 |
| | | */ |
| | | OperateResultExOne<byte[]> Read(String address, short length); |
| | | |
| | | /** |
| | | * 读取16位的有符号整型 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的short数据 |
| | | */ |
| | | OperateResultExOne<Short> ReadInt16(String address); |
| | | |
| | | /** |
| | | * 读取16位的有符号整型数组 |
| | | * @param address 起始地址 |
| | | * @param length 读取的数组长度 |
| | | * @return 带有成功标识的short数组 |
| | | */ |
| | | OperateResultExOne<short []> ReadInt16(String address, short length); |
| | | |
| | | /** |
| | | * 读取32位的有符号整型 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的int数据 |
| | | */ |
| | | OperateResultExOne<Integer> ReadInt32(String address); |
| | | |
| | | /** |
| | | * 读取32位有符号整型的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | OperateResultExOne<int[]> ReadInt32(String address, short length); |
| | | |
| | | /** |
| | | * 读取64位的有符号整型 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的long数据 |
| | | */ |
| | | OperateResultExOne<Long> ReadInt64(String address); |
| | | |
| | | /** |
| | | * 读取64位的有符号整型数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | OperateResultExOne<long[]> ReadInt64(String address, short length); |
| | | |
| | | /** |
| | | * 读取单浮点精度的数据 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的float数据 |
| | | */ |
| | | OperateResultExOne<Float> ReadFloat(String address); |
| | | |
| | | /** |
| | | * 读取单浮点精度的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | OperateResultExOne<float[]> ReadFloat(String address, short length); |
| | | |
| | | /** |
| | | * 读取双浮点精度的数据 |
| | | * @param address 起始地址 |
| | | * @return 带有成功标识的double数据 |
| | | */ |
| | | OperateResultExOne<Double> ReadDouble(String address); |
| | | |
| | | |
| | | /** |
| | | * 读取双浮点精度的数据的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | OperateResultExOne<double[]> ReadDouble(String address, short length); |
| | | |
| | | /** |
| | | * 读取字符串数据 |
| | | * @param address 起始地址 |
| | | * @param length 数据长度 |
| | | * @return 带有成功标识的string数据 |
| | | */ |
| | | OperateResultExOne<String> ReadString(String address, short length); |
| | | |
| | | |
| | | /** |
| | | * 读取自定义的数据类型,需要继承自IDataTransfer接口 |
| | | * @param address 起始地址 |
| | | * @param <T> 自定义的类型 |
| | | * @return 带有成功标识的自定义类型数据 |
| | | */ |
| | | <T extends IDataTransfer> OperateResultExOne<T> ReadCustomer(String address, Class<T> tClass); |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 写入short数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, short value); |
| | | |
| | | /** |
| | | * 写入short数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, short[] values); |
| | | |
| | | /** |
| | | * 写入int数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, int value); |
| | | |
| | | /** |
| | | * 写入int[]数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, int[] values); |
| | | |
| | | /** |
| | | * 写入long数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, long value); |
| | | |
| | | /** |
| | | * 写入long数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, long[] values); |
| | | |
| | | /** |
| | | * 写入float数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, float value); |
| | | |
| | | /** |
| | | * 写入float数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, float[] values); |
| | | |
| | | /** |
| | | * 写入double数据 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, double value); |
| | | |
| | | /** |
| | | * 写入double数组 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, double[] values); |
| | | |
| | | /** |
| | | * 写入字符串信息,编码为ASCII |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, String value); |
| | | |
| | | |
| | | /** |
| | | * 写入字符串信息,编码为ASCII |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @param length 写入的字符串的长度 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | OperateResult Write(String address, String value, int length); |
| | | |
| | | /** |
| | | * 写入自定义类型的数据,该类型必须继承自IDataTransfer接口 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @param <T> 类型对象 |
| | | * @return 带有成功标识的结果类对象 |
| | | */ |
| | | <T extends IDataTransfer> OperateResult WriteCustomer(String address, T value); |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.net; |
| | | |
| | | import com.zy.gateway.core.StringResources; |
| | | import com.zy.gateway.core.domain.HslTimeOut; |
| | | import com.zy.gateway.core.domain.OperateResult; |
| | | import com.zy.gateway.core.domain.OperateResultExOne; |
| | | import com.zy.gateway.core.domain.siemens.INetMessage; |
| | | import com.zy.gateway.core.log.ILogNet; |
| | | import com.zy.gateway.core.utils.Utilities; |
| | | |
| | | import java.io.DataOutputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.net.InetSocketAddress; |
| | | import java.net.Socket; |
| | | import java.net.SocketAddress; |
| | | import java.util.Date; |
| | | import java.util.UUID; |
| | | |
| | | |
| | | /** |
| | | * 本系统所有网络类的基类,该类为抽象类,无法进行实例化 |
| | | */ |
| | | public abstract class NetworkBase { |
| | | |
| | | /** |
| | | * 实例化一个NetworkBase对象 |
| | | */ |
| | | public NetworkBase( ) |
| | | { |
| | | Token = UUID.fromString("00000000-0000-0000-0000-000000000000"); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 通讯类的核心套接字 |
| | | */ |
| | | protected Socket CoreSocket = null; |
| | | |
| | | |
| | | /** |
| | | * 线程检查是否发生了超时的方法 |
| | | * @param timeout |
| | | * @param millisecond |
| | | */ |
| | | public static void ThreadPoolCheckConnect(HslTimeOut timeout, int millisecond) { |
| | | while (!timeout.IsSuccessful) { |
| | | if ((new Date().getTime() - timeout.StartTime.getTime()) > millisecond) { |
| | | // 连接超时或是验证超时 |
| | | if (!timeout.IsSuccessful) { |
| | | try { |
| | | if (timeout.WorkSocket != null) { |
| | | timeout.WorkSocket.close(); |
| | | } |
| | | } catch (IOException ex) { |
| | | // 不处理,放弃 |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从套接字接收定长度的字节数组 |
| | | * @param socket 套接字 |
| | | * @param length 数据长度 |
| | | * @return 消息类对象 |
| | | */ |
| | | protected OperateResultExOne<byte[]> Receive(Socket socket, int length, int timeout ) |
| | | { |
| | | OperateResultExOne<byte[]> resultExOne = new OperateResultExOne<>(); |
| | | |
| | | if (length == 0) { |
| | | resultExOne.IsSuccess = true; |
| | | resultExOne.Content = new byte[0]; |
| | | return resultExOne; |
| | | } |
| | | |
| | | int count_receive = 0; |
| | | byte[] bytes_receive = new byte[length]; |
| | | try { |
| | | if(timeout>0) socket.setSoTimeout(timeout); |
| | | InputStream input = socket.getInputStream(); |
| | | while (count_receive<length) |
| | | { |
| | | count_receive += input.read(bytes_receive, count_receive, length-count_receive); |
| | | } |
| | | } |
| | | catch (IOException ex) |
| | | { |
| | | CloseSocket(socket); |
| | | resultExOne.Message = ex.getMessage(); |
| | | return resultExOne; |
| | | } |
| | | |
| | | resultExOne.IsSuccess = true; |
| | | resultExOne.Content = bytes_receive; |
| | | return resultExOne; |
| | | } |
| | | |
| | | /** |
| | | * 从套接字接收定长度的字节数组 |
| | | * @param socket 套接字 |
| | | * @param length 数据长度 |
| | | * @return 消息类对象 |
| | | */ |
| | | protected OperateResultExOne<byte[]> Receive(Socket socket, int length ) |
| | | { |
| | | return Receive(socket,length,-1); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从套接字接收指定长度的字节数据 |
| | | * @param socket 网络套接字 |
| | | * @param timeOut 超时时间 |
| | | * @param netMsg 消息格式 |
| | | * @param <TNetMessage> 类型 |
| | | * @return 消息类 |
| | | */ |
| | | protected <TNetMessage extends INetMessage> OperateResultExOne<TNetMessage> ReceiveMessage(Socket socket, int timeOut, TNetMessage netMsg) |
| | | { |
| | | OperateResultExOne<TNetMessage> resultExOne = new OperateResultExOne<>(); |
| | | |
| | | // 接收指令头 |
| | | OperateResultExOne<byte[]> headResult = Receive( socket, netMsg.ProtocolHeadBytesLength(), timeOut ); |
| | | if (!headResult.IsSuccess) |
| | | { |
| | | resultExOne.CopyErrorFromOther( headResult ); |
| | | return resultExOne; |
| | | } |
| | | |
| | | netMsg.setHeadBytes( headResult.Content ); |
| | | if (!netMsg.CheckHeadBytesLegal(Utilities.UUID2Byte(Token))) |
| | | { |
| | | // 令牌校验失败 |
| | | CloseSocket(socket); |
| | | if(LogNet != null) LogNet.WriteError( toString( ), StringResources.Language.TokenCheckFailed() ); |
| | | resultExOne.Message = StringResources.Language.TokenCheckFailed(); |
| | | return resultExOne; |
| | | } |
| | | |
| | | |
| | | int contentLength = netMsg.GetContentLengthByHeadBytes( ); |
| | | if (contentLength == 0) |
| | | { |
| | | netMsg.setContentBytes( new byte[0] ); |
| | | } |
| | | else |
| | | { |
| | | OperateResultExOne<byte[]> contentResult = Receive( socket, contentLength, timeOut ); |
| | | if (!contentResult.IsSuccess) |
| | | { |
| | | resultExOne.CopyErrorFromOther( contentResult ); |
| | | return resultExOne; |
| | | } |
| | | |
| | | netMsg.setContentBytes( contentResult.Content); |
| | | } |
| | | |
| | | // 防止没有实例化造成后续的操作失败 |
| | | if (netMsg.getContentBytes() == null){ netMsg.setContentBytes( new byte[0]);} |
| | | resultExOne.Content = netMsg; |
| | | resultExOne.IsSuccess = true; |
| | | return resultExOne; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 发送一串数据到网络套接字中 |
| | | * @param socket 网络套接字 |
| | | * @param data 数据 |
| | | * @return 是否发送成功 |
| | | */ |
| | | protected OperateResult Send(Socket socket,byte[] data){ |
| | | OperateResult result = new OperateResult(); |
| | | if(data == null) { |
| | | result.IsSuccess = true; |
| | | return result; |
| | | } |
| | | try { |
| | | DataOutputStream output = new DataOutputStream(socket.getOutputStream()); |
| | | output.write(data, 0, data.length); |
| | | } |
| | | catch (IOException ex) |
| | | { |
| | | result.Message = ex.getMessage(); |
| | | return result; |
| | | } |
| | | |
| | | result.IsSuccess = true; |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 创建一个套接字并且连接到服务器 |
| | | * @param endPoint 目标节点 |
| | | * @param timeOut 超时时间 |
| | | * @return 连接成功的标志 |
| | | */ |
| | | protected OperateResultExOne<Socket> CreateSocketAndConnect(SocketAddress endPoint, int timeOut){ |
| | | OperateResultExOne<Socket> operateResultExOne = new OperateResultExOne<>(); |
| | | |
| | | Socket socket = new Socket(); |
| | | try { |
| | | socket.connect(endPoint,timeOut); |
| | | operateResultExOne.Content = socket; |
| | | operateResultExOne.IsSuccess = true; |
| | | } |
| | | catch (IOException ex) |
| | | { |
| | | operateResultExOne.Message = ex.getMessage(); |
| | | CloseSocket(socket); |
| | | } |
| | | |
| | | return operateResultExOne; |
| | | } |
| | | |
| | | /** |
| | | * 创建一个套接字并且连接到服务器 |
| | | * @param ipAddress ip地址 |
| | | * @param port 端口号 |
| | | * @param timeOut 超时时间 |
| | | * @return 连接成功的标志 |
| | | */ |
| | | protected OperateResultExOne<Socket> CreateSocketAndConnect(String ipAddress,int port, int timeOut) { |
| | | SocketAddress endPoint = new InetSocketAddress(ipAddress,port); |
| | | return CreateSocketAndConnect(endPoint,timeOut); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 读取流中的数据到缓存区 |
| | | * @param stream 流数据 |
| | | * @param buffer 缓冲数据 |
| | | * @return |
| | | */ |
| | | protected OperateResultExOne<Integer> ReadStream(InputStream stream, byte[] buffer) { |
| | | OperateResultExOne<Integer> resultExOne = new OperateResultExOne<>(); |
| | | int read_count = 0; |
| | | try { |
| | | while (read_count < buffer.length) { |
| | | read_count += stream.read(buffer, read_count, buffer.length - read_count); |
| | | } |
| | | resultExOne.Content = read_count; |
| | | resultExOne.IsSuccess = true; |
| | | } catch (IOException ex) { |
| | | resultExOne.Message = ex.getMessage(); |
| | | } |
| | | |
| | | return resultExOne; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字节流数据写入到输出流里面去 |
| | | * @param stream 字节流 |
| | | * @param buffer 缓存数据 |
| | | * @return 写入是否成功 |
| | | */ |
| | | protected OperateResult WriteStream(OutputStream stream, byte[] buffer ) { |
| | | OperateResult result = new OperateResultExOne<>(); |
| | | try { |
| | | stream.write(buffer, 0, buffer.length); |
| | | result.IsSuccess = true; |
| | | } catch (IOException ex) { |
| | | result.Message = ex.getMessage(); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 安全的关闭一个套接字 |
| | | * @param socket 网络套接字 |
| | | */ |
| | | protected void CloseSocket(Socket socket){ |
| | | if(socket != null){ |
| | | try { |
| | | socket.close(); |
| | | } |
| | | catch (Exception ex){ |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 组件的日志工具,支持日志记录 |
| | | */ |
| | | public ILogNet LogNet = null; |
| | | |
| | | /** |
| | | * 网络类的身份令牌 |
| | | */ |
| | | public UUID Token = null; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 返回对象的字符串表示形式 |
| | | * @return 字符串 |
| | | */ |
| | | @Override |
| | | public String toString(){ |
| | | return "NetworkBase"; |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.net; |
| | | |
| | | import com.zy.gateway.core.base.SoftBasic; |
| | | import com.zy.gateway.core.domain.IDataTransfer; |
| | | import com.zy.gateway.core.domain.OperateResult; |
| | | import com.zy.gateway.core.domain.OperateResultExOne; |
| | | import com.zy.gateway.core.domain.siemens.INetMessage; |
| | | import com.zy.gateway.core.transfer.IByteTransform; |
| | | import com.zy.gateway.core.utils.Utilities; |
| | | |
| | | |
| | | /** |
| | | * 设备类的基类,提供了基础的字节读写方法,采用泛型继承实现 |
| | | * @param <TNetMessage> 消息类型 |
| | | * @param <TTransform> 变换类型 |
| | | */ |
| | | public class NetworkDeviceBase<TNetMessage extends INetMessage,TTransform extends IByteTransform> extends NetworkDoubleBase<TNetMessage,TTransform> implements IReadWriteNet |
| | | { |
| | | |
| | | |
| | | |
| | | /************************************************************************************************** |
| | | * |
| | | * 说明:子类中需要重写基础的读取和写入方法,来支持不同的数据访问规则 |
| | | * |
| | | * 此处没有将读写位纳入进来,因为各种设备的支持不尽相同,比较麻烦 |
| | | * |
| | | **************************************************************************************************/ |
| | | |
| | | protected short WordLength = 1; |
| | | |
| | | |
| | | /** |
| | | * 从设备读取原始数据 |
| | | * @param address 地址信息 |
| | | * @param length 数据长度 |
| | | * @return 带有成功标识的结果对象 |
| | | */ |
| | | public OperateResultExOne<byte[]> Read(String address, short length) { |
| | | return new OperateResultExOne<byte[]>(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将原始数据写入设备 |
| | | * @param address 起始地址 |
| | | * @param value 原始数据 |
| | | * @return 带有成功标识的结果对象 |
| | | */ |
| | | public OperateResult Write(String address, byte[] value) { |
| | | return new OperateResult(); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取自定义类型的数据,需要规定解析规则 |
| | | * @param address 起始地址 |
| | | * @param tClass 类 |
| | | * @param <T> 类型名称 |
| | | * @return 带有成功标识的结果对象 |
| | | */ |
| | | public <T extends IDataTransfer> OperateResultExOne<T> ReadCustomer(String address , Class<T> tClass) |
| | | { |
| | | OperateResultExOne<T> result = new OperateResultExOne<T>(); |
| | | T Content; |
| | | try { |
| | | Content = tClass.newInstance(); |
| | | } |
| | | catch (Exception ex){ |
| | | Content = null; |
| | | } |
| | | OperateResultExOne<byte[]> read = Read(address, Content.getReadCount()); |
| | | if (read.IsSuccess) { |
| | | Content.ParseSource(read.Content); |
| | | result.Content = Content; |
| | | result.IsSuccess = true; |
| | | } else { |
| | | result.ErrorCode = read.ErrorCode; |
| | | result.Message = read.Message; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 写入自定义类型的数据到设备去,需要规定生成字节的方法 |
| | | * @param address 起始地址 |
| | | * @param data 实例对象 |
| | | * @param <T> 自定义类型 |
| | | * @return 带有成功标识的结果对象 |
| | | */ |
| | | public <T extends IDataTransfer> OperateResult WriteCustomer(String address, T data ) |
| | | { |
| | | return Write(address, data.ToSource()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 读取设备的short类型的数据 |
| | | * @param address 起始地址 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<Short> ReadInt16(String address) { |
| | | return GetInt16ResultFromBytes(Read(address, WordLength)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 读取设备的short类型的数组 |
| | | * @param address 起始地址 |
| | | * @param length 读取的数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<short[]> ReadInt16(String address, short length) { |
| | | OperateResultExOne<byte[]> read = Read(address, (short) (length * WordLength)); |
| | | if (!read.IsSuccess) { |
| | | OperateResultExOne<short[]> result = new OperateResultExOne<short[]>(); |
| | | result.CopyErrorFromOther(read); |
| | | return result; |
| | | } |
| | | return OperateResultExOne.CreateSuccessResult(super.getByteTransform().TransInt16(read.Content, 0, length)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取设备的int类型的数据 |
| | | * @param address 起始地址 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<Integer> ReadInt32(String address) { |
| | | return GetInt32ResultFromBytes(Read(address, (short) (2 * WordLength))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取设备的int类型的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<int[]> ReadInt32(String address, short length) { |
| | | OperateResultExOne<byte[]> read = Read(address, (short) (length * WordLength * 2)); |
| | | if (!read.IsSuccess) { |
| | | OperateResultExOne<int[]> result = new OperateResultExOne<int[]>(); |
| | | result.CopyErrorFromOther(read); |
| | | return result; |
| | | } |
| | | return OperateResultExOne.CreateSuccessResult(super.getByteTransform().TransInt32(read.Content, 0, length)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 读取设备的float类型的数据 |
| | | * @param address 起始地址 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<Float> ReadFloat(String address) { |
| | | return GetSingleResultFromBytes(Read(address, (short) (2 * WordLength))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取设备的float类型的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<float[]> ReadFloat(String address, short length) { |
| | | OperateResultExOne<byte[]> read = Read(address, (short) (length * WordLength * 2)); |
| | | if (!read.IsSuccess) { |
| | | OperateResultExOne<float[]> result = new OperateResultExOne<float[]>(); |
| | | result.CopyErrorFromOther(read); |
| | | return result; |
| | | } |
| | | return OperateResultExOne.CreateSuccessResult(super.getByteTransform().TransSingle(read.Content, 0, length)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取设备的long类型的数据 |
| | | * @param address 起始地址 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<Long> ReadInt64(String address) { |
| | | return GetInt64ResultFromBytes(Read(address, (short) (4 * WordLength))); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 读取设备的long类型的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<long[]> ReadInt64(String address, short length) { |
| | | OperateResultExOne<byte[]> read = Read(address, (short) (length * WordLength * 4)); |
| | | if (!read.IsSuccess) { |
| | | OperateResultExOne<long[]> result = new OperateResultExOne<long[]>(); |
| | | result.CopyErrorFromOther(read); |
| | | return result; |
| | | } |
| | | return OperateResultExOne.CreateSuccessResult(super.getByteTransform().TransInt64(read.Content, 0, length)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取设备的double类型的数据 |
| | | * @param address 起始地址 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<Double> ReadDouble(String address) { |
| | | return GetDoubleResultFromBytes(Read(address, (short) (4 * WordLength))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取设备的double类型的数组 |
| | | * @param address 起始地址 |
| | | * @param length 数组长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<double[]> ReadDouble(String address, short length) { |
| | | OperateResultExOne<byte[]> read = Read(address, (short) (length * WordLength * 4)); |
| | | if (!read.IsSuccess) { |
| | | OperateResultExOne<double[]> result = new OperateResultExOne<double[]>(); |
| | | result.CopyErrorFromOther(read); |
| | | return result; |
| | | } |
| | | return OperateResultExOne.CreateSuccessResult(super.getByteTransform().TransDouble(read.Content, 0, length)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取设备的字符串数据,编码为ASCII |
| | | * @param address 起始地址 |
| | | * @param length 数据长度 |
| | | * @return 带成功标志的结果数据对象 |
| | | */ |
| | | public OperateResultExOne<String> ReadString(String address, short length) { |
| | | return GetStringResultFromBytes(Read(address, length)); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入short数组,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, short[] values) { |
| | | return Write(address, super.getByteTransform().TransByte(values)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入short数据,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, short value) { |
| | | return Write(address, new short[]{value}); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入int数组,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | /// <returns>返回写入结果</returns> |
| | | public OperateResult Write(String address, int[] values) { |
| | | return Write(address, super.getByteTransform().TransByte(values)); |
| | | } |
| | | |
| | | /** |
| | | * 向设备中写入int数据,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, int value) { |
| | | return Write(address, new int[]{value}); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入float数组,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, float[] values) { |
| | | return Write(address, super.getByteTransform().TransByte(values)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入float数据,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, float value) { |
| | | return Write(address, new float[]{value}); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入long数组,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, long[] values) { |
| | | return Write(address, getByteTransform().TransByte(values)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入long数据,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, long value) { |
| | | return Write(address, new long[]{value}); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 设备中写入double数组,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param values 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, double[] values) { |
| | | return Write(address, getByteTransform().TransByte(values)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入double数据,返回是否写入成功 |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 返回写入结果 |
| | | */ |
| | | public OperateResult Write(String address, double value) { |
| | | return Write(address, new double[]{value}); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入字符串,编码格式为ASCII |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @return 返回读取结果 |
| | | */ |
| | | public OperateResult Write(String address, String value) { |
| | | byte[] temp = getByteTransform().TransByte(value, "US-ASCII"); |
| | | if (WordLength == 1) temp = SoftBasic.ArrayExpandToLengthEven(temp); |
| | | return Write(address, temp); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入字符串,编码格式为ASCII |
| | | * @param address 起始地址 |
| | | * @param value 写入值 |
| | | * @param length 写入的字符串的长度 |
| | | * @return 返回读取结果 |
| | | */ |
| | | public OperateResult Write(String address, String value, int length) { |
| | | byte[] temp = getByteTransform().TransByte(value, "US-ASCII"); |
| | | temp = SoftBasic.ArrayExpandToLength(temp, length); |
| | | if (WordLength == 1) temp = SoftBasic.ArrayExpandToLengthEven(temp); |
| | | return Write(address, temp); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入字符串,编码格式为Unicode |
| | | * @param address 要写入的数据地址 |
| | | * @param value 要写入的实际数据 |
| | | * @return 写入结果 |
| | | */ |
| | | public OperateResult WriteUnicodeString(String address, String value) { |
| | | byte[] temp = Utilities.string2Byte(value); |
| | | return Write(address, temp); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 向设备中写入字符串,超出截断,不够补0,编码格式为Unicode |
| | | * @param address 要写入的数据地址 |
| | | * @param value 要写入的实际数据 |
| | | * @param length 指定的字符串长度,必须大于0 |
| | | * @return 写入结果 |
| | | */ |
| | | public OperateResult WriteUnicodeString(String address, String value, int length) { |
| | | byte[] temp = Utilities.string2Byte(value); |
| | | temp = SoftBasic.ArrayExpandToLength(temp, length * 2); |
| | | return Write(address, temp); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 返回表示当前对象的字符串 |
| | | * @return 字符串数据 |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return "NetworkDeviceBase<TNetMessage, TTransform>"; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.net; |
| | | |
| | | import com.zy.gateway.core.StringResources; |
| | | import com.zy.gateway.core.base.SoftBasic; |
| | | import com.zy.gateway.core.domain.OperateResult; |
| | | import com.zy.gateway.core.domain.OperateResultExOne; |
| | | import com.zy.gateway.core.domain.OperateResultExTwo; |
| | | import com.zy.gateway.core.domain.siemens.INetMessage; |
| | | import com.zy.gateway.core.net.session.AlienSession; |
| | | import com.zy.gateway.core.transfer.ByteTransformHelper; |
| | | import com.zy.gateway.core.transfer.IByteTransform; |
| | | |
| | | import java.lang.reflect.ParameterizedType; |
| | | import java.net.Socket; |
| | | import java.util.concurrent.locks.Lock; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | /** |
| | | * 双模式的客户端基类, |
| | | * @param <TNetMessage> 消息类的类型 |
| | | * @param <TTransform> 转换类的类型 |
| | | */ |
| | | public class NetworkDoubleBase<TNetMessage extends INetMessage,TTransform extends IByteTransform> extends NetworkBase |
| | | { |
| | | /** |
| | | * 默认的无参构造函数 |
| | | */ |
| | | public NetworkDoubleBase( ) |
| | | { |
| | | queueLock = new ReentrantLock(); // 实例化数据访问锁 |
| | | byteTransform = getInstanceOfTTransform(); // 实例化数据转换规则 |
| | | connectionId = SoftBasic.GetUniqueStringByGuidAndRandom( ); |
| | | } |
| | | |
| | | |
| | | |
| | | private TTransform byteTransform; // 数据变换的接口 |
| | | private String ipAddress = "127.0.0.1"; // 连接的IP地址 |
| | | private int port = 10000; // 端口号 |
| | | private int connectTimeOut = 10000; // 连接超时时间设置 |
| | | private int receiveTimeOut = 10000; // 数据接收的超时时间 |
| | | private boolean isPersistentConn = false; // 是否处于长连接的状态 |
| | | private Lock queueLock = null; // 数据访问的同步锁 |
| | | private boolean IsSocketError = false; // 指示长连接的套接字是否处于错误的状态 |
| | | private boolean isUseSpecifiedSocket = false; // 指示是否使用指定的网络套接字访问数据 |
| | | private String connectionId = ""; // 当前连接 |
| | | |
| | | |
| | | |
| | | private TTransform getInstanceOfTTransform( ) |
| | | { |
| | | ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass(); |
| | | Class<TTransform> type = (Class<TTransform>) superClass.getActualTypeArguments()[1]; |
| | | try |
| | | { |
| | | return type.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | private TNetMessage getInstanceOfTNetMessage( ) |
| | | { |
| | | ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass(); |
| | | Class<TNetMessage> type = (Class<TNetMessage>) superClass.getActualTypeArguments()[0]; |
| | | try |
| | | { |
| | | return type.newInstance(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | // Oops, no default constructor |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 获取数据变换机制 |
| | | * @return |
| | | */ |
| | | public TTransform getByteTransform( ){ |
| | | return byteTransform; |
| | | } |
| | | |
| | | /** |
| | | * 设置数据变换机制 |
| | | * @param transform 数据变换 |
| | | */ |
| | | public void setByteTransform(TTransform transform) |
| | | { |
| | | byteTransform = transform; |
| | | } |
| | | |
| | | /** |
| | | * 获取连接的超时时间 |
| | | */ |
| | | public int getConnectTimeOut( ){ |
| | | return connectTimeOut; |
| | | } |
| | | |
| | | /** |
| | | * 设置连接的超时时间 |
| | | * @param connectTimeOut 超时时间,单位是秒 |
| | | */ |
| | | public void setConnectTimeOut(int connectTimeOut) { |
| | | this.connectTimeOut = connectTimeOut; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取接收服务器反馈的时间,如果为负数,则不接收反馈 |
| | | * @return |
| | | */ |
| | | public int getReceiveTimeOut( ){ |
| | | return receiveTimeOut; |
| | | } |
| | | |
| | | /** |
| | | * 设置接收服务器反馈的时间,如果为负数,则不接收反馈 |
| | | * @param receiveTimeOut |
| | | */ |
| | | public void setReceiveTimeOut(int receiveTimeOut){ |
| | | this.receiveTimeOut = receiveTimeOut; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取服务器的IP地址 |
| | | * @return Ip地址信息 |
| | | */ |
| | | public String getIpAddress() { |
| | | return ipAddress; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 设置服务器的IP地址 |
| | | * @param ipAddress IP地址 |
| | | */ |
| | | public void setIpAddress(String ipAddress) { |
| | | if(!ipAddress.isEmpty()){ |
| | | this.ipAddress = ipAddress; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取服务器的端口 |
| | | * @return 端口 |
| | | */ |
| | | public int getPort() { |
| | | return port; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 设置服务器的端口号 |
| | | * @param port 端口号 |
| | | */ |
| | | public void setPort(int port) { |
| | | this.port = port; |
| | | } |
| | | |
| | | /** |
| | | * 当前连接的唯一ID号,默认为长度20的guid码加随机数组成,也可以自己指定 |
| | | * @return |
| | | */ |
| | | public String getConnectionId() { |
| | | return connectionId; |
| | | } |
| | | |
| | | /** |
| | | * 设置当前的连接ID |
| | | * @param connectionId |
| | | */ |
| | | public void setConnectionId(String connectionId) { |
| | | this.connectionId = connectionId; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 当前的异形连接对象,如果设置了异性连接的话 |
| | | */ |
| | | public AlienSession AlienSession = null; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 在读取数据之前可以调用本方法将客户端设置为长连接模式,相当于跳过了ConnectServer的结果验证,对异形客户端无效 |
| | | */ |
| | | public void SetPersistentConnection( ) |
| | | { |
| | | isPersistentConn = true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 切换短连接模式到长连接模式,后面的每次请求都共享一个通道 |
| | | * @return 返回连接结果,如果失败的话(也即IsSuccess为False),包含失败信息 |
| | | */ |
| | | public OperateResult ConnectServer( ) |
| | | { |
| | | isPersistentConn = true; |
| | | OperateResult result = new OperateResult( ); |
| | | |
| | | // 重新连接之前,先将旧的数据进行清空 |
| | | CloseSocket(CoreSocket); |
| | | |
| | | OperateResultExOne<Socket> rSocket = CreateSocketAndInitialication( ); |
| | | |
| | | if (!rSocket.IsSuccess) |
| | | { |
| | | IsSocketError = true; // 创建失败 |
| | | rSocket.Content = null; |
| | | result.Message = rSocket.Message; |
| | | } |
| | | else |
| | | { |
| | | CoreSocket = rSocket.Content; // 创建成功 |
| | | result.IsSuccess = true; |
| | | if(LogNet != null) LogNet.WriteDebug( toString( ), StringResources.Language.NetEngineStart() ); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 使用指定的套接字创建异形客户端 |
| | | * @param session 会话 |
| | | * @return 通常都为成功 |
| | | */ |
| | | public OperateResult ConnectServer( AlienSession session ) |
| | | { |
| | | isPersistentConn = true; |
| | | isUseSpecifiedSocket = true; |
| | | |
| | | |
| | | if (session != null) |
| | | { |
| | | if(AlienSession != null ) CloseSocket(AlienSession.getSocket()); |
| | | |
| | | if (connectionId.isEmpty()) |
| | | { |
| | | connectionId = session.getDTU(); |
| | | } |
| | | |
| | | if (connectionId == session.getDTU()) |
| | | { |
| | | CoreSocket = session.getSocket(); |
| | | IsSocketError = false; |
| | | AlienSession = session; |
| | | return InitializationOnConnect( session.getSocket() ); |
| | | } |
| | | else |
| | | { |
| | | IsSocketError = true; |
| | | return new OperateResult( ); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | IsSocketError = true; |
| | | return new OperateResult( ); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 在长连接模式下,断开服务器的连接,并切换到短连接模式 |
| | | * @return 关闭连接,不需要查看IsSuccess属性查看 |
| | | */ |
| | | public OperateResult ConnectClose( ) |
| | | { |
| | | OperateResult result = new OperateResult( ); |
| | | isPersistentConn = false; |
| | | |
| | | queueLock.lock(); |
| | | |
| | | // 额外操作 |
| | | result = ExtraOnDisconnect( CoreSocket ); |
| | | // 关闭信息 |
| | | if(CoreSocket != null ) CloseSocket(CoreSocket); |
| | | CoreSocket = null; |
| | | |
| | | queueLock.unlock(); |
| | | |
| | | if(LogNet != null ) LogNet.WriteDebug( toString( ), StringResources.Language.NetEngineClose() ); |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 在连接的时候进行初始化 |
| | | * @param socket 网络套接字 |
| | | * @return 结果类对象 |
| | | */ |
| | | protected OperateResult InitializationOnConnect( Socket socket ) { |
| | | return OperateResult.CreateSuccessResult(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 在将要和服务器进行断开的情况下额外的操作 |
| | | * @param socket 网络套接字 |
| | | * @return 结果类对象 |
| | | */ |
| | | protected OperateResult ExtraOnDisconnect( Socket socket ) { |
| | | return OperateResult.CreateSuccessResult(); |
| | | } |
| | | |
| | | |
| | | /*************************************************************************************** |
| | | * |
| | | * 主要的数据交互分为4步 |
| | | * 1. 连接服务器,或是获取到旧的使用的网络信息 |
| | | * 2. 发送数据信息 |
| | | * 3. 接收反馈的数据信息 |
| | | * 4. 关闭网络连接,如果是短连接的话 |
| | | * |
| | | **************************************************************************************/ |
| | | |
| | | |
| | | /** |
| | | * 获取本次操作的可用的网络套接字 |
| | | * @return 是否成功,如果成功,使用这个套接字 |
| | | */ |
| | | private OperateResultExOne<Socket> GetAvailableSocket( ) { |
| | | // 是否处于长连接的状态 |
| | | if (isPersistentConn) { |
| | | // 如果是异形模式 |
| | | if (isUseSpecifiedSocket) { |
| | | // 指示长连接的套接字是否处于错误的状态 |
| | | if(IsSocketError) { |
| | | OperateResultExOne<Socket> rSocket = new OperateResultExOne<>(); |
| | | rSocket.Message = "连接不可用"; |
| | | return rSocket; |
| | | } else { |
| | | return OperateResultExOne.CreateSuccessResult( CoreSocket ); |
| | | } |
| | | } else { |
| | | // 长连接模式 |
| | | if (IsSocketError || CoreSocket == null) { |
| | | OperateResult connect = ConnectServer( ); |
| | | if (!connect.IsSuccess) { |
| | | IsSocketError = true; |
| | | OperateResultExOne<Socket> rSocket = new OperateResultExOne<>(); |
| | | rSocket.Message = connect.Message; |
| | | rSocket.ErrorCode = connect.ErrorCode; |
| | | return rSocket; |
| | | } else { |
| | | IsSocketError = false; |
| | | return OperateResultExOne.CreateSuccessResult( CoreSocket ); |
| | | } |
| | | } else { |
| | | return OperateResultExOne.CreateSuccessResult( CoreSocket ); |
| | | } |
| | | } |
| | | |
| | | } else { |
| | | // 短连接模式 |
| | | return CreateSocketAndInitialication( ); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 连接并初始化网络套接字 |
| | | * @return 最终的连接对象 |
| | | */ |
| | | private OperateResultExOne<Socket> CreateSocketAndInitialication( ) |
| | | { |
| | | OperateResultExOne<Socket> result = CreateSocketAndConnect( ipAddress , port , connectTimeOut ); |
| | | if (result.IsSuccess) |
| | | { |
| | | // 初始化 |
| | | OperateResult initi = InitializationOnConnect( result.Content ); |
| | | if (!initi.IsSuccess) |
| | | { |
| | | CloseSocket(result.Content); |
| | | result.IsSuccess = initi.IsSuccess; |
| | | result.CopyErrorFromOther( initi ); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 在其他指定的套接字上,使用报文来通讯,传入需要发送的消息,返回一条完整的数据指令 |
| | | * @param socket 指定的套接字 |
| | | * @param send 发送的完整的报文信息 |
| | | * @return 接收的完整的报文信息 |
| | | */ |
| | | public OperateResultExOne<byte[]> ReadFromCoreServer( Socket socket, byte[] send ) |
| | | { |
| | | OperateResultExOne<byte[]> result = new OperateResultExOne<byte[]>( ); |
| | | |
| | | OperateResultExTwo<byte[], byte[]> read = ReadFromCoreServerBase( socket, send ); |
| | | if (read.IsSuccess) |
| | | { |
| | | result.IsSuccess = read.IsSuccess; |
| | | result.Content = new byte[read.Content1.length + read.Content2.length]; |
| | | if (read.Content1.length > 0) System.arraycopy(read.Content1,0,result.Content,0,read.Content1.length); |
| | | if (read.Content2.length > 0) System.arraycopy(read.Content2,0,result.Content,read.Content1.length,read.Content2.length); |
| | | } |
| | | else |
| | | { |
| | | result.CopyErrorFromOther( read ); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 使用底层的数据报文来通讯,传入需要发送的消息,返回一条完整的数据指令 |
| | | * @param send 发送的完整的报文信息 |
| | | * @return 接收的完整的报文信息 |
| | | */ |
| | | public OperateResultExOne<byte[]> ReadFromCoreServer( byte[] send ) |
| | | { |
| | | OperateResultExOne<byte[]> result = new OperateResultExOne<byte[]>( ); |
| | | // string tmp1 = BasicFramework.SoftBasic.ByteToHexString( send, '-' ); |
| | | |
| | | queueLock.lock( ); |
| | | |
| | | // 获取有用的网络通道,如果没有,就建立新的连接 |
| | | OperateResultExOne<Socket> resultSocket = GetAvailableSocket( ); |
| | | if (!resultSocket.IsSuccess) |
| | | { |
| | | IsSocketError = true; |
| | | if (AlienSession != null) AlienSession.setIsStatusOk( false); |
| | | queueLock.unlock(); |
| | | result.CopyErrorFromOther( resultSocket ); |
| | | return result; |
| | | } |
| | | |
| | | OperateResultExOne<byte[]> read = ReadFromCoreServer( resultSocket.Content, send ); |
| | | |
| | | if (read.IsSuccess) |
| | | { |
| | | IsSocketError = false; |
| | | result.IsSuccess = read.IsSuccess; |
| | | result.Content = read.Content; |
| | | // string tmp2 = BasicFramework.SoftBasic.ByteToHexString( result.Content ) ; |
| | | } |
| | | else |
| | | { |
| | | IsSocketError = true; |
| | | if (AlienSession != null) AlienSession.setIsStatusOk(false); |
| | | result.CopyErrorFromOther( read ); |
| | | } |
| | | |
| | | queueLock.unlock(); |
| | | if (!isPersistentConn) CloseSocket(resultSocket.Content ); |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 使用底层的数据报文来通讯,传入需要发送的消息,返回最终的数据结果,被拆分成了头子节和内容字节信息 |
| | | * @param socket 网络套接字 |
| | | * @param send 发送的数据 |
| | | * @return 结果对象 |
| | | */ |
| | | protected OperateResultExTwo<byte[], byte[]> ReadFromCoreServerBase(Socket socket, byte[] send ) |
| | | { |
| | | OperateResultExTwo<byte[], byte[]> result = new OperateResultExTwo<byte[], byte[]>( ); |
| | | // LogNet?.WriteDebug( ToString( ), "Command: " + BasicFramework.SoftBasic.ByteToHexString( send ) ); |
| | | TNetMessage netMsg = getInstanceOfTNetMessage(); |
| | | netMsg.setSendBytes(send); |
| | | |
| | | // 发送数据信息 |
| | | OperateResult resultSend = Send( socket, send ); |
| | | if (!resultSend.IsSuccess) |
| | | { |
| | | CloseSocket(socket); |
| | | result.CopyErrorFromOther( resultSend ); |
| | | return result; |
| | | } |
| | | |
| | | // 接收超时时间大于0时才允许接收远程的数据 |
| | | if (receiveTimeOut >= 0) |
| | | { |
| | | // 接收数据信息 |
| | | OperateResultExOne<TNetMessage> resultReceive = ReceiveMessage(socket, receiveTimeOut, netMsg); |
| | | if (!resultReceive.IsSuccess) |
| | | { |
| | | CloseSocket(socket ); |
| | | result.CopyErrorFromOther( resultReceive ); |
| | | // result.Message = "Receive data timeout: " + receiveTimeOut; |
| | | return result; |
| | | } |
| | | |
| | | // 复制结果 |
| | | result.Content1 = resultReceive.Content.getHeadBytes(); |
| | | result.Content2 = resultReceive.Content.getContentBytes(); |
| | | } |
| | | |
| | | result.IsSuccess = true; |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 返回表示当前对象的字符串 |
| | | * @return |
| | | */ |
| | | @Override |
| | | public String toString( ) { |
| | | return "NetworkDoubleBase<TNetMessage>"; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @return 转化后的类型 |
| | | */ |
| | | protected OperateResultExOne<Boolean> GetBoolResultFromBytes( OperateResultExOne<byte[]> result ) |
| | | { |
| | | return ByteTransformHelper.GetBoolResultFromBytes( result, byteTransform); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @return 转化后的类型 |
| | | */ |
| | | protected OperateResultExOne<Byte> GetByteResultFromBytes( OperateResultExOne<byte[]> result ) |
| | | { |
| | | return ByteTransformHelper.GetByteResultFromBytes( result, byteTransform ); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @return 转化后的类型 |
| | | */ |
| | | protected OperateResultExOne<Short> GetInt16ResultFromBytes( OperateResultExOne<byte[]> result ) |
| | | { |
| | | return ByteTransformHelper.GetInt16ResultFromBytes( result, byteTransform ); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @return 转化后的类型 |
| | | */ |
| | | protected OperateResultExOne<Integer> GetInt32ResultFromBytes( OperateResultExOne<byte[]> result ) |
| | | { |
| | | return ByteTransformHelper.GetInt32ResultFromBytes( result, byteTransform ); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @return 转化后的类型 |
| | | */ |
| | | protected OperateResultExOne<Long> GetInt64ResultFromBytes( OperateResultExOne<byte[]> result ) |
| | | { |
| | | return ByteTransformHelper.GetInt64ResultFromBytes( result, byteTransform ); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @return 转化后的类型 |
| | | */ |
| | | protected OperateResultExOne<Float> GetSingleResultFromBytes( OperateResultExOne<byte[]> result ) |
| | | { |
| | | return ByteTransformHelper.GetSingleResultFromBytes( result, byteTransform ); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @return 转化后的类型 |
| | | */ |
| | | protected OperateResultExOne<Double> GetDoubleResultFromBytes( OperateResultExOne<byte[]> result ) |
| | | { |
| | | return ByteTransformHelper.GetDoubleResultFromBytes( result, byteTransform ); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @return 转化后的类型 |
| | | */ |
| | | protected OperateResultExOne<String> GetStringResultFromBytes( OperateResultExOne<byte[]> result ) |
| | | { |
| | | return ByteTransformHelper.GetStringResultFromBytes( result, byteTransform ); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.net.session; |
| | | |
| | | import java.net.Socket; |
| | | |
| | | /** |
| | | * 异形客户端的对象 |
| | | */ |
| | | public class AlienSession { |
| | | |
| | | /** |
| | | * 实例化一个默认对象 |
| | | */ |
| | | public AlienSession() |
| | | { |
| | | this.isStatusOk = true; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取套接字 |
| | | * @return |
| | | */ |
| | | public Socket getSocket() { |
| | | return socket; |
| | | } |
| | | |
| | | /** |
| | | * 设置套接字信息 |
| | | * @param socket 当前的值 |
| | | */ |
| | | public void setSocket(Socket socket) { |
| | | this.socket = socket; |
| | | } |
| | | |
| | | /** |
| | | * 获取设备唯一的DTU对象 |
| | | * @return |
| | | */ |
| | | public String getDTU() { |
| | | return DTU; |
| | | } |
| | | |
| | | /** |
| | | * 设置设备的唯一的DTU信息 |
| | | * @param DTU |
| | | */ |
| | | public void setDTU(String DTU) { |
| | | this.DTU = DTU; |
| | | } |
| | | |
| | | /** |
| | | * 获取当前的连接状态是否正常 |
| | | * @return |
| | | */ |
| | | public boolean getIsStatusOk() { |
| | | return this.isStatusOk; |
| | | } |
| | | |
| | | /** |
| | | * 设置当前的连接状态 |
| | | * @param isStatusOk |
| | | */ |
| | | public void setIsStatusOk(boolean isStatusOk) { |
| | | this.isStatusOk = isStatusOk; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | private Socket socket = null; // 网络套接字 |
| | | private String DTU = ""; // 唯一的标识 |
| | | private boolean isStatusOk = false; // 当前的网络状态 |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.net.session; |
| | | |
| | | import com.zy.gateway.core.base.SoftBasic; |
| | | import com.zy.gateway.core.net.HslProtocol; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.net.Socket; |
| | | import java.util.Date; |
| | | import java.util.concurrent.locks.Lock; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | |
| | | /** |
| | | * 网络会话信息 |
| | | */ |
| | | public class AppSession { |
| | | |
| | | /** |
| | | * 实例化一个构造方法 |
| | | */ |
| | | public AppSession() { |
| | | |
| | | ClientUniqueID = SoftBasic.GetUniqueStringByGuidAndRandom(); |
| | | HybirdLockSend = new ReentrantLock(); |
| | | HeartTime = new Date(); |
| | | BytesHead = new byte[HslProtocol.HeadByteLength]; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取IP地址信息 |
| | | * @return |
| | | */ |
| | | public String getIpAddress() { |
| | | return IpAddress; |
| | | } |
| | | |
| | | /** |
| | | * 设置IP地址信息 |
| | | * @param ipAddress |
| | | */ |
| | | void setIpAddress(String ipAddress) { |
| | | IpAddress = ipAddress; |
| | | } |
| | | |
| | | /** |
| | | * 获取此对象连接的远程客户端 |
| | | * @return 远程客户端 |
| | | */ |
| | | public InetAddress getIpEndPoint() { |
| | | return IpEndPoint; |
| | | } |
| | | |
| | | /** |
| | | * 设置此对象的远程连接客户端 |
| | | * @param ipEndPoint 远程客户端 |
| | | */ |
| | | public void setIpEndPoint(InetAddress ipEndPoint) { |
| | | IpEndPoint = ipEndPoint; |
| | | } |
| | | |
| | | /** |
| | | * 获取远程对象的别名 |
| | | * @return 别名 |
| | | */ |
| | | public String getLoginAlias() { |
| | | return LoginAlias; |
| | | } |
| | | |
| | | /** |
| | | * 设置远程对象的别名 |
| | | * @param loginAlias 别名 |
| | | */ |
| | | public void setLoginAlias(String loginAlias) { |
| | | LoginAlias = loginAlias; |
| | | } |
| | | |
| | | /** |
| | | * 获取当前的心跳时间 |
| | | * @return 心跳时间 |
| | | */ |
| | | public Date getHeartTime() { |
| | | return HeartTime; |
| | | } |
| | | |
| | | /** |
| | | * 设置当前的心跳时间 |
| | | * @param date 心跳时间 |
| | | */ |
| | | public void setHeartTime(Date date){ |
| | | this.HeartTime = date; |
| | | } |
| | | |
| | | /** |
| | | * 获取客户端的类型 |
| | | * @return 客户端类型 |
| | | */ |
| | | public String getClientType() { |
| | | return ClientType; |
| | | } |
| | | |
| | | /** |
| | | * 设置客户端的类型 |
| | | * @param clientType 客户端的类型 |
| | | */ |
| | | public void setClientType(String clientType) { |
| | | ClientType = clientType; |
| | | } |
| | | |
| | | /** |
| | | * 获取客户端的唯一的标识 |
| | | * @return |
| | | */ |
| | | public String getClientUniqueID() { |
| | | return ClientUniqueID; |
| | | } |
| | | |
| | | |
| | | private String IpAddress = null; |
| | | private InetAddress IpEndPoint = null; |
| | | private String LoginAlias = null; |
| | | private Date HeartTime = null; |
| | | private String ClientType = null; |
| | | private String ClientUniqueID = null; |
| | | private byte[] BytesHead = null; |
| | | private byte[] BytesContent = null; |
| | | private String KeyGroup = null; |
| | | private Socket WorkSocket = null; |
| | | private Lock HybirdLockSend = null; |
| | | |
| | | /** |
| | | * 获取头子节信息 |
| | | * @return 字节数组 |
| | | */ |
| | | public byte[] getBytesHead() { |
| | | return BytesHead; |
| | | } |
| | | |
| | | /** |
| | | * 设置头子节信息 |
| | | * @param bytesHead 头子节数组 |
| | | */ |
| | | public void setBytesHead(byte[] bytesHead) { |
| | | BytesHead = bytesHead; |
| | | } |
| | | |
| | | /** |
| | | * 获取内容字节 |
| | | * @return 字节数组 |
| | | */ |
| | | public byte[] getBytesContent() { |
| | | return BytesContent; |
| | | } |
| | | |
| | | /** |
| | | * 设置内容字节 |
| | | * @param bytesContent 字节数组 |
| | | */ |
| | | public void setBytesContent(byte[] bytesContent) { |
| | | BytesContent = bytesContent; |
| | | } |
| | | |
| | | /** |
| | | * 获取用于分类的关键字 |
| | | * @return 关键字 |
| | | */ |
| | | public String getKeyGroup() { |
| | | return KeyGroup; |
| | | } |
| | | |
| | | /** |
| | | * 设置用于分类的关键字 |
| | | * @param keyGroup 关键字 |
| | | */ |
| | | public void setKeyGroup(String keyGroup) { |
| | | KeyGroup = keyGroup; |
| | | } |
| | | |
| | | /** |
| | | * 获取网络套接字 |
| | | * @return socket对象 |
| | | */ |
| | | public Socket getWorkSocket() { |
| | | return WorkSocket; |
| | | } |
| | | |
| | | /** |
| | | * 设置网络套接字 |
| | | * @param workSocket socket对象 |
| | | */ |
| | | public void setWorkSocket(Socket workSocket) { |
| | | WorkSocket = workSocket; |
| | | } |
| | | |
| | | /** |
| | | * 获取同步锁 |
| | | * @return |
| | | */ |
| | | public Lock getHybirdLockSend() { |
| | | return HybirdLockSend; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 清除本次的接收内容 |
| | | */ |
| | | public void Clear() { |
| | | BytesHead = new byte[HslProtocol.HeadByteLength]; |
| | | BytesContent = null; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 返回表示当前对象的字符串,以IP,端口,客户端名称组成 |
| | | * @return 字符串数据 |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | if (LoginAlias.isEmpty()) { |
| | | return "[" + IpEndPoint.toString() + "]"; |
| | | } else { |
| | | return "[" + IpEndPoint + "] [" + LoginAlias + "]"; |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.net.siemens; |
| | | |
| | | import com.zy.gateway.core.StringResources; |
| | | import com.zy.gateway.core.base.SoftBasic; |
| | | import com.zy.gateway.core.domain.OperateResult; |
| | | import com.zy.gateway.core.domain.OperateResultExOne; |
| | | import com.zy.gateway.core.domain.OperateResultExThree; |
| | | import com.zy.gateway.core.domain.OperateResultExTwo; |
| | | import com.zy.gateway.core.domain.siemens.S7Message; |
| | | import com.zy.gateway.core.domain.siemens.SiemensPLCS; |
| | | import com.zy.gateway.core.net.NetworkDeviceBase; |
| | | import com.zy.gateway.core.transfer.ReverseBytesTransform; |
| | | import com.zy.gateway.core.utils.Utilities; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.net.Socket; |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * 西门子的数据交互类,采用s7协议实现 |
| | | */ |
| | | public class SiemensS7Net extends NetworkDeviceBase<S7Message, ReverseBytesTransform> { |
| | | |
| | | |
| | | /** |
| | | * 实例化一个西门子的S7协议的通讯对象 |
| | | * @param siemens 指定西门子的型号 |
| | | */ |
| | | public SiemensS7Net(SiemensPLCS siemens) { |
| | | Initialization(siemens, ""); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 实例化一个西门子的S7协议的通讯对象并指定Ip地址 |
| | | * @param siemens 指定西门子的型号 |
| | | * @param ipAddress Ip地址 |
| | | */ |
| | | public SiemensS7Net(SiemensPLCS siemens, String ipAddress) { |
| | | Initialization(siemens, ipAddress); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 初始化方法 |
| | | * @param siemens 西门子类型 |
| | | * @param ipAddress Ip地址 |
| | | */ |
| | | private void Initialization(SiemensPLCS siemens, String ipAddress) { |
| | | WordLength = 2; |
| | | setIpAddress(ipAddress); |
| | | setPort(102); |
| | | CurrentPlc = siemens; |
| | | |
| | | switch (siemens) { |
| | | case S1200: |
| | | plcHead1[21] = 0; |
| | | break; |
| | | case S300: |
| | | plcHead1[21] = 2; |
| | | break; |
| | | case S1500: |
| | | plcHead1[21] = 0; |
| | | break; |
| | | case S200Smart: { |
| | | plcHead1 = plcHead1_200smart; |
| | | plcHead2 = plcHead2_200smart; |
| | | break; |
| | | } |
| | | default: |
| | | plcHead1[18] = 0; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 在客户端连接上服务器后,所做的一些初始化操作 -> |
| | | * Two handshake actions required after connecting to the server |
| | | * @param socket 网络套接字 |
| | | * @return 返回连接结果 |
| | | */ |
| | | @Override |
| | | protected OperateResult InitializationOnConnect(Socket socket) { |
| | | // 第一层通信的初始化 |
| | | OperateResultExTwo<byte[], byte[]> read_first = ReadFromCoreServerBase(socket, plcHead1); |
| | | if (!read_first.IsSuccess) return read_first; |
| | | |
| | | // 第二层通信的初始化 |
| | | OperateResultExTwo<byte[], byte[]> read_second = ReadFromCoreServerBase(socket, plcHead2); |
| | | if (!read_second.IsSuccess) return read_second; |
| | | |
| | | // 返回成功的信号 |
| | | return OperateResult.CreateSuccessResult(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 从PLC读取订货号信息 |
| | | * @return |
| | | */ |
| | | public OperateResultExOne<String> ReadOrderNumber() { |
| | | OperateResultExOne<String> result = new OperateResultExOne<String>(); |
| | | OperateResultExOne<byte[]> read = ReadFromCoreServer(plcOrderNumber); |
| | | if (read.IsSuccess) { |
| | | if (read.Content.length > 100) { |
| | | result.IsSuccess = true; |
| | | result.Content = Utilities.getString(Arrays.copyOfRange(read.Content, 71, 20), "ASCII"); |
| | | } |
| | | } |
| | | |
| | | if (!result.IsSuccess) { |
| | | result.CopyErrorFromOther(read); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 从PLC读取数据,地址格式为I100,Q100,DB20.100,M100,T100,C100以字节为单位 |
| | | * @param address 起始地址,格式为I100,M100,Q100,DB20.100 |
| | | * @param length 读取的数量,以字节为单位 |
| | | * @return 结果对象 |
| | | */ |
| | | @Override |
| | | public OperateResultExOne<byte[]> Read(String address, short length) { |
| | | OperateResultExThree<Byte, Integer, Integer> addressResult = AnalysisAddress(address); |
| | | if (!addressResult.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult(addressResult); |
| | | |
| | | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| | | |
| | | short alreadyFinished = 0; |
| | | while (alreadyFinished < length) { |
| | | short readLength = (short) Math.min(length - alreadyFinished, 200); |
| | | |
| | | OperateResultExThree<Byte, Integer, Integer>[] list = new OperateResultExThree[1]; |
| | | list[0] = addressResult; |
| | | |
| | | OperateResultExOne<byte[]> read = Read(list, new short[]{readLength}); |
| | | if (read.IsSuccess) { |
| | | try { |
| | | outputStream.write(read.Content); |
| | | } catch (Exception ex) { |
| | | |
| | | } |
| | | } else { |
| | | return read; |
| | | } |
| | | |
| | | alreadyFinished += readLength; |
| | | addressResult.Content2 += readLength * 8; |
| | | } |
| | | |
| | | byte[] buffer = outputStream.toByteArray(); |
| | | |
| | | try { |
| | | outputStream.close(); |
| | | } catch (Exception ex) { |
| | | |
| | | } |
| | | |
| | | return OperateResultExOne.CreateSuccessResult(buffer); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从PLC读取数据,地址格式为I100,Q100,DB20.100,M100,以位为单位 |
| | | * @param address 起始地址,格式为I100,M100,Q100,DB20.100 |
| | | * @return 结果对象 |
| | | */ |
| | | private OperateResultExOne<byte[]> ReadBitFromPLC(String address) { |
| | | OperateResultExOne<byte[]> command = BuildBitReadCommand(address); |
| | | if (!command.IsSuccess) return command; |
| | | |
| | | OperateResultExOne<byte[]> read = ReadFromCoreServer(command.Content); |
| | | if (!read.IsSuccess) return read; |
| | | |
| | | |
| | | int receiveCount = 1; |
| | | if (read.Content.length >= 21 && read.Content[20] == 1) { |
| | | // 分析结果 |
| | | byte[] buffer = new byte[receiveCount]; |
| | | |
| | | if (22 < read.Content.length) { |
| | | if (read.Content[21] == (byte) 0xFF && read.Content[22] == 0x03) { |
| | | // 有数据 |
| | | buffer[0] = read.Content[25]; |
| | | } |
| | | } |
| | | |
| | | return OperateResultExOne.CreateSuccessResult(buffer); |
| | | } |
| | | else { |
| | | return new OperateResultExOne<byte[]>(read.ErrorCode, StringResources.Language.SiemensDataLengthCheckFailed()); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 一次性从PLC获取所有的数据,按照先后顺序返回一个统一的Buffer,需要按照顺序处理,两个数组长度必须一致 |
| | | * @param address 起始地址数组 |
| | | * @param length 数据长度数组 |
| | | * @return 结果数据对象 |
| | | */ |
| | | public OperateResultExOne<byte[]> Read(String[] address, short[] length) { |
| | | |
| | | OperateResultExThree<Byte, Integer, Integer>[] list = new OperateResultExThree[address.length]; |
| | | for (int i = 0; i < address.length; i++) { |
| | | OperateResultExThree<Byte, Integer, Integer> tmp = AnalysisAddress(address[i]); |
| | | if (!tmp.IsSuccess) return OperateResultExOne.CreateFailedResult(tmp); |
| | | |
| | | list[i] = tmp; |
| | | } |
| | | |
| | | return Read(list, length); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 读取真实的数据 |
| | | * @param address 起始地址 |
| | | * @param length 长度 |
| | | * @return 结果类对象 |
| | | */ |
| | | private OperateResultExOne<byte[]> Read(OperateResultExThree<Byte, Integer, Integer>[] address, short[] length) { |
| | | |
| | | OperateResultExOne<byte[]> command = BuildReadCommand(address, length); |
| | | if (!command.IsSuccess) return command; |
| | | |
| | | OperateResultExOne<byte[]> read = ReadFromCoreServer(command.Content); |
| | | if (!read.IsSuccess) return read; |
| | | |
| | | int receiveCount = 0; |
| | | for (int i = 0; i < length.length; i++) { |
| | | receiveCount += length[i]; |
| | | } |
| | | |
| | | if (read.Content.length >= 21 && read.Content[20] == length.length) { |
| | | // 分析结果 |
| | | byte[] buffer = new byte[receiveCount]; |
| | | int kk = 0; |
| | | int ll = 0; |
| | | for (int ii = 21; ii < read.Content.length; ii++) { |
| | | if ((ii + 1) < read.Content.length) { |
| | | if (read.Content[ii] == (byte) 0xFF && |
| | | read.Content[ii + 1] == 0x04) { |
| | | // 有数据 |
| | | System.arraycopy(read.Content, ii + 4, buffer, ll, length[kk]); |
| | | ii += length[kk] + 3; |
| | | ll += length[kk]; |
| | | kk++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return OperateResultExOne.CreateSuccessResult(buffer); |
| | | } else { |
| | | return new OperateResultExOne<byte[]>(read.ErrorCode,StringResources.Language.SiemensDataLengthCheckFailed()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取指定地址的bool数据 |
| | | * @param address 起始地址,格式为I100,M100,Q100,DB20.100 |
| | | * @return 结果类对象 |
| | | */ |
| | | public OperateResultExOne<Boolean> ReadBool(String address) { |
| | | return GetBoolResultFromBytes(ReadBitFromPLC(address)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 读取指定地址的byte数据 |
| | | * @param address 起始地址,格式为I100,M100,Q100,DB20.100 |
| | | * @return 结果类对象 |
| | | */ |
| | | public OperateResultExOne<Byte> ReadByte(String address) { |
| | | return GetByteResultFromBytes(Read(address, (short) 1)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 基础的写入数据的操作支持 |
| | | * @param entireValue 完整的字节数据 |
| | | * @return 写入结果 |
| | | */ |
| | | private OperateResult WriteBase(byte[] entireValue) { |
| | | OperateResultExOne<byte[]> write = ReadFromCoreServer(entireValue); |
| | | if (!write.IsSuccess) return write; |
| | | |
| | | if (write.Content[write.Content.length - 1] != (byte) 0xFF) { |
| | | return new OperateResult(write.Content[write.Content.length - 1], StringResources.Language.SiemensWriteError() + write.Content[write.Content.length - 1]); |
| | | } else { |
| | | return OperateResult.CreateSuccessResult(); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将数据写入到PLC数据,地址格式为I100,Q100,DB20.100,M100,以字节为单位 |
| | | * @param address 起始地址,格式为I100,M100,Q100,DB20.100 |
| | | * @param value 写入的数据,长度根据data的长度来指示 |
| | | * @return 写入结果 |
| | | */ |
| | | @Override |
| | | public OperateResult Write(String address, byte[] value) { |
| | | OperateResultExThree<Byte, Integer, Integer> analysis = AnalysisAddress( address ); |
| | | if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult( analysis ); |
| | | |
| | | int length = value.length; |
| | | int alreadyFinished = 0; |
| | | while (alreadyFinished < length) { |
| | | short writeLength = (short) Math.min( length - alreadyFinished, 200 ); |
| | | byte[] buffer = getByteTransform().TransByte( value, alreadyFinished, writeLength ); |
| | | |
| | | OperateResultExOne<byte[]> command = BuildWriteByteCommand( analysis, buffer ); |
| | | if (!command.IsSuccess) return command; |
| | | |
| | | OperateResult write = WriteBase( command.Content ); |
| | | if (!write.IsSuccess) return write; |
| | | |
| | | alreadyFinished += writeLength; |
| | | analysis.Content2 += writeLength * 8; |
| | | } |
| | | return OperateResult.CreateSuccessResult( ); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 写入PLC的一个位,例如"M100.6","I100.7","Q100.0","DB20.100.0",如果只写了"M100"默认为"M100.0 |
| | | * @param address 起始地址,格式为I100,M100,Q100,DB20.100 |
| | | * @param value 写入的数据,True或是False |
| | | * @return 写入结果 |
| | | */ |
| | | public OperateResult Write(String address, boolean value) { |
| | | // 生成指令 |
| | | OperateResultExOne<byte[]> command = BuildWriteBitCommand(address, value); |
| | | if (!command.IsSuccess) return command; |
| | | |
| | | return WriteBase(command.Content); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 向PLC中写入bool数组,返回值说明,比如你写入M100,那么data[0]对应M100.0 |
| | | * @param address 要写入的数据地址 |
| | | * @param values 要写入的实际数据,长度为8的倍数 |
| | | * @return 写入结果 |
| | | */ |
| | | public OperateResult Write(String address, boolean[] values) { |
| | | return Write(address, SoftBasic.BoolArrayToByte(values)); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 向PLC中写入byte数据,返回值说明 |
| | | * @param address 要写入的数据地址 |
| | | * @param value 要写入的实际数据 |
| | | * @return 写入结果 |
| | | */ |
| | | public OperateResult Write(String address, byte value) { |
| | | return Write(address, new byte[]{value}); |
| | | } |
| | | |
| | | |
| | | private byte[] plcHead1 = new byte[] |
| | | { |
| | | 0x03,0x00,0x00,0x16,0x11,(byte) 0xE0,0x00,0x00,0x00,0x01,0x00,(byte) 0xC0,0x01, |
| | | 0x0A,(byte) 0xC1,0x02,0x01,0x02,(byte) 0xC2,0x02,0x01,0x00 |
| | | }; |
| | | private byte[] plcHead2 = new byte[] |
| | | { |
| | | 0x03,0x00,0x00,0x19,0x02,(byte) 0xF0,(byte) 0x80,0x32,0x01,0x00,0x00,0x04,0x00,0x00,0x08,0x00,0x00, |
| | | (byte) 0xF0,0x00,0x00,0x01,0x00,0x01,0x01,(byte) 0xE0 |
| | | }; |
| | | private byte[] plcOrderNumber = new byte[] |
| | | { |
| | | 0x03,0x00,0x00,0x21,0x02,(byte) 0xF0,(byte) 0x80,0x32,0x07,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x08, |
| | | 0x00,0x01,0x12,0x04,0x11,0x44,0x01,0x00,(byte) 0xFF,0x09,0x00,0x04,0x00,0x11,0x00,0x00 |
| | | }; |
| | | private SiemensPLCS CurrentPlc = SiemensPLCS.S1200; |
| | | private byte[] plcHead1_200smart = new byte[] |
| | | { |
| | | 0x03,0x00,0x00,0x16,0x11,(byte) 0xE0,0x00,0x00,0x00,0x01,0x00,(byte) 0xC1,0x02,0x10,0x00,(byte) 0xC2, |
| | | 0x02,0x03,0x00,(byte) 0xC0,0x01,0x0A |
| | | }; |
| | | private byte[] plcHead2_200smart = new byte[] |
| | | { |
| | | 0x03,0x00,0x00,0x19,0x02,(byte) 0xF0,(byte) 0x80,0x32,0x01,0x00,0x00,(byte) 0xCC,(byte) 0xC1, |
| | | 0x00,0x08,0x00,0x00,(byte) 0xF0,0x00,0x00,0x01,0x00,0x01,0x03,(byte) 0xC0 |
| | | }; |
| | | |
| | | |
| | | /** |
| | | * 返回表示当前对象的字符串 |
| | | * @return 字符串信息 |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return "SiemensS7Net"; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 计算特殊的地址信息 |
| | | * @param address 字符串信息 |
| | | * @return 实际值 |
| | | */ |
| | | public static int CalculateAddressStarted(String address) { |
| | | if (address.indexOf('.') < 0) { |
| | | return Integer.parseInt(address) * 8; |
| | | } else { |
| | | String[] temp = address.split("\\."); |
| | | return Integer.parseInt(temp[0]) * 8 + Integer.parseInt(temp[1]); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 解析数据地址,解析出地址类型,起始地址,DB块的地址 |
| | | * @param address 数据地址 |
| | | * @return 解析出地址类型,起始地址,DB块的地址 |
| | | */ |
| | | public static OperateResultExThree<Byte, Integer, Integer> AnalysisAddress(String address) { |
| | | OperateResultExThree<Byte, Integer, Integer> result = new OperateResultExThree<Byte, Integer, Integer>(); |
| | | try { |
| | | result.Content3 = 0; |
| | | if (address.charAt(0) == 'I') { |
| | | result.Content1 = (byte) 0x81; |
| | | result.Content2 = CalculateAddressStarted(address.substring(1)); |
| | | } else if (address.charAt(0) == 'Q') { |
| | | result.Content1 = (byte) 0x82; |
| | | result.Content2 = CalculateAddressStarted(address.substring(1)); |
| | | } else if (address.charAt(0) == 'M') { |
| | | result.Content1 = (byte) 0x83; |
| | | result.Content2 = CalculateAddressStarted(address.substring(1)); |
| | | } else if (address.charAt(0) == 'D' || address.substring(0, 2).equals("DB")) { |
| | | result.Content1 = (byte) 0x84; |
| | | String[] adds = address.split("\\."); |
| | | if (address.charAt(1) == 'B') { |
| | | result.Content3 = Integer.parseInt(adds[0].substring(2)); |
| | | } else { |
| | | result.Content3 = Integer.parseInt(adds[0].substring(1)); |
| | | } |
| | | result.Content2 = CalculateAddressStarted(address.substring(address.indexOf('.') + 1)); |
| | | } else if (address.charAt(0) == 'T') { |
| | | result.Content1 = 0x1D; |
| | | result.Content2 = CalculateAddressStarted(address.substring(1)); |
| | | } else if (address.charAt(0) == 'C') { |
| | | result.Content1 = 0x1C; |
| | | result.Content2 = CalculateAddressStarted(address.substring(1)); |
| | | } |
| | | else if (address.charAt(0) == 'V') { |
| | | result.Content1 = (byte) 0x84; |
| | | result.Content3 = 1; |
| | | result.Content2 = CalculateAddressStarted( address.substring( 1 ) ); |
| | | } else { |
| | | return new OperateResultExThree<Byte, Integer, Integer>(StringResources.Language.NotSupportedDataType()); |
| | | } |
| | | } catch (Exception ex) { |
| | | result.Message = ex.getMessage(); |
| | | return result; |
| | | } |
| | | result.IsSuccess = true; |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * 生成一个读取字数据指令头的通用方法 -> |
| | | * A general method for generating a command header to read a Word data |
| | | * @param address 起始地址,例如M100,I0,Q0,DB2.100 -> Start address, such as M100,I0,Q0,DB2.100 |
| | | * @param length 读取数据长度 -> Read Data length |
| | | * @return 包含结果对象的报文 -> Message containing the result object |
| | | */ |
| | | public static OperateResultExOne<byte[]> BuildReadCommand( String address, short length ) |
| | | { |
| | | OperateResultExThree<Byte, Integer, Integer> analysis = AnalysisAddress( address ); |
| | | if (!analysis.IsSuccess) return OperateResultExOne.<byte[]>CreateFailedResult( analysis ); |
| | | |
| | | OperateResultExThree<Byte, Integer, Integer>[] addressList = new OperateResultExThree[1]; |
| | | addressList[0] = analysis; |
| | | short[] lengthList = new short[1]; |
| | | lengthList[0] = length; |
| | | |
| | | return BuildReadCommand( addressList, lengthList ); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 生成一个读取字数据指令头的通用方法 |
| | | * @param address 解析后的地址 |
| | | * @param length 每个地址的读取长度 |
| | | * @return 携带有命令字节 |
| | | */ |
| | | public static OperateResultExOne<byte[]> BuildReadCommand(OperateResultExThree<Byte, Integer, Integer>[] address, short[] length) { |
| | | if (address == null) throw new RuntimeException("address is null"); |
| | | if (length == null) throw new RuntimeException("count is null"); |
| | | if (address.length != length.length) throw new RuntimeException(StringResources.Language.TwoParametersLengthIsNotSame()); |
| | | if (length.length > 19) throw new RuntimeException(StringResources.Language.SiemensReadLengthCannotLargerThan19()); |
| | | |
| | | int readCount = length.length; |
| | | |
| | | byte[] _PLCCommand = new byte[19 + readCount * 12]; |
| | | |
| | | // ====================================================================================== |
| | | // Header |
| | | // 报文头 |
| | | _PLCCommand[0] = 0x03; |
| | | _PLCCommand[1] = 0x00; |
| | | // 长度 |
| | | _PLCCommand[2] = (byte) (_PLCCommand.length / 256); |
| | | _PLCCommand[3] = (byte) (_PLCCommand.length % 256); |
| | | // 固定 |
| | | _PLCCommand[4] = 0x02; |
| | | _PLCCommand[5] = (byte) 0xF0; |
| | | _PLCCommand[6] = (byte) 0x80; |
| | | // 协议标识 |
| | | _PLCCommand[7] = 0x32; |
| | | // 命令:发 |
| | | _PLCCommand[8] = 0x01; |
| | | // redundancy identification (reserved): 0x0000; |
| | | _PLCCommand[9] = 0x00; |
| | | _PLCCommand[10] = 0x00; |
| | | // protocol data unit reference; it’s increased by request event; |
| | | _PLCCommand[11] = 0x00; |
| | | _PLCCommand[12] = 0x01; |
| | | // 参数命令数据总长度 |
| | | _PLCCommand[13] = (byte) ((_PLCCommand.length - 17) / 256); |
| | | _PLCCommand[14] = (byte) ((_PLCCommand.length - 17) % 256); |
| | | |
| | | // 读取内部数据时为00,读取CPU型号为Data数据长度 |
| | | _PLCCommand[15] = 0x00; |
| | | _PLCCommand[16] = 0x00; |
| | | |
| | | |
| | | // ====================================================================================== |
| | | // Parameter |
| | | |
| | | // 读写指令,04读,05写 |
| | | _PLCCommand[17] = 0x04; |
| | | // 读取数据块个数 |
| | | _PLCCommand[18] = (byte) readCount; |
| | | |
| | | |
| | | for (int ii = 0; ii < readCount; ii++) { |
| | | //=========================================================================================== |
| | | // 指定有效值类型 |
| | | _PLCCommand[19 + ii * 12] = 0x12; |
| | | // 接下来本次地址访问长度 |
| | | _PLCCommand[20 + ii * 12] = 0x0A; |
| | | // 语法标记,ANY |
| | | _PLCCommand[21 + ii * 12] = 0x10; |
| | | // 按字为单位 |
| | | _PLCCommand[22 + ii * 12] = 0x02; |
| | | // 访问数据的个数 |
| | | _PLCCommand[23 + ii * 12] = (byte) (length[ii] / 256); |
| | | _PLCCommand[24 + ii * 12] = (byte) (length[ii] % 256); |
| | | // DB块编号,如果访问的是DB块的话 |
| | | _PLCCommand[25 + ii * 12] = (byte) (address[ii].Content3 / 256); |
| | | _PLCCommand[26 + ii * 12] = (byte) (address[ii].Content3 % 256); |
| | | // 访问数据类型 |
| | | _PLCCommand[27 + ii * 12] = address[ii].Content1; |
| | | // 偏移位置 |
| | | _PLCCommand[28 + ii * 12] = (byte) (address[ii].Content2 / 256 / 256 % 256); |
| | | _PLCCommand[29 + ii * 12] = (byte) (address[ii].Content2 / 256 % 256); |
| | | _PLCCommand[30 + ii * 12] = (byte) (address[ii].Content2 % 256); |
| | | } |
| | | |
| | | return OperateResultExOne.CreateSuccessResult(_PLCCommand); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 生成一个位读取数据指令头的通用方法 |
| | | * @param address 起始地址 |
| | | * @return 指令 |
| | | */ |
| | | public static OperateResultExOne<byte[]> BuildBitReadCommand(String address) { |
| | | byte[] _PLCCommand = new byte[31]; |
| | | // 报文头 |
| | | _PLCCommand[0] = 0x03; |
| | | _PLCCommand[1] = 0x00; |
| | | // 长度 |
| | | _PLCCommand[2] = (byte) (_PLCCommand.length / 256); |
| | | _PLCCommand[3] = (byte) (_PLCCommand.length % 256); |
| | | // 固定 |
| | | _PLCCommand[4] = 0x02; |
| | | _PLCCommand[5] = (byte) 0xF0; |
| | | _PLCCommand[6] = (byte) 0x80; |
| | | _PLCCommand[7] = 0x32; |
| | | // 命令:发 |
| | | _PLCCommand[8] = 0x01; |
| | | // 标识序列号 |
| | | _PLCCommand[9] = 0x00; |
| | | _PLCCommand[10] = 0x00; |
| | | _PLCCommand[11] = 0x00; |
| | | _PLCCommand[12] = 0x01; |
| | | // 命令数据总长度 |
| | | _PLCCommand[13] = (byte) ((_PLCCommand.length - 17) / 256); |
| | | _PLCCommand[14] = (byte) ((_PLCCommand.length - 17) % 256); |
| | | |
| | | _PLCCommand[15] = 0x00; |
| | | _PLCCommand[16] = 0x00; |
| | | |
| | | // 命令起始符 |
| | | _PLCCommand[17] = 0x04; |
| | | // 读取数据块个数 |
| | | _PLCCommand[18] = 0x01; |
| | | |
| | | |
| | | // 填充数据 |
| | | OperateResultExThree<Byte, Integer, Integer> analysis = AnalysisAddress(address); |
| | | if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult(analysis); |
| | | |
| | | //=========================================================================================== |
| | | // 读取地址的前缀 |
| | | _PLCCommand[19] = 0x12; |
| | | _PLCCommand[20] = 0x0A; |
| | | _PLCCommand[21] = 0x10; |
| | | // 读取的数据时位 |
| | | _PLCCommand[22] = 0x01; |
| | | // 访问数据的个数 |
| | | _PLCCommand[23] = 0x00; |
| | | _PLCCommand[24] = 0x01; |
| | | // DB块编号,如果访问的是DB块的话 |
| | | _PLCCommand[25] = (byte) (analysis.Content3 / 256); |
| | | _PLCCommand[26] = (byte) (analysis.Content3 % 256); |
| | | // 访问数据类型 |
| | | _PLCCommand[27] = analysis.Content1; |
| | | // 偏移位置 |
| | | _PLCCommand[28] = (byte) (analysis.Content2 / 256 / 256 % 256); |
| | | _PLCCommand[29] = (byte) (analysis.Content2 / 256 % 256); |
| | | _PLCCommand[30] = (byte) (analysis.Content2 % 256); |
| | | |
| | | return OperateResultExOne.CreateSuccessResult(_PLCCommand); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 生成一个写入字节数据的指令 -> Generate an instruction to write byte data |
| | | * @param address 起始地址,示例M100,I100,Q100,DB1.100 -> Start Address, example M100,I100,Q100,DB1.100 |
| | | * @param data 原始的字节数据 -> Raw byte data |
| | | * @return 包含结果对象的报文 -> Message containing the result object |
| | | */ |
| | | public static OperateResultExOne<byte[]> BuildWriteByteCommand( String address, byte[] data ) |
| | | { |
| | | if (data == null) data = new byte[0]; |
| | | |
| | | OperateResultExThree<Byte, Integer, Integer> analysis = AnalysisAddress( address ); |
| | | if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult( analysis ); |
| | | |
| | | return BuildWriteByteCommand( analysis, data ); |
| | | } |
| | | |
| | | /** |
| | | * 生成一个写入字节数据的指令 |
| | | * @param analysis 地址 |
| | | * @param data 数据 |
| | | * @return 指令 |
| | | */ |
| | | public static OperateResultExOne<byte[]> BuildWriteByteCommand(OperateResultExThree<Byte, Integer, Integer> analysis, byte[] data) { |
| | | if (data == null) data = new byte[0]; |
| | | |
| | | byte[] _PLCCommand = new byte[35 + data.length]; |
| | | _PLCCommand[0] = 0x03; |
| | | _PLCCommand[1] = 0x00; |
| | | // 长度 |
| | | _PLCCommand[2] = (byte) ((35 + data.length) / 256); |
| | | _PLCCommand[3] = (byte) ((35 + data.length) % 256); |
| | | // 固定 |
| | | _PLCCommand[4] = 0x02; |
| | | _PLCCommand[5] = (byte) 0xF0; |
| | | _PLCCommand[6] = (byte) 0x80; |
| | | _PLCCommand[7] = 0x32; |
| | | // 命令 发 |
| | | _PLCCommand[8] = 0x01; |
| | | // 标识序列号 |
| | | _PLCCommand[9] = 0x00; |
| | | _PLCCommand[10] = 0x00; |
| | | _PLCCommand[11] = 0x00; |
| | | _PLCCommand[12] = 0x01; |
| | | // 固定 |
| | | _PLCCommand[13] = 0x00; |
| | | _PLCCommand[14] = 0x0E; |
| | | // 写入长度+4 |
| | | _PLCCommand[15] = (byte) ((4 + data.length) / 256); |
| | | _PLCCommand[16] = (byte) ((4 + data.length) % 256); |
| | | // 读写指令 |
| | | _PLCCommand[17] = 0x05; |
| | | // 写入数据块个数 |
| | | _PLCCommand[18] = 0x01; |
| | | // 固定,返回数据长度 |
| | | _PLCCommand[19] = 0x12; |
| | | _PLCCommand[20] = 0x0A; |
| | | _PLCCommand[21] = 0x10; |
| | | // 写入方式,1是按位,2是按字 |
| | | _PLCCommand[22] = 0x02; |
| | | // 写入数据的个数 |
| | | _PLCCommand[23] = (byte) (data.length / 256); |
| | | _PLCCommand[24] = (byte) (data.length % 256); |
| | | // DB块编号,如果访问的是DB块的话 |
| | | _PLCCommand[25] = (byte) (analysis.Content3 / 256); |
| | | _PLCCommand[26] = (byte) (analysis.Content3 % 256); |
| | | // 写入数据的类型 |
| | | _PLCCommand[27] = analysis.Content1; |
| | | // 偏移位置 |
| | | _PLCCommand[28] = (byte) (analysis.Content2 / 256 / 256 % 256); |
| | | ; |
| | | _PLCCommand[29] = (byte) (analysis.Content2 / 256 % 256); |
| | | _PLCCommand[30] = (byte) (analysis.Content2 % 256); |
| | | // 按字写入 |
| | | _PLCCommand[31] = 0x00; |
| | | _PLCCommand[32] = 0x04; |
| | | // 按位计算的长度 |
| | | _PLCCommand[33] = (byte) (data.length * 8 / 256); |
| | | _PLCCommand[34] = (byte) (data.length * 8 % 256); |
| | | |
| | | System.arraycopy(data, 0, _PLCCommand, 35, data.length); |
| | | |
| | | return OperateResultExOne.CreateSuccessResult(_PLCCommand); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 生成一个写入位数据的指令 |
| | | * @param address 起始地址 |
| | | * @param data 数据 |
| | | * @return 指令 |
| | | */ |
| | | public static OperateResultExOne<byte[]> BuildWriteBitCommand(String address, boolean data) { |
| | | OperateResultExThree<Byte, Integer, Integer> analysis = AnalysisAddress(address); |
| | | if (!analysis.IsSuccess) return OperateResultExOne.CreateFailedResult(analysis); |
| | | |
| | | |
| | | byte[] buffer = new byte[1]; |
| | | buffer[0] = data ? (byte) 0x01 : (byte) 0x00; |
| | | |
| | | byte[] _PLCCommand = new byte[35 + buffer.length]; |
| | | _PLCCommand[0] = 0x03; |
| | | _PLCCommand[1] = 0x00; |
| | | // 长度 |
| | | _PLCCommand[2] = (byte) ((35 + buffer.length) / 256); |
| | | _PLCCommand[3] = (byte) ((35 + buffer.length) % 256); |
| | | // 固定 |
| | | _PLCCommand[4] = 0x02; |
| | | _PLCCommand[5] = (byte) 0xF0; |
| | | _PLCCommand[6] = (byte) 0x80; |
| | | _PLCCommand[7] = 0x32; |
| | | // 命令 发 |
| | | _PLCCommand[8] = 0x01; |
| | | // 标识序列号 |
| | | _PLCCommand[9] = 0x00; |
| | | _PLCCommand[10] = 0x00; |
| | | _PLCCommand[11] = 0x00; |
| | | _PLCCommand[12] = 0x01; |
| | | // 固定 |
| | | _PLCCommand[13] = 0x00; |
| | | _PLCCommand[14] = 0x0E; |
| | | // 写入长度+4 |
| | | _PLCCommand[15] = (byte) ((4 + buffer.length) / 256); |
| | | _PLCCommand[16] = (byte) ((4 + buffer.length) % 256); |
| | | // 命令起始符 |
| | | _PLCCommand[17] = 0x05; |
| | | // 写入数据块个数 |
| | | _PLCCommand[18] = 0x01; |
| | | _PLCCommand[19] = 0x12; |
| | | _PLCCommand[20] = 0x0A; |
| | | _PLCCommand[21] = 0x10; |
| | | // 写入方式,1是按位,2是按字 |
| | | _PLCCommand[22] = 0x01; |
| | | // 写入数据的个数 |
| | | _PLCCommand[23] = (byte) (buffer.length / 256); |
| | | _PLCCommand[24] = (byte) (buffer.length % 256); |
| | | // DB块编号,如果访问的是DB块的话 |
| | | _PLCCommand[25] = (byte) (analysis.Content3 / 256); |
| | | _PLCCommand[26] = (byte) (analysis.Content3 % 256); |
| | | // 写入数据的类型 |
| | | _PLCCommand[27] = analysis.Content1; |
| | | // 偏移位置 |
| | | _PLCCommand[28] = (byte) (analysis.Content2 / 256 / 256); |
| | | _PLCCommand[29] = (byte) (analysis.Content2 / 256); |
| | | _PLCCommand[30] = (byte) (analysis.Content2 % 256); |
| | | // 按位写入 |
| | | _PLCCommand[31] = 0x00; |
| | | _PLCCommand[32] = 0x03; |
| | | // 按位计算的长度 |
| | | _PLCCommand[33] = (byte) (buffer.length / 256); |
| | | _PLCCommand[34] = (byte) (buffer.length % 256); |
| | | |
| | | System.arraycopy(buffer, 0, _PLCCommand, 35, buffer.length); |
| | | |
| | | return OperateResultExOne.CreateSuccessResult(_PLCCommand); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.transfer; |
| | | |
| | | import com.zy.gateway.core.utils.Utilities; |
| | | |
| | | |
| | | /** |
| | | * 字节转换类的基类,提供了一些基础的转换方法 |
| | | */ |
| | | public class ByteTransformBase implements IByteTransform { |
| | | |
| | | /** |
| | | * 实例化一个对象 |
| | | */ |
| | | public ByteTransformBase(){ |
| | | this.dataFormat = DataFormat.DCBA; |
| | | } |
| | | |
| | | /** |
| | | * 从缓存中提取出bool结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return boolean值 |
| | | */ |
| | | public boolean TransBool(byte[] buffer, int index) { |
| | | return buffer[index] != 0x00; |
| | | } |
| | | |
| | | /** |
| | | * 缓存中提取byte结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return byte对象 |
| | | */ |
| | | public byte TransByte(byte[] buffer, int index) { |
| | | return buffer[index]; |
| | | } |
| | | |
| | | /** |
| | | * 从缓存中提取byte数组结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return byte数组 |
| | | */ |
| | | public byte[] TransByte(byte[] buffer, int index, int length) { |
| | | byte[] tmp = new byte[length]; |
| | | System.arraycopy(buffer, index, tmp, 0, length); |
| | | return tmp; |
| | | } |
| | | |
| | | /** |
| | | * 从缓存中提取short结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return short对象 |
| | | */ |
| | | public short TransInt16(byte[] buffer, int index) { |
| | | return Utilities.getShort(buffer, index); |
| | | } |
| | | |
| | | /** |
| | | * 从缓存中提取short结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return short数组对象 |
| | | */ |
| | | public short[] TransInt16(byte[] buffer, int index, int length) { |
| | | short[] tmp = new short[length]; |
| | | for (int i = 0; i < length; i++) { |
| | | tmp[i] = TransInt16(buffer, index + 2 * i); |
| | | } |
| | | return tmp; |
| | | } |
| | | |
| | | /** |
| | | * 从缓存中提取int结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return int对象 |
| | | */ |
| | | public int TransInt32(byte[] buffer, int index) { |
| | | return Utilities.getInt(ByteTransDataFormat4(buffer, index),0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取int数组结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return int数组对象 |
| | | */ |
| | | public int[] TransInt32(byte[] buffer, int index, int length) { |
| | | int[] tmp = new int[length]; |
| | | for (int i = 0; i < length; i++) { |
| | | tmp[i] = TransInt32(buffer, index + 4 * i); |
| | | } |
| | | return tmp; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取long结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return long对象 |
| | | */ |
| | | public long TransInt64(byte[] buffer, int index) { |
| | | return Utilities.getLong(ByteTransDataFormat8(buffer, index),0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取long数组结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return long数组对象 |
| | | */ |
| | | public long[] TransInt64(byte[] buffer, int index, int length) { |
| | | long[] tmp = new long[length]; |
| | | for (int i = 0; i < length; i++) { |
| | | tmp[i] = TransInt64(buffer, index + 8 * i); |
| | | } |
| | | return tmp; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取float结果 |
| | | * |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @return float对象 |
| | | */ |
| | | public float TransSingle(byte[] buffer, int index) { |
| | | return Utilities.getFloat(ByteTransDataFormat4(buffer, index),0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取float数组结果 |
| | | * |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return float数组对象 |
| | | */ |
| | | public float[] TransSingle(byte[] buffer, int index, int length) { |
| | | float[] tmp = new float[length]; |
| | | for (int i = 0; i < length; i++) { |
| | | tmp[i] = TransSingle(buffer, index + 4 * i); |
| | | } |
| | | return tmp; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取double结果 |
| | | * |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @return double对象 |
| | | */ |
| | | public double TransDouble(byte[] buffer, int index) { |
| | | return Utilities.getDouble(ByteTransDataFormat8(buffer, index),0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取double数组结果 |
| | | * |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return double数组 |
| | | */ |
| | | public double[] TransDouble(byte[] buffer, int index, int length) { |
| | | double[] tmp = new double[length]; |
| | | for (int i = 0; i < length; i++) { |
| | | tmp[i] = TransDouble(buffer, index + 8 * i); |
| | | } |
| | | return tmp; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取string结果,使用指定的编码 |
| | | * |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @param length byte数组长度 |
| | | * @param encoding 字符串的编码 |
| | | * @return string对象 |
| | | */ |
| | | public String TransString(byte[] buffer, int index, int length, String encoding) { |
| | | return Utilities.getString(TransByte(buffer, index, length), encoding); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * bool变量转化缓存数据 |
| | | * |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(boolean value) { |
| | | return TransByte(new boolean[]{value}); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * bool数组变量转化缓存数据 |
| | | * |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(boolean[] values) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | if (values[i]) buffer[i] = 0x01; |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * byte变量转化缓存数据 |
| | | * |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(byte value) { |
| | | return new byte[]{value}; |
| | | } |
| | | |
| | | /** |
| | | * short变量转化缓存数据 |
| | | * |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(short value) { |
| | | return TransByte(new short[]{value}); |
| | | } |
| | | |
| | | /** |
| | | * short数组变量转化缓存数据 |
| | | * |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(short[] values) { |
| | | if (values == null) return null; |
| | | byte[] buffer = new byte[values.length * 2]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | System.arraycopy(Utilities.getBytes(values[i]), 0, buffer, 2 * i, 2); |
| | | } |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * int变量转化缓存数据 |
| | | * |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(int value) { |
| | | return TransByte(new int[]{value}); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * int数组变量转化缓存数据 |
| | | * |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(int[] values) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 4]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | System.arraycopy(ByteTransDataFormat4(Utilities.getBytes(values[i])), 0, buffer, 4 * i, 4); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | /** |
| | | * long变量转化缓存数据 |
| | | * |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(long value) { |
| | | return TransByte(new long[]{value}); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * long数组变量转化缓存数据 |
| | | * |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(long[] values) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 8]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | System.arraycopy(ByteTransDataFormat8(Utilities.getBytes(values[i])), 0, buffer, 8 * i, 8); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * float变量转化缓存数据 |
| | | * |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(float value) { |
| | | return TransByte(new float[]{value}); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * float数组变量转化缓存数据 |
| | | * |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(float[] values) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 4]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | System.arraycopy(ByteTransDataFormat4(Utilities.getBytes(values[i])), 0, buffer, 4 * i, 4); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * double变量转化缓存数据 |
| | | * |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(double value) { |
| | | return TransByte(new double[]{value}); |
| | | } |
| | | |
| | | /** |
| | | * double数组变量转化缓存数据 |
| | | * |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(double[] values) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 8]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | System.arraycopy(ByteTransDataFormat8(Utilities.getBytes(values[i])), 0, buffer, 8 * i, 8); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | /** |
| | | * 使用指定的编码字符串转化缓存数据 |
| | | * |
| | | * @param value 等待转化的数据 |
| | | * @param encoding 字符串的编码方式 |
| | | * @return buffer数据 |
| | | */ |
| | | public byte[] TransByte(String value, String encoding) { |
| | | return Utilities.getBytes(value, encoding); |
| | | } |
| | | |
| | | |
| | | private DataFormat dataFormat = DataFormat.ABCD; |
| | | |
| | | /** |
| | | * 设置数据解析的格式,ABCD,BADC,CDAB,DCBA格式 |
| | | * |
| | | * @param dataFormat |
| | | */ |
| | | public void setDataFormat(DataFormat dataFormat) { |
| | | this.dataFormat = dataFormat; |
| | | } |
| | | |
| | | /** |
| | | * 获取数据解析的格式,默认ABCD,可选BADC,CDAB,DCBA格式 |
| | | * |
| | | * @return |
| | | */ |
| | | public DataFormat getDataFormat() { |
| | | return this.dataFormat; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 反转多字节的数据信息 |
| | | * |
| | | * @param value 数据字节 |
| | | * @param Index 起始索引,默认值为0 |
| | | * @return 实际字节信息 |
| | | */ |
| | | protected byte[] ByteTransDataFormat4(byte[] value, int Index) { |
| | | byte[] buffer = new byte[4]; |
| | | switch (dataFormat) { |
| | | case ABCD: { |
| | | buffer[0] = value[Index + 3]; |
| | | buffer[1] = value[Index + 2]; |
| | | buffer[2] = value[Index + 1]; |
| | | buffer[3] = value[Index + 0]; |
| | | break; |
| | | } |
| | | case BADC: { |
| | | buffer[0] = value[Index + 2]; |
| | | buffer[1] = value[Index + 3]; |
| | | buffer[2] = value[Index + 0]; |
| | | buffer[3] = value[Index + 1]; |
| | | break; |
| | | } |
| | | case CDAB: { |
| | | buffer[0] = value[Index + 1]; |
| | | buffer[1] = value[Index + 0]; |
| | | buffer[2] = value[Index + 3]; |
| | | buffer[3] = value[Index + 2]; |
| | | break; |
| | | } |
| | | case DCBA: { |
| | | buffer[0] = value[Index + 0]; |
| | | buffer[1] = value[Index + 1]; |
| | | buffer[2] = value[Index + 2]; |
| | | buffer[3] = value[Index + 3]; |
| | | break; |
| | | } |
| | | } |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 反转多字节的数据信息 |
| | | * |
| | | * @param value 数据字节 |
| | | * @return 实际字节信息 |
| | | */ |
| | | protected byte[] ByteTransDataFormat4(byte[] value) { |
| | | return ByteTransDataFormat4(value, 0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 反转多字节的数据信息 |
| | | * |
| | | * @param value 数据字节 |
| | | * @param Index 起始索引,默认值为0 |
| | | * @return 实际字节信息 |
| | | */ |
| | | protected byte[] ByteTransDataFormat8(byte[] value, int Index) { |
| | | byte[] buffer = new byte[8]; |
| | | switch (dataFormat) { |
| | | case ABCD: { |
| | | buffer[0] = value[Index + 7]; |
| | | buffer[1] = value[Index + 6]; |
| | | buffer[2] = value[Index + 5]; |
| | | buffer[3] = value[Index + 4]; |
| | | buffer[4] = value[Index + 3]; |
| | | buffer[5] = value[Index + 2]; |
| | | buffer[6] = value[Index + 1]; |
| | | buffer[7] = value[Index + 0]; |
| | | break; |
| | | } |
| | | case BADC: { |
| | | buffer[0] = value[Index + 6]; |
| | | buffer[1] = value[Index + 7]; |
| | | buffer[2] = value[Index + 4]; |
| | | buffer[3] = value[Index + 5]; |
| | | buffer[4] = value[Index + 2]; |
| | | buffer[5] = value[Index + 3]; |
| | | buffer[6] = value[Index + 0]; |
| | | buffer[7] = value[Index + 1]; |
| | | break; |
| | | } |
| | | |
| | | case CDAB: { |
| | | buffer[0] = value[Index + 1]; |
| | | buffer[1] = value[Index + 0]; |
| | | buffer[2] = value[Index + 3]; |
| | | buffer[3] = value[Index + 2]; |
| | | buffer[4] = value[Index + 5]; |
| | | buffer[5] = value[Index + 4]; |
| | | buffer[6] = value[Index + 7]; |
| | | buffer[7] = value[Index + 6]; |
| | | break; |
| | | } |
| | | case DCBA: { |
| | | buffer[0] = value[Index + 0]; |
| | | buffer[1] = value[Index + 1]; |
| | | buffer[2] = value[Index + 2]; |
| | | buffer[3] = value[Index + 3]; |
| | | buffer[4] = value[Index + 4]; |
| | | buffer[5] = value[Index + 5]; |
| | | buffer[6] = value[Index + 6]; |
| | | buffer[7] = value[Index + 7]; |
| | | break; |
| | | } |
| | | } |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 反转多字节的数据信息 |
| | | * |
| | | * @param value 数据字节 |
| | | * @return 实际字节信息 |
| | | */ |
| | | protected byte[] ByteTransDataFormat8(byte[] value) { |
| | | return ByteTransDataFormat8(value, 0); |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.transfer; |
| | | |
| | | import com.zy.gateway.core.base.SoftBasic; |
| | | import com.zy.gateway.core.domain.FunctionOperateExOne; |
| | | import com.zy.gateway.core.domain.OperateResultExOne; |
| | | |
| | | public class ByteTransformHelper { |
| | | |
| | | /** |
| | | * 结果转换操作的基础方法,需要支持类型,及转换的委托 |
| | | * @param result 数据源 |
| | | * @param translator 转换方式 |
| | | * @param <TResult> 结果类型 |
| | | * @return 最新的结果对象 |
| | | */ |
| | | public static <TResult> OperateResultExOne<TResult> GetResultFromBytes(OperateResultExOne<byte[]> result, FunctionOperateExOne<byte[], TResult> translator ) |
| | | { |
| | | OperateResultExOne<TResult> tmp = new OperateResultExOne<TResult>( ); |
| | | try |
| | | { |
| | | if (result.IsSuccess) |
| | | { |
| | | tmp.Content = translator.Action( result.Content ); |
| | | tmp.IsSuccess = result.IsSuccess; |
| | | } |
| | | tmp.CopyErrorFromOther( result ); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | tmp.Message = "数据转化失败,源数据:" + SoftBasic.ByteToHexString( result.Content ) + " 消息:" + ex.getMessage(); |
| | | } |
| | | |
| | | return tmp; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @param byteTransform 数据转换方法 |
| | | * @return 转化后的类型 |
| | | */ |
| | | public static OperateResultExOne<Boolean> GetBoolResultFromBytes( OperateResultExOne<byte[]> result, IByteTransform byteTransform ) |
| | | { |
| | | return GetResultFromBytes( result, new FunctionOperateExOne<byte[], Boolean>(){ |
| | | @Override |
| | | public Boolean Action(byte[] content) { |
| | | return byteTransform.TransBool( content, 0 ); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @param byteTransform 数据转换方法 |
| | | * @return 转化后的类型 |
| | | */ |
| | | public static OperateResultExOne<Byte> GetByteResultFromBytes( OperateResultExOne<byte[]> result, IByteTransform byteTransform ) |
| | | { |
| | | return GetResultFromBytes( result,new FunctionOperateExOne<byte[], Byte>(){ |
| | | @Override |
| | | public Byte Action(byte[] content) { |
| | | return byteTransform.TransByte( content, 0 ); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @param byteTransform 数据转换方法 |
| | | * @return 转化后的类型 |
| | | */ |
| | | public static OperateResultExOne<Short> GetInt16ResultFromBytes( OperateResultExOne<byte[]> result, IByteTransform byteTransform ) |
| | | { |
| | | return GetResultFromBytes( result,new FunctionOperateExOne<byte[], Short>(){ |
| | | @Override |
| | | public Short Action(byte[] content) { |
| | | return byteTransform.TransInt16( content, 0 ); |
| | | } |
| | | } ); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @param byteTransform 数据转换方法 |
| | | * @return 转化后的类型 |
| | | */ |
| | | public static OperateResultExOne<Integer> GetInt32ResultFromBytes( OperateResultExOne<byte[]> result, IByteTransform byteTransform ) |
| | | { |
| | | return GetResultFromBytes( result, new FunctionOperateExOne<byte[], Integer>(){ |
| | | @Override |
| | | public Integer Action(byte[] content) { |
| | | return byteTransform.TransInt32( content, 0 ); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @param byteTransform 数据转换方法 |
| | | * @return 转化后的类型 |
| | | */ |
| | | public static OperateResultExOne<Long> GetInt64ResultFromBytes( OperateResultExOne<byte[]> result, IByteTransform byteTransform ) |
| | | { |
| | | return GetResultFromBytes( result, new FunctionOperateExOne<byte[], Long>(){ |
| | | @Override |
| | | public Long Action(byte[] content) { |
| | | return byteTransform.TransInt64( content, 0 ); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @param byteTransform 数据转换方法 |
| | | * @return 转化后的类型 |
| | | */ |
| | | public static OperateResultExOne<Float> GetSingleResultFromBytes( OperateResultExOne<byte[]> result, IByteTransform byteTransform ) |
| | | { |
| | | return GetResultFromBytes( result, new FunctionOperateExOne<byte[], Float>(){ |
| | | @Override |
| | | public Float Action(byte[] content) { |
| | | return byteTransform.TransSingle( content, 0 ); |
| | | } |
| | | } ); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @param byteTransform 数据转换方法 |
| | | * @return 转化后的类型 |
| | | */ |
| | | public static OperateResultExOne<Double> GetDoubleResultFromBytes( OperateResultExOne<byte[]> result, IByteTransform byteTransform ) |
| | | { |
| | | return GetResultFromBytes( result, new FunctionOperateExOne<byte[], Double>(){ |
| | | @Override |
| | | public Double Action(byte[] content) { |
| | | return byteTransform.TransDouble( content, 0 ); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将指定的OperateResult类型转化 |
| | | * @param result 原始的类型 |
| | | * @param byteTransform 数据转换方法 |
| | | * @return 转化后的类型 |
| | | */ |
| | | public static OperateResultExOne<String> GetStringResultFromBytes( OperateResultExOne<byte[]> result, IByteTransform byteTransform ) |
| | | { |
| | | return GetResultFromBytes( result, new FunctionOperateExOne<byte[], String>(){ |
| | | @Override |
| | | public String Action(byte[] content) { |
| | | return byteTransform.TransString( content, 0, content.length, "US-ASCII" ); |
| | | } |
| | | } ); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.transfer; |
| | | |
| | | /** |
| | | * 应用于多字节数据的解析或是生成格式 |
| | | */ |
| | | public enum DataFormat { |
| | | /** |
| | | * 按照顺序的格式生成的解析规则 |
| | | */ |
| | | ABCD, |
| | | /** |
| | | * 按照单字反转 |
| | | */ |
| | | BADC, |
| | | /** |
| | | * 按照双字反转 |
| | | */ |
| | | CDAB, |
| | | /** |
| | | * 按照倒序排序 |
| | | */ |
| | | DCBA |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.transfer; |
| | | |
| | | public interface IByteTransform { |
| | | |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取出bool结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return boolean值 |
| | | */ |
| | | boolean TransBool(byte[] buffer, int index); |
| | | |
| | | /** |
| | | * 缓存中提取byte结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return byte对象 |
| | | */ |
| | | byte TransByte(byte[] buffer, int index); |
| | | |
| | | /** |
| | | * 从缓存中提取byte数组结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return |
| | | */ |
| | | byte[] TransByte(byte[] buffer, int index, int length); |
| | | |
| | | /** |
| | | * 从缓存中提取short结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return short对象 |
| | | */ |
| | | short TransInt16(byte[] buffer, int index); |
| | | |
| | | /** |
| | | * 从缓存中提取short结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return short数组对象 |
| | | */ |
| | | short[] TransInt16(byte[] buffer, int index, int length); |
| | | |
| | | /** |
| | | * 从缓存中提取int结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return int对象 |
| | | */ |
| | | int TransInt32(byte[] buffer, int index); |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取int数组结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return int数组对象 |
| | | */ |
| | | int[] TransInt32(byte[] buffer, int index, int length); |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取long结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return long对象 |
| | | */ |
| | | long TransInt64(byte[] buffer, int index); |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取long数组结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return long数组对象 |
| | | */ |
| | | long[] TransInt64(byte[] buffer, int index, int length); |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取float结果 |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @return float对象 |
| | | */ |
| | | float TransSingle(byte[] buffer, int index); |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取float数组结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return float数组对象 |
| | | */ |
| | | float[] TransSingle(byte[] buffer, int index, int length); |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取double结果 |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @return double对象 |
| | | */ |
| | | double TransDouble(byte[] buffer, int index); |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取double数组结果 |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @param length 读取的数组长度 |
| | | * @return double数组 |
| | | */ |
| | | double[] TransDouble(byte[] buffer, int index, int length); |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取string结果,使用指定的编码 |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @param length byte数组长度 |
| | | * @param encoding 字符串的编码 |
| | | * @return string对象 |
| | | */ |
| | | String TransString(byte[] buffer, int index, int length, String encoding); |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * bool变量转化缓存数据 |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(boolean value); |
| | | |
| | | |
| | | /** |
| | | * bool数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(boolean[] values); |
| | | |
| | | |
| | | /** |
| | | * byte变量转化缓存数据 |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(byte value); |
| | | |
| | | /** |
| | | * short变量转化缓存数据 |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(short value); |
| | | |
| | | /** |
| | | * short数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(short[] values); |
| | | |
| | | |
| | | /** |
| | | * int变量转化缓存数据 |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(int value); |
| | | |
| | | |
| | | /** |
| | | * int数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(int[] values); |
| | | |
| | | /** |
| | | * long变量转化缓存数据 |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(long value); |
| | | |
| | | |
| | | /** |
| | | * long数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return v |
| | | */ |
| | | byte[] TransByte(long[] values); |
| | | |
| | | |
| | | /** |
| | | * float变量转化缓存数据 |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(float value); |
| | | |
| | | |
| | | /** |
| | | * float数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(float[] values); |
| | | |
| | | |
| | | /** |
| | | * double变量转化缓存数据 |
| | | * @param value 等待转化的数据 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(double value); |
| | | |
| | | /** |
| | | * double数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(double[] values); |
| | | |
| | | /** |
| | | * 使用指定的编码字符串转化缓存数据 |
| | | * @param value 等待转化的数据 |
| | | * @param encoding 字符串的编码方式 |
| | | * @return buffer数据 |
| | | */ |
| | | byte[] TransByte(String value, String encoding); |
| | | |
| | | |
| | | /** |
| | | * 设置数据解析的格式,ABCD,BADC,CDAB,DCBA格式 |
| | | * @param dataFormat |
| | | */ |
| | | void setDataFormat(DataFormat dataFormat); |
| | | |
| | | /** |
| | | * 获取数据解析的格式,默认ABCD,可选BADC,CDAB,DCBA格式 |
| | | * @return |
| | | */ |
| | | DataFormat getDataFormat(); |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.transfer; |
| | | |
| | | import com.zy.gateway.core.utils.Utilities; |
| | | |
| | | /** |
| | | * 反转的字节变换类 |
| | | */ |
| | | public class ReverseBytesTransform extends ByteTransformBase |
| | | { |
| | | |
| | | /** |
| | | * 从缓存中提取short结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return short对象 |
| | | */ |
| | | @Override |
| | | public short TransInt16( byte[] buffer, int index ) { |
| | | byte[] tmp = new byte[2]; |
| | | tmp[0] = buffer[1 + index]; |
| | | tmp[1] = buffer[0 + index]; |
| | | return Utilities.getShort(tmp, 0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取int结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return int对象 |
| | | */ |
| | | @Override |
| | | public int TransInt32( byte[] buffer, int index ) { |
| | | byte[] tmp = new byte[4]; |
| | | tmp[0] = buffer[3 + index]; |
| | | tmp[1] = buffer[2 + index]; |
| | | tmp[2] = buffer[1 + index]; |
| | | tmp[3] = buffer[0 + index]; |
| | | return Utilities.getInt(ByteTransDataFormat4(tmp),0); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取long结果 |
| | | * @param buffer 缓存数据 |
| | | * @param index 索引位置 |
| | | * @return long对象 |
| | | */ |
| | | @Override |
| | | public long TransInt64( byte[] buffer, int index ) { |
| | | byte[] tmp = new byte[8]; |
| | | tmp[0] = buffer[7 + index]; |
| | | tmp[1] = buffer[6 + index]; |
| | | tmp[2] = buffer[5 + index]; |
| | | tmp[3] = buffer[4 + index]; |
| | | tmp[4] = buffer[3 + index]; |
| | | tmp[5] = buffer[2 + index]; |
| | | tmp[6] = buffer[1 + index]; |
| | | tmp[7] = buffer[0 + index]; |
| | | return Utilities.getLong(ByteTransDataFormat8(tmp), 0); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取float结果 |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @return float对象 |
| | | */ |
| | | @Override |
| | | public float TransSingle( byte[] buffer, int index ) { |
| | | byte[] tmp = new byte[4]; |
| | | tmp[0] = buffer[3 + index]; |
| | | tmp[1] = buffer[2 + index]; |
| | | tmp[2] = buffer[1 + index]; |
| | | tmp[3] = buffer[0 + index]; |
| | | return Utilities.getFloat(ByteTransDataFormat4(tmp), 0); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 从缓存中提取double结果 |
| | | * @param buffer 缓存对象 |
| | | * @param index 索引位置 |
| | | * @return double对象 |
| | | */ |
| | | @Override |
| | | public double TransDouble( byte[] buffer, int index ) { |
| | | byte[] tmp = new byte[8]; |
| | | tmp[0] = buffer[7 + index]; |
| | | tmp[1] = buffer[6 + index]; |
| | | tmp[2] = buffer[5 + index]; |
| | | tmp[3] = buffer[4 + index]; |
| | | tmp[4] = buffer[3 + index]; |
| | | tmp[5] = buffer[2 + index]; |
| | | tmp[6] = buffer[1 + index]; |
| | | tmp[7] = buffer[0 + index]; |
| | | return Utilities.getDouble(ByteTransDataFormat8(tmp), 0); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * short数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | @Override |
| | | public byte[] TransByte( short[] values ) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 2]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | byte[] tmp = Utilities.getBytes(values[i]); |
| | | Utilities.bytesReverse(tmp); |
| | | System.arraycopy(tmp, 0, buffer, 2 * i, tmp.length); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * int数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | @Override |
| | | public byte[] TransByte( int[] values ) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 4]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | byte[] tmp = Utilities.getBytes(values[i]); |
| | | Utilities.bytesReverse(tmp); |
| | | System.arraycopy(ByteTransDataFormat4(tmp), 0, buffer, 4 * i, tmp.length); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * long数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | @Override |
| | | public byte[] TransByte( long[] values ) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 8]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | byte[] tmp = Utilities.getBytes(values[i]); |
| | | Utilities.bytesReverse(tmp); |
| | | System.arraycopy(ByteTransDataFormat8(tmp), 0, buffer, 8 * i, tmp.length); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * float数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | @Override |
| | | public byte[] TransByte( float[] values ) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 4]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | byte[] tmp = Utilities.getBytes(values[i]); |
| | | Utilities.bytesReverse(tmp); |
| | | System.arraycopy(ByteTransDataFormat4(tmp), 0, buffer, 4 * i, tmp.length); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * double数组变量转化缓存数据 |
| | | * @param values 等待转化的数组 |
| | | * @return buffer数据 |
| | | */ |
| | | @Override |
| | | public byte[] TransByte( double[] values ) { |
| | | if (values == null) return null; |
| | | |
| | | byte[] buffer = new byte[values.length * 8]; |
| | | for (int i = 0; i < values.length; i++) { |
| | | byte[] tmp = Utilities.getBytes(values[i]); |
| | | Utilities.bytesReverse(tmp); |
| | | System.arraycopy(ByteTransDataFormat8(tmp), 0, buffer, 8 * i, tmp.length); |
| | | } |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.core.utils; |
| | | |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.DataOutputStream; |
| | | import java.io.IOException; |
| | | import java.nio.charset.Charset; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.UUID; |
| | | |
| | | |
| | | /** |
| | | * 一个工具类,为了支持和C#程序通信交互的转换工具类 |
| | | */ |
| | | public class Utilities { |
| | | |
| | | /** |
| | | * 将short数据类型转化成Byte数组 |
| | | * @param data short值 |
| | | * @return byte[]数组 |
| | | */ |
| | | public static byte[] getBytes(short data) { |
| | | byte[] bytes = new byte[2]; |
| | | bytes[0] = (byte) (data & 0xff); |
| | | bytes[1] = (byte) ((data & 0xff00) >> 8); |
| | | return bytes; |
| | | } |
| | | |
| | | /** |
| | | * 将int数据类型转化成Byte数组 |
| | | * @param data int值 |
| | | * @return byte[]数组 |
| | | */ |
| | | public static byte[] getBytes(int data) { |
| | | byte[] bytes = new byte[4]; |
| | | bytes[0] = (byte) (data & 0xff); |
| | | bytes[1] = (byte) ((data >> 8) & 0xff); |
| | | bytes[2] = (byte) ((data >> 16) & 0xff); |
| | | bytes[3] = (byte) ((data >> 24) & 0xff); |
| | | return bytes; |
| | | } |
| | | |
| | | /** |
| | | * 将long数据类型转化成Byte数组 |
| | | * @param data long值 |
| | | * @return byte[]数组 |
| | | */ |
| | | public static byte[] getBytes(long data) { |
| | | byte[] bytes = new byte[8]; |
| | | bytes[0] = (byte) (data & 0xff); |
| | | bytes[1] = (byte) ((data >> 8) & 0xff); |
| | | bytes[2] = (byte) ((data >> 16) & 0xff); |
| | | bytes[3] = (byte) ((data >> 24) & 0xff); |
| | | bytes[4] = (byte) ((data >> 32) & 0xff); |
| | | bytes[5] = (byte) ((data >> 40) & 0xff); |
| | | bytes[6] = (byte) ((data >> 48) & 0xff); |
| | | bytes[7] = (byte) ((data >> 56) & 0xff); |
| | | return bytes; |
| | | } |
| | | |
| | | /** |
| | | * 将float数据类型转化成Byte数组 |
| | | * @param data float值 |
| | | * @return byte[]数组 |
| | | */ |
| | | public static byte[] getBytes(float data) { |
| | | int intBits = Float.floatToIntBits(data); |
| | | return getBytes(intBits); |
| | | } |
| | | |
| | | /** |
| | | * 将double数据类型转化成Byte数组 |
| | | * @param data double值 |
| | | * @return byte[]数组 |
| | | */ |
| | | public static byte[] getBytes(double data) { |
| | | long intBits = Double.doubleToLongBits(data); |
| | | return getBytes(intBits); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字符串转换成byte[]数组 |
| | | * @param data 字符串值 |
| | | * @param charsetName 编码方式 |
| | | * @return 字节数组 |
| | | */ |
| | | public static byte[] getBytes(String data, String charsetName) { |
| | | Charset charset = Charset.forName(charsetName); |
| | | return data.getBytes(charset); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将int转换成一个字节的数据 |
| | | * @param num int数据 |
| | | * @return 一个字节的数据 |
| | | */ |
| | | public static byte int2OneByte(int num) { |
| | | return (byte) (num & 0x000000ff); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将一个有符号的byte转换成一个int数据对象 |
| | | * @param byteNum 有符号的字节对象 |
| | | * @return int数据类型 |
| | | */ |
| | | public static int oneByte2Int(byte byteNum) { |
| | | //针对正数的int |
| | | return byteNum > 0 ? byteNum : 256+ byteNum; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字节数组转换成short数据 |
| | | * @param bytes 字节数组 |
| | | * @param index 起始位置 |
| | | * @return short值 |
| | | */ |
| | | public static short getShort(byte[] bytes,int index) { |
| | | return (short) ((0xff & bytes[0 + index]) | (0xff00 & (bytes[1 + index] << 8))); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字节数组转换成int数据 |
| | | * @param bytes 字节数组 |
| | | * @param index 起始位置 |
| | | * @return int值 |
| | | */ |
| | | public static int getInt(byte[] bytes,int index) { |
| | | return (0xff & bytes[0 + index]) | |
| | | (0xff00 & (bytes[1 + index] << 8)) | |
| | | (0xff0000 & (bytes[2 + index] << 16)) | |
| | | (0xff000000 & (bytes[3 + index] << 24)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字节数组转换成long数据 |
| | | * @param bytes 字节数组 |
| | | * @param index 起始位置 |
| | | * @return long值 |
| | | */ |
| | | public static long getLong(byte[] bytes,int index) { |
| | | return (0xffL & (long) bytes[0 + index]) | |
| | | (0xff00L & ((long) bytes[1 + index] << 8)) | |
| | | (0xff0000L & ((long) bytes[2 + index] << 16)) | |
| | | (0xff000000L & ((long) bytes[3 + index] << 24)) | |
| | | (0xff00000000L & ((long) bytes[4 + index] << 32)) | |
| | | (0xff0000000000L & ((long) bytes[5 + index] << 40)) | |
| | | (0xff000000000000L & ((long) bytes[6 + index] << 48)) | |
| | | (0xff00000000000000L & ((long) bytes[7 + index] << 56)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字节数组转换成float数据 |
| | | * @param bytes 字节数组 |
| | | * @param index 起始位置 |
| | | * @return float值 |
| | | */ |
| | | public static float getFloat(byte[] bytes,int index) { |
| | | return Float.intBitsToFloat(getInt(bytes,index)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字节数组转换成double数据 |
| | | * @param bytes 字节数组 |
| | | * @param index 起始位置 |
| | | * @return double值 |
| | | */ |
| | | public static double getDouble(byte[] bytes,int index) { |
| | | long l = getLong(bytes, index); |
| | | System.out.println(l); |
| | | return Double.longBitsToDouble(l); |
| | | } |
| | | |
| | | /** |
| | | * 将字节数组转换成string数据 |
| | | * @param bytes 字节数组 |
| | | * @param charsetName 字符编码 |
| | | * @return string值 |
| | | */ |
| | | public static String getString(byte[] bytes, String charsetName) { |
| | | return new String(bytes, Charset.forName(charsetName)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字节数组转换成string数据 |
| | | * @param bytes 字节数组 |
| | | * @param index 起始位置 |
| | | * @param length 数据长度 |
| | | * @param charsetName 字符编码 |
| | | * @return string值 |
| | | */ |
| | | public static String getString(byte[] bytes,int index, int length, String charsetName) { |
| | | return new String(bytes,index,length,Charset.forName(charsetName)); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将一个byte[]数组转换成uuid对象 |
| | | * @param data 字节数组 |
| | | * @return uuid对象 |
| | | */ |
| | | public static UUID Byte2UUID(byte[] data) { |
| | | if (data.length != 16) { |
| | | throw new IllegalArgumentException("Invalid UUID byte[]"); |
| | | } |
| | | long msb = 0; |
| | | long lsb = 0; |
| | | for (int i = 0; i < 8; i++) |
| | | msb = (msb << 8) | (data[i] & 0xff); |
| | | for (int i = 8; i < 16; i++) |
| | | lsb = (lsb << 8) | (data[i] & 0xff); |
| | | |
| | | return new UUID(msb, lsb); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将一个uuid对象转化成byte[] |
| | | * @param uuid uuid对象 |
| | | * @return 字节数组 |
| | | */ |
| | | public static byte[] UUID2Byte(UUID uuid) { |
| | | ByteArrayOutputStream ba = new ByteArrayOutputStream(16); |
| | | DataOutputStream da = new DataOutputStream(ba); |
| | | try { |
| | | da.writeLong(uuid.getMostSignificantBits()); |
| | | da.writeLong(uuid.getLeastSignificantBits()); |
| | | ba.close(); |
| | | da.close(); |
| | | } |
| | | catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | byte[] buffer = ba.toByteArray(); |
| | | // 进行错位 |
| | | byte temp=buffer[0]; |
| | | buffer[0] = buffer[3]; |
| | | buffer[3] =temp; |
| | | temp=buffer[1]; |
| | | buffer[1]=buffer[2]; |
| | | buffer[2]=temp; |
| | | |
| | | temp = buffer[4]; |
| | | buffer[4]=buffer[5]; |
| | | buffer[5] =temp; |
| | | |
| | | temp = buffer[6]; |
| | | buffer[6]=buffer[7]; |
| | | buffer[7] =temp; |
| | | |
| | | return buffer; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 将字符串数据转换成字节数组,主要转换由C#的字符串的数据 |
| | | * @param str 字符串信息 |
| | | * @return 转化后的字节数组 |
| | | */ |
| | | public static byte[] string2Byte(String str) { |
| | | if (str == null) { |
| | | return null; |
| | | } |
| | | byte[] byteArray; |
| | | try { |
| | | byteArray = str.getBytes("unicode"); |
| | | } catch (Exception ex) { |
| | | byteArray = str.getBytes(); |
| | | } |
| | | |
| | | if (byteArray.length >= 2) { |
| | | if (byteArray[0] == -1 && byteArray[1] == -2) { |
| | | byte[] newArray = new byte[byteArray.length - 2]; |
| | | System.arraycopy(byteArray, 2, newArray, 0, newArray.length); |
| | | byteArray = newArray; |
| | | } else if (byteArray[0] == -2 && byteArray[1] == -1) { |
| | | for (int i = 0; i < byteArray.length; i++) { |
| | | byte temp = byteArray[i]; |
| | | byteArray[i] = byteArray[i + 1]; |
| | | byteArray[i + 1] = temp; |
| | | i++; |
| | | } |
| | | |
| | | |
| | | byte[] newArray = new byte[byteArray.length - 2]; |
| | | System.arraycopy(byteArray, 2, newArray, 0, newArray.length); |
| | | byteArray = newArray; |
| | | } |
| | | } |
| | | |
| | | return byteArray; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 将字节数组转换成字符串对象,主要转换由C#的字符串的数据 |
| | | * @param byteArray |
| | | * @return |
| | | */ |
| | | public static String byte2String(byte[] byteArray) { |
| | | if (byteArray == null) { |
| | | return null; |
| | | } |
| | | |
| | | for (int i = 0; i < byteArray.length; i++) { |
| | | byte temp = byteArray[i]; |
| | | byteArray[i] = byteArray[i + 1]; |
| | | byteArray[i + 1] = temp; |
| | | i++; |
| | | } |
| | | String str; |
| | | try { |
| | | str = new String(byteArray, "unicode"); |
| | | } catch (Exception ex) { |
| | | str = new String(byteArray); |
| | | } |
| | | return str; |
| | | } |
| | | |
| | | /** |
| | | * 将byte[]数组的数据进行翻转 |
| | | * @param reverse 等待反转的字符串 |
| | | */ |
| | | public static void bytesReverse(byte[] reverse) { |
| | | if (reverse != null) { |
| | | byte tmp = 0; |
| | | for (int i = 0; i < reverse.length / 2; i++) { |
| | | tmp = reverse[i]; |
| | | reverse[i] = reverse[reverse.length - 1 - i]; |
| | | reverse[reverse.length - 1 - i] = tmp; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', |
| | | '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
| | | |
| | | |
| | | /** |
| | | * 将字节数组转换成十六进制的字符串形式 |
| | | * @param bytes 原始的字节数组 |
| | | * @return 字符串信息 |
| | | */ |
| | | public static String bytes2HexString(byte[] bytes) { |
| | | char[] buf = new char[bytes.length * 2]; |
| | | int index = 0; |
| | | for(byte b : bytes) { // 利用位运算进行转换,可以看作方法一的变种 |
| | | buf[index++] = HEX_CHAR[b >>> 4 & 0xf]; |
| | | buf[index++] = HEX_CHAR[b & 0xf]; |
| | | } |
| | | |
| | | return new String(buf); |
| | | } |
| | | |
| | | /** |
| | | * 获取指定时间的指定格式的字符串 |
| | | * @param date 指定的时间 |
| | | * @param format 指定的格式 |
| | | * @return 最后字符串信息 |
| | | */ |
| | | public static String getStringDateShort(Date date,String format) { |
| | | SimpleDateFormat formatter = new SimpleDateFormat(format); |
| | | String dateString = formatter.format(date); |
| | | return dateString; |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.pipeline; |
| | | |
| | | |
| | | /** |
| | | * Created by vincent on 2020-06-04 |
| | | */ |
| | | public interface Bootstrap { |
| | | |
| | | void serverStart() throws Exception; |
| | | |
| | | void destroy(); |
| | | } |
New file |
| | |
| | | package com.zy.gateway.pipeline; |
| | | |
| | | import io.netty.channel.Channel; |
| | | import io.netty.channel.ChannelHandler; |
| | | import io.netty.channel.ChannelInitializer; |
| | | import io.netty.handler.timeout.IdleStateHandler; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | |
| | | /** |
| | | * handler管道 |
| | | * 控制所有netty handler流向 |
| | | * 待完成: 动态管理handler |
| | | * Created by vincent on 2019-04-02 |
| | | */ |
| | | @Component |
| | | @ChannelHandler.Sharable |
| | | public class HandlerInitializer extends ChannelInitializer<Channel> { |
| | | |
| | | @Autowired |
| | | private PipelineProperties pipelineProperties; |
| | | |
| | | /** |
| | | * Set some channel handlers on channel pipeline |
| | | */ |
| | | @Override |
| | | protected void initChannel(Channel channel) { |
| | | channel.pipeline() |
| | | // 心跳 |
| | | .addLast(new IdleStateHandler(pipelineProperties.getHeartSeconds(), 0, 0)) |
| | | // // 编码器 |
| | | // .addLast(protocolEncoder) |
| | | // // 解码器 |
| | | // .addLast(new ProtocolDecoder(4096)) |
| | | // // 校验码处理器 |
| | | // .addLast(validateHandler) |
| | | // // 认证处理器 |
| | | // .addLast(vehAuthHandler) |
| | | // // 业务处理器 |
| | | // .addLast(gbPackageServerHandler) |
| | | // // 通道保护器 |
| | | // .addLast(protectorHandler) |
| | | ; |
| | | |
| | | // Channel局部变量,相当于线程的ThreadLocal |
| | | // initAttrTrack(channel); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.zy.gateway.pipeline; |
| | | |
| | | import io.netty.bootstrap.ServerBootstrap; |
| | | import io.netty.buffer.PooledByteBufAllocator; |
| | | import io.netty.channel.Channel; |
| | | import io.netty.channel.ChannelOption; |
| | | import io.netty.channel.EventLoopGroup; |
| | | import io.netty.channel.nio.NioEventLoopGroup; |
| | | import io.netty.channel.socket.nio.NioServerSocketChannel; |
| | | import io.netty.util.ResourceLeakDetector; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | import javax.annotation.PreDestroy; |
| | | |
| | | /** |
| | | * 输送设备网关引导类 |
| | | * Created by vincent on 2020-06-04 |
| | | */ |
| | | @Component |
| | | public class PipelineBootstrap implements Bootstrap { |
| | | |
| | | private static Logger log = LoggerFactory.getLogger(PipelineBootstrap.class); |
| | | |
| | | private Channel channel; |
| | | private ServerBootstrap bootstrap; |
| | | private EventLoopGroup bossGroup; |
| | | private EventLoopGroup workerGroup; |
| | | @Autowired |
| | | private PipelineProperties pipelineProperties; |
| | | @Autowired |
| | | private HandlerInitializer handlerInitializer; |
| | | |
| | | { |
| | | bootstrap = new ServerBootstrap(); |
| | | bossGroup = new NioEventLoopGroup(1); |
| | | workerGroup = new NioEventLoopGroup(); |
| | | } |
| | | |
| | | /** |
| | | * 网关启动初始化 |
| | | */ |
| | | @Override |
| | | @PostConstruct |
| | | public void serverStart() throws Exception { |
| | | bootstrap.group(bossGroup, workerGroup) |
| | | .channel(NioServerSocketChannel.class) |
| | | .childHandler(handlerInitializer) |
| | | .option(ChannelOption.SO_BACKLOG, pipelineProperties.getBacklog()) |
| | | .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) |
| | | .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) |
| | | .childOption(ChannelOption.SO_KEEPALIVE, pipelineProperties.isKeepAlive()) |
| | | .childOption(ChannelOption.SO_SNDBUF, pipelineProperties.getSndbuf()) |
| | | .childOption(ChannelOption.SO_RCVBUF, pipelineProperties.getRcvbuf()); |
| | | |
| | | ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); |
| | | |
| | | log.info("TCP server started successfully, port:{}", pipelineProperties.getTcpPort()); |
| | | |
| | | channel = bootstrap.bind(pipelineProperties.getTcpPort()).sync().channel(); |
| | | } |
| | | |
| | | @Override |
| | | @PreDestroy |
| | | public void destroy() { |
| | | if (channel != null && channel.isActive()) { |
| | | channel.close(); |
| | | } |
| | | if (bossGroup != null) { |
| | | bossGroup.shutdownGracefully(); |
| | | } |
| | | if (workerGroup != null) { |
| | | workerGroup.shutdownGracefully(); |
| | | } |
| | | log.info("TCP server stopped successfully, port: {}", pipelineProperties.getTcpPort()); |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | package com.zy.gateway.pipeline; |
| | | |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.net.UnknownHostException; |
| | | |
| | | /** |
| | | * vc系统配置 |
| | | * Created by luxiaotao on 2018/10/15 |
| | | */ |
| | | @Configuration |
| | | @ConfigurationProperties(prefix = "pipeline") |
| | | public class PipelineProperties { |
| | | |
| | | public static String HOST_NAME; |
| | | |
| | | static { |
| | | try { |
| | | HOST_NAME = InetAddress.getLocalHost().getHostName(); |
| | | } catch (UnknownHostException e) { |
| | | System.err.println("find hostname err"); |
| | | } |
| | | } |
| | | |
| | | private int tcpPort; |
| | | |
| | | private int heartSeconds; |
| | | |
| | | private int backlog; |
| | | |
| | | private boolean keepAlive; |
| | | |
| | | private int sndbuf; |
| | | |
| | | private int rcvbuf; |
| | | |
| | | private boolean printPacLog; |
| | | |
| | | public int getTcpPort() { |
| | | return tcpPort; |
| | | } |
| | | |
| | | public void setTcpPort(int tcpPort) { |
| | | this.tcpPort = tcpPort; |
| | | } |
| | | |
| | | public int getHeartSeconds() { |
| | | return heartSeconds; |
| | | } |
| | | |
| | | public void setHeartSeconds(int heartSeconds) { |
| | | this.heartSeconds = heartSeconds; |
| | | } |
| | | |
| | | public int getBacklog() { |
| | | return backlog; |
| | | } |
| | | |
| | | public void setBacklog(int backlog) { |
| | | this.backlog = backlog; |
| | | } |
| | | |
| | | public boolean isKeepAlive() { |
| | | return keepAlive; |
| | | } |
| | | |
| | | public void setKeepAlive(boolean keepAlive) { |
| | | this.keepAlive = keepAlive; |
| | | } |
| | | |
| | | public int getSndbuf() { |
| | | return sndbuf; |
| | | } |
| | | |
| | | public void setSndbuf(int sndbuf) { |
| | | this.sndbuf = sndbuf; |
| | | } |
| | | |
| | | public int getRcvbuf() { |
| | | return rcvbuf; |
| | | } |
| | | |
| | | public void setRcvbuf(int rcvbuf) { |
| | | this.rcvbuf = rcvbuf; |
| | | } |
| | | |
| | | public boolean isPrintPacLog() { |
| | | return printPacLog; |
| | | } |
| | | |
| | | public void setPrintPacLog(final boolean printPacLog) { |
| | | this.printPacLog = printPacLog; |
| | | } |
| | | } |
New file |
| | |
| | | package com.zy.gateway.pipeline; |
| | | |
| | | import com.github.s7connector.api.S7Connector; |
| | | import com.github.s7connector.api.factory.S7ConnectorFactory; |
| | | |
| | | /** |
| | | * Created by vincent on 2020-06-04 |
| | | */ |
| | | public class Test { |
| | | |
| | | public static void main(String[] args) { |
| | | S7Connector connector = S7ConnectorFactory |
| | | .buildTCPConnector() |
| | | .withHost("10.0.0.220") |
| | | .withPort(90) |
| | | .withRack(0) //机架 |
| | | .withSlot(2) //optional |
| | | .build(); |
| | | |
| | | } |
| | | } |