Full sample device code

package org.tango.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tango.server.ServerManager;
import org.tango.server.annotation.Attribute;
import org.tango.server.annotation.Command;
import org.tango.server.annotation.Delete;
import org.tango.server.annotation.Device;
import org.tango.server.annotation.Init;

@Device
public class TestDevice {

    private final Logger logger = LoggerFactory.getLogger(TestDevice.class);
    /**
     * Attribute myAttribute READ WRITE, type DevDouble.
     */
    @Attribute
    public double myAttribute;

    /**
     * Starts the server.
     */
    public static void main(final String[] args) {
    ServerManager.getInstance().start(args, TestDevice.class);
    }

    /**
     * init device
     */
    @Init
    public void init() {
    logger.debug("init");
    }

    /**
     * delete device
     */
    @Delete
    public void delete() {
    logger.debug("delete");
    }

    /**
     * Execute command start. Type VOID-VOID
     */
    @Command
    public void start() {
    logger.debug("start");
    }

    /**
     * Read attribute myAttribute.  
     *
     * @return
     */
    public double getMyAttribute() {
    logger.debug("getMyAttribute {}", myAttribute);
    return myAttribute;
    }

    /**
     * Write attribute myAttribute
     * 
     * @param myAttribute
     */
    public void setMyAttribute(final double myAttribute) {
    logger.debug("setMyAttribute {}", myAttribute);
    this.myAttribute = myAttribute;
    }

}

Command with ICommandBehavior

package org.tango.test;

import org.tango.server.StateMachineBehavior;
import org.tango.server.command.CommandConfiguration;
import org.tango.server.command.ICommandBehavior;

import fr.esrf.Tango.DevFailed;

public class TestDynamicCommand implements ICommandBehavior {

    @Override
    public CommandConfiguration getConfiguration() throws DevFailed {
    final CommandConfiguration config = new CommandConfiguration();
    config.setName("testDynCmd");
    config.setInType(void.class);
    config.setOutType(double.class);
    return config;
    }

    @Override
    public Object execute(final Object arg) throws DevFailed {
    return 10.0;
    }

    @Override
    public StateMachineBehavior getStateMachine() throws DevFailed {
    return null;
    }

}

Attribute with IAttributeBehavior

package org.tango.test;

import org.tango.server.StateMachineBehavior;
import org.tango.server.attribute.AttributeConfiguration;
import org.tango.server.attribute.AttributeValue;
import org.tango.server.attribute.IAttributeBehavior;

import fr.esrf.Tango.AttrWriteType;
import fr.esrf.Tango.DevFailed;

/**
 * A sample attribute 
 * 
 */
public class TestDynamicAttribute implements IAttributeBehavior {

    private double readValue = 0;
    private double writeValue = 0;

    /**
     * Configure the attribute
     */
    @Override
    public AttributeConfiguration getConfiguration() throws DevFailed {
    final AttributeConfiguration config = new AttributeConfiguration();
    config.setName("testDynAttr");
    // attribute testDynAttr is a DevDouble
    config.setType(double.class);
    // attribute testDynAttr is READ_WRITE
    config.setWritable(AttrWriteType.READ_WRITE);
    return config;
    }

    /**
     * Read the attribute
     */
    @Override
    public AttributeValue getValue() throws DevFailed {
    readValue = readValue + writeValue;
    return new AttributeValue(readValue);
    }

    /**
     * Write the attribute
     */
    @Override
    public void setValue(final AttributeValue value) throws DevFailed {
    writeValue = (Double) value.getValue();
    }

    /**
     * Configure state machine if needed
     */
    @Override
    public StateMachineBehavior getStateMachine() throws DevFailed {
    final StateMachineBehavior stateMachine = new StateMachineBehavior();
    stateMachine.setDeniedStates(DeviceState.FAULT);
    stateMachine.setEndState(DeviceState.ON);
    return stateMachine;    
    }

    @Override
    public AttributeValue getSetValue() throws DevFailed {
    return new AttributeValue(writeValue);
    }

}

Extended example

package org.tango.test;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tango.DeviceState;
import org.tango.server.ServerManager;
import org.tango.server.annotation.Attribute;
import org.tango.server.annotation.ClassProperty;
import org.tango.server.annotation.Command;
import org.tango.server.annotation.Delete;
import org.tango.server.annotation.Device;
import org.tango.server.annotation.DeviceProperties;
import org.tango.server.annotation.DeviceProperty;
import org.tango.server.annotation.DynamicManagement;
import org.tango.server.annotation.Init;
import org.tango.server.annotation.State;
import org.tango.server.annotation.StateMachine;
import org.tango.server.dynamic.DynamicManager;
import org.tango.server.testserver.JTangoTest;

import fr.esrf.Tango.DevFailed;

