 
 ;; acq-engine
 
+(defmacro successful? [& body]
+  `(try (do ~@body true)
+     (catch Exception e#
+            (do (ReportingUtils/logError e#) false))))
+
+(defmacro device-best-effort [dev & body]
+  `(let [attempt# #(do (wait-for-device ~dev) ~@body)]
+    (when-not
+      (or
+        (successful? (attempt#)) ; first attempt
+        (do (log "second attempt") (successful? (attempt#)))
+        (do (log "reload and try a third time")
+            (successful? (reload-device ~dev) (attempt#)))) ; third attempt after reloading
+      (throw (Exception. (str "Device failure: " ~dev)))
+      (swap! state assoc :stop true)
+      nil)))
+
 (defn get-z-stage-position [stage]
   (if-not (empty? stage) (core getPosition stage) 0))
 


(defn snap-image [open-before close-after]
  (with-core-setting [getAutoShutter setAutoShutter false]
    (when open-before
      (core setShutterOpen true)
      (wait-for-device (core getShutterDevice)))
    (core snapImage)
    (when close-after
      (core setShutterOpen false))
      (wait-for-device (core getShutterDevice))))

(defn init-burst [length]
  (core setAutoShutter (@state :init-auto-shutter))

      (doall (map (partial await-for 10000) (vals device-agents))))
    (do
      (doseq [[dev action] action-map]
        (device-best-effort dev (action))))))

(defn run-autofocus []
  (.. gui getAutofocusManager getDevice fullFocus)
