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.math.BigDecimal;
|
import java.math.RoundingMode;
|
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<Integer, StaProtocol> 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<Integer, StaProtocol> 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<Integer> staNos = slave.getStaNos();
|
int staNoSize = staNos.size();
|
|
// 读取站点状态
|
OperateResultExOne<byte[]> 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();
|
|
// 称重
|
readWeight();
|
|
// 读取外形检测错误
|
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<Integer> barcodeArr = slave.getBarcodeArr();
|
if (barcodeArr == null || barcodeArr.isEmpty()) {
|
return;
|
}
|
|
OperateResultExOne<byte[]> 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));
|
if (staProtocol == null) {
|
log.warn("站点不存在 [id:{}] [staNo:{}]", slave.getId(), barcodeArr.get(i));
|
continue;
|
}
|
staProtocol.setBarcode(barcode);
|
News.info("料箱码:{}", barcode);
|
}
|
}
|
}
|
|
/**
|
* 读取条码信息
|
*/
|
private void readWeight() {
|
List<Integer> weightArr = slave.getWeightArr();
|
if (weightArr == null || weightArr.isEmpty()) {
|
return;
|
}
|
|
OperateResultExOne<byte[]> result = siemensS7Net.Read(
|
DeviceField.WEIGHT.buildAddress(),
|
(short) (weightArr.size() * DeviceField.WEIGHT.getByteLength()));
|
|
if (!result.IsSuccess) {
|
log.warn("读取重量失败 [id:{}]", slave.getId());
|
return;
|
}
|
for (int i = 0; i < weightArr.size(); i++) {
|
StaProtocol staProtocol = station.get(weightArr.get(i));
|
if (staProtocol == null) {
|
log.warn("站点不存在 [id:{}] [staNo:{}]", slave.getId(), weightArr.get(i));
|
continue;
|
}
|
double weight = siemensS7Net.getByteTransform().TransSingle(result.Content, i * DeviceField.WEIGHT.getByteLength());
|
staProtocol.setWeight(BigDecimal.valueOf(weight).setScale(4, RoundingMode.HALF_UP).doubleValue());
|
}
|
}
|
|
/**
|
* 读取外形检测错误
|
*/
|
private void readDimensionErrors() {
|
List<Integer> staNosError = slave.getStaNosError();
|
if (staNosError == null || staNosError.isEmpty()) {
|
return;
|
}
|
|
OperateResultExOne<byte[]> 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);
|
if (staProtocol == null){
|
log.warn("站点不存在 [id:{}] [staNo:{}]", slave.getId(), staNosError.get(i));
|
continue;
|
}
|
|
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<Integer> staNos, int staNoSize) {
|
OperateResultExOne<byte[]> 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) {
|
log.warn("站点不存在 [id:{}] [staNo:{}]", slave.getId(), siteId);
|
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<Integer> staNos = slave.getStaNos();
|
List<Devp> 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());
|
}
|
}
|
|
|
}
|