Commit 6c31e105 authored by Elisabetta Giani's avatar Elisabetta Giani
Browse files

AT5-262: Added TANGO devices to perform the monitoring of the CSP.LMC

Capabilities. CspMaster implements capabilty attributes as forwarded
attributes.
Added alarm flags for each power command.
Added dsconfig file to configure CSP.LMC TANGO DB.
Added docker and docker-compose files to build the docker images
and containers.
parent c7411ecf
Loading
Loading
Loading
Loading

csp-lmc-common/Pipfile

0 → 100644
+35 −0
Original line number Diff line number Diff line
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
# numpy and pytango versions must match those in the ska-python-builder image,
# otherwise pytango will be recompiled.
numpy = "==1.17.2"
pytango = "==9.3.1"
# itango is added to make it easier to exercise the device in a CLI session,
# but it's not mandatory. If you remove itango, you should also remove the
# 'RUN ipython profile create' line from Dockerfile.
itango = "*"
# If you want to debug devices running in containers, add pydevd to the dependencies
# pydevd = "*"

[dev-packages]
docutils = "*"
MarkupSafe = "*"
Pygments = "*"
pylint = "*"
pytest = "*"
pytest-cov = "*"
pytest-pylint = "*"
pytest-json-report = "*"
python-dotenv = ">=0.5.1"
ptvsd = "*"
Sphinx = "*"
sphinx_rtd_theme = "*"
sphinx-autobuild = "*"
sphinxcontrib-websupport = "*"

[requires]
python_version = "3"
+364 −0
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
#
# This file is part of the CspCapabilityMonitor project
#
# INAF, SKA Telescope
#
# Distributed under the terms of the GPL license.
# See LICENSE.txt for more info.

""" CSP.LMC Common  Class

CSP.LMC Common Class designed to monitoring the SCM
attributes of the CSP Capabilities: SearchBeams, TimingBeams,
VlbiBeams, Receptors/Stations.
"""
# PROTECTED REGION ID (CspMaster.standardlibray_import) ENABLED START #
# Python standard library
from __future__ import absolute_import
import sys
import os
from future.utils import with_metaclass
from collections import defaultdict
# PROTECTED REGION END# //CspMaster.standardlibray_import
# tango imports
import tango
from tango import DebugIt
from tango.server import run
from tango.server import Device, DeviceMeta
from tango.server import attribute, command
from tango.server import device_property
from tango import AttrQuality, DispLevel, DevState
from tango import AttrWriteType, PipeWriteType
# Additional import
# PROTECTED REGION ID(CspCapabilityMonitor.additionnal_import) ENABLED START #

from skabase.SKABaseDevice import SKABaseDevice
from skabase.auxiliary import utils
# add the path to import global_enum package.
file_path = os.path.dirname(os.path.abspath(__file__))
utils_path = os.path.abspath(os.path.join(file_path, os.pardir)) + "/utils"
sys.path.insert(0, utils_path)
import cspcommons
from cspcommons import HealthState, AdminMode, ObsState, ObsMode
 
# PROTECTED REGION END #    //  CspCapabilityMonitor.additionnal_import

__all__ = ["CspCapabilityMonitor", "main"]

