Skip to content
Snippets Groups Projects
ContextSaver.py 6.03 KiB
Newer Older
#!/usr/Local/pyroot/PyTangoRoot/bin/python
"""
Python module for scanning and saving configuration of devices.

Includes a Command Line Interface.
Can be imported as is to use function in user script.
"""
import PyTango as tango
import logging
import argparse
import json

__version__ = "1.0.0"

##---------------------------------------------------------------------------##
def get_wattr(proxy):
    """
    Get all writable attributes from a device and save their values in a python dict.

    Parameters
    ----------
    proxy : PyTango.DeviceProxy
    Proxy to the device.

    Returns
    -------
    config : dict
    Dictionnary, keys are attribute names and value their present values.
    """
    logger.debug("Scanning write attribute of device %s"%proxy.name())
    config = dict()

    # Get all attributes configuration
    cattr = proxy.get_attribute_config(proxy.get_attribute_list())
    wattr=[]
    for attr in cattr:
        logger.debug("Analyse attribute '%s' "%(
        if attr.writable in [
                    tango.AttrWriteType.WRITE,
                    tango.AttrWriteType.READ_WRITE,
                    tango.AttrWriteType.READ_WITH_WRITE]:

            # attr is writtable, savbing it into list
            wattr.append(attr.name)
            logger.debug("Detect writtable attribute '%s'"%(
                attr.name))

    # Read all writtable attributes
    rattr = proxy.read_attributes(wattr)
    for attr in rattr:
        v= attr.value
        if type(v) is numpy.ndarray:
            v=v.tolist()

        logger.debug("Read writtable attribute '%s' = %s"%(
            attr.name,
            v))

        config[attr.name]=v

    return config


##---------------------------------------------------------------------------##
def get_properties(proxy):
    """
    Get all properties from a device and save them in a python dict.

    Parameters
    ----------
    proxy : PyTango.DeviceProxy
    Proxy to the device.

    Returns
    -------
    config : dict
    Dictionnary, keys are attribute names and value their present values.
    """
    logger.debug("Scanning properties of device %s"%proxy.name())

    pl = proxy.get_property_list('*')

    _props = proxy.get_property(pl)

    props=dict()

    # Here we simply convert tango arrays to python arrays.
    # For properties, each prop is an array, one element in
    # the array is a line for the property.
    # Maybe we need to convert in one single string.
    for k in _props.keys():
        if k[:2] !="__":
            # Change type
            props[k] = list(_props[k])
            logger.debug("Detect property %s = %s"%(
                k, props[k]))


    return props


##########################################################################
""" Command Line Interface """
if __name__ == "__main__":

    # Name the logger after the filename
    logger = logging.getLogger("ContextSaver")

    #######################################################
    # Install argument parser
    import argparse

    parser = argparse.ArgumentParser(description="Copy attributes and properties to a JSON structure.\n"+
            "Version %s"%__version__)

    parser.add_argument("--fileout", type=str,
            help="Save the JSON structure to the specified file. Implicit set no output to stdout."),

    parser.add_argument('--log', type=str, default="INFO",
            help="Log level. Default: %(default)s.")

    parser.add_argument('-v', action="store_true",
            help="Print in stdout the context. Default is on if no fileout option specified.")

    parser.add_argument('--filemode', action="store_true",
            help="Set devices to filemode."+
            " Instead of specifying devices, put a path to a file containing a list of devices."+
            " The file contains one device path per line.")

    parser.add_argument('devices', type=str, nargs='+',
                        help="List of devices to inspect. Full tango path.")

    args = parser.parse_args()


    #######################################################
    # Configure logger

    # Add a stream handler
    s_handler = logging.StreamHandler()
    s_handler.setFormatter(logging.Formatter("%(levelname)s\t[%(funcName)s] \t%(message)s"))

    # Set level according to command line attribute
    s_handler.setLevel(level=getattr(logging, args.log.upper()))
    logger.setLevel(level=getattr(logging, args.log.upper()))
    logger.addHandler(s_handler)

    logger.debug("Parsed arguments: %s"%args)

    logger.info("Context Saver %s"%__version__)

    #######################################################
    # Filemode or not
    if args.filemode:
        logger.info("Filemode, openning file %s"%args.devices[0])
        # Read the file. Each line is an device
        with open(args.devices[0], "r") as fp:
            devices = fp.readlines()

        logger.debug("Read lines : %s"%devices)

        # Clean end of line
        for i_a in range(len(devices)):
            devices[i_a] = devices[i_a].rstrip()

    else:
        devices = args.devices

    #######################################################
    # Prepare array for result
    results = dict()

    #######################################################
    # Scan all devices

    for dev in devices:
        logger.info("Scanning device %s..."%dev)

        # Declare proxy
        prx = tango.DeviceProxy(dev)

        # Retrieve write attributes
        wattr = get_wattr(prx)

        # Retrieve properties
        props = get_properties(prx)

        # Build json dict
        jdict = {
                "wattributes":wattr,
                "properties":props,
                }

        # Add to results
        results[dev] = jdict

    logger.info("Done")

    if args.fileout is None:
        print(json.dumps(results, indent=4))
    else:
        with open(args.fileout, "w") as fp:
            json.dump(results, fp, indent=4)

        # Additionnal dump to stdout
        if args.v:
            print(json.dumps(results, indent=4))


else:
    # Name the logger after the module name
    logger = logging.getLogger(__name__)