sige 1 year ago
parent
commit
5a7e098caf
  1. BIN
      app.db
  2. 19
      src/main/java/com/iflytop/digester/DigestionTaskThread.java
  3. 13
      src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java
  4. 20
      src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableSlot.java
  5. 38
      src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java
  6. 31
      src/main/java/com/iflytop/digester/model/MdbDigestionTaskLog.java
  7. 31
      src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java
  8. 4
      src/main/java/com/iflytop/digester/underframework/command/UfCmdDelay.java
  9. 6
      src/main/java/com/iflytop/digester/underframework/command/UfCommand.java
  10. 6
      src/main/java/com/iflytop/digester/underframework/connection/UfModbusRTUOverTCP.java
  11. 6
      src/main/java/com/iflytop/digester/underframework/resourcecontrol/systemcommand/TsCommand.java
  12. 10
      src/main/resources/application-dev.yml
  13. 2
      web

BIN
app.db

19
src/main/java/com/iflytop/digester/DigestionTaskThread.java

@ -162,8 +162,25 @@ public class DigestionTaskThread extends Thread {
device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index); device.transferArm.moveTubeRackToLiquidPlate(this.heatingSlot.index);
// 拍照检查异常试管 // 拍照检查异常试管
this.takeShotAndCheckErrorTubes(); this.takeShotAndCheckErrorTubes();
// 申请异常处理位
var errorSlot = device.heatingTurntable.getErrorSlot();
var emptyTubeIndexes = errorSlot.getEmptyTubeIndexes(this.errorTubeIndexes.size());
var errorTubeIndexes = this.errorTubeIndexes;
if ( emptyTubeIndexes.size() < this.errorTubeIndexes.size() ) {
errorTubeIndexes = this.errorTubeIndexes.subList(0, emptyTubeIndexes.size());
}
// 将异常试管放入异常处理区域 // 将异常试管放入异常处理区域
device.transferArm.moveTubesToErrorSlot(this.errorTubeIndexes);
device.transferArm.moveTubesToErrorSlot(errorTubeIndexes, emptyTubeIndexes);
// 更新试管状态
for ( var tubeIndex : errorTubeIndexes ) {
var tube = this.heatingSlot.tubes.get(tubeIndex);
errorSlot.tubes.set(emptyTubeIndexes.get(0), tube);
this.heatingSlot.tubes.set(tubeIndex, null);
}
// 将正常试管放入加热转盘 // 将正常试管放入加热转盘
device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index); device.transferArm.moveTubeRackToHeatingTurntable(this.heatingSlot.index);
} }

13
src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableInstance.java

