diff --git a/src/main/java/com/qgs/dc/s7/controller/S7DemoController.java b/src/main/java/com/qgs/dc/s7/controller/S7DemoController.java index c484d22..1d06a2c 100644 --- a/src/main/java/com/qgs/dc/s7/controller/S7DemoController.java +++ b/src/main/java/com/qgs/dc/s7/controller/S7DemoController.java @@ -88,6 +88,12 @@ public class S7DemoController { return R.ok().put("l",(l1-l)).put("c",(c2-c1)); } + @PostMapping("/testFor1200") + public R testFor1200() throws UnsupportedEncodingException, ParseException { + Object subs = s7Service.read(PlcVarActual.INT1200, S7Client.S7_1200); + + return R.ok(); + } //demo3 @PostMapping("/writeTest") diff --git a/src/main/java/com/qgs/dc/s7/my/s7connector/api/utils/ByteUtil.java b/src/main/java/com/qgs/dc/s7/my/s7connector/api/utils/ByteUtil.java new file mode 100644 index 0000000..d7daf33 --- /dev/null +++ b/src/main/java/com/qgs/dc/s7/my/s7connector/api/utils/ByteUtil.java @@ -0,0 +1,328 @@ +package com.qgs.dc.s7.my.s7connector.api.utils; + +import java.nio.ByteOrder; + +/** + * @Desc: "" + * @Author: caixiang + * @DATE: 2022/4/1 17:32 + */ +//对数字和字节进行转换。 假设数据存储是以大端模式存储的: +// byte: 字节类型 占8位二进制 00000000 +// char: 字符类型 占2个字节 16位二进制 byte[0] byte[1] +// int : 整数类型 占4个字节 32位二进制 byte[0] byte[1] byte[2] byte[3] +// long: 长整数类型 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] +// long: 长整数类型 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] +// float: 浮点数(小数) 占4个字节 32位二进制 byte[0] byte[1] byte[2] byte[3] +// double: 双精度浮点数(小数) 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4]byte[5] byte[6] byte[7] + +public class ByteUtil { + + /** + * int转byte + * + * @param intValue int值 + * @return byte值 + */ + public static byte intToByte(int intValue) { + return (byte) intValue; + } + + /** + * byte转无符号int + * + * @param byteValue byte值 + * @return 无符号int值 + * @since 3.2.0 + */ + public static int byteToUnsignedInt(byte byteValue) { + // Java 总是把 byte 当做有符处理;我们可以通过将其和 0xFF 进行二进制与得到它的无符值 + return byteValue & 0xFF; + } + + /** + * byte数组转short
+ * 默认以小端序转换 + * + * @param bytes byte数组 + * @return short值 + */ + public static short bytesToShort(byte[] bytes) { + return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte数组转short
+ * 自定义端序 + * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return short值 + */ + public static short bytesToShort(byte[] bytes, ByteOrder byteOrder) { + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + //小端模式,数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中 + return (short) (bytes[0] & 0xff | (bytes[1] & 0xff) << Byte.SIZE); + } else { + return (short) (bytes[1] & 0xff | (bytes[0] & 0xff) << Byte.SIZE); + } + } + + /** + * short转byte数组
+ * 默认以小端序转换 + * + * @param shortValue short值 + * @return byte数组 + */ + public static byte[] shortToBytes(short shortValue) { + return shortToBytes(shortValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * short转byte数组
+ * 自定义端序 + * + * @param shortValue short值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] shortToBytes(short shortValue, ByteOrder byteOrder) { + byte[] b = new byte[Short.BYTES]; + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + b[0] = (byte) (shortValue & 0xff); + b[1] = (byte) ((shortValue >> Byte.SIZE) & 0xff); + } else { + b[1] = (byte) (shortValue & 0xff); + b[0] = (byte) ((shortValue >> Byte.SIZE) & 0xff); + } + return b; + } + + /** + * byte[]转int值
+ * 默认以小端序转换 + * + * @param bytes byte数组 + * @return int值 + */ + public static int bytesToInt(byte[] bytes) { + return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte[]转int值
+ * 自定义端序 + * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return int值 + */ + public static int bytesToInt(byte[] bytes, ByteOrder byteOrder) { + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + return bytes[0] & 0xFF | // + (bytes[1] & 0xFF) << 8 | // + (bytes[2] & 0xFF) << 16 | // + (bytes[3] & 0xFF) << 24; // + } else { + return bytes[3] & 0xFF | // + (bytes[2] & 0xFF) << 8 | // + (bytes[1] & 0xFF) << 16 | // + (bytes[0] & 0xFF) << 24; // + } + + } + + /** + * int转byte数组
+ * 默认以小端序转换 + * + * @param intValue int值 + * @return byte数组 + */ + public static byte[] intToBytes(int intValue) { + return intToBytes(intValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * int转byte数组
+ * 自定义端序 + * + * @param intValue int值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] intToBytes(int intValue, ByteOrder byteOrder) { + + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + return new byte[]{ // + (byte) (intValue & 0xFF), // + (byte) ((intValue >> 8) & 0xFF), // + (byte) ((intValue >> 16) & 0xFF), // + (byte) ((intValue >> 24) & 0xFF) // + }; + + } else { + return new byte[]{ // + (byte) ((intValue >> 24) & 0xFF), // + (byte) ((intValue >> 16) & 0xFF), // + (byte) ((intValue >> 8) & 0xFF), // + (byte) (intValue & 0xFF) // + }; + } + + } + + /** + * long转byte数组
+ * 默认以小端序转换
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param longValue long值 + * @return byte数组 + */ + public static byte[] longToBytes(long longValue) { + return longToBytes(longValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * long转byte数组
+ * 自定义端序
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param longValue long值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] longToBytes(long longValue, ByteOrder byteOrder) { + byte[] result = new byte[Long.BYTES]; + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + for (int i = 0; i < result.length; i++) { + result[i] = (byte) (longValue & 0xFF); + longValue >>= Byte.SIZE; + } + } else { + for (int i = (result.length - 1); i >= 0; i--) { + result[i] = (byte) (longValue & 0xFF); + longValue >>= Byte.SIZE; + } + } + return result; + } + + /** + * byte数组转long
+ * 默认以小端序转换
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param bytes byte数组 + * @return long值 + */ + public static long bytesToLong(byte[] bytes) { + return bytesToLong(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte数组转long
+ * 自定义端序
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return long值 + */ + public static long bytesToLong(byte[] bytes, ByteOrder byteOrder) { + long values = 0; + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + for (int i = (Long.BYTES - 1); i >= 0; i--) { + values <<= Byte.SIZE; + values |= (bytes[i] & 0xff); + } + } else { + for (int i = 0; i < Long.BYTES; i++) { + values <<= Byte.SIZE; + values |= (bytes[i] & 0xff); + } + } + + return values; + } + + /** + * double转byte数组
+ * 默认以小端序转换
+ * + * @param doubleValue double值 + * @return byte数组 + */ + public static byte[] doubleToBytes(double doubleValue) { + return doubleToBytes(doubleValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * double转byte数组
+ * 自定义端序
+ * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param doubleValue double值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] doubleToBytes(double doubleValue, ByteOrder byteOrder) { + return longToBytes(Double.doubleToLongBits(doubleValue), byteOrder); + } + + /** + * byte数组转Double
+ * 默认以小端序转换
+ * + * @param bytes byte数组 + * @return long值 + */ + public static double bytesToDouble(byte[] bytes) { + return bytesToDouble(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte数组转double
+ * 自定义端序
+ * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return long值 + */ + public static double bytesToDouble(byte[] bytes, ByteOrder byteOrder) { + return Double.longBitsToDouble(bytesToLong(bytes, byteOrder)); + } + + /** + * 将{@link Number}转换为 + * + * @param number 数字 + * @return bytes + */ + public static byte[] numberToBytes(Number number) { + return numberToBytes(number, ByteOrder.LITTLE_ENDIAN); + } + + /** + * 将{@link Number}转换为 + * + * @param number 数字 + * @param byteOrder 端序 + * @return bytes + */ + public static byte[] numberToBytes(Number number, ByteOrder byteOrder) { + if (number instanceof Double) { + return doubleToBytes((Double) number, byteOrder); + } else if (number instanceof Long) { + return longToBytes((Long) number, byteOrder); + } else if (number instanceof Integer) { + return intToBytes((Integer) number, byteOrder); + } else if (number instanceof Short) { + return shortToBytes((Short) number, byteOrder); + } else { + return doubleToBytes(number.doubleValue(), byteOrder); + } + } +} diff --git a/src/main/java/com/qgs/dc/s7/my/s7connector/api/utils/ByteUtils.java b/src/main/java/com/qgs/dc/s7/my/s7connector/api/utils/ByteUtils.java index b8fb1ab..7819017 100644 --- a/src/main/java/com/qgs/dc/s7/my/s7connector/api/utils/ByteUtils.java +++ b/src/main/java/com/qgs/dc/s7/my/s7connector/api/utils/ByteUtils.java @@ -6,8 +6,6 @@ package com.qgs.dc.s7.my.s7connector.api.utils; * @DATE: 2021/12/16 9:08 */ -import cn.hutool.core.util.ByteUtil; - import java.io.UnsupportedEncodingException; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/com/qgs/dc/s7/my/s7connector/enmuc/PlcVarActual.java b/src/main/java/com/qgs/dc/s7/my/s7connector/enmuc/PlcVarActual.java index e041453..c14511c 100644 --- a/src/main/java/com/qgs/dc/s7/my/s7connector/enmuc/PlcVarActual.java +++ b/src/main/java/com/qgs/dc/s7/my/s7connector/enmuc/PlcVarActual.java @@ -21,12 +21,13 @@ public enum PlcVarActual { DTL("DTL",PlcVar.DTL,1,DaveArea.DB,3,44,0), STRING1("STRING",PlcVar.STRING,1,DaveArea.DB,3,62,0,20), SUBID0("SUBID0",PlcVar.STRING,1,DaveArea.DB,3,3270,0), + INT1200("INT1200",PlcVar.INT,1,DaveArea.DB,1,2,0), //数组变量 CharArrays("CharArrays",PlcVar.CHAR_Array,2,DaveArea.DB,3,834,0), BooleanArrays("BooleanArrays",PlcVar.BOOL_Array,2,DaveArea.DB,3,830,0), - SubIdArrays("SubIdArrays",PlcVar.STRING_Array,60,DaveArea.DB,3,3270,0,18) - + SubIdArrays("SubIdArrays",PlcVar.STRING_Array,60,DaveArea.DB,3,3270,0,18), + SubIdArrays1200("SubIdArrays1200",PlcVar.STRING_Array,60,DaveArea.DB,1,20,0,18) diff --git a/src/main/java/com/qgs/dc/s7/my/s7connector/service/S7Service.java b/src/main/java/com/qgs/dc/s7/my/s7connector/service/S7Service.java index c161df6..ef7d1da 100644 --- a/src/main/java/com/qgs/dc/s7/my/s7connector/service/S7Service.java +++ b/src/main/java/com/qgs/dc/s7/my/s7connector/service/S7Service.java @@ -115,6 +115,56 @@ public class S7Service { return plcVarActual.getType().toObject(read); } } + public Object read(DaveArea area, Integer areaNumber, Integer byteOffset, Integer bitOffset, Integer length, Integer strSizes, PlcVar type,S7Client s7Client) throws UnsupportedEncodingException, ParseException { + S7Connector connector = s7Client.getConnector(); + //String 类型比较特殊。 String[] 也是同理,Sring数组里面的子项 也是有两个字节的 readBytes。 + if(type.equals(PlcVar.STRING)){ + Integer readBytes = 2; + byte[] read = connector.read( + area, + areaNumber, + readBytes, + byteOffset, + bitOffset, + type.getTransportSize() + ); + + Integer allLength = Integer.valueOf(read[1])+2; + byte[] readF = connector.read( + area, + areaNumber, + allLength, + byteOffset, + bitOffset, + type.getTransportSize() + ); + return type.toObject(readF); + }else if(type.equals(PlcVar.STRING_Array)){ + Integer arrayLength = length; + Integer strSize = strSizes; + + byte[] read = connector.read( + area, + areaNumber, + arrayLength*(strSize+2), + byteOffset, + bitOffset, + type.getTransportSize() + ); + return ByteUtils.toStrArray(read, arrayLength, strSize); + }else { + Integer readBytes = type.getTransportSize().getSizeInBytes() * length; + byte[] read = connector.read( + area, + areaNumber, + readBytes, + byteOffset, + bitOffset, + type.getTransportSize() + ); + return type.toObject(read); + } + } /** * @@ -194,9 +244,41 @@ public class S7Service { plcVarActual.getType() ); } + } + public void write(DaveArea area, Integer areaNumber, Integer byteOffset, Integer bitOffset,Integer strSize, PlcVar type, Object newValue, S7Client s7Client){ + S7Connector connector = s7Client.getConnector(); - - + //String 类型比较特殊。 String[] 也是同理,Sring数组里面的子项 也是有两个字节的 readBytes。 + if(type.equals(PlcVar.STRING)){ + connector.write( + area, + areaNumber, + byteOffset, + bitOffset, + ByteUtils.strToBytes(newValue.toString(), strSize), + type + ); + }else if(type.equals(PlcVar.STRING_Array)){ + //todo here 检查 read write service + connector.write( + area, + areaNumber, + byteOffset, + bitOffset, + ByteUtils.strArrayToBytes((String[])newValue, strSize), + type + ); + }else { + byte[] bytes = type.toBytes(newValue); + connector.write( + area, + areaNumber, + byteOffset, + bitOffset, + bytes, + type + ); + } } }