#!/usr/bin/env python
# -*- coding:utf-8 -*- 


##############################################################################
## license :
##============================================================================
##
## File :        XtcdomeScopeDome4M.py
## 
## Project :     Tango device server to control ExTrA ScopeDome 4M astronomical dome.
##
## This file is part of Tango device class.
## 
## Tango is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
## 
## Tango is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with Tango.  If not, see <http://www.gnu.org/licenses/>.
## 
##
## $Author :      sylvain.lafrasse$
##
## $Revision :    $
##
## $Date :        $
##
## $HeadUrl :     $
##============================================================================
##            This file is generated by POGO
##    (Program Obviously used to Generate tango Object)
##
##        (c) - Software Engineering Group - ESRF
##############################################################################

""""""

__all__ = ["XtcdomeScopeDome4M", "XtcdomeScopeDome4MClass", "main"]

__docformat__ = 'restructuredtext'

import PyTango
import sys
# Add additional import
#----- PROTECTED REGION ID(XtcdomeScopeDome4M.additionnal_import) ENABLED START -----#
from xtlpy.tango.IpagStateMachine import IpagStateMachine,IpagStateMachineClass
from xtcdome import scopedome_wrapper
import thread
import threading
import Queue
import time
import math
from xtlpy import logger
import logging
#----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.additionnal_import

## Device States Description
## INIT : This state is transitory. It is reserved to the starting phase of the DS. The DS is initializing. It means that the software is not yet fully operational, and that the end-user must wait. This corresponds to the init_device() method call.
## OFF : The DS is fully initialized, but the hardware device is not yet connected.
## STANDBY : The hardware device is connected, but not fully operational for end-user. E.g a motor is ready to move internaly, but the homing procedure is not yet done. E.g a dome is in parked position, but ready to respond.
## ON : The hardware device is fully operational, waiting for end-user operation commands.
## MOVING : Transitory state, indicated that the hardware device is busy. End-user cannot apply commands and must wait for device availability to operate again. E.g a dome is moving to a new position, an algorithm is computing data.
## ALARM : Automatic state reflecting if an out-of-range value for one of the DS attributes is detected (if any). Can also be triggered internaly if needed. E.g the hardware device is still doing its job, but something has to be done to avoid a bigger problem.
## FAULT : The hardware device has a major failure that prevent it to work. An explicit error message should be provided in the Status command. E.g the hardware device is misbehaving, something has to be done manualy on the hardware, or a reset should be done..
## UNKNOWN : The DS cannot retrieve its state. E.g Communication problem between the workstation and LCU.

