更新2级写入,以及前端处理
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
package com.fizz.business.comm.iot;
|
||||||
|
|
||||||
|
import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
|
||||||
|
import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于 iot-communication 的 S7 写入客户端(仅用于写入)。
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@ConditionalOnProperty(prefix = "iot.communication", name = "enabled", havingValue = "true")
|
||||||
|
public class S7WriteClient {
|
||||||
|
|
||||||
|
@Value("${iot.communication.s7.ip:127.0.0.1}")
|
||||||
|
private String ip;
|
||||||
|
|
||||||
|
@Value("${iot.communication.s7.port:102}")
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
@Value("${iot.communication.s7.rack:0}")
|
||||||
|
private int rack;
|
||||||
|
|
||||||
|
@Value("${iot.communication.s7.slot:1}")
|
||||||
|
private int slot;
|
||||||
|
|
||||||
|
@Value("${iot.communication.s7.plc-type:S1200}")
|
||||||
|
private String plcType;
|
||||||
|
|
||||||
|
public S7PLC newClient() {
|
||||||
|
EPlcType type = parsePlcType(plcType);
|
||||||
|
return new S7PLC(type, ip, port, rack, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private EPlcType parsePlcType(String value) {
|
||||||
|
try {
|
||||||
|
return EPlcType.valueOf(value.trim().toUpperCase(Locale.ROOT));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("未知 plc-type: {},回退到 S1200", value);
|
||||||
|
return EPlcType.S1200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ import javax.validation.Valid;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RequestMapping("/api/opc/data")
|
@RequestMapping("/api/opc/data")
|
||||||
@Tag(name = "OPC 数据读写")
|
@Tag(name = "OPC 数据读写")
|
||||||
@ConditionalOnProperty(prefix = "kangaroohy.milo", name = "enabled", havingValue = "true")
|
@ConditionalOnProperty(prefix = "iot.communication", name = "enabled", havingValue = "true")
|
||||||
@Anonymous
|
@Anonymous
|
||||||
public class OpcDataController {
|
public class OpcDataController {
|
||||||
|
|
||||||
|
|||||||
@@ -1,52 +1,96 @@
|
|||||||
package com.fizz.business.service.impl;
|
package com.fizz.business.service.impl;
|
||||||
|
|
||||||
import com.fizz.business.comm.OPC.OpcMessageSend;
|
import com.fizz.business.comm.iot.S7WriteClient;
|
||||||
import com.fizz.business.form.OpcBatchWriteDataForm;
|
import com.fizz.business.form.OpcBatchWriteDataForm;
|
||||||
import com.fizz.business.form.OpcWriteDataForm;
|
import com.fizz.business.form.OpcWriteDataForm;
|
||||||
import com.fizz.business.service.OpcDataService;
|
import com.fizz.business.service.OpcDataService;
|
||||||
|
import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OPC 数据读写服务实现类
|
* OPC 数据读写服务实现类
|
||||||
|
*
|
||||||
|
* 说明:
|
||||||
|
* 1) 写入逻辑已切换为 iot-communication(S7)
|
||||||
|
* 2) 读取逻辑仍保留在原 OPC 体系(不在本类中)
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ConditionalOnProperty(prefix = "kangaroohy.milo", name = "enabled", havingValue = "true")
|
@ConditionalOnProperty(prefix = "iot.communication", name = "enabled", havingValue = "true")
|
||||||
public class OpcDataServiceImpl implements OpcDataService {
|
public class OpcDataServiceImpl implements OpcDataService {
|
||||||
|
|
||||||
private final OpcMessageSend opcMessageSend;
|
private final S7WriteClient s7WriteClient;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean writeData(OpcWriteDataForm form) {
|
public boolean writeData(OpcWriteDataForm form) {
|
||||||
try {
|
try (S7PLC s7PLC = s7WriteClient.newClient()) {
|
||||||
return opcMessageSend.writeDataByFieldName(form.getFieldName(), form.getValue());
|
writeByGuessType(s7PLC, form.getFieldName(), form.getValue());
|
||||||
|
return true;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("写入 OPC 数据异常,fieldName={}, value={}", form.getFieldName(), form.getValue(), e);
|
log.error("写入 S7 数据异常,address={}, value={}", form.getFieldName(), form.getValue(), e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean batchWriteData(OpcBatchWriteDataForm form) {
|
public boolean batchWriteData(OpcBatchWriteDataForm form) {
|
||||||
try {
|
try (S7PLC s7PLC = s7WriteClient.newClient()) {
|
||||||
Map<String, Object> fieldDataMap = form.getDataList().stream()
|
for (OpcWriteDataForm item : form.getDataList()) {
|
||||||
.collect(Collectors.toMap(
|
writeByGuessType(s7PLC, item.getFieldName(), item.getValue());
|
||||||
OpcWriteDataForm::getFieldName,
|
}
|
||||||
OpcWriteDataForm::getValue,
|
return true;
|
||||||
(v1, v2) -> v2 // 如果有重复的 key,保留后面的值
|
|
||||||
));
|
|
||||||
return opcMessageSend.batchWriteDataByFieldName(fieldDataMap);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("批量写入 OPC 数据异常", e);
|
log.error("批量写入 S7 数据异常", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
private void writeByGuessType(S7PLC s7PLC, String address, Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new IllegalArgumentException("写入值不能为空");
|
||||||
|
}
|
||||||
|
if (address == null || address.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("写入地址不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof Boolean) {
|
||||||
|
s7PLC.writeBoolean(address, (Boolean) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Byte) {
|
||||||
|
s7PLC.writeByte(address, (Byte) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Short) {
|
||||||
|
s7PLC.writeInt16(address, (Short) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Integer) {
|
||||||
|
s7PLC.writeInt32(address, (Integer) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Long) {
|
||||||
|
s7PLC.writeInt64(address, (Long) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Float) {
|
||||||
|
s7PLC.writeFloat32(address, (Float) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof Double) {
|
||||||
|
s7PLC.writeFloat64(address, (Double) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value instanceof byte[]) {
|
||||||
|
s7PLC.writeByte(address, (byte[]) value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兜底按字符串写入
|
||||||
|
s7PLC.writeString(address, String.valueOf(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -181,6 +181,18 @@ kangaroohy:
|
|||||||
min-idle: 2
|
min-idle: 2
|
||||||
initial-size: 3
|
initial-size: 3
|
||||||
|
|
||||||
|
# iot-communication(S7)写入开关与连接参数
|
||||||
|
# 注意:写入使用 iot-communication;读取逻辑仍沿用 OPC 现有体系
|
||||||
|
iot:
|
||||||
|
communication:
|
||||||
|
enabled: true
|
||||||
|
s7:
|
||||||
|
ip: 127.0.0.1
|
||||||
|
port: 102
|
||||||
|
rack: 0
|
||||||
|
slot: 1
|
||||||
|
plc-type: S1200
|
||||||
|
|
||||||
|
|
||||||
#kangaroohy:
|
#kangaroohy:
|
||||||
# milo:
|
# milo:
|
||||||
|
|||||||
Reference in New Issue
Block a user