package com.zy.acs.conveyor.core.thread; import HslCommunication.Core.Types.OperateResultExOne; import HslCommunication.Profinet.Siemens.SiemensS7Net; import com.zy.acs.common.utils.News; import com.zy.acs.conveyor.core.constant.DeviceField; import com.zy.acs.conveyor.core.constant.PlcAlarmDefinition; import com.zy.acs.conveyor.core.constant.StationStatusField; import com.zy.acs.conveyor.core.model.StaProtocol; import com.zy.acs.conveyor.core.properties.DevpSlave; import com.zy.acs.conveyor.core.service.DevpS7Service; import com.zy.acs.conveyor.core.service.StationService; import com.zy.acs.conveyor.entity.Devp; import com.zy.acs.conveyor.service.DevpService; import com.zy.acs.conveyor.utils.SpringContextUtil; import com.zy.acs.framework.common.Cools; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 输送线线程 * Created by vincent on 2020/8/4 */ @Data @Slf4j public class SiemensDevpThread implements Runnable { private DevpSlave slave; private SiemensS7Net siemensS7Net; private Map station; private static final int WRITE_RETRY_MAX = 5; private static final int WRITE_RETRY_INTERVAL_MS = 200; private static final int READ_INTERVAL_MS = 100; private static final int DB_UPDATE_INTERVAL_MS = 2000; // 数据库更新间隔 private long lastDbUpdateTime = 0; public SiemensDevpThread(DevpSlave slave, SiemensS7Net siemensS7Net, Map station) { this.slave = slave; this.siemensS7Net = siemensS7Net; this.station = station; } @Override @SuppressWarnings("InfiniteLoopStatement") public void run() { while (!Thread.currentThread().isInterrupted()) { try { read(); Thread.sleep(READ_INTERVAL_MS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); log.warn("SiemensDevp线程被中断 [id:{}]", slave.getId()); break; } catch (Exception e) { log.error("SiemensDevp线程运行异常 [id:{}]", slave.getId(), e); } } log.info("SiemensDevp读线程已退出 [id:{}]", slave.getId()); } /** * 读取状态 ====> 整块plc */ private void read() throws InterruptedException { if (siemensS7Net == null) { DevpS7Service devpS7Service = SpringContextUtil.getBean(DevpS7Service.class); if (devpS7Service != null) { siemensS7Net = devpS7Service.get(slave.getId()); } log.warn("PLC未连接,跳过读取 [id:{}]", slave.getId()); return; } if (station == null) { StationService stationService = SpringContextUtil.getBean(StationService.class); if (stationService != null) { station = stationService.getStationMap(slave.getId()); } log.warn("站点未连接,跳过读取 [id:{}]", slave.getId()); return; } List staNos = slave.getStaNos(); int staNoSize = staNos.size(); // 读取站点状态 OperateResultExOne result = siemensS7Net.Read( StationStatusField.ALL.buildAddress(), (short) (staNoSize * StationStatusField.ALL.getByteLength())); if (!result.IsSuccess) { log.error("读取站点状态失败 [id:{}] [error:{}]", slave.getId(), result.Message); return; } byte[] content = result.Content; for (int i = 0; i < staNoSize; i++) { StaProtocol staProtocol = station.get(staNos.get(staNoSize)); parseStationStatus(content, i, staProtocol); } // 读取条码 readBarcodes(); // 读取外形检测错误 readDimensionErrors(); // 读取PLC故障 readPlcAlarms(staNos, staNoSize); // 定期更新数据库(降低频率) updateDatabaseIfNeeded(); } /** * 解析单个站点状态 */ private void parseStationStatus(byte[] content, int index, StaProtocol staProtocol) { int offset = index * StationStatusField.ALL.getByteLength(); staProtocol.setWorkNo(siemensS7Net.getByteTransform().TransInt32(content, offset)); staProtocol.setStaNo((int) siemensS7Net.getByteTransform().TransInt16( content, offset + StationStatusField.FINAL_TARGET.getOffset())); boolean[] status = siemensS7Net.getByteTransform().TransBool( content, offset + StationStatusField.STATUS_WORD.getOffset(), StationStatusField.STATUS_WORD.getByteLength()); staProtocol.setAutoing(status[0]); staProtocol.setLoading(status[1]); staProtocol.setInEnable(status[2]); staProtocol.setOutEnable(status[3]); staProtocol.setEmptyMk(status[4]); staProtocol.setFullPlt(status[5]); staProtocol.setHigh(status[6]); staProtocol.setLow(status[7]); } /** * 读取条码信息 */ private void readBarcodes() { List barcodeArr = slave.getBarcodeArr(); if (barcodeArr == null || barcodeArr.isEmpty()) { return; } OperateResultExOne result = siemensS7Net.Read( DeviceField.BARCODE.buildAddress(), (short) (barcodeArr.size() * DeviceField.BARCODE.getByteLength())); if (!result.IsSuccess) { log.warn("读取条码失败 [id:{}]", slave.getId()); return; } byte[] content = result.Content; for (int i = 0; i < barcodeArr.size(); i++) { String barcode = siemensS7Net.getByteTransform().TransString( content, i * DeviceField.BARCODE.getByteLength(), DeviceField.BARCODE.getByteLength(), "UTF-8"); if (!Cools.isEmpty(barcode)) { StaProtocol staProtocol = station.get(barcodeArr.get(i)); staProtocol.setBarcode(barcode); News.info("料箱码:{}", barcode); } } } /** * 读取外形检测错误 */ private void readDimensionErrors() { List staNosError = slave.getStaNosError(); if (staNosError == null || staNosError.isEmpty()) { return; } OperateResultExOne result = siemensS7Net.Read( DeviceField.DIMENSION_WORD.buildAddress(), (short) (staNosError.size() * DeviceField.DIMENSION_WORD.getByteLength())); if (!result.IsSuccess) { log.warn("读取外形检测错误失败 [id:{}]", slave.getId()); return; } byte[] content = result.Content; for (int i = 0; i < staNosError.size(); i++) { Integer siteId = staNosError.get(i); StaProtocol staProtocol = station.get(siteId); boolean[] status = siemensS7Net.getByteTransform().TransBool( content, i * DeviceField.DIMENSION_WORD.getByteLength(), DeviceField.DIMENSION_WORD.getByteLength()); staProtocol.setFrontErr(status[0]); staProtocol.setBackErr(status[1]); staProtocol.setHighErr(status[2]); staProtocol.setLeftErr(status[3]); staProtocol.setRightErr(status[4]); staProtocol.setWeightErr(status[5]); staProtocol.setBarcodeErr(status[6]); } } /** * 读取PLC故障信息 */ private void readPlcAlarms(List staNos, int staNoSize) { OperateResultExOne result = siemensS7Net.Read( PlcAlarmDefinition.ALL.buildAddress(), (short) (staNoSize * PlcAlarmDefinition.ALL.getByteLength())); if (!result.IsSuccess) { log.warn("读取PLC故障信息失败 [id:{}]", slave.getId()); return; } byte[] content = result.Content; for (int i = 0; i < staNoSize; i++) { Integer siteId = staNos.get(i); StaProtocol staProtocol = station.get(siteId); if (staProtocol == null) { continue; } boolean[] status = siemensS7Net.getByteTransform().TransBool( content, i * PlcAlarmDefinition.ALL.getByteLength(), 1); staProtocol.setBreakerErr(status[0]); staProtocol.setInfraredErr(status[1]); staProtocol.setOutTimeErr(status[2]); staProtocol.setSeizeSeatErr(status[3]); staProtocol.setWrkYgoodsN(status[4]); staProtocol.setInverterErr(status[5]); staProtocol.setContactErr(status[6]); staProtocol.setUpcontactErr(status[7]); } } /** * 按需更新数据库(降低更新频率) */ private void updateDatabaseIfNeeded() { long currentTime = System.currentTimeMillis(); if (currentTime - lastDbUpdateTime < DB_UPDATE_INTERVAL_MS) { return; } try { List staNos = slave.getStaNos(); List devps = new ArrayList<>(staNos.size()); for (Integer siteId : staNos) { StaProtocol staProtocol = station.get(siteId); if (staProtocol != null) { devps.add(staProtocol.toSqlModel()); } } if (devps.isEmpty()) { return; } DevpService devpService = SpringContextUtil.getBean(DevpService.class); if (devpService != null) { devpService.updateBatchByDevpNo(devps); lastDbUpdateTime = currentTime; log.debug("批量更新数据库成功 [id:{}] [count:{}]", slave.getId(), devps.size()); } else { log.error("DevpService未找到,无法更新数据库 [id:{}]", slave.getId()); } } catch (Exception e) { log.error("更新数据库数据失败 [id:{}]", slave.getId(), e); News.error("SiemensDevp - 3 - 更新数据库数据失败 ===>> [id:{}]", slave.getId()); } } }