@ -1,12 +1,15 @@
package com.iflytop.digester.deviceinstance; package com.iflytop.digester.deviceinstance;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.TimerTask; import java.util.TimerTask;
@Component @Component
public class HeatingTurntableInstance { public class HeatingTurntableInstance {
@Value("${app.errorSlotIndex}")
private Integer errorSlotIndex;
// 槽位列表 // 槽位列表
private final List<HeatingTurntableSlot> slots = new ArrayList<>(); private final List<HeatingTurntableSlot> slots = new ArrayList<>();
@ -15,6 +18,9 @@ public class HeatingTurntableInstance {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
HeatingTurntableSlot slot = new HeatingTurntableSlot(); HeatingTurntableSlot slot = new HeatingTurntableSlot();
slot.index = i; slot.index = i;
if (i == errorSlotIndex) {
slot.isErrorSlot = true;
}
slots.add(slot); slots.add(slot);
} }
} }
@ -24,6 +30,11 @@ public class HeatingTurntableInstance {
return slots; return slots;
} }
// 获取异常槽位
public HeatingTurntableSlot getErrorSlot() {
return slots.get(errorSlotIndex);
}
// 根据索引获取槽位 // 根据索引获取槽位
public HeatingTurntableSlot getSlotByIndex(Integer index) { public HeatingTurntableSlot getSlotByIndex(Integer index) {
return slots.get(index); return slots.get(index);

20
src/main/java/com/iflytop/digester/deviceinstance/HeatingTurntableSlot.java

@ -23,6 +23,8 @@ public class HeatingTurntableSlot {
public List<HeatingTurntableSlotTube> tubes = new ArrayList<>(); public List<HeatingTurntableSlotTube> tubes = new ArrayList<>();
// 试管架位置 // 试管架位置
public String tubeRackLocation = null; // heating-turntable:加热转盘 liquid-plate :加液盘 public String tubeRackLocation = null; // heating-turntable:加热转盘 liquid-plate :加液盘
// 是否异常槽位
public Boolean isErrorSlot = false;
// Constructor // Constructor
public HeatingTurntableSlot() { public HeatingTurntableSlot() {
@ -43,6 +45,17 @@ public class HeatingTurntableSlot {
} }
} }
// 获取空试管索引列表
public List<Integer> getEmptyTubeIndexes( Integer limit ) {
List<Integer> indexes = new ArrayList<>();
for (int i = 0; i < tubes.size(); i++) {
if ( null == tubes.get(i) && indexes.size() < limit ) {
indexes.add(i);
}
}
return indexes;
}
// 获取非空试管索引列表 // 获取非空试管索引列表
public List<Integer> getExistTubeIndexes() { public List<Integer> getExistTubeIndexes() {
List<Integer> indexes = new ArrayList<>(); List<Integer> indexes = new ArrayList<>();
@ -60,8 +73,11 @@ public class HeatingTurntableSlot {
this.heatingDuration = duration; this.heatingDuration = duration;
this.heatingStatus = "on"; this.heatingStatus = "on";
var snippetName = "HeatingTurntableSlotHeating.Start." + this.index;
Map<String,Object> snippetParams = Map.of("temperature", temperature, "duration", duration);
var snippetName = "HeatingTurntableSlotHeating." + this.index;
Map<String,Object> snippetParams = Map.of(
"temperature", temperature,
"duration", duration * 60 * 1000
);
UfCmdSnippetExecutor.execute(snippetName, snippetParams); UfCmdSnippetExecutor.execute(snippetName, snippetParams);
// 加热完成 // 加热完成

38
src/main/java/com/iflytop/digester/deviceinstance/TransferRobotArmInstance.java

@ -1,7 +1,9 @@
package com.iflytop.digester.deviceinstance; package com.iflytop.digester.deviceinstance;
import com.iflytop.digester.underframework.UfCmdSnippetExecutor; import com.iflytop.digester.underframework.UfCmdSnippetExecutor;
import com.iflytop.digester.underframework.dao.model.UfMdbOption;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -16,37 +18,33 @@ public class TransferRobotArmInstance {
this.lockArm(lock); this.lockArm(lock);
// 执行从异常槽位取出试管 // 执行从异常槽位取出试管
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlotStart");
for (Integer tubeIndex : tubeIndexes) { for (Integer tubeIndex : tubeIndexes) {
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlot", Map.of(
"MotorLiquidPlatePos", 100,
"MotorArmLeftRightSrcPos", 100,
"MotorArmLeftRightDstPos", 100,
"MotorHeatingTurntablePos", 100
));
var snippetKey = "TubeTakeOutFromErrorSlot";
var snippetParams = new HashMap<String, Object>();
snippetParams.put("LiquidPlatePos", UfMdbOption.getInteger("LiquidPlateTube." + tubeIndex, 0));
snippetParams.put("TransLrSrcPos", UfMdbOption.getInteger("HeatPlateErrorSlotTube." + tubeIndex, 0));
snippetParams.put("HeatingPlatePos", UfMdbOption.getInteger("TransLrMotorLiquidPlateTube." + tubeIndex, 0));
snippetParams.put("TransLrDestPos", UfMdbOption.getInteger("TransLrMotorHeatingPlateTube." + tubeIndex, 0));
UfCmdSnippetExecutor.execute(snippetKey, snippetParams);
} }
UfCmdSnippetExecutor.execute("TubeTakeOutFromErrorSlotEnd");
this.unlockArm(lock); this.unlockArm(lock);
} }
// 移动试管到异常槽位 // 移动试管到异常槽位
public void moveTubesToErrorSlot(List<Integer> tubeIndexes) {
public void moveTubesToErrorSlot(List<Integer> srcIndexes, List<Integer> destIndexes) {
var lock = new Object(); var lock = new Object();
this.lockArm(lock); this.lockArm(lock);
// 执行移动试管到异常槽位 // 执行移动试管到异常槽位
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlotStart");
for (Integer tubeIndex : tubeIndexes) {
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlot", Map.of(
"MotorLiquidPlatePos", 100,
"MotorArmLeftRightSrcPos", 100,
"MotorArmLeftRightDstPos", 100,
"MotorHeatingTurntablePos", 100
));
for (Integer tubeIndex : srcIndexes) {
String snippetKey = "TubeMoveToErrorSlot";
Map<String,Object> snippetParams = new HashMap<>();
snippetParams.put("LiquidPlatePos", UfMdbOption.getInteger("LiquidPlateTube." + tubeIndex, 0));
snippetParams.put("TransLrSrcPos", UfMdbOption.getInteger("TransLrMotorLiquidPlateTube." + tubeIndex, 0));
snippetParams.put("HeatingPlatePos", UfMdbOption.getInteger("HeatPlateErrorSlotTube." + tubeIndex, 0));
snippetParams.put("TransLrDestPos", UfMdbOption.getInteger("TransLrMotorHeatingPlateTube." + tubeIndex, 0));
UfCmdSnippetExecutor.execute(snippetKey, snippetParams);
} }
UfCmdSnippetExecutor.execute("TubeMoveToErrorSlotEnd");
this.unlockArm(lock); this.unlockArm(lock);
} }