@Device
public class TestDevice {

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

    /**
     * A device property
     */
    @DeviceProperty(defaultValue = "", description = "an example device property")
    private String myProp;

    @ClassProperty(defaultValue = "0", description = "an example class property")
    private int myClassProp;

    @DeviceProperties
    private Map<String, String[]> deviceProperties;

    /**
     * Attribute myAttribute READ WRITE, type DevDouble.
     */
    @Attribute
    public double myAttribute;

    /**
     * Manage dynamic attributes and commands
     */
    @DynamicManagement
    public DynamicManager dynamicManager;
    /**
     * Manage state of the device
     */
    @State
    private DeviceState state = DeviceState.OFF;

    /**
     * Starts the server.
     */
    public static void main(final String[] args) {
    ServerManager.getInstance().start(args, TestDevice.class);
    }

    public static final String NO_DB_DEVICE_NAME = "1/1/1";
    public static final String NO_DB_GIOP_PORT = "12354";
    public static final String NO_DB_INSTANCE_NAME = "1";


    /**
     * Starts the server in nodb mode.
     * 
     * @throws DevFailed
     */
    public static void startNoDb() {
    System.setProperty("OAPort", NO_DB_GIOP_PORT);
    ServerManager.getInstance().start(new String[] { NO_DB_INSTANCE_NAME, "-nodb", "-dlist", NO_DB_DEVICE_NAME },
        TestDevice.class);
    }

    /**
     * Starts the server in nodb mode with a file for device and class properties
     * 
     * @throws DevFailed
     */
    public static void startNoDbFile() throws DevFailed {
    System.setProperty("OAPort", NO_DB_GIOP_PORT);
    ServerManager.getInstance().start(
        new String[] { NO_DB_INSTANCE_NAME, "-nodb", "-dlist", NO_DB_DEVICE_NAME,
            "-file=" + JTangoTest.class.getResource("/noDbproperties.txt").getPath() }, TestDevice.class);
    }

    /**
     * init device
     * 
     * @throws DevFailed
     */
    @Init
    @StateMachine(endState = DeviceState.ON)
    public void init() throws DevFailed {
    logger.debug("myProp value = {}", myProp);
    logger.debug("myClassProp value = {}", myClassProp);
    logger.debug("deviceProperties value = {}", deviceProperties);
    // create a new dynamic attribute
    dynamicManager.addAttribute(new TestDynamicAttribute());
    // create a new dynamic command
    dynamicManager.addCommand(new TestDynamicCommand());
    logger.debug("init done");
    }

    /**
     * delete device
     * 
     * @throws DevFailed
     */
    @Delete
    public void delete() throws DevFailed {
    logger.debug("delete");
    // remove all dynamic commands and attributes
    dynamicManager.clearAll();
    }

    /**
     * Execute command start.
     */
    @Command
    @StateMachine(endState = DeviceState.RUNNING, deniedStates = DeviceState.FAULT)
    public void start() {
    logger.debug("start");
    }

    /**
     * Read attribute myAttribute.
     * 
     * @return
     */
    public double getMyAttribute() {
    logger.debug("getMyAttribute {}", myAttribute);
    return myAttribute;
    }

    /**
     * Write attribute myAttribute
     * 
     * @param myAttribute
     */
    public void setMyAttribute(final double myAttribute) {
    logger.debug("setMyAttribute {}", myAttribute);
    this.myAttribute = myAttribute;
    }

    public void setMyProp(final String myProp) {
    this.myProp = myProp;
    }

    public void setMyClassProp(final int myClassProp) {
    this.myClassProp = myClassProp;
    }

    public Map<String, String[]> getDeviceProperties() {
    return deviceProperties;
    }

    public DeviceState getState() {
    return state;
    }

    public void setState(final DeviceState state) {
    this.state = state;
    }
}

Logging configuration with logback

In this example, the logging is output to the console. The underlying APIs Jacorb and ehcache will log only errors while the classes “org.tango.test” will log in debug level. And the rest of classes will log in debug (root level). See http://logback.qos.ch/manual/configuration.html for details.

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>

    <jmxConfigurator />

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%-5level %d{HH:mm:ss.SSS} [%thread - %X{deviceName}] %logger{36}.%M:%L - %msg%n</pattern>
        </layout>
    </appender>

    <logger name="jacorb" level="ERROR" />
    <logger name="net.sf.ehcache" level="ERROR" />
    <logger name="org.tango" level="ERROR" />
    <logger name="org.tango.test" level="DEBUG" />  

    <root level="DEBUG">
        <appender-ref ref="CONSOLE" />
    </root>

</configuration>

Properties file for a device without Tango Database

# --- 1/1/1 properties
1/1/1->myProp:titi


CLASS/TestDevice->myClassProp: 10