package com.dreamworks.boditech.service; import com.dreamworks.boditech.driver.*; import com.dreamworks.boditech.driver.consumable.CsmLargeBufferTube; import com.dreamworks.boditech.driver.consumable.CsmPipetteTip; import com.dreamworks.boditech.driver.task.Task; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; @Service public class DeviceService { @Resource public Device device; // pipette tips public List pipetteTips; // buffer tubes public List bufferTubes; // test cards public List testCards; // tasks private final List tasks = new ArrayList<>(); // task executor private TaskExecutor taskExecutor; // task executor thread private Thread taskExecutorThread; // reset to initial state public void reset() { } // start public void start() { this.device.appendPipetteTip(0, 10); this.device.appendPipetteTip(1, 10); this.device.appendPipetteTip(2, 10); this.device.appendBufferTubeA(0, 10); this.taskExecutor = new TaskExecutor(this.tasks, this.device); this.taskExecutorThread = new Thread(this.taskExecutor); this.taskExecutorThread.setName("task-executor"); this.taskExecutorThread.start(); } // stop public void stop() { this.taskExecutor.stop(); try { this.taskExecutorThread.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } } // append new task public void taskAppend(Task task) { synchronized (this.tasks) { this.tasks.add(task); this.tasks.notifyAll(); } } // private static final Logger LOG = LoggerFactory.getLogger(DeviceService.class); // // @Resource // private BoditechDeviceClient device; // // // device request list // private Map deviceRequests; // // request id // private short requestId = 0; // // /** // * initialize device service // */ // @PostConstruct // public void init() { // LOG.info("init"); // this.deviceRequests = new HashMap(); // this.device.setOnMessageCallback(this::handleDeviceOnMessage); // } // // /** // * event handler for receiving binary message from device // * @param buffer message from device // */ // public void handleDeviceOnMessage(ByteBuffer buffer) { // LOG.info("handleDeviceOnMessage"); // buffer.order(ByteOrder.LITTLE_ENDIAN); // short reqId = buffer.getShort(); // BoditechDeviceRequest request = this.deviceRequests.get(reqId); // if ( null == request ) { // return ; // } // request.setResponseBuffer(buffer); // } // // /** // * call device command // * @param mid module id // * @param cmd command definition // * @param params arguments for command // */ // public ByteBuffer call( int mid, short[] cmd, int ... params ) { // this.requestId += 1; // if ( 30000 < this.requestId ) { // this.requestId = 1; // } // // // build request buffer and send to device // int requestBufferLength = 8 + params.length * 4; // ByteBuffer requestBuffer = ByteBuffer.allocate(requestBufferLength); // requestBuffer.order(ByteOrder.LITTLE_ENDIAN); // requestBuffer.putShort(this.requestId); // request id (2 bytes) // requestBuffer.putShort(cmd[0]); // main cmd (2 bytes) // requestBuffer.put((byte)cmd[1]); // sub cmd (1 byte) // requestBuffer.put((byte)0); // directive type // requestBuffer.putShort((short)mid); // module id (2 bytes) // for ( int param : params ) { // requestBuffer.putInt(param); // param (4 bytes) // } // byte[] bytes = requestBuffer.array(); // this.device.send(bytes); // LOG.info("request({}) : send = {} ", this.requestId, bytes); // // // wait for response // BoditechDeviceRequest request = new BoditechDeviceRequest(); // this.deviceRequests.put(this.requestId, request); // ByteBuffer responseBuffer = request.waitForResponse(); // this.deviceRequests.remove(this.requestId); // // ByteBuffer responseData = responseBuffer.slice(8, responseBuffer.capacity() - 8); // LOG.info("request({}) : response = {} ", this.requestId, responseData); // return responseData; // } // // // motor enable / disable // public void motorEnable (int mid, boolean enable) { // LOG.info("motorEnable : mid={}, enable={}", mid, enable); // this.call(mid, BoditechDeviceCmd.MOTOR_ENABLE, enable ? 1 : 0); // } // // // motor easy move to // public void motorEasyMoveTo(int mid, int position) { // LOG.info("motorEasyMoveTo : mid={}, position={}", mid, position); // this.call(mid, BoditechDeviceCmd.MOTOR_EASY_MOVE_TO, position); // } // // // motor easy move by // public void motorEasyMoveBy(int mid, int distance) { // LOG.info("motorEasyMoveBy : mid={}, distance={}", mid, distance); // this.call(mid, BoditechDeviceCmd.MOTOR_EASY_MOVE_BY, distance); // } // // // motor easy move to zero // public void motorEasyMoveToZero(int mid, int direction) { // LOG.info("motorEasyMoveToZero : mid={}, direction={}", mid, direction); // this.call(mid, BoditechDeviceCmd.MOTOR_EASY_MOVE_TO_ZERO, direction); // } // // // motor easy rotate // public void motorEasyRotate(int mid, int direction) { // LOG.info("motorEasyRotate : mid={}, direction={}", mid, direction); // this.call(mid, BoditechDeviceCmd.MOTOR_EASY_ROTATE, direction); // } // // // motor easy set current pos // public void motorEasySetCurrentPos(int mid, int pos) { // LOG.info("motorEasySetCurrentPos : mid={}, pos={}", mid, pos); // this.call(mid, BoditechDeviceCmd.MOTOR_EASY_SET_CURRENT_POS, pos); // } // // // motor move by // public void motorMoveBy(int mid, int distance, int motorVelocity, int acc) { // LOG.info("motorMoveBy : mid={}, distance={}, motorVelocity={}, acc={}", mid, distance, motorVelocity, acc); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_BY, distance, motorVelocity, acc); // } // // // motor move by acctime // public void motorMoveByAcctime(int mid, int distance, int motorVelocity, int acctime) { // LOG.info("motorMoveByAcctime : mid={}, distance={}, motorVelocity={}, acctime={}", mid, distance, motorVelocity, acctime); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_BY_ACCTIME, distance, motorVelocity, acctime); // } // // // motor move to // public void motorMoveTo(int mid, int position, int motorVelocity, int acc) { // LOG.info("motorMoveTo : mid={}, position={}, motorVelocity={}, acc={}", mid, position, motorVelocity, acc); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_TO, position, motorVelocity, acc); // } // // // motor move to acctime // public void motorMoveToAcctime(int mid, int position, int motorVelocity, int acctime) { // LOG.info("motorMoveToAcctime : mid={}, position={}, motorVelocity={}, acctime={}", mid, position, motorVelocity, acctime); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_TO_ACCTIME, position, motorVelocity, acctime); // } // // // motor move to torque // public void motorMoveToTorque(int mid, int pos, int torque, int overtime) { // LOG.info("motorMoveToTorque : mid={}, pos={}, torque={}, overtime={}", mid, pos, torque, overtime); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_TO_TORQUE, pos, torque, overtime); // } // // // motor move to zero backward // public void motorMoveToZeroBackward(int mid, int findzerospeed, int findzeroedgeSpeed, int acc, int overtime) { // LOG.info("motorMoveToZeroBackward : mid={}, findzerospeed={}, findzeroedgeSpeed={}, acc={}, overtime={}", mid, findzerospeed, findzeroedgeSpeed, acc, overtime); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_TO_ZERO_BACKWARD, findzerospeed, findzeroedgeSpeed, acc, overtime); // } // // // motor move to zero backward and calculated shift // public void motorMoveToZeroBackwardAndCalculatedShift(int mid, int findzerospeed, int findzeroedgeSpeed, int acc, int overtime) { // LOG.info("motorMoveToZeroBackwardAndCalculatedShift : mid={}, findzerospeed={}, findzeroedgeSpeed={}, acc={}, overtime={}", mid, findzerospeed, findzeroedgeSpeed, acc, overtime); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_TO_ZERO_BACKWARD_AND_CALCULATED_SHIFT, findzerospeed, findzeroedgeSpeed, acc, overtime); // } // // // motor move to zero forward // public void motorMoveToZeroForward(int mid, int findzerospeed, int findzeroedgeSpeed, int acc, int overtime) { // LOG.info("motorMoveToZeroForward : mid={}, findzerospeed={}, findzeroedgeSpeed={}, acc={}, overtime={}", mid, findzerospeed, findzeroedgeSpeed, acc, overtime); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_TO_ZERO_FORWARD, findzerospeed, findzeroedgeSpeed, acc, overtime); // } // // // motor move to zero forward and calculated shift // public void motorMoveToZeroForwardAndCalculatedShift(int mid, int findzerospeed, int findzeroedgeSpeed, int acc, int overtime) { // LOG.info("motorMoveToZeroForwardAndCalculatedShift : mid={}, findzerospeed={}, findzeroedgeSpeed={}, acc={}, overtime={}", mid, findzerospeed, findzeroedgeSpeed, acc, overtime); // this.call(mid, BoditechDeviceCmd.MOTOR_MOVE_TO_ZERO_FORWARD_AND_CALCULATED_SHIFT, findzerospeed, findzeroedgeSpeed, acc, overtime); // } // // // motor rotate // public void motorRotate(int mid, int direction, int motorVelocity, int acc) { // LOG.info("motorRotate : mid={}, direction={}, motorVelocity={}, acc={}", mid, direction, motorVelocity, acc); // this.call(mid, BoditechDeviceCmd.MOTOR_ROTATE, direction, motorVelocity, acc); // } // // // motor rotate acctime // public void motorRotateAcctime(int mid, int direction, int motorVelocity, int acctime) { // LOG.info("motorRotateAcctime : mid={}, direction={}, motorVelocity={}, acctime={}", mid, direction, motorVelocity, acctime); // this.call(mid, BoditechDeviceCmd.MOTOR_ROTATE_ACCTIME, direction, motorVelocity, acctime); // } // // // motor rotate with torque // public void motorRotateWithTorque(int mid, int pos, int torque) { // LOG.info("motorRotateWithTorque : mid={}, pos={}, torque={}", mid, pos, torque); // this.call(mid, BoditechDeviceCmd.MOTOR_ROTATE_WITH_TORQUE, pos, torque); // } // // // motor calculated pos by move to zero // public void motorCalculatedPosByMoveToZero(int mid) { // LOG.info("motorCalculatedPosByMoveToZero : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MOTOR_CALCULATED_POS_BY_MOVE_TO_ZERO); // } // // // motor read pos // public void motorReadPos(int mid) { // LOG.info("motorReadPos : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MOTOR_READ_POS); // } // // // motor set current pos by change shift // public void motorSetCurrentPosByChangeShift(int mid, int pos) { // LOG.info("motorSetCurrentPosByChangeShift : mid={}, pos={}", mid, pos); // this.call(mid, BoditechDeviceCmd.MOTOR_SET_CURRENT_POS_BY_CHANGE_SHIFT, pos); // } // // // xymotor calculated pos by move to zero // public void xymotorCalculatedPosByMoveToZero(int mid) { // LOG.info("xymotorCalculatedPosByMoveToZero : mid={}", mid); // this.call(mid, BoditechDeviceCmd.XYMOTOR_CALCULATED_POS_BY_MOVE_TO_ZERO); // } // // // xymotor enable // public void xymotorEnable(int mid, boolean enable) { // LOG.info("xymotorEnable : mid={}, enable={}", mid, enable); // this.call(mid, BoditechDeviceCmd.XYMOTOR_ENABLE, enable ? 1 : 0); // } // // // xymotor move by // public void xymotorMoveBy(int mid, int dx, int dy, int motorVelocity) { // LOG.info("xymotorMoveBy : mid={}, dx={}, dy={}, motorVelocity={}", mid, dx, dy, motorVelocity); // this.call(mid, BoditechDeviceCmd.XYMOTOR_MOVE_BY, dx, dy, motorVelocity); // } // // // xymotor move to // public void xymotorMoveTo(int mid, int x, int y, int motorVelocity) { // LOG.info("xymotorMoveTo : mid={}, x={}, y={}, motorVelocity={}", mid, x, y, motorVelocity); // this.call(mid, BoditechDeviceCmd.XYMOTOR_MOVE_TO, x, y, motorVelocity); // } // // // xymotor move to zero // public void xymotorMoveToZero(int mid) { // LOG.info("xymotorMoveToZero : mid={}", mid); // this.call(mid, BoditechDeviceCmd.XYMOTOR_MOVE_TO_ZERO); // } // // // xymotor move to zero and calculated shift // public void xymotorMoveToZeroAndCalculatedShift(int mid) { // LOG.info("xymotorMoveToZeroAndCalculatedShift : mid={}", mid); // this.call(mid, BoditechDeviceCmd.XYMOTOR_MOVE_TO_ZERO_AND_CALCULATED_SHIFT); // } // // // xymotor read pos // public void xymotorReadPos(int mid) { // LOG.info("xymotorReadPos : mid={}", mid); // this.call(mid, BoditechDeviceCmd.XYMOTOR_READ_POS); // } // // // pipette ctrl init device // public void pipetteCtrlInitDevice(int mid) { // LOG.info("pipetteCtrlInitDevice : mid={}", mid); // this.call(mid, BoditechDeviceCmd.PIPETTE_CTRL_INIT_DEVICE); // } // // // pipette ctrl move to ul // public void pipetteCtrlMoveToUl(int mid, int ul) { // LOG.info("pipetteCtrlMoveToUl : mid={}, ul={}", mid, ul); // this.call(mid, BoditechDeviceCmd.PIPETTE_CTRL_MOVE_TO_UL, ul); // } // // // pipette ctrl put tip // public void pipetteCtrlPutTip(int mid) { // LOG.info("pipetteCtrlPutTip : mid={}", mid); // this.call(mid, BoditechDeviceCmd.PIPETTE_CTRL_PUT_TIP); // } // // // module active cfg // public void moduleActiveCfg(int mid) { // LOG.info("moduleActiveCfg : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_ACTIVE_CFG); // } // // // module break // public void moduleBreak(int mid) { // LOG.info("moduleBreak : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_BREAK); // } // // // module clear error // public void moduleClearError(int mid) { // LOG.info("moduleClearError : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_CLEAR_ERROR); // } // // // module enable // public void moduleEnable(int mid, boolean enable) { // LOG.info("moduleEnable : mid={}, enable={}", mid, enable); // this.call(mid, BoditechDeviceCmd.MODULE_ENABLE, enable ? 1 : 0); // } // // // module factory reset // public void moduleFactoryReset(int mid) { // LOG.info("moduleFactoryReset : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_FACTORY_RESET); // } // // // module flush cfg // public void moduleFlushCfg(int mid) { // LOG.info("moduleFlushCfg : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_FLUSH_CFG); // } // // // module get error // public void moduleGetError(int mid) { // LOG.info("moduleGetError : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_GET_ERROR); // } // // // module get inited flag // public void moduleGetInitedFlag(int mid) { // LOG.info("moduleGetInitedFlag : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_GET_INITED_FLAG); // } // // // module get last exec status // public void moduleGetLastExecStatus(int mid) { // LOG.info("moduleGetLastExecStatus : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_GET_LAST_EXEC_STATUS); // } // // // module get reg // public void moduleGetReg(int mid, int param_id) { // LOG.info("moduleGetReg : mid={}, param_id={}", mid, param_id); // this.call(mid, BoditechDeviceCmd.MODULE_GET_REG, param_id); // } // // // module get status // public void moduleGetStatus(int mid) { // LOG.info("moduleGetStatus : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_GET_STATUS); // } // // // module ping // public void modulePing(int mid) { // LOG.info("modulePing : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_PING); // } // // // module read adc // public void moduleReadAdc(int mid, int adc_id, int adcIndex) { // LOG.info("moduleReadAdc : mid={}, adc_id={}, adcIndex={}", mid, adc_id, adcIndex); // this.call(mid, BoditechDeviceCmd.MODULE_READ_ADC, adc_id, adcIndex); // } // // // module read raw // public void moduleReadRaw(int mid, int startIndex) { // LOG.info("moduleReadRaw : mid={}, startIndex={}", mid, startIndex); // this.call(mid, BoditechDeviceCmd.MODULE_READ_RAW, startIndex); // } // // // module read io // public void moduleReadIO(int mid) { // LOG.info("moduleReadIO : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_READIO); // } // // // module set inited flag // public void moduleSetInitedFlag(int mid, int flag) { // LOG.info("moduleSetInitedFlag : mid={}, flag={}", mid, flag); // this.call(mid, BoditechDeviceCmd.MODULE_SET_INITED_FLAG, flag); // } // // // module set reg // public void moduleSetReg(int mid, int param_id, int param_value) { // LOG.info("moduleSetReg : mid={}, param_id={}, param_value={}", mid, param_id, param_value); // this.call(mid, BoditechDeviceCmd.MODULE_SET_REG, param_id, param_value); // } // // // module start // public void moduleStart(int mid) { // LOG.info("moduleStart : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_START); // } // // // module stop // public void moduleStop(int mid) { // LOG.info("moduleStop : mid={}", mid); // this.call(mid, BoditechDeviceCmd.MODULE_STOP); // } // // // module write io // public void moduleWriteIO(int mid, int ioIndex, int io) { // LOG.info("moduleWriteIO : mid={}, ioIndex={}, io={}", mid, ioIndex, io); // this.call(mid, BoditechDeviceCmd.MODULE_WRITEIO, ioIndex, io); // } }