diff --git a/ruoyi-admin/src/main/java/com/ruoyi/device/srgv/domain/DeviceSrgv.java b/ruoyi-admin/src/main/java/com/ruoyi/device/srgv/domain/DeviceSrgv.java index 58da29c..fc28d6a 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/device/srgv/domain/DeviceSrgv.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/device/srgv/domain/DeviceSrgv.java @@ -18,69 +18,40 @@ import lombok.NoArgsConstructor; public class DeviceSrgv extends BaseEntity { private static final long serialVersionUID = 1L; + /* + * 实时数据 + * */ + private int taskNo;//任务号 + private String srcSite;//原地址 + private String tarSite;//目标地址 + private String currSite;//当期地址 - /** $column.columnComment */ - private Long id; + private int taskType;//任务类型 - /** 设备唯一编码 */ - @Excel(name = "设备唯一编码") - private String deviceCode ; + private int battery;//电量 + private int workMode;//工作模式 + private int alarm;//报警 + private int status;//车状态 + private int finish;//接收完成标志 1接收完成 + private int chargeFlag;//充电标志 todo 充电状态值确认 + private int workPhase;//工作阶段 + private int errorMsg;//异常信息 + private int deviceRequest;//输送机对接请求 + private int changeLayer;//换层标志 + private int cargoFlag;//载货 0未知 1空载 2载货 + private int manualCharge;//手动充电 0未知 1充电 - /** 设备名称 */ - @Excel(name = "设备名称") - private String name ; + private int undefined1;// + private int undefined2;// - /** 类型 */ - @Excel(name = "类型") - private String type; + private String path;//路径 - /** 设备IP */ - @Excel(name = "设备IP") - private String ipAddress; + //其他属性 + private int currFloor;//当前层 - /** PLC读取地址 */ - @Excel(name = "PLC读取地址") - private String plcDbReadAddress; + private String spaceArea;//当前库存 01小库 02大库 - /** 0-F 1-T */ - @Excel(name = "0-F 1-T") - private String isActive; - - /** PLC写入地址 */ - @Excel(name = "PLC写入地址") - private String plcDbWriteAddress; - - /** 入库请求 */ - @Excel(name = "入库请求") - private int rkqq; - - /** 空闲 */ - @Excel(name = "空闲") - private int kx; - - /** 到位 */ - @Excel(name = "到位") - private int dw; - - /** 条码 */ - @Excel(name = "条码") - private String trayCode; - - /** 任务号 */ - @Excel(name = "任务号") - private int taskNo; - - @Excel(name = "异常") - private int exception; - - @Excel(name = "托盘尺寸") - private int traySize; - - @Excel(name="允许放货") - private int allowPut; - - @Excel(name="输送线模式 1-入库 2-出库") - private int model; + private int allowSend;//1允许下发 diff --git a/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/ddj/PlcDdjRead.java b/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/ddj/PlcDdjRead.java index f96758f..6da78b8 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/ddj/PlcDdjRead.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/ddj/PlcDdjRead.java @@ -17,7 +17,7 @@ import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ConcurrentHashMap; @Slf4j -public class PlcDdjRead extends Thread { +public class PlcDdjRead implements Runnable { public static ConcurrentHashMap deviceDdjMap; public volatile boolean isRun = true; diff --git a/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/srgv/FloorUtils.java b/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/srgv/FloorUtils.java new file mode 100644 index 0000000..1442bfd --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/srgv/FloorUtils.java @@ -0,0 +1,33 @@ +package com.ruoyi.schedule.plcRead.srgv; + +public class FloorUtils { + + /** + * 从cur值中提取楼层信息 + * @param cur 原始楼层值 + * @return 处理后的楼层值,如果小于等于0则返回0 + */ + public static int extractFloor(Integer cur) { + // 处理null值 + if (cur == null) { + return 0; + } + + // 获取后两位(处理负数情况) + int floor = Math.abs(cur) % 100; + + // 如果结果小于等于0,返回默认值0 + return floor <= 0 ? 0 : floor; + } + + /** + * 重载方法,处理int类型 + */ + public static int extractFloor(int cur) { + // 获取后两位(处理负数情况) + int floor = Math.abs(cur) % 100; + + // 如果结果小于等于0,返回默认值0 + return floor <= 0 ? 0 : floor; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/srgv/PlcSrgvRead.java b/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/srgv/PlcSrgvRead.java new file mode 100644 index 0000000..67d86c6 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/schedule/plcRead/srgv/PlcSrgvRead.java @@ -0,0 +1,197 @@ +package com.ruoyi.schedule.plcRead.srgv; + +import HslCommunication.Core.Net.IReadWriteNet; +import HslCommunication.Core.Transfer.DataFormat; +import HslCommunication.Core.Transfer.IByteTransform; +import HslCommunication.Core.Types.OperateResult; +import HslCommunication.Core.Types.OperateResultExOne; +import HslCommunication.ModBus.ModbusTcpNet; +import com.ruoyi.common.domain.HslRead; +import com.ruoyi.common.domain.PlcConnectInfo; +import com.ruoyi.device.srgv.domain.DeviceSrgv; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +@Slf4j +public class PlcSrgvRead implements Runnable{ + + public static ConcurrentHashMap deviceSrgvMap; + private ModbusTcpNet modbusTcpNet; + public static IReadWriteNet readWriteNet = null; + public volatile boolean isRun = true; + private final String ip; + private final int port; + private byte station; + private Integer layer; + private boolean success = false; + private IByteTransform byteTransform = null; + + public PlcSrgvRead(ConcurrentHashMap deviceSrgvMap, PlcConnectInfo plcConnectInfo){ + PlcSrgvRead.deviceSrgvMap = deviceSrgvMap; + this.ip = plcConnectInfo.getIp(); + this.port = plcConnectInfo.getPort(); + this.station=(byte)1; + } + public static int WriteToSSJ(String address, byte[] data) { + int a = 0; + if (readWriteNet != null) { + a = HslRead.WriteResultRender(readWriteNet.Write(address, data), address); + } + return a; + } + + + + @Override + public void run() { + while (isRun) { + try { + if (IsConnect()) { + for(String srgvId:deviceSrgvMap.keySet()){ + DeviceSrgv deviceSrgv = deviceSrgvMap.get(srgvId); + if(deviceSrgv!=null){ + readSrgvPlc(deviceSrgv); + } + } + + Thread.sleep(1000); + } else { + reConnect(); + } + }catch (InterruptedException e) { + // 捕获中断异常,退出循环 + Thread.currentThread().interrupt(); // 重新设置中断标志 + return; + } catch (Exception e) { + log.info("********IP:" + this.ip + " port:" + this.port + "读取数据异常 " + e.getMessage()); + } + + } + } + private void readSrgvPlc(DeviceSrgv deviceSrgv){ + OperateResultExOne read1 = modbusTcpNet.Read("2400",(short)15);//2400-2414 + if (read1.IsSuccess) { + setValueByByte1(read1.Content,deviceSrgv); + } + + //读取双字 + OperateResultExOne read2 = modbusTcpNet.Read("4800",(short)8);// 4800-4807任务号、原点、目标点、当前 + if(read2.IsSuccess){ + setValueByByte2(read2.Content,deviceSrgv); + } + + //读取双字,路径 + OperateResultExOne read3 = modbusTcpNet.Read("5000",(short)800);// 5000-5799 路径 400个 + setValueByByte3(read3.Content,deviceSrgv); + } + + //单字 + private void setValueByByte1(byte[] content , DeviceSrgv agvData) { + agvData.setTaskType(byteTransform.TransInt16(content,0)); + agvData.setBattery(byteTransform.TransInt16(content,2)); + agvData.setWorkMode(byteTransform.TransInt16(content,4)); + agvData.setAlarm(byteTransform.TransInt16(content,6)); + agvData.setStatus(byteTransform.TransInt16(content,8)); + agvData.setFinish(byteTransform.TransInt16(content,10)); + agvData.setChargeFlag(byteTransform.TransInt16(content,12)); + agvData.setWorkPhase(byteTransform.TransInt16(content,14)); + agvData.setErrorMsg(byteTransform.TransInt16(content,16)); + agvData.setDeviceRequest(byteTransform.TransInt16(content,18)); + agvData.setChangeLayer(byteTransform.TransInt16(content,20)); + agvData.setCargoFlag(byteTransform.TransInt16(content,22)); + agvData.setManualCharge(byteTransform.TransInt16(content,24)); + agvData.setUndefined1(byteTransform.TransInt16(content,26)); + agvData.setAllowSend(byteTransform.TransInt16(content,16)); + + + } + + private void setValueByByte2(byte[] content, DeviceSrgv agvData) { + byteTransform.setDataFormat(DataFormat.CDAB); + // TODO 注意双字反转 + agvData.setTaskNo(byteTransform.TransInt32(content,0)); + agvData.setSrcSite(String.format("%06d", byteTransform.TransInt32(content,4))); + agvData.setTarSite(String.format("%06d", byteTransform.TransInt32(content,8))); + agvData.setCurrSite(String.format("%06d", byteTransform.TransInt32(content,12))); + + //设置库区 + String currSite = agvData.getCurrSite(); + String l = currSite.substring(2, 4); + int li = Integer.parseInt(l);//列 + if(li<23){ + agvData.setSpaceArea("01"); + }else { + agvData.setSpaceArea("02"); + } + + //截取cur的后俩位,获取当前楼层 + int floor = FloorUtils.extractFloor(Integer.parseInt(agvData.getCurrSite())); + this.layer = floor; + agvData.setCurrFloor(floor); + } + + private void setValueByByte3(byte[] content, DeviceSrgv agvData) { + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < content.length; i += 4) { + // 检查剩余字节是否足够4个 + if (i + 4 > content.length) break; + // TODO 注意双字反转 + int value = byteTransform.TransInt32(content, i); + + // 如果值为0,终止循环 + if (value == 0) { + break; + } + sb.append(String.format("%06d", value)).append(","); // 用逗号分隔每个int值 + } + + // 移除最后多余的 "," + if (sb.length() > 0) { + sb.setLength(sb.length() - 1); + } + agvData.setPath(sb.toString()); + } + + public void ConnectServer(){ + ModbusTcpNet modbusTcpNet = new ModbusTcpNet();//创建一个Modbus对象 + try{ + modbusTcpNet.setIpAddress(this.ip); + modbusTcpNet.setPort(this.port); + modbusTcpNet.setStation(station); + this.byteTransform=modbusTcpNet.getByteTransform(); + OperateResult connect = modbusTcpNet.ConnectServer(); + if (connect.IsSuccess) { + setIsConnect(true); + readWriteNet = modbusTcpNet; + } + }catch (Exception ex) { + log.info("********IP:" + this.ip + " port:" + this.port + "连接失败 " + ex.getMessage()); + } + } + public void setIsConnect(boolean bflag) { + if (!success) { + success = bflag; + } + } + + public boolean IsConnect() { + if (success) { + return success; + } + return false; + } + void reConnect() { + closeServer(); + ConnectServer(); + log.info("重新连接 SSJ-PLC"); + } + + void closeServer() { + if (readWriteNet != null) { + readWriteNet.ConnectClose(); + } + setIsConnect(false); + } +}