refactor(ft546): register shuttle runtimes from configuration
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.project.ft546.device;
|
||||
|
||||
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@Component
|
||||
public class Ft546DeviceRuntimeRegistry {
|
||||
private final ConcurrentMap<String, PlcSrgvRead> shuttleRuntimes =
|
||||
new ConcurrentHashMap<String, PlcSrgvRead>();
|
||||
|
||||
public void register(String deviceId, PlcSrgvRead runtime) {
|
||||
String id = requireText(deviceId, "deviceId");
|
||||
PlcSrgvRead value = Objects.requireNonNull(runtime, "runtime");
|
||||
PlcSrgvRead existing = shuttleRuntimes.putIfAbsent(id, value);
|
||||
if (existing != null && existing != value) {
|
||||
throw new IllegalStateException(
|
||||
"runtime already registered for device " + id);
|
||||
}
|
||||
}
|
||||
|
||||
public PlcSrgvRead requireSrgv(String deviceId) {
|
||||
String id = requireText(deviceId, "deviceId");
|
||||
PlcSrgvRead runtime = shuttleRuntimes.get(id);
|
||||
if (runtime == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"shuttle runtime not found: " + id);
|
||||
}
|
||||
return runtime;
|
||||
}
|
||||
|
||||
public Map<String, PlcSrgvRead> allSrgv() {
|
||||
return Collections.unmodifiableMap(
|
||||
new LinkedHashMap<String, PlcSrgvRead>(shuttleRuntimes));
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
shuttleRuntimes.clear();
|
||||
}
|
||||
|
||||
private static String requireText(String value, String field) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException(field + " must not be blank");
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ruoyi.project.ft546.device.shuttle;
|
||||
|
||||
import com.ruoyi.common.domain.PlcConnectInfo;
|
||||
import com.ruoyi.device.srgv.domain.DeviceSrgv;
|
||||
import com.ruoyi.project.ft546.config.Ft546DeviceProfile;
|
||||
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class Ft546SrgvRuntimeFactory {
|
||||
|
||||
public PlcSrgvRead create(DeviceSrgv device,
|
||||
Ft546DeviceProfile profile) {
|
||||
if (device == null || device.getDeviceId() == null) {
|
||||
throw new IllegalArgumentException("device identity is required");
|
||||
}
|
||||
if (profile == null
|
||||
|| !String.valueOf(device.getDeviceId()).equals(
|
||||
profile.getDeviceId())) {
|
||||
throw new IllegalArgumentException(
|
||||
"profile belongs to another device");
|
||||
}
|
||||
if (!"SHUTTLE".equals(profile.getDeviceType())
|
||||
|| !"FT546_LEGACY_SRGV".equals(profile.getAdapterType())) {
|
||||
throw new IllegalArgumentException(
|
||||
"profile is not a legacy shuttle profile");
|
||||
}
|
||||
String ip = hasText(profile.getIp()) ? profile.getIp().trim()
|
||||
: device.getIp();
|
||||
Integer port = profile.getPort() != null ? profile.getPort()
|
||||
: device.getPort();
|
||||
if (!hasText(ip) || port == null || port <= 0 || port > 65535) {
|
||||
throw new IllegalArgumentException(
|
||||
"device endpoint is not configured");
|
||||
}
|
||||
int station = profile.getStation() == null ? 1 : profile.getStation();
|
||||
return new PlcSrgvRead(device, new PlcConnectInfo(ip, port), station);
|
||||
}
|
||||
|
||||
public PlcSrgvRead create(DeviceSrgv device) {
|
||||
Ft546DeviceProfile profile = new Ft546DeviceProfile();
|
||||
profile.setDeviceId(String.valueOf(device.getDeviceId()));
|
||||
profile.setDeviceType("SHUTTLE");
|
||||
profile.setAdapterType("FT546_LEGACY_SRGV");
|
||||
profile.setIp(device.getIp());
|
||||
profile.setPort(device.getPort());
|
||||
return create(device, profile);
|
||||
}
|
||||
|
||||
private static boolean hasText(String value) {
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import com.ruoyi.device.ssj.domain.DeviceSsj;
|
||||
import com.ruoyi.device.ssj.service.IDeviceSsjService;
|
||||
import com.ruoyi.device.tsj.domain.DeviceTsj;
|
||||
import com.ruoyi.device.tsj.service.IDeviceTsjService;
|
||||
import com.ruoyi.project.ft546.device.Ft546DeviceRuntimeRegistry;
|
||||
import com.ruoyi.project.ft546.device.shuttle.Ft546SrgvRuntimeFactory;
|
||||
import com.ruoyi.schedule.plcRead.cdz.PlcCdzRead;
|
||||
import com.ruoyi.schedule.plcRead.ddj.PlcDdjRead;
|
||||
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
|
||||
@@ -30,6 +32,7 @@ import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@@ -39,9 +42,9 @@ public class ScheduleThread {
|
||||
public CustomThread<PlcSsjRead> plcSsjReadCustomThread;
|
||||
public CustomThread<PlcTsjRead> plcTsjReadCustomThread;
|
||||
public CustomThread<PlcCdzRead> plcCdzReadCustomThread;
|
||||
public CustomThread<PlcSrgvRead> plcSrgvReadCustomThread1;
|
||||
public CustomThread<PlcSrgvRead> plcSrgvReadCustomThread2;
|
||||
public CustomThread<PlcSrgvRead> plcSrgvReadCustomThread3;
|
||||
public final Map<String, CustomThread<PlcSrgvRead>>
|
||||
plcSrgvReadCustomThreads =
|
||||
new ConcurrentHashMap<String, CustomThread<PlcSrgvRead>>();
|
||||
|
||||
|
||||
public CustomThread<MonitoringThread> monitoringCustomThread;
|
||||
@@ -58,6 +61,10 @@ public class ScheduleThread {
|
||||
private IDeviceTsjService deviceTsjService;
|
||||
@Autowired
|
||||
private IDeviceCdzService deviceCdzService;
|
||||
@Autowired
|
||||
private Ft546DeviceRuntimeRegistry deviceRuntimeRegistry;
|
||||
@Autowired
|
||||
private Ft546SrgvRuntimeFactory srgvRuntimeFactory;
|
||||
|
||||
private boolean isRun = false;
|
||||
private boolean isRun2 = false;
|
||||
@@ -128,25 +135,14 @@ public class ScheduleThread {
|
||||
ConcurrentHashMap<String, DeviceSrgv> srgvList = new ConcurrentHashMap<>();
|
||||
List<DeviceSrgv> srgvs=deviceSrgvService.selectDeviceSrgvList(new DeviceSrgv());
|
||||
for(DeviceSrgv srgv:srgvs){
|
||||
srgvList.put(srgv.getDeviceId().toString(),srgv);
|
||||
switch (srgv.getDeviceId()){
|
||||
case 1:
|
||||
PlcSrgvRead plcSrgvRead1=new PlcSrgvRead(srgv,new PlcConnectInfo(srgv.getIp(),srgv.getPort()));
|
||||
Thread plcSrgvReadThread1 = new Thread((plcSrgvRead1));
|
||||
plcSrgvReadCustomThread1=new CustomThread<PlcSrgvRead>(plcSrgvReadThread1,plcSrgvRead1);
|
||||
break;
|
||||
case 2:
|
||||
PlcSrgvRead plcSrgvRead2=new PlcSrgvRead(srgv,new PlcConnectInfo(srgv.getIp(),srgv.getPort()));
|
||||
Thread plcSrgvReadThread2 = new Thread((plcSrgvRead2));
|
||||
plcSrgvReadCustomThread2=new CustomThread<PlcSrgvRead>(plcSrgvReadThread2,plcSrgvRead2);
|
||||
break;
|
||||
case 3:
|
||||
PlcSrgvRead plcSrgvRead3=new PlcSrgvRead(srgv,new PlcConnectInfo(srgv.getIp(),srgv.getPort()));
|
||||
Thread plcSrgvReadThread3 = new Thread((plcSrgvRead3));
|
||||
plcSrgvReadCustomThread3=new CustomThread<PlcSrgvRead>(plcSrgvReadThread3,plcSrgvRead3);
|
||||
break;
|
||||
}
|
||||
|
||||
String deviceId = srgv.getDeviceId().toString();
|
||||
srgvList.put(deviceId,srgv);
|
||||
PlcSrgvRead plcSrgvRead = srgvRuntimeFactory.create(srgv);
|
||||
deviceRuntimeRegistry.register(deviceId, plcSrgvRead);
|
||||
Thread plcSrgvReadThread = new Thread(plcSrgvRead);
|
||||
plcSrgvReadCustomThreads.put(deviceId,
|
||||
new CustomThread<PlcSrgvRead>(plcSrgvReadThread,
|
||||
plcSrgvRead));
|
||||
}
|
||||
PlcSrgvRead.deviceSrgvMap=srgvList;
|
||||
|
||||
@@ -177,9 +173,10 @@ public class ScheduleThread {
|
||||
*/
|
||||
public void startAllThread() {
|
||||
plcSsjReadCustomThread.getThread().start();
|
||||
plcSrgvReadCustomThread1.getThread().start();
|
||||
plcSrgvReadCustomThread2.getThread().start();
|
||||
plcSrgvReadCustomThread3.getThread().start();
|
||||
for (CustomThread<PlcSrgvRead> reader
|
||||
: plcSrgvReadCustomThreads.values()) {
|
||||
reader.getThread().start();
|
||||
}
|
||||
plcTsjReadCustomThread.getThread().start();
|
||||
plcCdzReadCustomThread.getThread().start();
|
||||
|
||||
@@ -205,6 +202,12 @@ public class ScheduleThread {
|
||||
*/
|
||||
public void stopAllThread() {
|
||||
plcSsjReadCustomThread.runnable.isRun = false;
|
||||
for (CustomThread<PlcSrgvRead> reader
|
||||
: plcSrgvReadCustomThreads.values()) {
|
||||
reader.runnable.isRun = false;
|
||||
}
|
||||
plcSrgvReadCustomThreads.clear();
|
||||
deviceRuntimeRegistry.clear();
|
||||
// plcDdj1ReadCustomThread.runnable.isRun = false;
|
||||
/* plcDdj2ReadCustomThread.runnable.isRun = false;
|
||||
plcDdj3ReadCustomThread.runnable.isRun = false;
|
||||
|
||||
@@ -29,10 +29,22 @@ public class PlcSrgvRead implements Runnable {
|
||||
private IByteTransform byteTransform = null;
|
||||
|
||||
public PlcSrgvRead(DeviceSrgv deviceSrgv, PlcConnectInfo plcConnectInfo) {
|
||||
this(deviceSrgv, plcConnectInfo, 1);
|
||||
}
|
||||
|
||||
public PlcSrgvRead(DeviceSrgv deviceSrgv, PlcConnectInfo plcConnectInfo,
|
||||
int station) {
|
||||
if (station < 0 || station > 255) {
|
||||
throw new IllegalArgumentException("station is invalid");
|
||||
}
|
||||
this.deviceSrgv = deviceSrgv;
|
||||
this.ip = plcConnectInfo.getIp();
|
||||
this.port = plcConnectInfo.getPort();
|
||||
this.station = (byte) 1;
|
||||
this.station = (byte) station;
|
||||
}
|
||||
|
||||
public DeviceSrgv getDeviceSrgv() {
|
||||
return deviceSrgv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.ruoyi.bas.srgvmap.domain.WcsSrgvMap;
|
||||
import com.ruoyi.bas.srgvmap.service.IWcsSrgvMapService;
|
||||
import com.ruoyi.bas.srgvmap.service.RoadCacheService;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.domain.CustomThread;
|
||||
import com.ruoyi.common.domain.SendData2;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.device.srgv.domain.DeviceSrgv;
|
||||
@@ -28,7 +27,7 @@ import com.ruoyi.job.service.impl.JobCallBackServiceImpl;
|
||||
import com.ruoyi.queue.srgv.domain.WcsSrgvQueue;
|
||||
import com.ruoyi.queue.srgv.service.IWcsSrgvQueueFinishService;
|
||||
import com.ruoyi.queue.srgv.service.IWcsSrgvQueueService;
|
||||
import com.ruoyi.schedule.ScheduleThread;
|
||||
import com.ruoyi.project.ft546.device.Ft546DeviceRuntimeRegistry;
|
||||
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
|
||||
import com.ruoyi.schedule.plcRead.srgv.roadUtil.PathFinder;
|
||||
import com.ruoyi.schedule.plcRead.ssj.PlcSsjRead;
|
||||
@@ -73,10 +72,10 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
|
||||
public void init() {
|
||||
sRgvCodeList = new HashMap<>();
|
||||
ArrayList<String> sRgvCodes = new ArrayList<>();
|
||||
sRgvCodes.add("1");
|
||||
sRgvCodes.add("2");
|
||||
sRgvCodes.add("3");
|
||||
Ft546DeviceRuntimeRegistry runtimeRegistry =
|
||||
SpringUtils.getBean(Ft546DeviceRuntimeRegistry.class);
|
||||
ArrayList<String> sRgvCodes = new ArrayList<>(
|
||||
runtimeRegistry.allSrgv().keySet());
|
||||
sRgvCodeList.put("srgv", sRgvCodes);
|
||||
|
||||
wcsSagvQueueMapper = SpringUtils.getBean(IWcsSrgvQueueService.class);
|
||||
@@ -1380,26 +1379,18 @@ public class BaseSRgvThread implements Runnable, SRgvThreadInterface {
|
||||
private boolean sendCarTask(List<SendData2> sendDataList, DeviceSrgv deviceSrgv) {
|
||||
|
||||
boolean b = true;
|
||||
ScheduleThread scheduleThread = SpringUtils.getBean(ScheduleThread.class);
|
||||
CustomThread<?> ct = null;
|
||||
Integer deviceId = deviceSrgv.getDeviceId();
|
||||
if (deviceId != null) {
|
||||
switch (deviceId) {
|
||||
case 1:
|
||||
ct = scheduleThread.plcSrgvReadCustomThread1;
|
||||
break;
|
||||
case 2:
|
||||
ct = scheduleThread.plcSrgvReadCustomThread2;
|
||||
break;
|
||||
case 3:
|
||||
ct = scheduleThread.plcSrgvReadCustomThread3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (deviceId == null) {
|
||||
return false;
|
||||
}
|
||||
PlcSrgvRead plcReader = ct != null ? (PlcSrgvRead) ct.getRunnable() : null;
|
||||
if (plcReader == null) {
|
||||
Ft546DeviceRuntimeRegistry runtimeRegistry =
|
||||
SpringUtils.getBean(Ft546DeviceRuntimeRegistry.class);
|
||||
PlcSrgvRead plcReader;
|
||||
try {
|
||||
plcReader = runtimeRegistry.requireSrgv(
|
||||
String.valueOf(deviceId));
|
||||
} catch (IllegalArgumentException missingRuntime) {
|
||||
log.warn("小车 {} 没有已注册的 PLC 运行时,取消本次下发", deviceId);
|
||||
return false;
|
||||
}
|
||||
for (SendData2 sendData : sendDataList) {
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.ruoyi.project.ft546.device;
|
||||
|
||||
import com.ruoyi.common.domain.PlcConnectInfo;
|
||||
import com.ruoyi.device.srgv.domain.DeviceSrgv;
|
||||
import com.ruoyi.project.ft546.config.Ft546DeviceProfile;
|
||||
import com.ruoyi.project.ft546.device.shuttle.Ft546SrgvRuntimeFactory;
|
||||
import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class Ft546DeviceRuntimeRegistryTest {
|
||||
|
||||
@Test
|
||||
void registersAnyConfiguredNumberOfShuttleRuntimes() {
|
||||
Ft546DeviceRuntimeRegistry registry = new Ft546DeviceRuntimeRegistry();
|
||||
PlcSrgvRead first = runtime("1");
|
||||
PlcSrgvRead second = runtime("2");
|
||||
PlcSrgvRead ninth = runtime("9");
|
||||
|
||||
registry.register("1", first);
|
||||
registry.register("2", second);
|
||||
registry.register("9", ninth);
|
||||
|
||||
assertEquals(3, registry.allSrgv().size());
|
||||
assertSame(ninth, registry.requireSrgv("9"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void duplicateDeviceCannotSilentlyReplaceAnActiveRuntime() {
|
||||
Ft546DeviceRuntimeRegistry registry = new Ft546DeviceRuntimeRegistry();
|
||||
registry.register("1", runtime("1"));
|
||||
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> registry.register("1", runtime("1")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void factoryRejectsAProfileForAnotherDevice() {
|
||||
DeviceSrgv device = device("1");
|
||||
Ft546DeviceProfile profile = new Ft546DeviceProfile();
|
||||
profile.setDeviceId("2");
|
||||
profile.setDeviceType("SHUTTLE");
|
||||
profile.setAdapterType("FT546_LEGACY_SRGV");
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new Ft546SrgvRuntimeFactory().create(device, profile));
|
||||
}
|
||||
|
||||
@Test
|
||||
void schedulingAndLegacySendPathsDoNotSelectThreeFixedReaders()
|
||||
throws Exception {
|
||||
String schedule = readSource(
|
||||
"com/ruoyi/schedule/ScheduleThread.java");
|
||||
String legacy = readSource("com/ruoyi/schedule/scheduleTask/srgv/"
|
||||
+ "BaseSRgvThread.java");
|
||||
|
||||
assertFalse(schedule.contains("plcSrgvReadCustomThread1"));
|
||||
assertFalse(schedule.contains("case 1:"));
|
||||
assertFalse(legacy.contains("plcSrgvReadCustomThread1"));
|
||||
assertFalse(legacy.contains("switch (deviceId)"));
|
||||
}
|
||||
|
||||
private static PlcSrgvRead runtime(String id) {
|
||||
DeviceSrgv device = device(id);
|
||||
return new PlcSrgvRead(device,
|
||||
new PlcConnectInfo(device.getIp(), device.getPort()));
|
||||
}
|
||||
|
||||
private static DeviceSrgv device(String id) {
|
||||
DeviceSrgv device = new DeviceSrgv();
|
||||
device.setDeviceId(Integer.valueOf(id));
|
||||
device.setIp("127.0.0." + id);
|
||||
device.setPort(502);
|
||||
return device;
|
||||
}
|
||||
|
||||
private static String readSource(String relative) throws Exception {
|
||||
Path current = Paths.get(System.getProperty(
|
||||
"maven.multiModuleProjectDirectory", "."))
|
||||
.toAbsolutePath().normalize();
|
||||
while (current != null) {
|
||||
Path source = current.resolve(Paths.get("ruoyi-admin", "src",
|
||||
"main", "java", relative));
|
||||
if (Files.isRegularFile(source)) {
|
||||
return new String(Files.readAllBytes(source),
|
||||
StandardCharsets.UTF_8);
|
||||
}
|
||||
current = current.getParent();
|
||||
}
|
||||
throw new java.nio.file.NoSuchFileException(relative);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user