class CspCapabilityMonitor(with_metaclass(DeviceMeta,SKABaseDevice)):
    """
    CSP.LMC Common Class designed to monitoring the SCM
    attributes of the CSP Capabilities: SearchBeams, TimingBeams,
    VlbiBeams, Receptors/Stations.

    **Properties:**

    - Device Property
    
    CapabilityDevices
        - The list of the CSP Capability devices FQDNs monitored\nby the instance.
        - Type:'DevVarStringArray'

    
    """
    # PROTECTED REGION ID(CspCapabilityMonitor.class_variable) ENABLED START #
    # PROTECTED REGION END #    //  CspCapabilityMonitor.class_variable

    # -----------------
    # Device Properties
    # -----------------
        
    CapabilityDevices = device_property(
        dtype='DevVarStringArray',
    )

    # ----------
    # Attributes
    # ----------

    numOfUnassignedIDs = attribute(
        dtype='DevUShort',
    )

    capabilityState = attribute(
        dtype=('DevState',),
        max_dim_x=1500,
        label="Capability State",
        doc="Report the State of the capabilities.",
    )

    capabilityHealthState = attribute(
        dtype=('DevUShort',),
        max_dim_x=1500,
    )

    capabilityAdminMode = attribute(
        dtype=('DevUShort',),
        access=AttrWriteType.READ_WRITE,
        max_dim_x=1500,
    )

    capabilityObsState = attribute(
        dtype=('DevUShort',),
        max_dim_x=1500,
    )

    unassignedIDs = attribute(
        dtype=('DevUShort',),
        max_dim_x=1500,
    )

    cspCapabilityAddresses = attribute(
        dtype=('DevString',),
        max_dim_x=1500,
        label="CSP.LMC Capability devices FQDNs",
        doc="The FQDNs of the CSP.LMC Capability devices: SearchBeams, TimingBeams, VlbiBeams,\nReceptors (MID instance), Stations (LOW instance)",
    )
    
    capabilityMembership = attribute(
        dtype=('DevUShort',),
        max_dim_x=1500,
        label="Capability sub-array affiliation",
    )

    # ---------------
    # General methods
    # ---------------

    def init_device(self):
        """Initialises the attributes and properties of the CspCapabilityMonitor."""
        SKABaseDevice.init_device(self)
        # PROTECTED REGION ID(CspCapabilityMonitor.init_device) ENABLED START #
        self.set_state(tango.DevState.INIT)
        self._capability_fqdn = self.CapabilityDevices
        print("self._capability_fqdn:", self._capability_fqdn)
        self._capability_proxies = {}
        self._event_id = defaultdict(lambda: defaultdict(lambda: 0))
        self._capability_state = {}
        self._capability_health_state = {}
        self._capability_admin_mode = {}
        self._capability_obs_state = {} 
        self._capability_membership = {}
        self._capability_proxies = {}
        self._unassigned_ids = [0]* len(self._capability_fqdn)
        self._capability_state = {fqdn:tango.DevState.DISABLE for fqdn in self._capability_fqdn}
        self._capability_health_state = {fqdn:HealthState.UNKNOWN for fqdn in self._capability_fqdn}
        self._capability_admin_mode = {fqdn:AdminMode.NOTFITTED for fqdn in self._capability_fqdn}
        self._capability_obs_state = {fqdn:ObsState.IDLE for fqdn in self._capability_fqdn} 
        self._capability_membership = {fqdn:0 for fqdn in self._capability_fqdn}
        self._csp_tango_db = 0
        
        # establish connection with the CSP.LMC TANGO DB
        self._csp_tango_db = tango.Database()
        attribute_properties = self._csp_tango_db.get_device_attribute_property(self.get_name(),
                                                                          {'adminMode': ['__value']})
        admin_mode_memorized = attribute_properties['adminMode']['__value']
        self._admin_mode = int(admin_mode_memorized[0])
        self._connect_to_capability()
        self._healthState = HealthState.OK
        self.set_state(tango.DevState.ON)
        
    def _connect_to_capability(self):
        # connect to DB and read the adminMode of each capability
        
        for fqdn in self.CapabilityDevices:
            attribute_properties = self._csp_tango_db.get_device_attribute_property(fqdn, {'adminMode': ['__value'],})
            try:
                admin_mode_memorized = attribute_properties['adminMode']['__value']
                self._capability_admin_mode[fqdn] = int(admin_mode_memorized[0])
            except KeyError as key_err:
                print(key_err)
            try:
                device_proxy = tango.DeviceProxy(fqdn)
                self._capability_proxies[fqdn] = device_proxy
                ev_id = device_proxy.subscribe_event("adminMode",
                                                     EventType.CHANGE_EVENT,
                                                     self._attributes_change_event_cb,
                                                     stateless=True)
                self._event_id[fqdn] = ev_id
                
                ev_id = device_proxy.subscribe_event("State",
                                                     EventType.CHANGE_EVENT,
                                                     self._attributes_change_event_cb,
                                                     stateless=True)
                self._event_id[fqdn] = ev_id

                ev_id = device_proxy.subscribe_event("healthState",
                                                     EventType.CHANGE_EVENT,
                                                     self._attributes_change_event_cb,
                                                     stateless=True)
                self._event_id[fqdn] = ev_id
                
                ev_id = device_proxy.subscribe_event("obsState",
                                                     EventType.CHANGE_EVENT,
                                                     self._attributes_change_event_cb,
                                                     stateless=True)
                self._event_id[fqdn]= ev_id
                
                ev_id = device_proxy.subscribe_event("subarrayMemebership",
                                                     EventType.CHANGE_EVENT,
                                                     self._attributes_change_event_cb,
                                                     stateless=True)
                self._event_id[fqdn]['subarrayMembership'] = ev_id
            except tango.DevFailed as tango_err:
                print(tango_err.args[0].desc)
                
    def _attributes_change_event_cb(self, evt):
        dev_name = evt.device.dev_name()
        if not evt.err:
            try:
                if dev_name in self.CapabilityDevices:
                    if evt.attr_value.name.lower() == "state":
                        print("{}: received event on {} value {}".format(dev_name,
                                                                         evt.attr_value.name,
                                                                         evt.attr_value.value))
                        self._capability_state[dev_name] = evt.attr_value.value
                        
                    elif evt.attr_value.name.lower() == "healthstate":
                        self._capability_health_state[dev_name] = evt.attr_value.value
                    elif evt.attr_value.name.lower() == "adminmode":
                        print("device: {} adminMode value {}".format(dev_name,evt.attr_value.value ))
                        self._capability_admin_mode[dev_name] = evt.attr_value.value
                    elif evt.attr_value.name.lower() == "obsstate":
                        print("device: {} adminMode value {}".format(dev_name,evt.attr_value.value ))
                        self._capability_obsstate[dev_name] = evt.attr_value.value
                    elif evt.attr_value.name.lower() == "subarrayMembershp":
                        self._capability_membership[dev_name] = evt.attr_value.value   
                    else:
                        print("Attribute {} not still "
                                   "handled".format(evt.attr_name))
                else:
                    print("Unexpected change event for"
                               " attribute: {}".format(str(evt.attr_name)))
                    return
                log_msg = "New value for {} is {}".format(str(evt.attr_name),
                                                          str(evt.attr_value.value))
            except tango.DevFailed as df:
                self.dev_logging(str(df.args[0].desc), tango.LogLevel.LOG_ERROR)
            except Exception as except_occurred:
                self.dev_logging(str(except_occurred), tango.LogLevel.LOG_ERROR)
        else:
            for item in evt.errors:
                # API_EventTimeout: if sub-element device not reachable it transitions
                # to UNKNOWN state.
                if item.reason == "API_EventTimeout":
                    self._capability_state[dev_name] = tango.DevState.DISABLED
                    self._capability_health_state[dev_name] = HealthState.UNKNOWN
                    self._capability_admin_mode[dev_name] = AdminMode.NOTFITTED
                    self._capability_health_state[dev_name] = ObsState.IDLE
                log_msg = item.reason + ": on attribute " + str(evt.attr_name)
                print(log_msg)
                
    def always_executed_hook(self):
        """Method always executed before any TANGO command is executed."""
        # PROTECTED REGION ID(CspCapabilityMonitor.always_executed_hook) ENABLED START #
        # PROTECTED REGION END #    //  CspCapabilityMonitor.always_executed_hook

    def delete_device(self):
        """Hook to delete resources allocated in init_device.

        This method allows for any memory or other resources allocated in the
        init_device method to be released.  This method is called by the device
        destructor and by the device Init command.
        """
        # PROTECTED REGION ID(CspCapabilityMonitor.delete_device) ENABLED START #
        event_to_remove = []
        for fqdn in self._capability_fqdn:
            try: 
                self._capability_proxies[fqdn].unsubscribe_event(self._event_id[fqdn])
                event_to_remove.append(fqdn)
            except KeyError as key_err:
                msg = ("Failure unsubscribing event {} "
                       "on device {}. Reason: {}".format(event_id,
                                                         fqdn,
                                                         key_err))
                self.dev_logging(msg, tango.LogLevel.LOG_ERROR)
        # remove the events id from the list
        for k in _event_id[fqdn].remove(k):
            if self._event_id[fqdn]:
                msg = "Still subscribed events: {}".format(self._event_id)
                self.dev_logging(msg, tango.LogLevel.LOG_WARN)
            else:
                # remove the dictionary element
                self._event_id.pop(fqdn)
            
        self._capability_fqdn.clear()
        self._capability_state.clear()
        self._capability_health_state.clear()
        self._capability_admin_mode.clear()
        self._capability_obs_state.clear() 
        self._capability_membership.clear()
        # PROTECTED REGION END #    //  CspCapabilityMonitor.delete_device
    # ------------------
    # Attributes methods
    # ------------------

    def read_numOfUnassignedIDs(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.numOfUnassignedIDs_read) ENABLED START #
        """Return the numOfUnassignedIDs attribute."""
        return len(self._unassigned_ids)
        # PROTECTED REGION END #    //  CspCapabilityMonitor.numOfUnassignedIDs_read

    def read_capabilityState(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityState_read) ENABLED START #
        """Return the capabilityState attribute."""
        return list(self._capability_state.values())
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityState_read

    def read_capabilityHealthState(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityHealthState_read) ENABLED START #
        """Return the capabilityHealthState attribute."""
        return list(self._capability_health_state.values())
       
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityHealthState_read

    def read_capabilityAdminMode(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityAdminMode_read) ENABLED START #
        """Return the capabilityAdminMode attribute."""
        return list(self._capability_admin_mode.values())
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityAdminMode_read

    def write_capabilityAdminMode(self, value):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityAdminMode_write) ENABLED START #
        """Set the capabilityAdminMode attribute."""
        pass
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityAdminMode_write

    def read_capabilityObsState(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityObsState_read) ENABLED START #
        """Return the capabilityObsState attribute."""
        return list(self._capability_obs_state.values())
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityObsState_read

    def read_unassignedIDs(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.unassignedIDs_read) ENABLED START #
        """Return the unassignedIDs attribute."""
        return self._unassigned_ids
        # PROTECTED REGION END #    //  CspCapabilityMonitor.unassignedIDs_read
        
    def read_cspCapabilityAddresses(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityAddresses_read) ENABLED START #
        return self.CapabilityDevices
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityAddresses_read
    
    def read_capabilityMembership(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.membership_read) ENABLED START #
        """Return the membership attribute."""
        return list(self._capability_membership.values())
        # PROTECTED REGION END #    //  CspCapabilityMonitor.membership_read
    # --------
    # Commands
    # --------

