#
zc
2025-04-29 62b1f39e60f64ec4e05b21d11af3e36f5891a91a
src/main/java/com/zy/core/thread/ShuttleThread.java
@@ -1,274 +1,80 @@
package com.zy.core.thread;
import HslCommunication.Core.Transfer.DataFormat;
import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.ModBus.ModbusTcpNet;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSON;
import com.core.common.DateUtils;
import com.core.common.RadixTools;
import com.core.exception.CoolException;
import com.zy.common.utils.CommonUtils;
import com.zy.core.News;
import com.zy.common.ExecuteSupport;
import com.zy.common.model.NavigateNode;
import com.zy.core.ThreadHandler;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.ShuttleStatusType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.SteSlave;
import com.zy.core.model.Task;
import com.zy.core.enums.ShuttleProtocolStatusType;
import com.zy.core.enums.ShuttleTaskNoType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.command.SteCommand;
import com.zy.core.model.param.ShuttleMoveLocParam;
import com.zy.core.model.protocol.ShuttleProtocol;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Random;
import java.util.List;
/**
 * 四向穿梭车线程
 */
@Data
@Slf4j
public class ShuttleThread implements  Runnable, ThreadHandler {
public interface ShuttleThread extends ThreadHandler {
    private ModbusTcpNet modbusTcpNet;
    private ShuttleSlave slave;
    private ShuttleProtocol shuttleProtocol;
    private SiemensS7Net siemensS7Net;
    ShuttleProtocol getStatus(boolean clone);//获取四向穿梭车状态
    public ShuttleThread(ShuttleSlave slave) {
        this.slave = slave;
    }
    ShuttleProtocol getStatus();//获取四向穿梭车状态-默认clone
    @Override
    public void run() {
        this.connect();
        while (true) {
            try {
                int step = 1;
                Task task = MessageQueue.poll(SlaveType.Shuttle, slave.getId());
                if (task != null) {
                    step = task.getStep();
                }
                switch (step) {
                    // 读数据
                    case 1:
                        readStatus();
                        break;
                    // 写入数据
                    case 2:
                        write((ShuttleCommand) task.getData());
                        break;
                    default:
                        break;
                }
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    CommandResponse movePath(List<NavigateNode> nodes, Integer taskNo);//路径下发
    @Override
    public boolean connect() {
        boolean result = false;
        //-------------------------四向穿梭车连接方法------------------------//
        modbusTcpNet = new ModbusTcpNet(slave.getIp(), slave.getPort(), (byte) 0x01);
        // 当你需要指定格式的数据解析时,就需要设置下面的这个信息
        modbusTcpNet.setDataFormat(DataFormat.ABCD);
        OperateResult connect = modbusTcpNet.ConnectServer();
        if(connect.IsSuccess){
            result = true;
            OutputQueue.CRN.offer(MessageFormat.format( "【{0}】四向穿梭车plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            log.info("四向穿梭车plc连接成功 ===>> [id:{}] [ip:{}] [port:{}] ", slave.getId(), slave.getIp(), slave.getPort());
        } else {
            OutputQueue.CRN.offer(MessageFormat.format("【{0}】四向穿梭车plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            log.error("四向穿梭车plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}] ", slave.getId(), slave.getIp(), slave.getPort());
        }
        modbusTcpNet.ConnectClose();
        //-------------------------四向穿梭车连接方法------------------------//
        return result;
    }
    CommandResponse move(ShuttleCommand command);//移动
    @Override
    public void close() {
    CommandResponse lift(ShuttleCommand command);//顶升
    }
    CommandResponse charge(ShuttleCommand command);//充电开关
    private void readStatus() {
        try {
            OperateResultExOne<byte[]> result = modbusTcpNet.Read("200", (short) 17);
            if (result.IsSuccess) {
                if (null == shuttleProtocol) {
                    shuttleProtocol = new ShuttleProtocol();
                    shuttleProtocol.setShuttleNo(slave.getId().shortValue());
                }
    CommandResponse reset(ShuttleCommand command);//复位开关
                //----------读取四向穿梭车状态-----------
                //获取数据
                byte[] content = result.Content;
                //小车忙状态位
                shuttleProtocol.setBusyStatus(modbusTcpNet.getByteTransform().TransInt16(content,0));
                //当前二维码
                shuttleProtocol.setCurrentCode(modbusTcpNet.getByteTransform().TransInt16(content,2));
                //电池电量百分比
                shuttleProtocol.setBatteryPower(modbusTcpNet.getByteTransform().TransInt16(content,4));
                //电池温度
                shuttleProtocol.setBatteryTemp(modbusTcpNet.getByteTransform().TransInt16(content,6));
                //错误编号
                shuttleProtocol.setErrorCode(modbusTcpNet.getByteTransform().TransInt16(content,8));
                //Plc输出状态IO
                shuttleProtocol.setPlcOutputStatusIO(modbusTcpNet.getByteTransform().TransInt16(content,10));
                //错误信息码
                shuttleProtocol.setStatusErrorCode(modbusTcpNet.getByteTransform().TransInt16(content,12));
                //PLC输入状态
                shuttleProtocol.setPlcInputStatus(modbusTcpNet.getByteTransform().TransInt16(content,14));
                //当前或者之前读到的二维码值
                shuttleProtocol.setCurrentOrBeforeCode(modbusTcpNet.getByteTransform().TransInt16(content,16));
                //读到的二维码X方向偏移量
                shuttleProtocol.setCodeOffsetX(modbusTcpNet.getByteTransform().TransInt16(content,18));
                //读到的二维码Y方向偏移量
                shuttleProtocol.setCodeOffsetY(modbusTcpNet.getByteTransform().TransInt16(content,20));
                //当前的电压值
                shuttleProtocol.setCurrentVoltage(modbusTcpNet.getByteTransform().TransInt16(content,22));
                //当前的模拟量值
                shuttleProtocol.setCurrentAnalogValue(modbusTcpNet.getByteTransform().TransInt16(content,24));
                //当前的升降伺服速度
                shuttleProtocol.setCurrentLiftServoSpeed(modbusTcpNet.getByteTransform().TransInt16(content,26));
                //当前的行走伺服速度
                shuttleProtocol.setCurrentMoveServoSpeed(modbusTcpNet.getByteTransform().TransInt16(content,28));
                //当前的升降伺服负载率
                shuttleProtocol.setCurrentLiftServoLoad(modbusTcpNet.getByteTransform().TransInt16(content,30));
                //当前的行走伺服负载率
                shuttleProtocol.setCurrentMoveServoLoad(modbusTcpNet.getByteTransform().TransInt16(content,32));
    CommandResponse updateLocation(ShuttleCommand command);//更新坐标
                ///读取四向穿梭车状态-end
    boolean isIdle();
                OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
                log.info(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
    boolean isIdle(ExecuteSupport support);//是否空闲
                // 根据实时信息更新数据库
                //.....
    boolean isDeviceIdle();//设备是否空闲
            }else {
                OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】{1}四向穿梭车plc状态信息失败", DateUtils.convert(new Date()), slave.getId()));
                throw new CoolException(MessageFormat.format( "四向穿梭车plc状态信息失败 ===>> [id:{0}] [ip:{1}] [port:{2}]", slave.getId(), slave.getIp(), slave.getPort()));
            }
        } catch (Exception e) {
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            initShuttle();
        }
    }
    boolean isDeviceIdle(ExecuteSupport support);//设备是否空闲
    private boolean write(ShuttleCommand command){
        if (null == command) {
            News.error("四向穿梭车写入命令为空");
            return false;
        }
    boolean isRequireCharge();//是否满足充电状态
        command.setShuttleNo(slave.getId());
        // 开始任务
        //...
        short[] array = new short[17];
        //控制指令字
        array[0] = command.getCommandWord();
        //启始二维编号
        array[1] = command.getStartCodeNum();
        //中间二维编号
        array[2] = command.getMiddleCodeNum();
        //目标二维编号
        array[3] = command.getDistCodeNum();
    boolean isCharging();//是否充电中
        //起点到目标点的距离长度,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
        short[] startToDistDistances = CommonUtils.intToShorts(command.getStartToDistDistance());
        array[4] = startToDistDistances[0];
        array[5] = startToDistDistances[1];
    boolean isChargingCompleted();//是否充电完成
        //中间点到目标点的距离长度,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
        short[] middleToDistDistances = CommonUtils.intToShorts(command.getMiddleToDistDistance());
        array[6] = middleToDistDistances[0];
        array[7] = middleToDistDistances[1];
    boolean isFault();//是否故障
        //小车运行方向
        array[8] = command.getRunDirection();
        //托盘顶升
        array[9] = command.getPalletLift();
    List<NavigateNode> getMoveAdvancePath();//获取穿梭车任务路径
        //小车强制移动距离,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
        short[] forceMoveDistances = CommonUtils.intToShorts(command.getForceMoveDistance());
        array[10] = forceMoveDistances[0];
        array[11] = forceMoveDistances[1];
    int generateDeviceTaskNo(int taskNo, ShuttleTaskNoType type);//生成硬件设备工作号
        //充电开关
        array[12] = command.getChargeSwitch();
        //小车IO控制
        array[13] = command.getIOControl();
        //小车运行速度
        array[14] = command.getRunSpeed();
        //小车雷达备用
        array[15] = command.getRadarTmp();
        //指令结束位
        array[16] = command.getCommandEnd();
    boolean setProtocolStatus(ShuttleProtocolStatusType status);//设置工作状态
        OperateResult result = modbusTcpNet.Write("0", array);;
        if (result != null && result.IsSuccess) {
            News.info("四向穿梭车命令下发[id:{}] >>>>> {}", slave.getId(), JSON.toJSON(command));
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2}", DateUtils.convert(new Date()), slave.getId(), JSON.toJSON(command)));
            return true;
        } else {
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】写入四向穿梭车plc数据失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            News.error("写入四向穿梭车plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
            return false;
        }
    }
    boolean setTaskNo(Integer taskNo);//设置工作号
    /**
     * 初始化四向穿梭车
     */
    private void initShuttle() {
        if (null == shuttleProtocol) {
            shuttleProtocol = new ShuttleProtocol();
        }
//        shuttleProtocol.setShuttleNo(slave.getId().shortValue());
//        shuttleProtocol.setBusyStatus(ShuttleStatusType.BUSY);
//        shuttleProtocol.setCurrentCode("0");
    }
    boolean setSyncTaskNo(Integer taskNo);//设置工作号
    /******************************************************************************************/
    /**************************************** 测试专用 *****************************************/
    /*****************************************************************************************/
    public static void main(String[] args) throws InterruptedException {
        ShuttleSlave slave = new ShuttleSlave();
        slave.setId(1);
        slave.setIp("192.168.4.24");
        slave.setPort(502);
        ShuttleThread thread = new ShuttleThread(slave);
        thread.connect();
        thread.readStatus();
    boolean setPakMk(boolean pakMk);//设置标记
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 0);
        command.setStartCodeNum((short) 12323);
        command.setMiddleCodeNum((short) 22323);
        command.setDistCodeNum((short) 29999);
        command.setStartToDistDistance(109999);
        command.setMiddleToDistDistance(5000);
        command.setRunDirection((short) 1);
        command.setPalletLift((short) 2);
        command.setForceMoveDistance(3000);
        command.setChargeSwitch((short) 2);
        command.setIOControl((short) 0);
        command.setRunSpeed((short) 0);
        command.setRadarTmp((short) 0);
        command.setCommandEnd((short) 1);
        thread.write(command);
    boolean enableMoveLoc(ShuttleMoveLocParam param, boolean enable);
    }
    boolean requestWaiting();
    boolean enableDemo(boolean enable);//演示模式
    boolean offerSystemMsg(String format, Object... arguments);
    //***************获取命令*****************
    ShuttleCommand getMoveCommand(Integer taskNo, String startCodeNum, String distCodeNum, Integer allDistance, Integer runDirection, Integer runSpeed, List<NavigateNode> nodes);//获取移动命令
    ShuttleCommand getLiftCommand(Integer taskNo, Boolean lift);//顶升命令 true=>顶升 false=>下降
    ShuttleCommand getChargeCommand(Integer taskNo, Boolean charge);//充电开关命令 true=>开 false=>关
    ShuttleCommand getUpdateLocationCommand(Integer taskNo, String locNo);//获取更新坐标命令
}