/* * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. */ package ch.psi.mxsc; import ch.psi.mxsc.Puck.PuckType; import ch.psi.pshell.core.Context; import ch.psi.pshell.core.DevicePool; import ch.psi.pshell.core.DevicePoolListener; import ch.psi.pshell.core.JsonSerializer; import ch.psi.pshell.device.Device; import ch.psi.pshell.device.DeviceAdapter; import ch.psi.pshell.device.DeviceListener; import ch.psi.pshell.device.GenericDevice; import ch.psi.pshell.device.ReadbackDevice; import ch.psi.pshell.ui.Panel; import ch.psi.utils.State; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.script.ScriptException; import javax.swing.JComponent; import javax.swing.table.DefaultTableModel; /** * */ public class Controller { static Controller instance; final BasePlate basePlate; final /*Panel*/ MainPanel mainFrame; Device hexiposi; Device barcode_reader; Device puck_detection; public static Controller getInstance() { return instance; } static void createInstance(Panel mainFrame) { instance = new Controller(mainFrame); } enum PuckSensorAccess { RaspberryPi, Esera; } public enum PuckTypes { unipuck, minispine, mixed } PuckTypes puckTypes = PuckTypes.mixed; public PuckTypes getPuckTypes() { return puckTypes; } void updatePuckTypes(){ try{ puckTypes = PuckTypes.valueOf(getMainFrame().eval("get_puck_types()", true).toString()); } catch( Exception ex){ puckTypes = PuckTypes.mixed; } switch(puckTypes){ case unipuck: setSinglePuckType(PuckType.Unipuck); break; case minispine: setSinglePuckType(PuckType.Minispine); break; case mixed: //setSinglePuckType(PuckType.Unknown); break; } } final PuckSensorAccess puckSensorAccess = PuckSensorAccess.RaspberryPi; static String PUCK_ESERA_DEVICE = "onewire"; public static final int NUMBER_OF_PUCKS = 30; private Controller(Panel mainFrame) { basePlate = new BasePlate(); puckState = new PuckState[NUMBER_OF_PUCKS]; for (int i = 0; i < NUMBER_OF_PUCKS; i++) { puckState[i] = new PuckState(i + 1); } this.mainFrame = (MainPanel) mainFrame; instance = this; clearPuckStates(); basePlate.addListener(basePlateListener); } final DeviceListener basePlateListener = new DeviceAdapter() { @Override public void onValueChanged(Device device, Object value, Object former) { if (value!=null){ String segment = ((Object[])value)[0].toString(); Integer puck = (Integer) ((Object[])value)[1]; Integer sample = (Integer) ((Object[])value)[2]; Controller.this.mainFrame.onSelectionChanged(segment, puck, sample); } else { Controller.this.mainFrame.onSelectionChanged(null,null,null); } } }; String getCurrentSelection(){ Object value = basePlate.take(); if (value!=null){ String segment = ((Object[])value)[0].toString(); Integer puck = (Integer) ((Object[])value)[1]; Integer sample = (Integer) ((Object[])value)[2]; String ret = segment + String.valueOf(puck); if (sample!=null){ ret = ret + String.valueOf(sample); } return ret; } return null; } public void selectPuck(Puck puck){ getMainFrame().basePlatePanel.selectPuck(puck); } public void selectSample(Sample sample){ getMainFrame().basePlatePanel.selectSample(sample); } //public Panel getMainFrame() { public MainPanel getMainFrame() { return mainFrame; } public void updateView() { getMainFrame().refresh(); } void onInitialize(int runCount) { getMainFrame().addDevice(basePlate); basePlate.addListener(basePlateListener); System.out.println(basePlate.getState()); if (puckSensorAccess == PuckSensorAccess.Esera) { getMainFrame().getContext().getDevicePool().addListener(new DevicePoolListener() { @Override public void onDeviceAdded(GenericDevice dev) { if (dev.getName().equals(PUCK_ESERA_DEVICE)) { detection = new EseraDetection((Device) dev); } } @Override public void onDeviceRemoved(GenericDevice dev) { if (dev.getName().equals(PUCK_ESERA_DEVICE)) { detection.close(); detection = null; } } }); if (detection != null) { detection.close(); detection = null; } if ((Device) getMainFrame().getDevice(PUCK_ESERA_DEVICE) != null) { detection = new EseraDetection((Device) getMainFrame().getDevice(PUCK_ESERA_DEVICE)); } } getDevicePool().addListener(new DevicePoolListener() { @Override public void onDeviceAdded(GenericDevice dev) { updateDevices(); } @Override public void onDeviceRemoved(GenericDevice dev) { } }); updateDevices(); updatePuckTypes(); clearSamplesTable(); refreshSamplesTable(); } public void onStateChange(State state, State former) { if (state == State.Initializing){ getMainFrame().removeDevice(basePlate); } else if (state==State.Ready){ refreshSamplesTable(); } } void onTimer(){ try { setPuckLoading(Controller.getInstance().isPuckLoading()); } catch (Exception ex) { setPuckLoading(false); } refreshSamplesTable(); } final DeviceListener hexiposiListener = new DeviceAdapter() { @Override public void onValueChanged(Device device, Object value, Object former) { updateView(); } }; final DeviceListener barcodeReaderListener = new DeviceAdapter() { @Override public void onValueChanged(Device device, Object value, Object former) { if (value!=null){ //Keep last value String valStr = value.toString().trim(); if (puckLoading && isBarcodeReaderScanPucks()){ onPuckBarcode(valStr); } else { getMainFrame().setSampleDatamatrix(valStr); } } } }; final DeviceListener puckDetectionListener = new DeviceAdapter() { @Override public void onValueChanged(Device device, Object value, Object former) { if (value!=null){ //Keep last value onPuckDetectionChanged(); } } }; void updateDevices(){ if (hexiposi!=null){ hexiposi.removeListener(hexiposiListener); } if (barcode_reader!=null){ hexiposi.removeListener(barcodeReaderListener); } if (puck_detection!=null){ hexiposi.removeListener(puckDetectionListener); } hexiposi = (Device) getMainFrame().getDevice("hexiposi"); if (hexiposi != null) { hexiposi.addListener(hexiposiListener); } else { Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, "No hexiposi detected."); } mainFrame.hexiposiPanel.setDevice(hexiposi); barcode_reader = (Device) getDevice("barcode_reader"); if (barcode_reader!=null){ barcode_reader.addListener(barcodeReaderListener); } else { Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, "No barcode_reader detected."); } puck_detection = (Device) getDevice("puck_detection"); if (puck_detection!=null){ puck_detection.addListener(puckDetectionListener); } else { Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, "No puck_detection detected."); } } final PuckState[] puckState; public PuckState[] getPuckStates() { return puckState; } public Puck getPuck(String name) { return basePlate.getPuckByName(name); } EseraDetection detection; //From 1 to PUCKS_NUMBER public PuckState getPuckState(int id) throws Exception { if ((id <= 0) || (id > NUMBER_OF_PUCKS)) { throw new Exception("invalid puck id: " + id); } return getPuckStates()[id - 1]; } public int getPuckIndex(int address) throws Exception { if ((address <= 0) || (address > NUMBER_OF_PUCKS)) { throw new Exception("invalid puck address: " + address); } for (int i = 0; i < Puck.ADDRESSES.length; i++) { if (Puck.ADDRESSES[i] == address) { return i + 1; } } return -1; } public void clearPuckStates() { for (PuckState puck : getPuckStates()) { puck.clear(); } updateView(); } public String getHexiposiPosition() { try { return (String) ((ReadbackDevice) hexiposi).getReadback().take(); } catch (Exception ex) { return null; } } public boolean isSelectedPuck(Puck puck){ return ("" + puck.getSegment()).equalsIgnoreCase(getHexiposiPosition()); } public List getSelectedPucks(){ List ret = new ArrayList<>(); for (int i=0; i< NUMBER_OF_PUCKS; i++){ if (isSelectedPuck(basePlate.getPucks()[i])){ ret.add(basePlate.getPucks()[i]); } } return ret; } public Boolean isLedRoomTemp() { try { return getMainFrame().eval("is_led_room_temp()", true).equals(true); } catch (Exception ex) { return null; } } public Boolean isRoomTemp() { try { return getMainFrame().eval("is_room_temp()", true).equals(true); } catch (Exception ex) { return null; } } public Boolean isBarcodeReaderScanPucks() { try { return getMainFrame().eval("is_barcode_reader_scan_pucks()", true).equals(true); } catch (Exception ex) { return false; } } public Boolean isPuckLoading() { try { return getMainFrame().eval("is_puck_loading()", true).equals(true); } catch (Exception ex) { return null; } } public String getWorkingMode() { try { return String.valueOf(getMainFrame().eval("robot.working_mode", true)); } catch (Exception ex) { return "Unknown"; } } public boolean isManualMode() { try { return getMainFrame().eval("is_manual_mode()", true).equals(true); } catch (Exception ex) { return false; } } public void imageDetectPucks() throws Context.ContextStateException { imageDetectPucks(null, null, null); } public void imageDetectPucks(JComponent plot, JComponent renderer, JComponent text) throws Context.ContextStateException { Map args = new HashMap(); args.put("PLOT", plot); args.put("RENDERER", renderer); args.put("TEXT", text); getMainFrame().runAsync("imgproc/LedDetectionProc", args).handle((ret, ex) -> { if (ex == null) { Map> map = (Map>) ret; setImageDetection(map); } else { getMainFrame().showException((Exception) ex); } return ret; }); updateView(); } public void clearImageDetection() throws Context.ContextStateException, ScriptException, IOException, InterruptedException { Map> map = (Map>) getMainFrame().eval("clear_detection(None)"); setImageDetection(map); } void setImageDetection(Map> map) { for (Puck.PuckType puckType : Puck.PuckType.values()) { for (String name : map.get(puckType.toString())) { Puck p = basePlate.getPuckByName(name); if (p != null) { p.setPuckType(puckType); } } } updateView(); } void setSinglePuckType(Puck.PuckType puckType) { for (Puck p : basePlate.getPucks()) { p.setPuckType(puckType); } } void resetPuckTypes() { for (Puck p : basePlate.getPucks()) { p.setPuckType(Puck.PuckType.Unknown); } } BasePlatePanel puckPanel; void onPuckPressed(Puck puck){ //JPanel panel = new SinglePuckPanel(puck); //panel.setOpaque(false); //getMainFrame().setDetail(panel); if ((puckPanel==null) || (puckPanel != getMainFrame().getDetail())){ puckPanel = new BasePlatePanel(); puckPanel.setMode(BasePlatePanel.Mode.puck); puckPanel.setSelectionMode(BasePlatePanel.SelectionMode.Samples); puckPanel.setDevice((Device) getDevice("BasePlate")); puckPanel.setEnabled(true); //TODO: Puck cannot be shared between two panels (device store single coordinates foe comparing to click) getMainFrame().setDetail(puckPanel); } } void onPuckReleased(Puck puck){ if (!puck.isSelected()){ getMainFrame().setDefaultDetail(); puckPanel = null; } } void onSamplePressed(Sample sample){ onPuckPressed(sample.getPuck()); } void onSampleReleased(Sample sample){ onPuckReleased(sample.getPuck()); } void onPlatePressed(BasePlate plate){ if (plate.getSelectedPuck() == null){ getMainFrame().setDefaultDetail(); puckPanel = null; } } void onPlateReleased(BasePlate palte){ } GenericDevice getDevice(String name){ return getMainFrame().getDevice(name); } DevicePool getDevicePool(){ return getMainFrame().getContext().getDevicePool(); } Context getContext(){ return getMainFrame().getContext(); } State getState(){ return getMainFrame().getState(); } void execute(String statement){ getMainFrame().execute(statement); } void execute(String statement, boolean background){ getMainFrame().execute(statement, background); } void execute(String statement, boolean background, boolean showReturn){ getMainFrame().execute(statement, background, showReturn); } ////////////////////// Sample Info ///////////////////////////////// String samplesTableJson; final Object samplesTableLock = new Object(); void refreshSamplesTable() { synchronized(samplesTableLock){ try { String json = (String) Context.getInstance().evalLineBackground("get_samples_info()"); if (!json.equals(samplesTableJson)) { samplesTableJson = json; //SamplesInfo sampleInfo = (SamplesInfo) JsonSerializer.decode(json, SampleInfo.class); SampleInfo[] samples = (SampleInfo[]) JsonSerializer.decode(json, SampleInfo[].class); Object[][] sampleData = new Object[samples.length][]; for (int i = 0; i < samples.length; i++) { sampleData[i] = samples[i].getData(); } getMainFrame().setSamplesTable(sampleData); } } catch (Exception ex) { clearSamplesTable(); Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex); } } } void clearSamplesTable() { samplesTableJson = null; getMainFrame().setSamplesTable(new Object[][]{}); } ////////////////////// Puck Loading ///////////////////////////////// Boolean puckLoading; Puck.Detection[] currentDetection; void setPuckLoading(Boolean value){ if (value==null){ value = false; } if (value != puckLoading){ puckLoading = value; getMainFrame().setPuckDatamatrix(null); if (isBarcodeReaderScanPucks()){ if (puckLoading){ execute("barcode_reader.enable()", true); execute("barcode_reader.polling = 100", true); currentDetection = basePlate.getDetection(); } else if (getState().isInitialized()){ execute("barcode_reader.polling = 0", true); execute("barcode_reader.disable()", true); } } } } void onPuckBarcode(String datamatrix){ if (puckLoading){ getMainFrame().setPuckDatamatrix(datamatrix); System.out.println(datamatrix); } } void onPuckDetectionChanged(){ if (puckLoading){ String datamatrix = getMainFrame().getPuckDatamatrix(); Puck.Detection[] detection = basePlate.getDetection(); for (int i=0; i< Controller.NUMBER_OF_PUCKS; i++){ Puck puck = basePlate.getPucks()[i]; if (isSelectedPuck(puck)){ boolean detectedPuckInserted = (currentDetection[i] != Puck.Detection.Present) && (detection[i] == Puck.Detection.Present); boolean detectedPuckRemoved = (currentDetection[i] != Puck.Detection.Empty) && (detection[i] == Puck.Detection.Empty); if (detectedPuckInserted){ System.out.println("Detected puck at position: " + puck.getName() + " - Datamatrix: " + (datamatrix.isEmpty() ? null : datamatrix)); if (!datamatrix.isEmpty()){ getMainFrame().setPuckDatamatrix(null); setPuckDatamatrix(puck, datamatrix); } } else if (detectedPuckRemoved){ System.out.println("Removed puck from position " + puck.getName() + " - Datamatrix: " + puck.getId()); setPuckDatamatrix(puck, null); } } } currentDetection = detection; } } void setPuckDatamatrix(Puck puck, String datamatrix){ if ( ((puck.getId()==null) && (datamatrix!=null)) || (puck.getId()!=null) && (!puck.getId().equals(datamatrix))){ System.out.println("Setting to: " + puck.getName() + " datamatrix: " + datamatrix); puck.setId(datamatrix); getMainFrame().refresh(); } } }