# ----------
# Run server
# ----------

def main(args=None, **kwargs):
    # PROTECTED REGION ID(CspCapabilityMonitor.main) ENABLED START #
    return run((CspCapabilityMonitor,), args=args, **kwargs)
    # PROTECTED REGION END #    //  CspCapabilityMonitor.main

if __name__ == '__main__':
    main()
+314 −336

File changed.

Preview size limit exceeded, changes collapsed.

+227 −0
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
#
# This file is part of the CspCapabilityMonitor project
#
# INAF, SKA Telescope
#
# Distributed under the terms of the GPL license.
# See LICENSE.txt for more info.

""" CSP.LMC Common  Class

CSP.LMC Common Class designed to monitoring the SCM
attributes of the CSP Capabilities: SearchBeams, TimingBeams,
VlbiBeams, Receptors/Stations.
"""

# PyTango imports
import tango
from tango import DebugIt
from tango.server import run
from tango.server import Device, DeviceMeta
from tango.server import attribute, command
from tango.server import device_property
from tango import AttrQuality, DispLevel, DevState
from tango import AttrWriteType, PipeWriteType
from SKABaseDevice import SKABaseDevice
# Additional import
# PROTECTED REGION ID(CspCapabilityMonitor.additionnal_import) ENABLED START #
# PROTECTED REGION END #    //  CspCapabilityMonitor.additionnal_import