31
src/main/java/com/iflytop/digester/model/MdbDigestionTaskLog.java

@ -0,0 +1,31 @@
package com.iflytop.digester.model;
import com.iflytop.digester.underframework.dao.record.UfActiveRecord;
import com.iflytop.digester.underframework.dao.record.UfActiveRecordField;
public class MdbDigestionTaskLog extends UfActiveRecord {
@UfActiveRecordField
public String taskId;
@UfActiveRecordField
public String action;
@UfActiveRecordField
public String content;
@UfActiveRecordField
public Long timestamp;
// get table name
public static String getTableName() {
return "app_digestion_task_logs";
}
// log
public static void log(String taskId, String action, String content) {
var log = new MdbDigestionTaskLog();
log.taskId = taskId;
log.action = action;
log.content = content;
log.timestamp = System.currentTimeMillis();
log.save();
}
}

31
src/main/java/com/iflytop/digester/underframework/UfCmdSnippetExecutor.java

@ -2,6 +2,8 @@ package com.iflytop.digester.underframework;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.iflytop.digester.underframework.command.UfCommand;
import com.iflytop.digester.underframework.util.UfClassHelper;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.Template; import freemarker.template.Template;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
@ -14,6 +16,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.io.StringWriter; import java.io.StringWriter;
public class UfCmdSnippetExecutor { public class UfCmdSnippetExecutor {
@ -79,15 +82,36 @@ public class UfCmdSnippetExecutor {
public void executeStep(String cmdId, String cmdParams) { public void executeStep(String cmdId, String cmdParams) {
var cmd = UfActiveRecord.findOne(UfMdbActuatorCmd.class, cmdId); var cmd = UfActiveRecord.findOne(UfMdbActuatorCmd.class, cmdId);
if (null == cmd) { if (null == cmd) {
this.executeBuildInCmd(cmdId, cmdParams);
return;
}
cmd.parameters = this.compileParameterString(cmdParams);
UfActuatorCmdExecutor.execute(cmd);
}
// execute build-in command
private void executeBuildInCmd( String cmdId, String cmdParams ) {
var buildInCmdClassName = this.getClass().getPackageName() + ".command.UfCmd" + cmdId;
UfCommand buildInCmd = null;
try {
buildInCmd = (UfCommand)UfClassHelper.newInstance(buildInCmdClassName);
} catch ( Exception e ) {
throw new RuntimeException("无效的指令ID : " + cmdId); throw new RuntimeException("无效的指令ID : " + cmdId);
} }
// 编译参数为模板
cmdParams = this.compileParameterString(cmdParams);
List<String> args = List.of(cmdParams.split(","));
buildInCmd.execute(args);
}
// 编译参数字符串
private String compileParameterString( String paramText ) {
freemarker.template.Configuration cfg = new Configuration(Configuration.VERSION_2_3_31); freemarker.template.Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
cfg.setNumberFormat("0"); cfg.setNumberFormat("0");
Template template = null; Template template = null;
try { try {
template = new Template("", cmdParams, cfg);
template = new Template("", paramText, cfg);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -97,7 +121,6 @@ public class UfCmdSnippetExecutor {
} catch (TemplateException | IOException e) { } catch (TemplateException | IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
cmd.parameters = paramStrWriter.toString();
UfActuatorCmdExecutor.execute(cmd);
return paramStrWriter.toString();
} }
} }

4
src/main/java/com/iflytop/digester/underframework/resourcecontrol/systemcommand/TsCmdDelay.java → src/main/java/com/iflytop/digester/underframework/command/UfCmdDelay.java

@ -1,6 +1,6 @@
package com.iflytop.digester.underframework.resourcecontrol.systemcommand;
package com.iflytop.digester.underframework.command;
import java.util.List; import java.util.List;
public class TsCmdDelay implements TsCommand {
public class UfCmdDelay implements UfCommand {
@Override @Override
public void execute( List<String> args ) { public void execute( List<String> args ) {
// get delay time // get delay time

6
src/main/java/com/iflytop/digester/underframework/command/UfCommand.java

@ -0,0 +1,6 @@
package com.iflytop.digester.underframework.command;
import java.util.List;
public interface UfCommand {
// execute
void execute( List<String> args );
}

6
src/main/java/com/iflytop/digester/underframework/connection/UfModbusRTUOverTCP.java

@ -38,14 +38,14 @@ public class UfModbusRTUOverTCP extends UfConnectionBase {
synchronized public String execute(UfMdbActuatorCmd command) { synchronized public String execute(UfMdbActuatorCmd command) {
if ( "03".equals(command.cmdId) ) { if ( "03".equals(command.cmdId) ) {
Integer slaveId = Integer.parseInt(command.cmdFlags); Integer slaveId = Integer.parseInt(command.cmdFlags);
Integer address = Integer.parseInt(command.parameters);
Integer address = Integer.parseInt(command.parameters.trim());
Integer value = this.readHoldingRegister(slaveId, address); Integer value = this.readHoldingRegister(slaveId, address);
return value.toString(); return value.toString();
} else if ( "06".equals(command.cmdId) ) { } else if ( "06".equals(command.cmdId) ) {
Integer slaveId = Integer.parseInt(command.cmdFlags); Integer slaveId = Integer.parseInt(command.cmdFlags);
String[] params = command.parameters.split(","); String[] params = command.parameters.split(",");
Integer address = Integer.parseInt(params[0]);
Integer value = Integer.parseInt(params[1]);
Integer address = Integer.parseInt(params[0].trim());
Integer value = Integer.parseInt(params[1].trim());
this.writeHoldingRegister(slaveId, address, value); this.writeHoldingRegister(slaveId, address, value);
return ""; return "";
} else { } else {

6
src/main/java/com/iflytop/digester/underframework/resourcecontrol/systemcommand/TsCommand.java

@ -1,6 +0,0 @@
package com.iflytop.digester.underframework.resourcecontrol.systemcommand;
import java.util.List;
public interface TsCommand {
// execute
void execute( List<String> args );
}

10
src/main/resources/application-dev.yml

@ -13,16 +13,16 @@ device:
connections: connections:
- name : zcancmder - name : zcancmder
key : zcancmder key : zcancmder
enable : false
enable : true
type : ZcancmderWebsocket type : ZcancmderWebsocket
# uri: ws://192.168.8.10:19005
uri : ws://127.0.0.1:19005
uri: ws://192.168.8.10:19005
# uri : ws://127.0.0.1:19005
- name : modbus - name : modbus
key : modbus key : modbus
enable : true enable : true
type : ModbusRTUOverTCP type : ModbusRTUOverTCP
host: 127.0.0.1
port: 502
host: 192.168.8.10
port: 20000
mqtt-broker: mqtt-broker:
uri: tcp://broker.emqx.io:1883 uri: tcp://broker.emqx.io:1883

2
web

@ -1 +1 @@
Subproject commit 1513f7b9d26f452c6ded8c1d7fe43c047fab162a
Subproject commit 464111807ce66ce1d0f0652455cc17689d12ab7e
Loading…
Cancel
Save