#
Junjie
9 天以前 dc3f9cc91759823ce59486f19b138be4b296a0f1
src/main/java/com/zy/core/network/ZyStationConnectDriver.java
@@ -10,16 +10,16 @@
import com.zy.core.network.entity.ZyStationStatusEntity;
import java.util.List;
import com.zy.core.network.fake.ZyStationFakeSegConnect;
import com.zy.core.network.fake.ZyStationV4FakeSegConnect;
import com.zy.core.network.real.ZyStationRealConnect;
import com.zy.core.network.real.ZyStationV3RealConnect;
import com.zy.core.network.real.ZyStationV4RealConnect;
import com.zy.core.network.real.ZyStationV5RealConnect;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.UUID;
/**
 * 输送站连接驱动
@@ -28,7 +28,10 @@
public class ZyStationConnectDriver implements ThreadHandler {
    private static final ZyStationFakeSegConnect zyStationFakeSegConnect = new ZyStationFakeSegConnect();
    private static final ZyStationV4FakeSegConnect zyStationV4FakeSegConnect = new ZyStationV4FakeSegConnect();
    private static final long SEND_LOCK_WARN_MS = 500L;
    private static final long SEND_COST_WARN_MS = 5_000L;
    private static final long SEND_LOCK_POLL_MS = 20L;
    private static final long SEND_LOCK_EXPIRE_SECONDS = 15L;
    private volatile boolean connected = false;
    private volatile boolean connecting = false;
@@ -69,27 +72,14 @@
                if (deviceConfig.getFake() == 0) {
                    if ("ZyStationV3Thread".equals(deviceConfig.getThreadImpl())) {
                        connectApi = new ZyStationV3RealConnect(deviceConfig, redisUtil);
                    } else if ("ZyStationV4Thread".equals(deviceConfig.getThreadImpl())
                            || "ZyStationV5Thread".equals(deviceConfig.getThreadImpl())) {
                        connectApi = new ZyStationV4RealConnect(deviceConfig, redisUtil);
                    } else if ("ZyStationV5Thread".equals(deviceConfig.getThreadImpl())) {
                        connectApi = new ZyStationV5RealConnect(deviceConfig, redisUtil);
                    } else {
                        connectApi = new ZyStationRealConnect(deviceConfig, redisUtil);
                    }
                } else {
                    if ("ZyStationV3Thread".equals(deviceConfig.getThreadImpl())) {
                        zyStationFakeSegConnect.addFakeConnect(deviceConfig, redisUtil);
                        connectApi = zyStationFakeSegConnect;
                    } else if ("ZyStationV4Thread".equals(deviceConfig.getThreadImpl())
                            || "ZyStationV5Thread".equals(deviceConfig.getThreadImpl())) {
                        zyStationV4FakeSegConnect.addFakeConnect(deviceConfig, redisUtil);
                        connectApi = zyStationV4FakeSegConnect;
                    } else {
                        fakeConfigUnsupported = true;
                        zyStationConnectApi = null;
                        log.error("旧版输送站 fake 已移除,deviceNo={}, threadImpl={}, 请切换到 ZyStationV3Thread、ZyStationV4Thread 或 ZyStationV5Thread",
                                deviceConfig.getDeviceNo(), deviceConfig.getThreadImpl());
                        return false;
                    }
                    zyStationFakeSegConnect.addFakeConnect(deviceConfig, redisUtil);
                    connectApi = zyStationFakeSegConnect;
                }
                boolean connect = connectApi.connect();
@@ -160,22 +150,65 @@
        if (!connected || connecting || connectApi == null) {
            return new CommandResponse(false, "设备未连接,命令下发失败");
        }
        while (true) {
            Object lock = redisUtil.get(RedisKeyType.STATION_EXECUTE_COMMAND_LOCK.key);
            if(lock != null) {
        String lockKey = buildStationExecuteLockKey();
        String lockToken = UUID.randomUUID().toString();
        long lockWaitStart = System.currentTimeMillis();
        int waitRounds = 0;
        if (redisUtil != null) {
            while (true) {
                if (redisUtil.trySetStringIfAbsent(lockKey, lockToken, SEND_LOCK_EXPIRE_SECONDS)) {
                    break;
                }
                waitRounds++;
                try {
                    Thread.sleep(500);
                }catch (Exception e) {
                    Thread.sleep(SEND_LOCK_POLL_MS);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }else {
                redisUtil.set(RedisKeyType.STATION_EXECUTE_COMMAND_LOCK.key, "lock", 60 * 5);
                break;
            }
        }
        CommandResponse commandResponse = connectApi.sendCommand(deviceConfig.getDeviceNo(), command);
        redisUtil.del(RedisKeyType.STATION_EXECUTE_COMMAND_LOCK.key);
        return commandResponse;
        long lockWaitCost = System.currentTimeMillis() - lockWaitStart;
        if (lockWaitCost >= SEND_LOCK_WARN_MS) {
            log.warn("输送命令等待设备发送锁超时,deviceNo={}, taskNo={}, stationId={}, targetStaNo={}, waitMs={}, waitRounds={}, lockKey={}",
                    deviceConfig == null ? null : deviceConfig.getDeviceNo(),
                    command == null ? null : command.getTaskNo(),
                    command == null ? null : command.getStationId(),
                    command == null ? null : command.getTargetStaNo(),
                    lockWaitCost,
                    waitRounds,
                    lockKey);
        }
        long sendStart = System.currentTimeMillis();
        try {
            return connectApi.sendCommand(deviceConfig.getDeviceNo(), command);
        } finally {
            releaseDeviceSendLock(lockKey, lockToken);
            long sendCostMs = System.currentTimeMillis() - sendStart;
            if (sendCostMs >= SEND_COST_WARN_MS) {
                log.warn("输送命令底层发送耗时过长,deviceNo={}, taskNo={}, stationId={}, targetStaNo={}, sendCostMs={}",
                        deviceConfig == null ? null : deviceConfig.getDeviceNo(),
                        command == null ? null : command.getTaskNo(),
                        command == null ? null : command.getStationId(),
                        command == null ? null : command.getTargetStaNo(),
                        sendCostMs);
            }
        }
    }
    private String buildStationExecuteLockKey() {
        Integer deviceNo = deviceConfig == null ? null : deviceConfig.getDeviceNo();
        return RedisKeyType.STATION_EXECUTE_COMMAND_LOCK.key + ":" + deviceNo;
    }
    private void releaseDeviceSendLock(String lockKey, String lockToken) {
        if (redisUtil == null || lockKey == null) {
            return;
        }
        try {
            redisUtil.compareAndDelete(lockKey, lockToken);
        } catch (Exception e) {
            log.warn("释放输送设备发送锁失败,lockKey={}", lockKey, e);
        }
    }
    public CommandResponse sendOriginCommand(String address, short[] data) {
@@ -186,6 +219,15 @@
        return connectApi.sendOriginCommand(address, data);
    }
    public boolean clearTaskBufferSlot(Integer stationId, Integer slotIdx) {
        ZyStationConnectApi connectApi = zyStationConnectApi;
        if (!connected || connecting || connectApi == null) {
            return false;
        }
        CommandResponse response = connectApi.clearTaskBufferSlot(deviceConfig.getDeviceNo(), stationId, slotIdx);
        return response != null && Boolean.TRUE.equals(response.getResult());
    }
    public byte[] readOriginCommand(String address, int length) {
        ZyStationConnectApi connectApi = zyStationConnectApi;
        if (!connected || connecting || connectApi == null) {