__all__ = ["CspCapabilityMonitor", "main"]


class CspCapabilityMonitor(SKABaseDevice):
    """
    CSP.LMC Common Class designed to monitoring the SCM
    attributes of the CSP Capabilities: SearchBeams, TimingBeams,
    VlbiBeams, Receptors/Stations.

    **Properties:**

    - Device Property
    
    
    
    
    
        CapabilityDevices
            - The list of the CSP Capability devices FQDNs monitored\nby the instance.
            - Type:'DevVarStringArray'
    
    """
    __metaclass__ = DeviceMeta
    # PROTECTED REGION ID(CspCapabilityMonitor.class_variable) ENABLED START #
    # PROTECTED REGION END #    //  CspCapabilityMonitor.class_variable

    # -----------------
    # Device Properties
    # -----------------






    CapabilityDevices = device_property(
        dtype='DevVarStringArray',
    )

    # ----------
    # Attributes
    # ----------











    numOfUnassignedIDs = attribute(
        dtype='DevUShort',
    )

    capabilityState = attribute(
        dtype=('DevState',),
        max_dim_x=1500,
        label="Capability State",
        doc="Report the State of the capabilities.",
    )

    capabilityHealthState = attribute(
        dtype=('DevUShort',),
        max_dim_x=1500,
    )

    capabilityAdminMode = attribute(
        dtype=('DevUShort',),
        access=AttrWriteType.READ_WRITE,
        max_dim_x=1500,
    )

    capabilityObsState = attribute(
        dtype=('DevUShort',),
        max_dim_x=1500,
    )

    unassignedIDs = attribute(
        dtype=('DevUShort',),
        max_dim_x=1500,
    )

    capabilityAddresses = attribute(
        dtype=('DevString',),
        max_dim_x=1500,
        label="CSP.LMC Capability devices FQDNs",
        doc="The FQDNs of the CSP.LMC Capability devices: SearchBeams, TimingBeams, VlbiBeams,\nReceptors (MID instance), Stations (LOW instance)",
    )

    membership = attribute(
        dtype=('DevUShort',),
        max_dim_x=1500,
        label="Capabiity sub-array affilitiation",
    )

    # ---------------
    # General methods
    # ---------------

    def init_device(self):
        """Initialises the attributes and properties of the CspCapabilityMonitor."""
        SKABaseDevice.init_device(self)
        # PROTECTED REGION ID(CspCapabilityMonitor.init_device) ENABLED START #
        # PROTECTED REGION END #    //  CspCapabilityMonitor.init_device

    def always_executed_hook(self):
        """Method always executed before any TANGO command is executed."""
        # PROTECTED REGION ID(CspCapabilityMonitor.always_executed_hook) ENABLED START #
        # PROTECTED REGION END #    //  CspCapabilityMonitor.always_executed_hook

    def delete_device(self):
        """Hook to delete resources allocated in init_device.

        This method allows for any memory or other resources allocated in the
        init_device method to be released.  This method is called by the device
        destructor and by the device Init command.
        """
        # PROTECTED REGION ID(CspCapabilityMonitor.delete_device) ENABLED START #
        # PROTECTED REGION END #    //  CspCapabilityMonitor.delete_device
    # ------------------
    # Attributes methods
    # ------------------

    def read_numOfUnassignedIDs(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.numOfUnassignedIDs_read) ENABLED START #
        """Return the numOfUnassignedIDs attribute."""
        return 0
        # PROTECTED REGION END #    //  CspCapabilityMonitor.numOfUnassignedIDs_read

    def read_capabilityState(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityState_read) ENABLED START #
        """Return the capabilityState attribute."""
        return (PyTango.DevState.UNKNOWN,)
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityState_read

    def read_capabilityHealthState(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityHealthState_read) ENABLED START #
        """Return the capabilityHealthState attribute."""
        return (0,)
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityHealthState_read

    def read_capabilityAdminMode(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityAdminMode_read) ENABLED START #
        """Return the capabilityAdminMode attribute."""
        return (0,)
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityAdminMode_read

    def write_capabilityAdminMode(self, value):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityAdminMode_write) ENABLED START #
        """Set the capabilityAdminMode attribute."""
        pass
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityAdminMode_write

    def read_capabilityObsState(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityObsState_read) ENABLED START #
        """Return the capabilityObsState attribute."""
        return (0,)
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityObsState_read

    def read_unassignedIDs(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.unassignedIDs_read) ENABLED START #
        """Return the unassignedIDs attribute."""
        return (0,)
        # PROTECTED REGION END #    //  CspCapabilityMonitor.unassignedIDs_read

    def read_capabilityAddresses(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.capabilityAddresses_read) ENABLED START #
        """Return the capabilityAddresses attribute."""
        return ('',)
        # PROTECTED REGION END #    //  CspCapabilityMonitor.capabilityAddresses_read

    def read_membership(self):
        # PROTECTED REGION ID(CspCapabilityMonitor.membership_read) ENABLED START #
        """Return the membership attribute."""
        return (0,)
        # PROTECTED REGION END #    //  CspCapabilityMonitor.membership_read


    # --------
    # Commands
    # --------

# ----------
# Run server
# ----------


def main(args=None, **kwargs):
    # PROTECTED REGION ID(CspCapabilityMonitor.main) ENABLED START #
    return run((CspCapabilityMonitor,), args=args, **kwargs)
    # PROTECTED REGION END #    //  CspCapabilityMonitor.main

if __name__ == '__main__':
    main()
+211 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading