/** {@inheritDoc} */ @Override public Object start(final IApplicationContext context) throws Exception { // Display configuration info synchronized (Application.class) { final String version = (String) context.getBrandingBundle().getHeaders().get("Bundle-Version"); bundle_version = context.getBrandingName() + " " + version; } // Create parser for arguments and run it. final String args[] = (String[]) context.getArguments().get("application.args"); final ArgParser parser = new ArgParser(); final BooleanOption help_opt = new BooleanOption(parser, "-help", "Display help"); final BooleanOption version_opt = new BooleanOption(parser, "-version", "Display version info"); parser.addEclipseParameters(); try { parser.parse(args); } catch (final Exception ex) { System.out.println(ex.getMessage() + "\n" + parser.getHelp()); return IApplication.EXIT_OK; } if (help_opt.get()) { System.out.println(bundle_version + "\n\n" + parser.getHelp()); return IApplication.EXIT_OK; } if (version_opt.get()) { System.out.println(bundle_version); return IApplication.EXIT_OK; } final Logger log = Logger.getLogger(getClass().getName()); try { // Display config info final Bundle bundle = context.getBrandingBundle(); log.info(bundle_version); LogConfigurator.configureFromPreferences(); log.config("Scan config : " + ScanSystemPreferences.getScanConfigPath()); log.config("Simulation config : " + ScanSystemPreferences.getSimulationConfigPath()); log.config( "Server host:port : " + ScanSystemPreferences.getServerHost() + ":" + ScanSystemPreferences.getServerPort()); log.config("Pre-scan commands : " + Arrays.toString(ScanSystemPreferences.getPreScanPaths())); log.config( "Post-scan commands: " + Arrays.toString(ScanSystemPreferences.getPostScanPaths())); log.config("Script paths : " + Arrays.toString(ScanSystemPreferences.getScriptPaths())); // Start server final int port = ScanSystemPreferences.getServerPort(); server = new ScanServerImpl(); server.start(); log.config("Scan Server REST interface on http://localhost:" + port + "/index.html"); final ScanWebServer httpd = new ScanWebServer(bundle.getBundleContext(), server, port); // TODO // final PVAccessServer pva = new PVAccessServer(server); // pva.initializeServerContext(); // Register console commands ConsoleCommands commands = new ConsoleCommands(server); final BundleContext bundle_context = bundle.getBundleContext(); bundle_context.registerService(CommandProvider.class.getName(), commands, null); // Keep running... run.await(); server.stop(); httpd.stop(); // pva.destroyServerContext(); // Release commands commands = null; } catch (Exception ex) { log.log(Level.SEVERE, "Exiting on error", ex); return Integer.valueOf(-1); } return EXIT_OK; }
/** {@inheritDoc} */ @Override public boolean performOk() { ScanSystemPreferences.setSystemPropertiesFromPreferences(); return super.performOk(); }
/** * Condition that waits for a Device to reach a certain numeric value. * * <p>For absolute checks (Comparison.EQUALS, ABOVE, ...) the current value of the device is * monitored. * * <p>For relative checks (INCREASED_BY, DECREASED_BY), the reference point is the initial value of * the device when await() was called, resetting in case the desired value is changed while await() * is pending. * * @author Kay Kasemir */ @SuppressWarnings("nls") public class NumericValueCondition implements DeviceCondition, DeviceListener { protected static final TimeDuration value_check_timeout = TimeDuration.ofSeconds(ScanSystemPreferences.getValueCheckTimeout()); /** Device to monitor */ private final Device device; /** Comparison */ private final Comparison comparison; /** Desired value of device */ private double desired_value; /** Tolerance to use for Comparison.EQUALS */ private final double tolerance; /** Timeout in seconds, <code>null</code> to "wait forever" */ private final TimeDuration timeout; /** Initial value to await Comparison.INCREASE_BY/DECREASE_BY */ private volatile double initial_value = Double.NaN; /** Updated by device listener */ private volatile boolean is_condition_met; /** Updated by device listener */ private volatile Exception error = null; /** * Initialize * * @param device {@link Device} where values should be read * @param comparison Comparison to use * @param desired_value Desired numeric value of device * @param tolerance Tolerance, e.g. 0.1 * @param timeout Time out in seconds, or <code>null</code> for "wait forever" */ public NumericValueCondition( final Device device, final Comparison comparison, final double desired_value, final double tolerance, final TimeDuration timeout) { this.device = device; this.comparison = comparison; this.tolerance = Math.abs(tolerance); this.timeout = timeout; setDesiredValue(desired_value); } /** @param desired_value (New) desired value, replacing the one set at initialization time */ public void setDesiredValue(final double desired_value) { // Invalidate initial value initial_value = Double.NaN; this.desired_value = desired_value; } /** * Wait for value of device to reach the desired value (within tolerance) * * @throws TimeoutException on timeout * @throws Exception on interruption or device read error */ @Override public void await() throws TimeoutException, Exception { final WaitWithTimeout timeout = new WaitWithTimeout(this.timeout); // Fetch initial value with get-callback initial_value = VTypeHelper.toDouble(device.read(value_check_timeout)); device.addListener(this); try { // Synchronize to avoid the following situation: // 1. not at desired value // 2. device changes and we would be notified // 3. ... but that's before we call wait, so we wait forever synchronized (this) { is_condition_met = isConditionMet(); while (!is_condition_met) { // Wait for update from device if (timeout.waitUntilTimeout(this)) throw new TimeoutException( "Timeout while waiting for " + device + " " + comparison + " " + desired_value); if (error != null) throw error; } } } finally { device.removeListener(this); } } /** * Determine if the condition is currently met * * @return <code>true</code> if condition is met * @throws Exception on error reading from the device */ public boolean isConditionMet() throws Exception { final double value = VTypeHelper.toDouble(device.read()); // Note that these need to fail "safe" if any of the values are NaN switch (comparison) { case EQUALS: return Math.abs(desired_value - value) <= tolerance; case AT_LEAST: return value >= desired_value; case ABOVE: return value > desired_value; case AT_MOST: return value <= desired_value; case BELOW: return value < desired_value; case INCREASE_BY: return value >= initial_value + desired_value; case DECREASE_BY: return value <= initial_value - desired_value; default: throw new Error("Condition not implemented: " + comparison); } } /** Trigger another check of device's value {@inheritDoc} */ @Override public void deviceChanged(final Device device) { synchronized (this) { try { if (Double.isNaN(initial_value)) initial_value = VTypeHelper.toDouble(device.read()); is_condition_met = isConditionMet(); } catch (Exception ex) { is_condition_met = false; error = ex; } // Notify await() so it can check again. notifyAll(); } } /** @return Debug representation */ @Override public String toString() { return "Wait for '" + device + "' " + comparison + " " + desired_value + ", tolerance=" + tolerance + ", timeout=" + timeout; } }