org.dawb.tango.extensions.factory.TangoConnectionImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.dawb.tango.extensions.factory.TangoConnectionImpl.java

Source

/*
 * Copyright (c) 2012 European Synchrotron Radiation Facility,
 *                    Diamond Light Source Ltd.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.dawb.tango.extensions.factory;

import org.dawb.common.ui.Activator;
import org.dawb.common.ui.preferences.CommonUIPreferenceConstants;
import org.dawb.tango.extensions.TangoUtils;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.preference.IPreferenceStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.esrf.Tango.DevFailed;
import fr.esrf.TangoApi.DeviceAttribute;
import fr.esrf.TangoApi.DeviceData;
import fr.esrf.TangoApi.DeviceProxy;
import fr.esrf.TangoApi.events.ITangoChangeListener;
import fr.esrf.TangoApi.events.TangoChangeEvent;
import fr.esrf.TangoApi.events.TangoEventsAdapter;

class TangoConnectionImpl extends AbstractTangoConnection {

    private static final Logger logger = LoggerFactory.getLogger(TangoConnectionImpl.class);

    protected DeviceProxy tangoProxy;
    protected TangoEventsAdapter tangoEvents;
    protected ITangoChangeListener listener;
    protected long lastEvent = 0;

    public TangoConnectionImpl(final String uri, String attributeName, boolean requireEvents) throws Exception {

        super(uri, attributeName);

        createTangoHost();

        this.tangoProxy = new DeviceProxy(uri);

        if (requireEvents) {
            this.tangoEvents = new TangoEventsAdapter(tangoProxy);
            this.listener = new ITangoChangeListener() {
                @Override
                public void change(TangoChangeEvent event) {
                    fireTangoConnectionListeners(event);
                    lastEvent = System.currentTimeMillis();
                }
            };
            if (attributeName != null) {
                tangoEvents.addTangoChangeListener(listener, attributeName, new String[0]);
            } else {
                this.attributeName = "Output";
                tangoEvents.addTangoChangeListener(listener, attributeName, new String[0]);
            }
        }
    }

    /**
     * If dispose has been called, throws an exception
     * @param listener
     */
    public void addTangoConnectionListener(final TangoConnectionListener l) {
        if (tangoEvents == null)
            throw new RuntimeException("This tango connection, '" + getUri() + "', is not listening to events!");
        super.addTangoConnectionListener(l);
    }

    private void createTangoHost() {
        IPreferenceStore store = Activator.getDefault().getPreferenceStore();

        final StringBuffer buf = new StringBuffer();
        buf.append(store.getString(CommonUIPreferenceConstants.SERVER_NAME));
        buf.append(":");
        buf.append(store.getInt(CommonUIPreferenceConstants.SERVER_PORT));
        System.setProperty("TANGO_HOST", buf.toString());
    }

    /**
     * Can throw tango exceptions. Once called this connection is dead.
     * 
     * 
     * @throws Exeption
     */
    public synchronized void dispose() throws Exception {

        super.dispose();

        if (tangoEvents != null && listener != null) {
            tangoEvents.removeTangoChangeListener(listener, attributeName);
        }
        tangoProxy = null;
        tangoEvents = null;
        listener = null;
    }

    @Override
    public DeviceAttribute getValue() throws Exception {
        if (attributeName == null)
            throw new NullPointerException("Cannot read attribute " + null);
        return tangoProxy.read_attribute(attributeName);
    }

    @Override
    public void setValue(DeviceAttribute value) throws Exception {

        if (attributeName == null)
            throw new NullPointerException("Cannot read attribute " + null);
        tangoProxy.write_attribute(value); // Does not block for spec motors!

        // TODO Talk to Andy about blocking until setValue has completed? Spec does not...

        // For now we check value
        // FIXME
        // START BODGE WARNING

        try {
            Thread.sleep(50); // Fudge incase tango is not blocking properly again.
        } catch (Exception ignored) {

        }

        try {
            double current = getValue().extractDouble();
            double required = value.extractDouble();
            double tolerance = 0.001; // That does not really work!!

            int total = 0;
            while (current > (required + tolerance) || current < (required - tolerance)) {

                if (total > 5000) {
                    logger.error("TIMEOUT: Cannot set motor value " + getUri() + " synchronously!");
                    return;
                }
                try {
                    Thread.sleep(200);
                } catch (Exception ne) {
                    break;
                }
                total += 200;
                current = getValue().extractDouble();
            }
        } catch (Exception ignored) {
            return;
        }
        // END BODGE WARNING
    }

    /**
     * Runs command in eclipse job
     */
    @Override
    public void executeCommand(final String cmdAttribute, final String originalCommand, final boolean async)
            throws Exception {
        // Clean command
        String cmd = TangoUtils.getBracketedCommand(originalCommand);
        final DeviceData cmdData = new DeviceData();
        cmdData.insert(new String[] { cmd });

        executeCommand(cmdAttribute, originalCommand, cmdData, async);
    }

    /**
     * Runs command in eclipse job if async (and returns null) or returns the new value if !async
     */
    @Override
    public DeviceData executeCommand(final String cmdAttribute, final DeviceData cmdData, final boolean async)
            throws Exception {
        return executeCommand(cmdAttribute, cmdData.toString(), cmdData, async);
    }

    /**
     * Runs command in eclipse job
     */
    private DeviceData executeCommand(final String cmdAttribute, final String originalCommand,
            final DeviceData cmdData, final boolean async) throws Exception {

        // Use job for this, it is blocking
        if (async) {
            final Job executeCommand = new Job(originalCommand) {
                @Override
                protected IStatus run(IProgressMonitor monitor) {
                    executeCommand(cmdAttribute, originalCommand, cmdData);
                    return Status.OK_STATUS;
                }

            };
            executeCommand.setPriority(Job.BUILD);
            executeCommand.schedule();
            return null;
        } else {
            return executeCommand(cmdAttribute, originalCommand, cmdData);
        }
    }

    private DeviceData executeCommand(final String cmdAttribute, final String originalCommand,
            final DeviceData cmdData) {

        try {
            final String timeout = System.getProperty("org.dawb.tango.spec.command.timeout");
            tangoProxy.set_timeout_millis(timeout != null ? Integer.parseInt(timeout) : Integer.MAX_VALUE);
            DeviceData ret = tangoProxy.command_inout(cmdAttribute, cmdData);

            // For fast scans this returns before the spec events have finished being sent
            // over by tango.
            while ((System.currentTimeMillis() - lastEvent) < 1000)
                try {
                    Thread.sleep(500);// Fudge
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            TangoConnectionEvent event = new TangoConnectionEvent(TangoConnectionImpl.this, new TangoMockEvent(),
                    "Finished '" + originalCommand + "'");
            event.setFinished(true);
            fireTangoConnectionListeners(event);

            return ret;

        } catch (DevFailed e) {
            TangoConnectionEvent event = new TangoConnectionEvent(TangoConnectionImpl.this, new TangoMockEvent(),
                    "Failed '" + originalCommand + "'");

            if (e.errors != null && e.errors.length > 0) {
                event.setErrorMessage(e.errors[e.errors.length - 1].desc);
            } else {
                event.setErrorMessage(e.getLocalizedMessage());
            }

            event.setFinished(true);
            fireTangoConnectionListeners(event);

            return null;
        }
    }

    public static void clear() {
        // clear anything cached statically

    }

}