|
|
package com.dreamworks.boditech.driver; import com.dreamworks.boditech.driver.actuator.*; import com.dreamworks.boditech.driver.connection.ComSerialPort; import com.dreamworks.boditech.driver.consumable.CsmBufferTubeA; import com.dreamworks.boditech.driver.consumable.CsmBufferTubeB; import com.dreamworks.boditech.driver.consumable.CsmLargeBufferTube; import com.dreamworks.boditech.driver.consumable.CsmPipetteTip; import com.dreamworks.boditech.service.RuntimeOptionService; import com.dreamworks.boditech.utils.MyByteBuffer; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Component public class Device { private static final Logger LOG = LoggerFactory.getLogger(Device.class);
@Value("${app.device.debug}") private Boolean debug;
@Resource private ComSerialPort serialPort;
@Resource private RuntimeOptionService runtimeOptionService;
// actuators
private final Map<Integer, Actuator> actuators = new HashMap<Integer, Actuator>(); // pipette tips
private final List<CsmPipetteTip> pipetteTips = new ArrayList<CsmPipetteTip>(); // buffer tube larges
private final List<CsmLargeBufferTube> largeBufferTubes = new ArrayList<CsmLargeBufferTube>(); // buffer tube A
private final List<CsmBufferTubeA> bufferTubeAList = new ArrayList<CsmBufferTubeA>(); // buffer tube B
private final List<CsmBufferTubeB> bufferTubeBList = new ArrayList<CsmBufferTubeB>(); // message index
private short messageIndex = 0;
@PostConstruct public void init() { this.appendActuator(new ActModuleTestTubeRackMovement(ActuatorModule.TEST_TUBE_RACK_MOVEMENT, this)); this.appendActuator(new ActMotor(ActuatorModule.TEST_TUBE_RACK_FEED_MOTOR, this)); this.appendActuator(new ActMotor(ActuatorModule.TEST_TUBE_RACK_MOVE_MOTOR, this)); this.appendActuator(new ActMotor(ActuatorModule.TEST_TUBE_RACK_EXIT_MOTOR, this)); this.appendActuator(new ActCodeScanner(ActuatorModule.TEST_TUBE_RACK_SCANNER, this)); this.appendActuator(new ActMotor(ActuatorModule.TEST_TUBE_SHAKING_MOVE_MOTOR, this)); this.appendActuator(new ActMotor(ActuatorModule.TEST_TUBE_SHAKING_CAP_CLIP_MOTOR, this)); this.appendActuator(new ActMotor(ActuatorModule.TEST_TUBE_SHAKING_SHAKE_MOTOR, this)); this.appendActuator(new ActMotor(ActuatorModule.TEST_TUBE_SHAKING_ROTATE_MOTOR, this)); this.appendActuator(new ActMotor(ActuatorModule.TEST_TUBE_SHAKING_CLIP_MOTOR, this)); this.appendActuator(new ActArmXY(ActuatorModule.ARM_XY, this)); this.appendActuator(new ActMotor(ActuatorModule.ARM_Z_MOTOR, this)); this.appendActuator(new ActPipette(ActuatorModule.ARM_Z_PIPETTE, this)); }
// append actuator
private void appendActuator(Actuator actuator) { this.actuators.put(actuator.getMid(), actuator); }
// get actuator by module id
public Actuator getActuator(Integer mid) { return this.actuators.get(mid); }
// append buffer tube A
public void appendBufferTubeA( Integer areaIndex, Integer amount ) { for (int i = 0; i<amount; i++ ) { CsmBufferTubeA tube = new CsmBufferTubeA(); tube.areaIndex = areaIndex; tube.position = i; this.bufferTubeAList.add(tube); } }
// get buffer tube A
public CsmBufferTubeA getBufferTubeA( String projectName ) { for (CsmBufferTubeA tube : this.bufferTubeAList) { if (!tube.projectName.equals(projectName)) { continue; } this.bufferTubeAList.remove(tube); return tube; } throw new RuntimeException("no buffer tube A for project " + projectName); }
// append buffer tube B
public void appendBufferTubeB( Integer areaIndex, Integer amount ) { for (int i = 0; i<amount; i++ ) { CsmBufferTubeB tube = new CsmBufferTubeB(); tube.areaIndex = areaIndex; tube.position = i; this.bufferTubeBList.add(tube); } }
// get buffer tube B
public CsmBufferTubeB getBufferTubeB( String projectName ) { for (CsmBufferTubeB tube : this.bufferTubeBList) { if (!tube.projectName.equals(projectName)) { continue; } this.bufferTubeBList.remove(tube); return tube; } throw new RuntimeException("no buffer tube B for project " + projectName); }
// append pipette tip
public void appendPipetteTip( Integer areaIndex, Integer amount ) { for (int i = 0; i<amount; i++ ) { CsmPipetteTip tip = new CsmPipetteTip(); tip.areaIndex = areaIndex; tip.position = i; this.pipetteTips.add(tip); } }
// get pipette tip
public CsmPipetteTip getPipetteTip() { if ( this.pipetteTips.isEmpty() ) { throw new RuntimeException("no pipette tip"); } CsmPipetteTip tip = this.pipetteTips.remove(0); return tip; }
// append large buffer tube
public void appendLargeBufferTube( Integer position ) { CsmLargeBufferTube tube = new CsmLargeBufferTube(); tube.position = position; this.largeBufferTubes.removeIf(tmp -> tmp.position.equals(position)); this.largeBufferTubes.add(tube); }
// get large buffer tube
public CsmLargeBufferTube getLargeBufferTube( String projectName ) { CsmLargeBufferTube tube = null; for ( CsmLargeBufferTube tmp : this.largeBufferTubes ) { if ( !tmp.projectName.equals(projectName) ) { continue ; } if ( tmp.isEmpty() ) { continue; } tube = tmp; break; } if ( null == tube ) { throw new RuntimeException("no large buffer tube"); } return tube; }
// get location by name
public Integer getLocationByName( String name ) { String key = "device.location." + name; Integer value = this.runtimeOptionService.getInteger(key); return value; }
// call device command and wait for response
public ByteBuffer call( Integer cmd, Integer mid, Object ... params ) {
int length = 2 + 2 + 1 + 1 + 2; for ( Object param : params ) { if ( param instanceof Integer ) { length += 4; } else { throw new RuntimeException("param type error"); } }
int subCmdId = cmd & 0xFF; int mainCmdId = (cmd >> 8) & 0xFFFF; int moduleId = mid;
ByteBuffer request = ByteBuffer.allocate(length); request.order(ByteOrder.LITTLE_ENDIAN); request.putShort(this.messageIndex); request.putShort((short)mainCmdId); // main cmd id
request.put((byte)subCmdId); // sub cmd id
request.put((byte)0); // directive type
request.putShort((short)moduleId); // mid
for ( Object param : params ) { if ( param instanceof Integer ) { request.putInt((Integer)param); } }
this.messageIndex ++; if ( this.debug ) { return this.serialPortCall(request); } return this.prodCall(cmd, mid, params); }
// call device command in debug mode
private ByteBuffer serialPortCall(ByteBuffer request) { LOG.info("Device serial port => {}", MyByteBuffer.toHex(request)); this.serialPort.write(request);
ByteBuffer response = ByteBuffer.allocate(0); while ( 0 == response.capacity() ) { try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } response = this.serialPort.read(); }
LOG.info("Device serial port <= {}", MyByteBuffer.toHex(response)); return response; }
private ByteBuffer prodCall(Integer cmd, Integer mid, Object[] params) { System.out.println("Device prodCall"); return null; } }
|