Browse Source

胶水采集

master
shenzhouyu 1 month ago
parent
commit
860e1f08b9
  1. 31
      src/main/java/com/xujie/sys/common/utils/ModbusUtils.java
  2. 188
      src/main/java/com/xujie/sys/modules/pms/service/Impl/QcServiceImpl.java

31
src/main/java/com/xujie/sys/common/utils/ModbusUtils.java

@ -27,11 +27,8 @@ public class ModbusUtils {
try { try {
master.connect(); master.connect();
Register[] registers = master.readMultipleRegisters(unitId, ref, 1); Register[] registers = master.readMultipleRegisters(unitId, ref, 1);
Register[] registers2 = master.readMultipleRegisters(unitId, 300, 1);
log.info("读取300地址寄存器成功 - IP: {}, Port: {}, Ref: {}, Value: {}",
ip, port, 300, registers2[0].getValue());
if (registers != null && registers.length > 0) { if (registers != null && registers.length > 0) {
log.info("读取302地址寄存器成功 - IP: {}, Port: {}, Ref: {}, Value: {}",
log.info("读取保持寄存器成功 - IP: {}, Port: {}, Ref: {}, Value: {}",
ip, port, ref, registers[0].getValue()); ip, port, ref, registers[0].getValue());
return registers[0].getValue(); return registers[0].getValue();
} }
@ -203,6 +200,32 @@ public class ModbusUtils {
return resultMap; return resultMap;
} }
/**
* 连续读取多字保持寄存器按批拆分后合并
* Modbus FC03 单次请求的字数超过从站允许上限常见 100125从站会返回异常码 0x03 Illegal Data Value
*/
public static Map<Integer, Integer> readHoldingRegistersBatched(String ip, int port, int slaveId, int offset, int quantity) {
final int maxPerRequest = 100;
Map<Integer, Integer> merged = new HashMap<>();
int pos = offset;
int left = quantity;
while (left > 0) {
int chunk = Math.min(maxPerRequest, left);
Map<Integer, Integer> part = readHoldingRegisters(ip, port, slaveId, pos, chunk);
if (part == null || part.isEmpty()) {
log.warn("分批读取保持寄存器中断 - offset={}, 本批 quantity={}, 已合并 {} 字", pos, chunk, merged.size());
break;
}
merged.putAll(part);
pos += chunk;
left -= chunk;
}
if (merged.size() < quantity) {
log.warn("分批读取保持寄存器未凑满 - 期望 {} 字, 实际 {} 字", quantity, merged.size());
}
return merged;
}
public static Map<Integer, Float> readFloatHoldingRegisters(String ip, int port, int slaveId, int offset, int quantity) { public static Map<Integer, Float> readFloatHoldingRegisters(String ip, int port, int slaveId, int offset, int quantity) {
Map<Integer, Float> resultMap = new HashMap<>(); Map<Integer, Float> resultMap = new HashMap<>();
ModbusTCPMaster master = new ModbusTCPMaster(ip, port); ModbusTCPMaster master = new ModbusTCPMaster(ip, port);

188
src/main/java/com/xujie/sys/modules/pms/service/Impl/QcServiceImpl.java

@ -4827,12 +4827,14 @@ public class QcServiceImpl implements QcService {
// 无工单检验先看302异常信号1则读取异常数据并复位0则直接返回空数据 // 无工单检验先看302异常信号1则读取异常数据并复位0则直接返回空数据
logger.info("orderNo:{}",data.getOrderNo()); logger.info("orderNo:{}",data.getOrderNo());
if ("000#1".equals(data.getOrderNo())) { if ("000#1".equals(data.getOrderNo())) {
Integer abnormalSignal = ModbusUtils.readSingleRegister(ip, port, unitId, isexceptionAdress);
//logCollectorModelModbusProbe(ip, port, unitId, isexceptionAdress);
Integer abnormalSignal = ModbusUtils.readSingleRegister(ip, port, unitId, isexceptionAdress-1);
if (abnormalSignal == null || abnormalSignal == 0) { if (abnormalSignal == null || abnormalSignal == 0) {
return new ArrayList<>(); return new ArrayList<>();
} }
ArrayList<SubDetailValues> abnormalRows = getAbnormalCollectorData(ip, port, unitId, data); ArrayList<SubDetailValues> abnormalRows = getAbnormalCollectorData(ip, port, unitId, data);
resetCollectorAbnormalRegisters(ip, port, unitId);
//resetCollectorAbnormalRegisters(ip, port, unitId);
return abnormalRows; return abnormalRows;
}else{ }else{
logger.info(port+","+ip+","+unitId+","+baseAddr+","+groups+","); logger.info(port+","+ip+","+unitId+","+baseAddr+","+groups+",");
@ -4862,6 +4864,77 @@ public class QcServiceImpl implements QcService {
return abnormalSignal != null && abnormalSignal == 1; return abnormalSignal != null && abnormalSignal == 1;
} }
/**
* 无工单 000#1屏显 40300/40302 等与 j2mod PDU(ref) 换算方式不一致时会导致采集器型号读错
* 一次性读取窗口并打印多种常见换算便于对照 Modbus 调试工具选用正确 ref
*/
private void logCollectorModelModbusProbe(String ip, int port, int unitId, Integer dbExceptionAddr) {
final int windowStart = 288;
final int windowLen = 36;
Map<Integer, Integer> raw = ModbusUtils.readHoldingRegisters(ip, port, unitId, windowStart, windowLen);
logger.info("[采集器型号探测] ip={} port={} unitId={} DB异常寄存器ref(isexceptionAdress)={}",
ip, port, unitId, dbExceptionAddr);
if (raw == null || raw.isEmpty()) {
logger.warn("[采集器型号探测] 批量读取 {}~{} 失败或无返回,后续单项读取仍可能成功", windowStart, windowStart + windowLen - 1);
logSingleRegisterProbe(ip, port, unitId);
return;
}
StringBuilder sb = new StringBuilder();
for (int r = windowStart; r < windowStart + windowLen; r++) {
Integer v = raw.get(r);
sb.append(String.format(Locale.ROOT, "%d=%s ", r, v == null ? "null" : String.valueOf(v & 0xFFFF)));
}
logger.info("[采集器型号探测] pdu {}~{} (unsigned): {}", windowStart, windowStart + windowLen - 1, sb.toString().trim());
int v299 = regU(raw, 299);
int v300 = regU(raw, 300);
int v301 = regU(raw, 301);
int v302 = regU(raw, 302);
int v303 = regU(raw, 303);
logger.info("[采集器型号探测] 常用单点: pdu299={} pdu300={} pdu301={} pdu302={} pdu303={}",
v299, v300, v301, v302, v303);
logger.info("[采集器型号探测] 换算A 屏显40300≈40001+299 → 看 pdu299={}; 屏显40302≈40001+301 → 看 pdu301={}", v299, v301);
logger.info("[采集器型号探测] 换算B 屏显40300≈40000+300 → 看 pdu300={}; 屏显40302≈40000+302 → 看 pdu302={}", v300, v302);
logger.info("[采集器型号探测] 换算C 后三位0300/0302 即 pdu300/pdu302 → {} / {}", v300, v302);
Map<Integer, Integer> batch299 = ModbusUtils.readHoldingRegisters(ip, port, unitId, 299, 10);
Map<Integer, Integer> batch300 = ModbusUtils.readHoldingRegisters(ip, port, unitId, 300, 10);
logger.info("[采集器型号探测] FC03 连续10个自 pdu299: {}", formatRegisterBlock(batch299, 299, 10));
logger.info("[采集器型号探测] FC03 连续10个自 pdu300: {}", formatRegisterBlock(batch300, 300, 10));
Integer single300 = ModbusUtils.readSingleRegister(ip, port, unitId, 300);
Integer single302 = ModbusUtils.readSingleRegister(ip, port, unitId, 302);
Integer single301 = ModbusUtils.readSingleRegister(ip, port, unitId, 301);
logger.info("[采集器型号探测] readSingleRegister 对照: ref301={} ref300={} ref302={}", single301, single300, single302);
}
/** 批量失败时再逐项单读,排除连接/批量限制问题 */
private static void logSingleRegisterProbe(String ip, int port, int unitId) {
for (int ref : new int[]{297, 298, 299, 300, 301, 302, 303}) {
Integer v = ModbusUtils.readSingleRegister(ip, port, unitId, ref);
logger.info("[采集器型号探测] 单读 pdu{} → {}", ref, v);
}
}
private static String formatRegisterBlock(Map<Integer, Integer> raw, int start, int count) {
if (raw == null || raw.isEmpty()) {
return "(empty)";
}
StringBuilder b = new StringBuilder();
for (int i = 0; i < count; i++) {
int r = start + i;
Integer v = raw.get(r);
b.append(String.format(Locale.ROOT, "[%d]=%s ", r, v == null ? "null" : String.valueOf(v & 0xFFFF)));
}
return b.toString().trim();
}
private static int regU(Map<Integer, Integer> raw, int ref) {
Integer v = raw.get(ref);
return v == null ? -1 : (v & 0xFFFF);
}
private EquipmentFolderLocation getCollectorLocation(String site) { private EquipmentFolderLocation getCollectorLocation(String site) {
LambdaQueryWrapper<EquipmentFolderLocation> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<EquipmentFolderLocation> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EquipmentFolderLocation::getEquipmentNo, "J001"); wrapper.eq(EquipmentFolderLocation::getEquipmentNo, "J001");
@ -4872,8 +4945,8 @@ public class QcServiceImpl implements QcService {
private ArrayList<SubDetailValues> getAbnormalCollectorData(String ip, int port, int unitId, QcFAIRecordData data) throws Exception { private ArrayList<SubDetailValues> getAbnormalCollectorData(String ip, int port, int unitId, QcFAIRecordData data) throws Exception {
int readStartAddr = 400; int readStartAddr = 400;
int readCount = 195; // 覆盖 400~594
Map<Integer, Integer> raw = ModbusUtils.readHoldingRegisters(ip, port, unitId, readStartAddr, readCount);
int readCount = 195; // 覆盖 400~594单次 FC03 字数不宜超过从站上限需分批读
Map<Integer, Integer> raw = ModbusUtils.readHoldingRegistersBatched(ip, port, unitId, readStartAddr, readCount);
ArrayList<SubDetailValues> subDetailValues = new ArrayList<>(); ArrayList<SubDetailValues> subDetailValues = new ArrayList<>();
if (raw == null || raw.isEmpty()) { if (raw == null || raw.isEmpty()) {
return subDetailValues; return subDetailValues;
@ -4911,6 +4984,12 @@ public class QcServiceImpl implements QcService {
continue; continue;
} }
// 每组 1 套时间6 个寄存器对应 5 个异常通道拆成 5 条记录每条 1 数值 + 1 时间
String collectedTime = String.format(Locale.ROOT,
"%d-%d %d:%d:%d",
timeParts.get(0), timeParts.get(1), timeParts.get(2),
timeParts.get(3), timeParts.get(4));
for (int i = 0; i < 5; i++) {
SubDetailValues detailValues = new SubDetailValues(); SubDetailValues detailValues = new SubDetailValues();
detailValues.setBuNo(data.getBu()); detailValues.setBuNo(data.getBu());
detailValues.setInspectionNo(data.getInspectionNo()); detailValues.setInspectionNo(data.getInspectionNo());
@ -4918,19 +4997,14 @@ public class QcServiceImpl implements QcService {
detailValues.setIsSubmit("N"); detailValues.setIsSubmit("N");
detailValues.setSite(data.getSite()); detailValues.setSite(data.getSite());
detailValues.setNum(1); detailValues.setNum(1);
detailValues.setSubDetailValue(String.valueOf(abnormalValues.get(0)));
detailValues.setSubDetailValueB(String.valueOf(abnormalValues.get(1)));
detailValues.setSubDetailValueC(String.valueOf(abnormalValues.get(2)));
detailValues.setSubDetailValueD(String.valueOf(abnormalValues.get(3)));
detailValues.setSubDetailValueE(String.valueOf(abnormalValues.get(4)));
detailValues.setSamplingLocation(String.format(
"%d-%d-%d %d:%d:%d",
timeParts.get(0), timeParts.get(1), timeParts.get(2),
timeParts.get(3), timeParts.get(4), timeParts.get(5)
));
detailValues.setSubDetailValue(String.valueOf(abnormalValues.get(i)));
detailValues.setSubDetailValueB(collectedTime);
detailValues.setSamplingLocationB(collectedTime);
subDetailValues.add(detailValues); subDetailValues.add(detailValues);
} }
}
logger.info("解析后获取到的数据:{}",subDetailValues.toString()); logger.info("解析后获取到的数据:{}",subDetailValues.toString());
batchInsertCollectorSubDetailRecords(data, subDetailValues);
return subDetailValues; return subDetailValues;
} }
@ -4953,13 +5027,50 @@ public class QcServiceImpl implements QcService {
logger.info("复位结束"); logger.info("复位结束");
} }
/**
* 按检验类型将采集子表明细批量写入对应 qc_*_sub_detail_record 常规 Modbus 与无工单异常采集共用
*/
private void batchInsertCollectorSubDetailRecords(QcFAIRecordData data, ArrayList<SubDetailValues> subDetailValues) {
if (subDetailValues == null || subDetailValues.isEmpty()) {
return;
}
if ("ipqc".equals(data.getSopType())) {
StringBuilder sql = new StringBuilder();
sql.append(" INSERT INTO qc_ipqc_sub_detail_record ");
sql.append(" (inspection_no, item_no, sub_detail_value, sampling_location, site, sampling_location_b, bu_no ,num) ");
sql.append(" VALUES ");
sql.append(" (:inspectionNo, :itemNo, :subDetailValue, :samplingLocation, :site, :samplingLocationB, :buNo ,:num) ");
parameterJdbcTemplate.batchUpdate(sql.toString(), SqlParameterSourceUtils.createBatch(subDetailValues.toArray()));
} else if ("iqc".equals(data.getSopType())) {
StringBuilder sql = new StringBuilder();
sql.append(" INSERT INTO qc_iqc_sub_detail_record ");
sql.append(" (inspection_no, item_no, sub_detail_value, sampling_location, site, sampling_location_b, bu_no ,num) ");
sql.append(" VALUES ");
sql.append(" (:inspectionNo, :itemNo, :subDetailValue, :samplingLocation, :site, :samplingLocationB, :buNo ,:num) ");
parameterJdbcTemplate.batchUpdate(sql.toString(), SqlParameterSourceUtils.createBatch(subDetailValues.toArray()));
} else if ("fai".equals(data.getSopType())) {
StringBuilder sql = new StringBuilder();
sql.append(" INSERT INTO qc_fai_sub_detail_record ");
sql.append(" (inspection_no, item_no, sub_detail_value, sampling_location, site, sampling_location_b, bu_no ,num) ");
sql.append(" VALUES ");
sql.append(" (:inspectionNo, :itemNo, :subDetailValue, :samplingLocation, :site, :samplingLocationB, :buNo ,:num) ");
parameterJdbcTemplate.batchUpdate(sql.toString(), SqlParameterSourceUtils.createBatch(subDetailValues.toArray()));
} else if ("fqc".equals(data.getSopType())) {
StringBuilder sql = new StringBuilder();
sql.append(" INSERT INTO qc_fqc_sub_detail_record ");
sql.append(" (inspection_no, item_no, sub_detail_value, sampling_location, site, sampling_location_b, bu_no,num) ");
sql.append(" VALUES ");
sql.append(" (:inspectionNo, :itemNo, :subDetailValue, :samplingLocation, :site, :samplingLocationB, :buNo ,:num) ");
parameterJdbcTemplate.batchUpdate(sql.toString(), SqlParameterSourceUtils.createBatch(subDetailValues.toArray()));
}
}
public ArrayList<SubDetailValues> getCollectorDataByModbus(int port,String ip,int unitId,int baseAddr,int groups,QcFAIRecordData data) throws Exception { public ArrayList<SubDetailValues> getCollectorDataByModbus(int port,String ip,int unitId,int baseAddr,int groups,QcFAIRecordData data) throws Exception {
final int avgAddr = 220;
// 每个点占用 2 个寄存器连续读取 200~221 22 个寄存器
final int quantity = (groups + 1) * 2; // 11 * 2 = 22
// 每个点占用 2 个寄存器只读 groups 个测量点不包含平均值 220 不再采集入库
final int quantity = groups * 2;
//固定采集两次
// 固定采集两次每次 groups 2 * groups 例如 10 通道时为 20
ArrayList<SubDetailValues> subDetailValues = new ArrayList<>(); ArrayList<SubDetailValues> subDetailValues = new ArrayList<>();
@ -4995,17 +5106,6 @@ public class QcServiceImpl implements QcService {
} }
} }
// 平均值地址 220同样按照高字在前组合
int highRefAvg = avgAddr;
int lowRefAvg = avgAddr + 1;
Integer highAvg = raw.get(highRefAvg);
Integer lowAvg = raw.get(lowRefAvg);
if (lowAvg != null && highAvg != null) {
int bits = (highAvg << 16) | (lowAvg & 0xFFFF);
float f = Float.intBitsToFloat(bits);
resultMap.put(String.valueOf(avgAddr), f);
}
for (Map.Entry<String, Float> entry : resultMap.entrySet()) { for (Map.Entry<String, Float> entry : resultMap.entrySet()) {
SubDetailValues detailValues = new SubDetailValues(); SubDetailValues detailValues = new SubDetailValues();
detailValues.setBuNo(data.getBu()); detailValues.setBuNo(data.getBu());
@ -5021,35 +5121,7 @@ public class QcServiceImpl implements QcService {
} }
if("ipqc".equals(data.getSopType())){
StringBuilder sql = new StringBuilder();
sql.append(" INSERT INTO qc_ipqc_sub_detail_record ");
sql.append(" (inspection_no, item_no, sub_detail_value, sampling_location, site, sampling_location_b, bu_no ,num) ");
sql.append(" VALUES ");
sql.append(" (:inspectionNo, :itemNo, :subDetailValue, :samplingLocation, :site, :samplingLocationB, :buNo ,:num) ");
parameterJdbcTemplate.batchUpdate(sql.toString(), SqlParameterSourceUtils.createBatch(subDetailValues.toArray()));
}else if("iqc".equals(data.getSopType())){
StringBuilder sql = new StringBuilder();
sql.append(" INSERT INTO qc_iqc_sub_detail_record ");
sql.append(" (inspection_no, item_no, sub_detail_value, sampling_location, site, sampling_location_b, bu_no ,num) ");
sql.append(" VALUES ");
sql.append(" (:inspectionNo, :itemNo, :subDetailValue, :samplingLocation, :site, :samplingLocationB, :buNo ,:num) ");
parameterJdbcTemplate.batchUpdate(sql.toString(), SqlParameterSourceUtils.createBatch(subDetailValues.toArray()));
}else if("fai".equals(data.getSopType())){
StringBuilder sql = new StringBuilder();
sql.append(" INSERT INTO qc_fai_sub_detail_record ");
sql.append(" (inspection_no, item_no, sub_detail_value, sampling_location, site, sampling_location_b, bu_no ,num) ");
sql.append(" VALUES ");
sql.append(" (:inspectionNo, :itemNo, :subDetailValue, :samplingLocation, :site, :samplingLocationB, :buNo ,:num) ");
parameterJdbcTemplate.batchUpdate(sql.toString(), SqlParameterSourceUtils.createBatch(subDetailValues.toArray()));
}else if("fqc".equals(data.getSopType())){
StringBuilder sql = new StringBuilder();
sql.append(" INSERT INTO qc_fqc_sub_detail_record ");
sql.append(" (inspection_no, item_no, sub_detail_value, sampling_location, site, sampling_location_b, bu_no,num) ");
sql.append(" VALUES ");
sql.append(" (:inspectionNo, :itemNo, :subDetailValue, :samplingLocation, :site, :samplingLocationB, :buNo ,:num) ");
parameterJdbcTemplate.batchUpdate(sql.toString(), SqlParameterSourceUtils.createBatch(subDetailValues.toArray()));
}
batchInsertCollectorSubDetailRecords(data, subDetailValues);
return subDetailValues; return subDetailValues;
} }

Loading…
Cancel
Save