From 49fb976c2bbb1685230e2dff088cc53265b8d4db Mon Sep 17 00:00:00 2001 From: Alexandre Gobbo Date: Fri, 7 Jul 2017 08:55:23 +0200 Subject: [PATCH] Included recovery from camera reconnection & restart --- pom.xml | 2 +- .../ch/psi/pshell/prosilica/Prosilica.java | 90 ++++++++++++++++--- 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/pom.xml b/pom.xml index e5960b5..e2958d6 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 ch.psi prosilica - 1.0.0 + 1.0.2 jar UTF-8 diff --git a/src/main/java/ch/psi/pshell/prosilica/Prosilica.java b/src/main/java/ch/psi/pshell/prosilica/Prosilica.java index c22dd9d..2891154 100644 --- a/src/main/java/ch/psi/pshell/prosilica/Prosilica.java +++ b/src/main/java/ch/psi/pshell/prosilica/Prosilica.java @@ -10,6 +10,7 @@ import ch.psi.pshell.device.ReadonlyRegisterBase; import ch.psi.pshell.imaging.Source.EmbeddedCameraSource; import ch.psi.pshell.imaging.SourceBase; import ch.psi.pshell.imaging.Renderer; +import ch.psi.pshell.imaging.SourceConfig; import ch.psi.pshell.imaging.Utils; import java.io.File; import java.io.IOException; @@ -26,6 +27,7 @@ import ch.psi.utils.NamedThreadFactory; import ch.psi.utils.State; import ch.psi.utils.Sys; import java.util.LinkedHashMap; +import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -35,10 +37,10 @@ import java.util.logging.Level; import prosilica.Pv; public class Prosilica extends SourceBase implements EmbeddedCameraSource { - - final long uid; + final HashMap pars; final boolean monitor; + long uid; volatile boolean opened; volatile boolean started; @@ -53,8 +55,11 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { final int IMAGE_BUFFER_SIZE = 5; // constructor + public Prosilica(String name, long uid) { + this(name, uid, null); + } public Prosilica(String name, long uid, String pars) { - super(name); + super(name, new SourceConfig()); this.uid = uid; this.monitor = "monitor".equalsIgnoreCase(pars); this.pars = new LinkedHashMap<>(); @@ -75,7 +80,16 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { this.pars.put(parName, parVal); } } + } + } + + public static void shutdown(){ + synchronized(instances){ + for (Prosilica prosilica: instances){ + prosilica.close(); + } } + disposePvapi(); } void writePars() throws IOException { @@ -83,6 +97,37 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { writeParameter(par, pars.get(par)); } } + + + + @Override + protected void onTimeout(){ + { + setState(State.Offline); + try + { + if (started){ + getLogger().warning("Detected camera timeout. Restarting..."); + stop(); + closeCamera(); + } + + if (hasCamera(uid)){ + openCamera(uid); + writePars(); + start(); + setState(State.Ready); + getLogger().info("Successfully restarted camera"); + } + } + catch (Exception ex){ + getLogger().log(Level.FINER, null, ex); + }} + //If restart failed try again in 10s + if (!started){ + setTimeout(10000); + } + } /////////////////////////////////////////////////////////////////////////////////////////////// //Monitoring @@ -129,7 +174,9 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { @Override protected void doInitialize() throws IOException, InterruptedException { super.doInitialize(); - instances++; + synchronized(instances){ + instances.add(this); + } doClose(); loadPvapi(); opened = true; @@ -137,17 +184,16 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { try { waitCamera(uid, 5000); - if (uid > 0) { - openCamera(uid); - } else { + if (uid <= 0) { HashMap[] info = getCameras(); if (info.length == 0) { throw new IOException("No camera detected"); } - openCamera((Long) info[0].get("uid")); + uid = (Long) (info[0].get("uid")); } - setState(State.Ready); + openCamera(uid); writePars(); + setState(State.Ready); camera.initialize(); } catch (IOException ex) { getLogger().warning("Error opening the camera: " + ex.getMessage()); @@ -174,7 +220,9 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { if (opened) { opened = false; started = false; - instances--; + synchronized(instances){ + instances.remove(this); + } try { stop(); } catch (Exception ex) { @@ -187,8 +235,10 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { camera.close(); } catch (Exception ex) { } - if (instances == 0) { - disposePvapi(); + synchronized(instances){ + if (instances.size() == 0) { + disposePvapi(); + } } } } catch (Exception ex) { @@ -261,16 +311,18 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { throw new IOException("Error startic acquisition"); } started = true; + setTimeout(10000); } public void stop() throws IOException { assertInitialized(); + setTimeout(-1); started = false; if (isStreaming()) { Pv.CommandRun(handle, "AcquisitionStop"); Pv.CaptureQueueClear(handle); Pv.CaptureEnd(handle); - } + } } public boolean isStarted() { @@ -301,7 +353,7 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { /////////////////////////////////////////////////////////////////////////////////////////////// //PvAPI initialization /////////////////////////////////////////////////////////////////////////////////////////////// - private static int instances = 0; + private static final List instances = new ArrayList<>(); private static boolean loadedPvapi = false; private static void loadPvapi() throws IOException { @@ -342,6 +394,16 @@ public class Prosilica extends SourceBase implements EmbeddedCameraSource { } } + private static boolean hasCamera(Long uid) { + Chrono chrono = new Chrono(); + for (HashMap info : getCameras()) { + if ((uid == null) || uid.equals(info.get("uid"))) { + return true; + } + } + return false; + } + /////////////////////////////////////////////////////////////////////////////////////////////// //Camera selection ///////////////////////////////////////////////////////////////////////////////////////////////