From 626409626c93f74a001edcb048661cbf6dde91fc Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Thu, 5 Mar 2026 17:16:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20plcs7=E5=8D=8F=E8=AE=AE=EF=BC=88?= =?UTF-8?q?=E6=9C=AA=E6=B5=8B=E8=AF=95=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nl-iot/pom.xml | 7 ++ .../plcs7/PlcS7ProtocolDriverImpl.java | 79 ++++++++++++++++++- nl-web-app/src/test/java/org/nl/ApiTest.java | 74 +++++++++++++++++ 3 files changed, 158 insertions(+), 2 deletions(-) diff --git a/nl-iot/pom.xml b/nl-iot/pom.xml index 8456bb6..5c86aa9 100644 --- a/nl-iot/pom.xml +++ b/nl-iot/pom.xml @@ -23,6 +23,13 @@ org.nl nl-common + + + + org.eclipse.milo + sdk-client + 0.6.16 + \ No newline at end of file diff --git a/nl-iot/src/main/java/org/nl/iot/core/driver/protocol/plcs7/PlcS7ProtocolDriverImpl.java b/nl-iot/src/main/java/org/nl/iot/core/driver/protocol/plcs7/PlcS7ProtocolDriverImpl.java index 82c60c0..1fb39fb 100644 --- a/nl-iot/src/main/java/org/nl/iot/core/driver/protocol/plcs7/PlcS7ProtocolDriverImpl.java +++ b/nl-iot/src/main/java/org/nl/iot/core/driver/protocol/plcs7/PlcS7ProtocolDriverImpl.java @@ -1,5 +1,6 @@ package org.nl.iot.core.driver.protocol.plcs7; +import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,6 +11,7 @@ import org.nl.common.exception.CommonException; import org.nl.iot.core.driver.bo.AttributeBO; import org.nl.iot.core.driver.entity.RValue; import org.nl.iot.core.driver.entity.WValue; +import org.nl.iot.core.driver.enums.AttributeTypeFlagEnum; import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.PlcS7PointVariable; import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.api.S7Connector; import org.nl.iot.core.driver.protocol.plcs7.com.github.s7.api.S7Serializer; @@ -39,6 +41,8 @@ public class PlcS7ProtocolDriverImpl implements DriverCustomService { * 仅供参考 */ private Map connectMap; + + @PostConstruct @Override public void initial() { connectMap = new ConcurrentHashMap<>(16); @@ -81,9 +85,80 @@ public class PlcS7ProtocolDriverImpl implements DriverCustomService { @Override public Boolean write(Map driverConfig, Map pointConfig, IotConnect device, IotConfig point, WValue wValue) { - return null; - } + log.debug("Plc S7 Write, device: {}, value: {}", device, wValue); + MyS7Connector myS7Connector = getS7Connector(String.valueOf(device.getId()), driverConfig); + myS7Connector.lock.writeLock().lock(); + S7Serializer serializer = S7SerializerFactory.buildSerializer(myS7Connector.getConnector()); + PlcS7PointVariable plcs7PointVariable = getPointVariable(pointConfig, wValue.getType()); + try { + store(serializer, plcs7PointVariable, wValue.getType(), wValue.getValue()); + return true; + } catch (Exception e) { + log.error("Plc S7 Write Error: {}", e.getMessage()); + return false; + } finally { + myS7Connector.lock.writeLock().unlock(); + } + } + /** + * 向 PLC S7 写入数据 + *

+ * 该方法用于将指定类型的数据写入到 PLC S7 的指定点位。 + * 1. 根据类型字符串获取对应的 {@link AttributeTypeFlagEnum} 枚举值。 + * 2. 如果类型不支持, 抛出 {@link UnSupportException} 异常。 + * 3. 根据类型将字符串值转换为相应的 Java 类型。 + * 4. 使用 {@link S7Serializer} 将数据写入到 PLC S7 的指定数据块和字节偏移量位置。 + *

+ * 支持的数据类型包括: + * - INT: 整型 + * - LONG: 长整型 + * - FLOAT: 单精度浮点型 + * - DOUBLE: 双精度浮点型 + * - BOOLEAN: 布尔型 + * - STRING: 字符串 + * + * @param serializer S7 序列化器, 用于与 PLC S7 进行数据交互 + * @param plcS7PointVariable PLC S7 点位变量信息, 包含数据块编号, 字节偏移量等 + * @param type 数据类型字符串, 用于标识要写入的数据类型 + * @param value 要写入的字符串形式的数据值 + * @throws CommonException 如果数据类型不支持, 抛出此异常 + */ + private void store(S7Serializer serializer, PlcS7PointVariable plcS7PointVariable, String type, String value) { + AttributeTypeFlagEnum valueType = AttributeTypeFlagEnum.ofCode(type); + if (Objects.isNull(valueType)) { + throw new CommonException("Unsupported type of " + type); + } + AttributeBO attributeBOConfig = new AttributeBO(value); + + switch (valueType) { + case INT: + int intValue = attributeBOConfig.getValueByClass(Integer.class); + serializer.store(intValue, plcS7PointVariable.getDbNum(), plcS7PointVariable.getByteOffset()); + break; + case LONG: + long longValue = attributeBOConfig.getValueByClass(Long.class); + serializer.store(longValue, plcS7PointVariable.getDbNum(), plcS7PointVariable.getByteOffset()); + break; + case FLOAT: + float floatValue = attributeBOConfig.getValueByClass(Float.class); + serializer.store(floatValue, plcS7PointVariable.getDbNum(), plcS7PointVariable.getByteOffset()); + break; + case DOUBLE: + double doubleValue = attributeBOConfig.getValueByClass(Double.class); + serializer.store(doubleValue, plcS7PointVariable.getDbNum(), plcS7PointVariable.getByteOffset()); + break; + case BOOLEAN: + boolean booleanValue = attributeBOConfig.getValueByClass(Boolean.class); + serializer.store(booleanValue, plcS7PointVariable.getDbNum(), plcS7PointVariable.getByteOffset()); + break; + case STRING: + serializer.store(value, plcS7PointVariable.getDbNum(), plcS7PointVariable.getByteOffset()); + break; + default: + break; + } + } /** * 获取 PLC S7 连接器 *

diff --git a/nl-web-app/src/test/java/org/nl/ApiTest.java b/nl-web-app/src/test/java/org/nl/ApiTest.java index 0a1f1df..871dae4 100644 --- a/nl-web-app/src/test/java/org/nl/ApiTest.java +++ b/nl-web-app/src/test/java/org/nl/ApiTest.java @@ -5,6 +5,7 @@ import org.junit.runner.RunWith; import org.nl.iot.core.driver.bo.AttributeBO; import org.nl.iot.core.driver.entity.RValue; import org.nl.iot.core.driver.protocol.modbustcp.ModBusProtocolDriverImpl; +import org.nl.iot.core.driver.protocol.plcs7.PlcS7ProtocolDriverImpl; import org.nl.iot.modular.iot.entity.IotConfig; import org.nl.iot.modular.iot.entity.IotConnect; import org.springframework.beans.factory.annotation.Autowired; @@ -152,8 +153,81 @@ public class ApiTest { } } + @Autowired + private PlcS7ProtocolDriverImpl plcS7ProtocolDriver; + @Test public void plcS7TestRead() { + // 初始化驱动 + plcS7ProtocolDriver.initial(); + + // 构建驱动配置(连接配置) + Map driverConfig = new HashMap<>(); + driverConfig.put("host", AttributeBO.builder().value("192.168.10.33").build()); + driverConfig.put("port", AttributeBO.builder().value("102").build()); + // 构建点位配置 + Map pointConfig = new HashMap<>(); + pointConfig.put("dbNum", AttributeBO.builder().value("1").build()); // 数据块编号 + pointConfig.put("byteOffset", AttributeBO.builder().value("0").build()); // 字节偏移量 + pointConfig.put("bitOffset", AttributeBO.builder().value("0").build()); // 位偏移量 + pointConfig.put("blockSize", AttributeBO.builder().value("1").build()); // 数据块大小 + pointConfig.put("data_type", AttributeBO.builder().value("int").build()); // 数据类型 + + // 构建连接对象 + IotConnect connect = IotConnect.builder() + .id(1) + .code("PLC_S7_001") + .host("192.168.10.33") + .port(102) + .protocol("plc-s7") + .enabled(true) + .description("测试PLC S7连接") + .build(); + + // 构建配置对象 + IotConfig config = IotConfig.builder() + .id(1) + .connectId(1) + .alias("pressure") + .aliasName("压力传感器") + .registerAddress("DB1.DBW0") + .dataType("int") + .readonly(true) + .enabled(true) + .description("测试PLC S7数据读取") + .build(); + + try { + System.out.println("=== PLC S7读取测试开始 ==="); + System.out.println("连接地址: " + driverConfig.get("host").getValue() + ":" + driverConfig.get("port").getValue()); + System.out.println("数据块: DB" + pointConfig.get("dbNum").getValue() + + ", 偏移: " + pointConfig.get("byteOffset").getValue() + + ", 类型: " + pointConfig.get("data_type").getValue()); + + // 调用read方法进行测试 + RValue result = plcS7ProtocolDriver.read(driverConfig, pointConfig, connect, config); + + // 检查结果是否为null + if (result != null) { + System.out.println("\n✓ 读取成功!"); + System.out.println("连接信息: " + result.getConnect()); + System.out.println("配置信息: " + result.getConfig()); + System.out.println("读取值: " + result.getValue()); + } else { + System.err.println("\n✗ 读取失败:返回结果为null"); + System.err.println("可能原因:"); + System.err.println("1. PLC设备未连接或IP地址不正确"); + System.err.println("2. 端口号配置错误(S7-300/400默认102)"); + System.err.println("3. 数据块(DB)不存在或无访问权限"); + System.err.println("4. 数据类型或偏移量配置错误"); + } + + System.out.println("\n=== 测试完成 ==="); + + } catch (Exception e) { + System.err.println("\n✗ 测试异常: " + e.getMessage()); + e.printStackTrace(); + } } }