class XtcdomeScopeDome4M (IpagStateMachine):

    #--------- Add you global variables here --------------------------
    #----- PROTECTED REGION ID(XtcdomeScopeDome4M.global_variables) ENABLED START -----#
    
    def OffThread(self):
        if self.get_state() == PyTango.DevState.INIT:
            self.__dome = scopedome_wrapper.ScopeDomeWrapper()
        elif self.get_state() == PyTango.DevState.STANDBY:
            # Stop failure-checking thread first
            self.__failureChecking = False
            self.__failureThread.join(1.0) # One second timeout
            if self.__failureThread.isAlive():
                self.warn_stream("Could not terminate failure-checking thread properly")
            # Stop wrapper
            self.__dome.exit()
        # TODO : check errors before !
        self.set_state(PyTango.DevState.OFF)

    def StandbyThread(self):
        if self.get_state() == PyTango.DevState.OFF:
            # Start wrapper first
            self.__dome.connect(self.attr_SIM_FLAG_read)
            # Start failure-checking thread
            self.__failureChecking = True
            self.__failureThread = threading.Thread(target=self.FailureThread, args=())
            self.__failureThread.setDaemon(True)
            self.__failureThread.start()
        elif self.get_state() == PyTango.DevState.ON:
            self.set_state(PyTango.DevState.MOVING)
            self.__dome.goHome()
        # TODO : check errors before !
        self.set_state(PyTango.DevState.STANDBY)
            
    def OnThread(self):
        if self.get_state() == PyTango.DevState.STANDBY:
            self.set_state(PyTango.DevState.MOVING)
            self.__dome.goHome()
        # TODO : check errors before !
        self.set_state(PyTango.DevState.ON)

    def SlewThread(self, argin):
        self.set_state(PyTango.DevState.MOVING)
        self.__dome.slewToAzimuth(argin)
        reachedAzimuth = self.__dome.getAzimuth()

        if math.fabs(reachedAzimuth - argin) > self.AzimuthalTolerance:
            self.set_state(PyTango.DevState.ALARM)
            # TODO : set status
        else:
            self.set_state(PyTango.DevState.ON)

    def EncGotoThread(self, argin):
        self.set_state(PyTango.DevState.MOVING)
        self.__dome.encGoTo(argin)
        reachedEncoder = self.__dome.getEncoderCounter()

        if math.fabs(reachedEncoder - argin) > 1:
            self.set_state(PyTango.DevState.ALARM)
            self.set_status("Did not reach encoder position '" + str(argin) + "'.")
            # TODO : set status
        else:
            self.set_state(PyTango.DevState.ON)

    def OpenThread(self):
        self.set_state(PyTango.DevState.MOVING)
        #self.__dome.openShutter()
        self.__dome.asyncOpenShutter()
        if self.__dome.getShutterStatus() != scopedome_wrapper.SHUTTER.OPEN:
            self.set_state(PyTango.DevState.ALARM)
            self.set_status("Did not open shutter.")
            # TODO : set status
        else:
            self.set_state(PyTango.DevState.ON)

    def CloseThread(self):
        self.set_state(PyTango.DevState.MOVING)
        #self.__dome.closeShutter()
        self.__dome.asyncCloseShutter()
        if self.__dome.getShutterStatus() != scopedome_wrapper.SHUTTER.CLOSED:
            self.set_state(PyTango.DevState.ALARM)
            self.set_status("Did not close shutter.")
            # TODO : set status
        else:
            self.set_state(PyTango.DevState.ON)

    def FindHomeThread(self):
        self.set_state(PyTango.DevState.MOVING)
        self.__dome.goHome()
        if not self.__dome.isAtHome():
            self.set_state(PyTango.DevState.ALARM)
            self.set_status("Did not find home position.")
            # TODO : set status
        else:
            self.set_state(PyTango.DevState.ON)

    def StopThread(self):
        self.__dome.abort()
        self.__dome.waitStop()
        self.set_state(PyTango.DevState.ON)

    def DerotateThread(self):
        self.set_state(PyTango.DevState.MOVING)
        self.__dome.derotate()
        if math.fabs(self.__dome.getEncoderCounter()) > 1:
            self.set_state(PyTango.DevState.ALARM)
            self.set_status("Did not derotate dome.")
            # TODO : set status
        else:
            self.set_state(PyTango.DevState.STANDBY)

    def ResetAzimuthThread(self):
        self.__dome.resetAzimuthEncoder()
        if math.fabs(self.__dome.getEncoderCounter()) > self.AzimuthalTolerance:
            self.set_state(PyTango.DevState.ALARM)
            self.set_status("Did not reset azimuth encoder.")
            # TODO : set status

    def ResetEncoderThread(self):
        self.__dome.resetEncoderCounter()
        if math.fabs(self.__dome.getEncoderCounter()) > 1:
            self.set_state(PyTango.DevState.ALARM)
            self.set_status("Did not reset encoder counter.")
            # TODO : set status

    def CalibrateAzimuthThread(self):
        self.set_state(PyTango.DevState.MOVING)
        self.__dome.calibrateAzimuthEncoder()
        self.set_state(PyTango.DevState.STANDBY)

    def CalibrateInertiaThread(self):
        self.set_state(PyTango.DevState.MOVING)
        self.__dome.calibrateInertia()
        self.set_state(PyTango.DevState.STANDBY)

    def RestoreDefaultsThread(self):
        self.__dome.restoreDefault()
        self.set_state(PyTango.DevState.FAULT)

    def RelayThread(self, relay, state):
        self.set_state(PyTango.DevState.MOVING) # To circumvent concurrent access risks
        self.__dome.setRelayState(relay, state)
        if self.__dome.getRelayState(relay) != state:
            self.set_state(PyTango.DevState.ALARM)
            self.set_status("Did not switch relay '" + str(relay) + "' to '" + str(state) + "'.")
            # TODO : set status
        else:
            self.set_state(PyTango.DevState.ON)

    def FailureThread(self):
        failureQueue = self.__dome.getFailureQueue()
        failureQueueIsEmpty = True
        hardwareConnexionIsOk = True

        while self.__failureChecking == True:

            failureQueueIsEmpty = (failureQueue.empty() == True)

            if failureQueueIsEmpty: # Rely on driver only if available !
                hardwareConnexionIsOk = (self.__dome.isHardwareConnexionOk() == True)

            if self.attr_SIM_FLAG_read == True or (failureQueueIsEmpty and hardwareConnexionIsOk):
                time.sleep(0.5)
            else:
                self.__failureChecking = False # Stop checking
                exc = None
                self.set_state(PyTango.DevState.FAULT)
                if not failureQueueIsEmpty:
                    try:
                        exc = failureQueue.get(True, 0.5)
                    except:
                        # TODO : Handle this !
                        assert(False)
                elif not hardwareConnexionIsOk:
                    exc = "Lost hardware connexion !!!"
                # TODO : set status
                self.set_status("ASCOM failure detected '" + str(exc) + "'.")
                print "FAILED :((( [failureQueueIsEmpty = %d ; hardwareConnexionIsOk = %d]" % (failureQueueIsEmpty, hardwareConnexionIsOk)
                print exc
                # TODO : Handle situation !!!
                # TODO : Manager should look for state and status, then handle return to normal sequence (try DS restart; except: cycle ScopeDome PDU; finally: raise exception and emergency stop)

    #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.global_variables

    def __init__(self,cl, name):
        PyTango.Device_4Impl.__init__(self,cl,name)
        self.debug_stream("In __init__()")
        XtcdomeScopeDome4M.init_device(self)
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.__init__) ENABLED START -----#
        my_logger = logger.createLogger(__name__)
        logger.useLogger(consoleLevel = logging.INFO, fileLevel = logging.DEBUG)
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.__init__
        
    def delete_device(self):
        self.debug_stream("In delete_device()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.delete_device) ENABLED START -----#
        print "delete_device"
        if self.__dome != None:
            self.__dome.exit()
        self.__dome = None
        self.set_state(PyTango.DevState.UNKNOWN)
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.delete_device

    def init_device(self):
        self.debug_stream("In init_device()")
        self.get_device_properties(self.get_device_class())
        self.attr_SIM_FLAG_read = False
        self.attr_atHome_read = False
        self.attr_atPark_read = False
        self.attr_atmosphericHumidity_read = 0.0
        self.attr_atmosphericPressure_read = 0.0
        self.attr_azimuth_read = 0.0
        self.attr_dewPoint_read = 0.0
        self.attr_encoder_read = 0
        self.attr_externalTemperature_read = 0.0
        self.attr_internalTemperature_read = 0.0
        self.attr_powerFPUControlers_read = False
        self.attr_powerFlatFieldCalib_read = False
        self.attr_powerScopeDomeControler_read = False
        self.attr_powerSpectralCalib_read = False
        self.attr_radioStrength_read = 0
        self.attr_shutterClosed_read = False
        self.attr_weatherInterlockActive_read = False
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.init_device) ENABLED START -----#
        self.set_state(PyTango.DevState.UNKNOWN)
        print "init_device"
        self.__dome = None
        self.__failureThread = None
        self.__failureChecking = False
        self.set_state(PyTango.DevState.INIT)
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.init_device

    def always_executed_hook(self):
        self.debug_stream("In always_excuted_hook()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.always_executed_hook) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.always_executed_hook

    #-----------------------------------------------------------------------------
    #    XtcdomeScopeDome4M read/write attribute methods
    #-----------------------------------------------------------------------------
    
    def read_SIM_FLAG(self, attr):
        self.debug_stream("In read_SIM_FLAG()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.SIM_FLAG_read) ENABLED START -----#
        attr.set_value(self.attr_SIM_FLAG_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.SIM_FLAG_read
        
    def write_SIM_FLAG(self, attr):
        self.debug_stream("In write_SIM_FLAG()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.SIM_FLAG_write) ENABLED START -----#
        self.attr_SIM_FLAG_read = data
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.SIM_FLAG_write
        
    def read_atHome(self, attr):
        self.debug_stream("In read_atHome()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.atHome_read) ENABLED START -----#
        self.attr_atHome_read = self.__dome.isAtHome()
        attr.set_value(self.attr_atHome_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.atHome_read
        
    def write_atHome(self, attr):
        self.debug_stream("In write_atHome()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.atHome_write) ENABLED START -----#
        if data == True:
            thread.start_new_thread(self.FindHomeThread, () )
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.atHome_write
        
    def is_atHome_allowed(self, attr):
        self.debug_stream("In is_atHome_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_atHome_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_atHome_allowed
        return state_ok
        
    def read_atPark(self, attr):
        self.debug_stream("In read_atPark()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.atPark_read) ENABLED START -----#
        currentAzimuth = self.__dome.getAzimuth()
        if math.fabs(currentAzimuth - self.ParkAzimuth) > self.AzimuthalTolerance:
            self.attr_atPark_read = False
        else:
            self.attr_atPark_read = True
        attr.set_value(self.attr_atPark_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.atPark_read
        
    def write_atPark(self, attr):
        self.debug_stream("In write_atPark()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.atPark_write) ENABLED START -----#
        thread.start_new_thread(self.SlewThread, (self.ParkAzimuth,) )
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.atPark_write
        
    def is_atPark_allowed(self, attr):
        self.debug_stream("In is_atPark_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_atPark_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_atPark_allowed
        return state_ok
        
    def read_atmosphericHumidity(self, attr):
        self.debug_stream("In read_atmosphericHumidity()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.atmosphericHumidity_read) ENABLED START -----#
        self.attr_AtmosphericHumidity_read = self.__dome.getHumidity()
        attr.set_value(self.attr_AtmosphericHumidity_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.atmosphericHumidity_read
        
    def is_atmosphericHumidity_allowed(self, attr):
        self.debug_stream("In is_atmosphericHumidity_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_atmosphericHumidity_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_atmosphericHumidity_allowed
        return state_ok
        
    def read_atmosphericPressure(self, attr):
        self.debug_stream("In read_atmosphericPressure()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.atmosphericPressure_read) ENABLED START -----#
        self.attr_AtmosphericPressure_read = self.__dome.getPressure()
        attr.set_value(self.attr_AtmosphericPressure_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.atmosphericPressure_read
        
    def is_atmosphericPressure_allowed(self, attr):
        self.debug_stream("In is_atmosphericPressure_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_atmosphericPressure_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_atmosphericPressure_allowed
        return state_ok
        
    def read_azimuth(self, attr):
        self.debug_stream("In read_azimuth()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.azimuth_read) ENABLED START -----#
        self.attr_Azimuth_read = self.__dome.getAzimuth()
        attr.set_value(self.attr_Azimuth_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.azimuth_read
        
    def write_azimuth(self, attr):
        self.debug_stream("In write_azimuth()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.azimuth_write) ENABLED START -----#
        thread.start_new_thread(self.SlewThread, (data,) )
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.azimuth_write
        
    def is_azimuth_allowed(self, attr):
        self.debug_stream("In is_azimuth_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_azimuth_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_azimuth_allowed
        return state_ok
        
    def read_dewPoint(self, attr):
        self.debug_stream("In read_dewPoint()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.dewPoint_read) ENABLED START -----#
        self.attr_DewPoint_read = self.__dome.getDewPoint()
        attr.set_value(self.attr_DewPoint_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.dewPoint_read
        
    def is_dewPoint_allowed(self, attr):
        self.debug_stream("In is_dewPoint_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_dewPoint_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_dewPoint_allowed
        return state_ok
        
    def read_encoder(self, attr):
        self.debug_stream("In read_encoder()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.encoder_read) ENABLED START -----#
        self.attr_Encoder_read = self.__dome.getEncoderCounter()
        attr.set_value(self.attr_Encoder_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.encoder_read
        
    def write_encoder(self, attr):
        self.debug_stream("In write_encoder()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.encoder_write) ENABLED START -----#
        thread.start_new_thread(self.EncGotoThread, (data,) )
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.encoder_write
        
    def is_encoder_allowed(self, attr):
        self.debug_stream("In is_encoder_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_encoder_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_encoder_allowed
        return state_ok
        
    def read_externalTemperature(self, attr):
        self.debug_stream("In read_externalTemperature()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.externalTemperature_read) ENABLED START -----#
        self.attr_ExternalTemperature_read = self.__dome.getOutsideTemperature()
        attr.set_value(self.attr_ExternalTemperature_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.externalTemperature_read
        
    def is_externalTemperature_allowed(self, attr):
        self.debug_stream("In is_externalTemperature_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_externalTemperature_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_externalTemperature_allowed
        return state_ok
        
    def read_internalTemperature(self, attr):
        self.debug_stream("In read_internalTemperature()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.internalTemperature_read) ENABLED START -----#
        self.attr_InternalTemperature_read = self.__dome.getInsideTemperature()
        attr.set_value(self.attr_InternalTemperature_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.internalTemperature_read
        
    def is_internalTemperature_allowed(self, attr):
        self.debug_stream("In is_internalTemperature_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_internalTemperature_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_internalTemperature_allowed
        return state_ok
        
    def read_powerFPUControlers(self, attr):
        self.debug_stream("In read_powerFPUControlers()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.powerFPUControlers_read) ENABLED START -----#
        self.attr_powerFPUControlers_read = self.__dome.getRelayState(scopedome_wrapper.RELAY.FOUR)
        attr.set_value(self.attr_powerFPUControlers_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.powerFPUControlers_read
        
    def write_powerFPUControlers(self, attr):
        self.debug_stream("In write_powerFPUControlers()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.powerFPUControlers_write) ENABLED START -----#
        thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.FOUR, data) )
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.powerFPUControlers_write
        
    def is_powerFPUControlers_allowed(self, attr):
        self.debug_stream("In is_powerFPUControlers_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_powerFPUControlers_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_powerFPUControlers_allowed
        return state_ok
        
    def read_powerFlatFieldCalib(self, attr):
        self.debug_stream("In read_powerFlatFieldCalib()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.powerFlatFieldCalib_read) ENABLED START -----#
        relay2State = self.__dome.getRelayState(scopedome_wrapper.RELAY.TWO)
        relay3State = self.__dome.getRelayState(scopedome_wrapper.RELAY.THREE)
        attr.set_quality(PyTango.AttrQuality.ATTR_VALID)
        if relay2State == True and relay3State == False:
            self.attr_powerFPUControlers_read = False
        elif relay2State == False and relay3State == True:
            self.attr_powerFPUControlers_read = True
        else:
            attr.set_quality(PyTango.AttrQuality.ATTR_INVALID)
        attr.set_value(self.attr_powerFlatFieldCalib_read)
        # TODO
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.powerFlatFieldCalib_read
        
    def write_powerFlatFieldCalib(self, attr):
        self.debug_stream("In write_powerFlatFieldCalib()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.powerFlatFieldCalib_write) ENABLED START -----#
        if data == True:
            thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.TWO, False))
            thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.THREE, True))
        else:
            thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.THREE, False))
            thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.TWO, True))
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.powerFlatFieldCalib_write
        
    def is_powerFlatFieldCalib_allowed(self, attr):
        self.debug_stream("In is_powerFlatFieldCalib_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_powerFlatFieldCalib_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_powerFlatFieldCalib_allowed
        return state_ok
        
    def read_powerScopeDomeControler(self, attr):
        self.debug_stream("In read_powerScopeDomeControler()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.powerScopeDomeControler_read) ENABLED START -----#
        self.attr_powerScopeDomeControler_read = self.__dome.getRelayState(scopedome_wrapper.RELAY.ONE)
        attr.set_value(self.attr_powerScopeDomeControler_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.powerScopeDomeControler_read
        
    def write_powerScopeDomeControler(self, attr):
        self.debug_stream("In write_powerScopeDomeControler()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.powerScopeDomeControler_write) ENABLED START -----#
        if data == True:
            thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.ONE, True))
        else: # Should never be used obviously !
            thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.ONE, False))
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.powerScopeDomeControler_write
        
    def is_powerScopeDomeControler_allowed(self, attr):
        self.debug_stream("In is_powerScopeDomeControler_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_powerScopeDomeControler_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_powerScopeDomeControler_allowed
        return state_ok
        
    def read_powerSpectralCalib(self, attr):
        self.debug_stream("In read_powerSpectralCalib()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.powerSpectralCalib_read) ENABLED START -----#
        self.attr_powerSpectralCalib_read = self.__dome.getRelayState(scopedome_wrapper.RELAY.LIGHT)
        attr.set_value(self.attr_powerSpectralCalib_read)
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.powerSpectralCalib_read
        
    def write_powerSpectralCalib(self, attr):
        self.debug_stream("In write_powerSpectralCalib()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.powerSpectralCalib_write) ENABLED START -----#
        # TODO : Must be at home first !!!
        if data == True:
            thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.LIGHT, True))
        else:
            thread.start_new_thread(self.RelayThread, (scopedome_wrapper.RELAY.LIGHT, False))
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.powerSpectralCalib_write
        
    def is_powerSpectralCalib_allowed(self, attr):
        self.debug_stream("In is_powerSpectralCalib_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_powerSpectralCalib_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_powerSpectralCalib_allowed
        return state_ok
        
    def read_radioStrength(self, attr):
        self.debug_stream("In read_radioStrength()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.radioStrength_read) ENABLED START -----#
        self.attr_RadioStrength_read = self.__dome.getRadioSignalStength()
        attr.set_value(self.attr_RadioStrength_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.radioStrength_read
        
    def is_radioStrength_allowed(self, attr):
        self.debug_stream("In is_radioStrength_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_radioStrength_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_radioStrength_allowed
        return state_ok
        
    def read_shutterClosed(self, attr):
        self.debug_stream("In read_shutterClosed()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.shutterClosed_read) ENABLED START -----#
        status = self.__dome.getShutterStatus()
        self.attr_ShutterClosed_read = False
        if status == scopedome_wrapper.SHUTTER.CLOSED:
            self.attr_ShutterClosed_read = True
        elif  status == scopedome_wrapper.SHUTTER.ERROR:
            self.set_state(PyTango.DevState.ALARM)
            # TODO : set status
        attr.set_value(self.attr_ShutterClosed_read)
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.shutterClosed_read
        
    def write_shutterClosed(self, attr):
        self.debug_stream("In write_shutterClosed()")
        data=attr.get_write_value()
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.shutterClosed_write) ENABLED START -----#
        if data == True:
            thread.start_new_thread(self.CloseThread, () )
        else:
            thread.start_new_thread(self.OpenThread, () )
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.shutterClosed_write
        
    def is_shutterClosed_allowed(self, attr):
        self.debug_stream("In is_shutterClosed_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_shutterClosed_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_shutterClosed_allowed
        return state_ok
        
    def read_weatherInterlockActive(self, attr):
        self.debug_stream("In read_weatherInterlockActive()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.weatherInterlockActive_read) ENABLED START -----#
        self.attr_weatherInterlockActive_read = self.__dome.isCloudSensorActive()
        attr.set_value(self.attr_weatherInterlockActive_read)
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.weatherInterlockActive_read
        
    def is_weatherInterlockActive_allowed(self, attr):
        self.debug_stream("In is_weatherInterlockActive_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_weatherInterlockActive_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_weatherInterlockActive_allowed
        return state_ok
        
    
    
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.initialize_dynamic_attributes) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.initialize_dynamic_attributes
            
    def read_attr_hardware(self, data):
        self.debug_stream("In read_attr_hardware()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.read_attr_hardware) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.read_attr_hardware


    #-----------------------------------------------------------------------------
    #    XtcdomeScopeDome4M command methods
    #-----------------------------------------------------------------------------
    
    def Kill(self):
        """ Exit the DS process. ASTOR should restart it automatically.
        Last resort operation when a DS is stuck or failed.
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In Kill()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.Kill) ENABLED START -----#
        print "Killing me hardly..."
        sys.exit(-1)
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.Kill
        
    def Off(self):
        """ Go to OFF state : disconnect the hardware device or deallocate software service.
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In Off()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.Off) ENABLED START -----#
        thread.start_new_thread(self.OffThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.Off
        
    def is_Off_allowed(self):
        self.debug_stream("In is_Off_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.OFF,
            PyTango.DevState.ON,
            PyTango.DevState.MOVING])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_Off_allowed) ENABLED START -----#

        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_Off_allowed
        return state_ok
        
    def Standby(self):
        """ Go to STANDBY state :
        - comming from the OFF state : connect the hardware device or allocate the software service.
        - comming from the ON state : put the hardware device is safe or sleep mode (e.g motor brake, dome park position).
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In Standby()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.Standby) ENABLED START -----#
        thread.start_new_thread(self.StandbyThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.Standby
        
    def is_Standby_allowed(self):
        self.debug_stream("In is_Standby_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.STANDBY,
            PyTango.DevState.MOVING,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_Standby_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_Standby_allowed
        return state_ok
        
    def On(self):
        """ Go to the ON state : initialize the hardware device or software service for effective operation.
        E.g performs the homing procedure for a motor.
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In On()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.On) ENABLED START -----#
        thread.start_new_thread(self.OnThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.On
        
    def is_On_allowed(self):
        self.debug_stream("In is_On_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.ON,
            PyTango.DevState.MOVING,
            PyTango.DevState.FAULT,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_On_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_On_allowed
        return state_ok
        
    def Stop(self):
        """ Stop ongoing motion (if any)
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In Stop()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.Stop) ENABLED START -----#
        thread.start_new_thread(self.StopThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.Stop
        
    def is_Stop_allowed(self):
        self.debug_stream("In is_Stop_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_Stop_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_Stop_allowed
        return state_ok
        
    def Derotate(self):
        """ 
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In Derotate()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.Derotate) ENABLED START -----#
        thread.start_new_thread(self.DerotateThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.Derotate
        
    def is_Derotate_allowed(self):
        self.debug_stream("In is_Derotate_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.ON,
            PyTango.DevState.MOVING,
            PyTango.DevState.ALARM,
            PyTango.DevState.FAULT,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_Derotate_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_Derotate_allowed
        return state_ok
        
    def ResetAzimuthEncoder(self):
        """ 
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In ResetAzimuthEncoder()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.ResetAzimuthEncoder) ENABLED START -----#
        thread.start_new_thread(self.ResetAzimuthThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.ResetAzimuthEncoder
        
    def is_ResetAzimuthEncoder_allowed(self):
        self.debug_stream("In is_ResetAzimuthEncoder_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.ON,
            PyTango.DevState.MOVING,
            PyTango.DevState.ALARM,
            PyTango.DevState.FAULT,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_ResetAzimuthEncoder_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_ResetAzimuthEncoder_allowed
        return state_ok
        
    def ResetEncoderCounter(self):
        """ 
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In ResetEncoderCounter()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.ResetEncoderCounter) ENABLED START -----#
        thread.start_new_thread(self.ResetEncoderThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.ResetEncoderCounter
        
    def is_ResetEncoderCounter_allowed(self):
        self.debug_stream("In is_ResetEncoderCounter_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.ON,
            PyTango.DevState.MOVING,
            PyTango.DevState.ALARM,
            PyTango.DevState.FAULT,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_ResetEncoderCounter_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_ResetEncoderCounter_allowed
        return state_ok
        
    def CalibrateAzimuthEncoder(self):
        """ 
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In CalibrateAzimuthEncoder()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.CalibrateAzimuthEncoder) ENABLED START -----#
        thread.start_new_thread(self.CalibrateAzimuthThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.CalibrateAzimuthEncoder
        
    def is_CalibrateAzimuthEncoder_allowed(self):
        self.debug_stream("In is_CalibrateAzimuthEncoder_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.ON,
            PyTango.DevState.MOVING,
            PyTango.DevState.ALARM,
            PyTango.DevState.FAULT,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_CalibrateAzimuthEncoder_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_CalibrateAzimuthEncoder_allowed
        return state_ok
        
    def CalibrateInertia(self):
        """ Can take a very long time
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In CalibrateInertia()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.CalibrateInertia) ENABLED START -----#
        thread.start_new_thread(self.CalibrateInertiaThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.CalibrateInertia
        
    def is_CalibrateInertia_allowed(self):
        self.debug_stream("In is_CalibrateInertia_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.ON,
            PyTango.DevState.MOVING,
            PyTango.DevState.ALARM,
            PyTango.DevState.FAULT,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_CalibrateInertia_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_CalibrateInertia_allowed
        return state_ok
        
    def RestoreDriverDefaults(self):
        """ WARNING : Will erase all driver settings ! Last resort action !
        
        :param : 
        :type: PyTango.DevVoid
        :return: 
        :rtype: PyTango.DevVoid """
        self.debug_stream("In RestoreDriverDefaults()")
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.RestoreDriverDefaults) ENABLED START -----#
        thread.start_new_thread(self.RestoreDefaultsThread, ())
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.RestoreDriverDefaults
        
    def is_RestoreDriverDefaults_allowed(self):
        self.debug_stream("In is_RestoreDriverDefaults_allowed()")
        state_ok = not(self.get_state() in [PyTango.DevState.INIT,
            PyTango.DevState.OFF,
            PyTango.DevState.ON,
            PyTango.DevState.MOVING,
            PyTango.DevState.ALARM,
            PyTango.DevState.FAULT,
            PyTango.DevState.UNKNOWN])
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.is_RestoreDriverDefaults_allowed) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.is_RestoreDriverDefaults_allowed
        return state_ok
        

class XtcdomeScopeDome4MClass(IpagStateMachineClass):
    #--------- Add you global class variables here --------------------------
    #----- PROTECTED REGION ID(XtcdomeScopeDome4M.global_class_variables) ENABLED START -----#
    
    #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.global_class_variables

    def dyn_attr(self, dev_list):
        """Invoked to create dynamic attributes for the given devices.
        Default implementation calls
        :meth:`XtcdomeScopeDome4M.initialize_dynamic_attributes` for each device
    
        :param dev_list: list of devices
        :type dev_list: :class:`PyTango.DeviceImpl`"""
    
        for dev in dev_list:
            try:
                dev.initialize_dynamic_attributes()
            except:
                import traceback
                dev.warn_stream("Failed to initialize dynamic attributes")
                dev.debug_stream("Details: " + traceback.format_exc())
        #----- PROTECTED REGION ID(XtcdomeScopeDome4M.dyn_attr) ENABLED START -----#
        
        #----- PROTECTED REGION END -----#	//	XtcdomeScopeDome4M.dyn_attr

    #    Class Properties
    class_property_list = {
        }
    class_property_list.update(IpagStateMachineClass.class_property_list)


    #    Device Properties
    device_property_list = {
        'ParkAzimuth':
            [PyTango.DevDouble,
            "Azimuthal position to park the dome",
            [90.0]],
        'AzimuthalTolerance':
            [PyTango.DevDouble,
            "Maximum difference (in degrees) allowed between desired and reached azimuthal position before raising an error",
            [1]],
        }
    device_property_list.update(IpagStateMachineClass.device_property_list)


    #    Command definitions
    cmd_list = {
        'Kill':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Off':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Standby':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'On':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Stop':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"]],
        'Derotate':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"],
            {
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        'ResetAzimuthEncoder':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"],
            {
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        'ResetEncoderCounter':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"],
            {
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        'CalibrateAzimuthEncoder':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"],
            {
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        'CalibrateInertia':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"],
            {
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        'RestoreDriverDefaults':
            [[PyTango.DevVoid, "none"],
            [PyTango.DevVoid, "none"],
            {
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        }
    cmd_list.update(IpagStateMachineClass.cmd_list)


    #    Attribute definitions
    attr_list = {
        'SIM_FLAG':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Simulation Flag",
                'description': "True if the hardware device is simulated, false otherwise.\nCan only be changed in OFF state !\n",
            } ],
        'atHome':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Is at home ?",
                'description': "True if the dome is at its homing position, false otherwise.",
            } ],
        'atPark':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Is at park ?",
                'description': "True if the dome is at the position defined in ParkAzimuth property, false otherwise.",
            } ],
        'atmosphericHumidity':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "Atmospheric humidity",
                'unit': "%",
                'format': "%5.1f",
                'max value': "100",
                'min value': "0",
                'max alarm': "100",
                'min alarm': "0",
                'description': "Atmospheric humidity near the dome.",
            } ],
        'atmosphericPressure':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "Atmospheric pressure",
                'unit': "hpa",
                'format': "%6.1f",
                'min value': "0",
                'min alarm': "0",
                'description': "Atmospheric pressure near the dome.",
            } ],
        'azimuth':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Azimuth",
                'unit': "degrees",
                'format': "%7.3f",
                'max value': "360",
                'min value': "0",
                'description': "Azimuthal position of the dome (between 0 and 360 degrees).",
            } ],
        'dewPoint':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "Dew point",
                'unit': "degrees Celsius",
                'format': "%4.1f",
                'min value': "-255",
                'min alarm': "-255",
                'description': "Dew point temperature computed by the dome controler.",
            } ],
        'encoder':
            [[PyTango.DevLong,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Encoder counter",
                'format': "%d",
                'description': "Encoder position of the dome.",
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        'externalTemperature':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "External Temperature",
                'unit': "degrees Celsius",
                'format': "%4.1f",
                'min value': "-255",
                'min alarm': "-255",
                'description': "Dome external temperature.",
            } ],
        'internalTemperature':
            [[PyTango.DevDouble,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "Internal Temperature",
                'unit': "degrees Celsius",
                'format': "%4.1f",
                'min value': "-255",
                'min alarm': "-255",
                'description': "Dome internal temperature.",
            } ],
        'powerFPUControlers':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Are FPU controlers powered ?",
                'description': "True to power FPU controlers, false otherwise.",
            } ],
        'powerFlatFieldCalib':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Is flat-field calibration lamp powered ?",
                'description': "True to power flat-field calibration lamp, false otherwise.",
            } ],
        'powerScopeDomeControler':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Is ScopeDome main controler powered ?",
                'description': "True to power the ScopeDome main controler, false otherwise (will hard-reboot the controler).",
                'Display level': PyTango.DispLevel.EXPERT,
            } ],
        'powerSpectralCalib':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Is spectral calibration lamp powered ?",
                'description': "True to power spectral calibration lamp, false otherwise.",
            } ],
        'radioStrength':
            [[PyTango.DevUChar,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "Radio Strength",
                'unit': "%",
                'format': "%d",
                'max value': "100",
                'min value': "0",
                'description': "Quality of the radio signal (in %) received by the rotating controler, if any.",
            } ],
        'shutterClosed':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ_WRITE],
            {
                'label': "Is shutter closed ?",
                'description': "True if the shutter is closed, false otherwise.",
            } ],
        'weatherInterlockActive':
            [[PyTango.DevBoolean,
            PyTango.SCALAR,
            PyTango.READ],
            {
                'label': "Is weather interlock active ?",
                'description': "True if the weather interlock is active and dome should close, false otherwise.",
            } ],
        }
    attr_list.update(IpagStateMachineClass.attr_list)


def main():
    try:
        py = PyTango.Util(sys.argv)
        py.add_class(XtcdomeScopeDome4MClass,XtcdomeScopeDome4M,'XtcdomeScopeDome4M')

        U = PyTango.Util.instance()
        U.server_init()
        U.server_run()

    except PyTango.DevFailed,e:
        print '-------> Received a DevFailed exception:',e
    except Exception,e:
        print '-------> An unforeseen exception occured....',e

if __name__ == '__main__':
    main()
