You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
8.3 KiB
232 lines
8.3 KiB
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;
|
|
}
|
|
}
|