From dc67660256af945cca4c7ab4063d1cfe7701eaaa Mon Sep 17 00:00:00 2001
From: caixiang <939387484@qq.com>
Date: Fri, 1 Apr 2022 18:18:50 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=20=E3=80=82S7=20=EF=BC=8C?=
=?UTF-8?q?=E4=B8=8D=E5=9C=A8=E5=BC=95=E7=94=A8=E7=AC=AC=E4=B8=89=E6=96=B9?=
=?UTF-8?q?=E4=BE=9D=E8=B5=96=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../dc/s7/controller/S7DemoController.java | 6 +
.../s7/my/s7connector/api/utils/ByteUtil.java | 328 ++++++++++++++++++
.../my/s7connector/api/utils/ByteUtils.java | 2 -
.../s7/my/s7connector/enmuc/PlcVarActual.java | 5 +-
.../s7/my/s7connector/service/S7Service.java | 86 ++++-
5 files changed, 421 insertions(+), 6 deletions(-)
create mode 100644 src/main/java/com/qgs/dc/s7/my/s7connector/api/utils/ByteUtil.java
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
+ );
+ }
}
}