diff --git a/src/dynamic-srv.py b/src/dynamic-srv.py index 284da0ac5c3b74758b70c624fa67dbc18b80c432..666a92eb83452d34bbbe1c561e66c6a59e72c156 100755 --- a/src/dynamic-srv.py +++ b/src/dynamic-srv.py @@ -1,52 +1,16 @@ -#!/usr/bin/env python -# "$Name: $"; -# "$Header: $"; -#============================================================================= -# -# file : Dynamic.py -# -# description : Python source for the Dynamic and its commands. -# The class is derived from Device. It represents the -# CORBA servant object which will be accessed from the -# network. All commands which can be executed on the -# Dynamic are implemented in this file. -# -# project : TANGO Device Server -# -# $Author: $ -# -# $Revision: $ -# -# $Log: $ -# -# copyleft : European Synchrotron Radiation Facility -# BP 220, Grenoble 38043 -# FRANCE -# -#============================================================================= -# This file is generated by POGO -# (Program Obviously used to Generate tango Object) -# -# (c) - Software Engineering Group - ESRF -#============================================================================= -# +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- """ -Dynamic Server. - - - +Dynamic Server providing creation and management of custom dynamic attributes """ import sys import os sys.path.insert(0, os.path.abspath('.')) from UserDict import UserDict -from xmlconfig import (ScriptXmlConfig, IS_COMMAND,READ_WRITE, READ_ONLY, WRITE_ONLY,InvalidFileError ) import PyTango -import time import numpy as np - -import signal +import importlib def fromPyTango2NumpyType(pytango_type): """ Return the numpy type based on the PyTango type @@ -268,99 +232,109 @@ class Dynamic(PyTango.Device_4Impl): self.set_status("Invalid Filters Script " + self.FiltersScript ) return + # import the configuration script as a module + try: + self.cfg_module_name = os.path.splitext(os.path.basename(self.ConfiguratorScript))[0] + self.cfg_module_path = os.path.dirname(self.ConfiguratorScript) + print(self.cfg_module_name,self.cfg_module_path) + sys.path.append(self.cfg_module_path) + self.cfg_module = importlib.import_module(self.cfg_module_name) + print("imported cfg") + except Exception as ex: + self.cfg_module = None + #self.warn_stream("Invalid cfg script file\n") + print("Invalid cfg script file\n",ex) + self.set_state(PyTango.DevState.OFF) + return + #link to the Tango DB self.db = PyTango.Database() + dynattrs = self.cfg_module.createDynAttrsDict() #creation of dynamic attributes. - try: - xml_file = ScriptXmlConfig(self.XmlConfigurator) - except InvalidFileError as ex: - self.warn_stream("Invalid xml file\n") - self.set_state(PyTango.DevState.OFF) - return - for (key, value) in xml_file.entries.items(): - if value.flag == IS_COMMAND: continue - if not (value.handler.lower() == self.get_name().lower() or value.handler.lower() == 'self'): + for attr in dynattrs: + attr_obj = dynattrs[attr] + + if not (attr_obj.handler.lower() == self.get_name().lower() or attr_obj.handler.lower() == 'self'): try: - #print 'creation of attribute proxy: ', str(value.tango_name) - attr_proxy = PyTango.AttributeProxy(str(value.tango_name)) - attr_value = attr_proxy.read() + attr_proxy = PyTango.AttributeProxy(str(attr_obj.tango_name)) attr_config = attr_proxy.get_config() - # + if str(attr_config.data_format) == "SCALAR": - attr = PyTango.Attr(str(value.name), attr_config.data_type, attr_config.writable) + attr = PyTango.Attr(str(attr_obj.name), attr_config.data_type, attr_config.writable) elif str(attr_config.data_format) == "SPECTRUM": - attr = PyTango.SpectrumAttr(str(value.name), attr_config.data_type, attr_config.writable,attr_config.max_dim_x) + attr = PyTango.SpectrumAttr(str(attr_obj.name), attr_config.data_type, attr_config.writable,attr_config.max_dim_x) elif str(attr_config.data_format) == "IMAGE": - attr = PyTango.ImageAttr(str(value.name), attr_config.data_type, attr_config.writable,attr_config.max_dim_x,attr_config.max_dim_y) + attr = PyTango.ImageAttr(str(attr_obj.name), attr_config.data_type, attr_config.writable,attr_config.max_dim_x,attr_config.max_dim_y) self.add_attribute(attr, self.read_proxy, self.write_proxy) - self.myattrs[value.name] = attr_proxy + self.myattrs[attr_obj.name] = attr_proxy + except PyTango.DevFailed as ex: self.warn_stream("%s" % str(ex)) continue - if self.myattrs.has_key(value.name): + if self.myattrs.has_key(attr_obj.name): PyTango.Except.throw_exception("Exist", - "Attribute "+value.name+ " already defined", + "Attribute "+attr_obj.name+ " already defined", "NewAttribute") - tango_type = dataType2TangoType(value.type.upper()) + tango_type = dataType2TangoType(attr_obj.type.upper()) permission = READ_ONLY - if value.flag == READ_ONLY: + if attr_obj.flag == READ_ONLY: permission = PyTango.AttrWriteType.READ - elif value.flag == READ_WRITE: + elif attr_obj.flag == READ_WRITE: permission = PyTango.AttrWriteType.READ_WRITE - elif value.flag == WRITE_ONLY: + elif attr_obj.flag == WRITE_ONLY: #FIXME: check if it is possible to have write only permission = PyTango.AttrWriteType.READ_WRITE # It's possible to define python methods for calculating the attribute value - self.read_functions[value.name] = value.read_function - self.write_functions[value.name] = value.write_function - if value.dimension == 1: - attr = PyTango.Attr(str(value.name), tango_type, permission) - if value.memorized == 1: + self.read_functions[attr_obj.name] = attr_obj.read_function + self.write_functions[attr_obj.name] = attr_obj.write_function + if attr_obj.dimension == 1: + attr = PyTango.Attr(str(attr_obj.name), tango_type, permission) + if attr_obj.memorized == 1: attr.set_memorized() self.add_attribute(attr, self.read_Scalar,self.write_Scalar) if tango_type == PyTango.ArgType.DevString: - self.myattrs[value.name] = "" + self.myattrs[attr_obj.name] = "" else: - self.myattrs[value.name] = 0 - if value.default: - self.myattrs[value.name] = eval(value.default) - if value.memorized == 1: - dev_attr_props = self.db.get_device_attribute_property(self.get_name(),[value.name]) - attr_prop = dev_attr_props[value.name] + self.myattrs[attr_obj.name] = 0 + if attr_obj.default: + self.myattrs[attr_obj.name] = eval(attr_obj.default) + if attr_obj.memorized == 1: + dev_attr_props = self.db.get_device_attribute_property(self.get_name(),[attr_obj.name]) + attr_prop = dev_attr_props[attr_obj.name] for pr in attr_prop.keys(): if (pr == '__value') and (tango_type == PyTango.ArgType.DevString): - self.myattrs[value.name] = attr_prop['__value'][0] + self.myattrs[attr_obj.name] = attr_prop['__value'][0] elif (pr == '__value') and (tango_type == PyTango.ArgType.DevFloat): - self.myattrs[value.name] = float(attr_prop['__value'][0]) + self.myattrs[attr_obj.name] = float(attr_prop['__value'][0]) elif (pr == '__value') and (tango_type == PyTango.ArgType.DevDouble): - self.myattrs[value.name] = float(attr_prop['__value'][0]) + self.myattrs[attr_obj.name] = float(attr_prop['__value'][0]) elif (pr == '__value') and (tango_type == PyTango.ArgType.DevBoolean): - self.myattrs[value.name] = bool(attr_prop['__value'][0] == "True") + self.myattrs[attr_obj.name] = bool(attr_prop['__value'][0] == "True") elif (pr == '__value'): - self.myattrs[value.name] = int(attr_prop['__value'][0]) - elif isinstance(value.dimension, tuple): - sizx = value.dimension[0] - sizy = value.dimension[1] - attr = PyTango.ImageAttr(str(value.name), tango_type, permission,sizx, sizy) + self.myattrs[attr_obj.name] = int(attr_prop['__value'][0]) + elif isinstance(attr_obj.dimension, tuple): + sizx = attr_obj.dimension[0] + sizy = attr_obj.dimension[1] + attr = PyTango.ImageAttr(str(attr_obj.name), tango_type, permission,sizx, sizy) self.add_attribute(attr, self.read_Image, self.write_Image) - if value.default: - self.myattrs[value.name] = eval(value.default) + if attr_obj.default: + self.myattrs[attr_obj.name] = eval(attr_obj.default) elif tango_type == PyTango.ArgType.DevString: - self.myattrs[value.name] = [[],[]] + self.myattrs[attr_obj.name] = [[],[]] else: - self.myattrs[value.name] = np.zeros((sizy,sizx),fromPyTango2NumpyType(tango_type)) + self.myattrs[attr_obj.name] = np.zeros((sizy,sizx),fromPyTango2NumpyType(tango_type)) else : - self.debug_stream("Creation of attribute %s, dimension = %s" % (value.name, str(value.dimension))) - attr = PyTango.SpectrumAttr(str(value.name), tango_type, permission,value.dimension) + self.debug_stream("Creation of attribute %s, dimension = %s" % (attr_obj.name, str(attr_obj.dimension))) + attr = PyTango.SpectrumAttr(str(attr_obj.name), tango_type, permission,attr_obj.dimension) self.add_attribute(attr, self.read_Spectrum, self.write_Spectrum) - if value.default: - self.myattrs[value.name] = eval(value.default) + if attr_obj.default: + self.myattrs[attr_obj.name] = eval(attr_obj.default) elif tango_type == PyTango.ArgType.DevString: - self.myattrs[value.name] = [] + self.myattrs[attr_obj.name] = [] else: - self.myattrs[value.name] = np.zeros(value.dimension, fromPyTango2NumpyType(tango_type)) + self.myattrs[attr_obj.name] = np.zeros(attr_obj.dimension, fromPyTango2NumpyType(tango_type)) self.set_state(PyTango.DevState.ON) @@ -389,8 +363,6 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def read_Scalar(self, attr): #print "In ", self.get_name(), "::read_Scalar()" - - # Add your own code here data = self.read_dynamic_attribute(attr.get_name()) # attr.set_value(data) @@ -401,8 +373,6 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def write_Scalar(self, attr): #print "In ", self.get_name(), "::write_Scalar()" - - # Add your own code here value_in = attr.get_write_value(PyTango.ExtractAs.Numpy) self.write_dynamic_attribute(attr.get_name(), value_in) @@ -411,8 +381,6 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def read_Spectrum(self, attr): #print "In ", self.get_name(), "::read_Spectrum()" - - # Add your own code here data = self.read_dynamic_attribute(attr.get_name()) attr.set_value(data,len(data)) @@ -422,7 +390,6 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def write_Spectrum(self, attr): #print "In ", self.get_name(), "::write_Spectrum()" - # Add your own code here value_in = attr.get_write_value(PyTango.ExtractAs.Numpy) self.write_dynamic_attribute(attr.get_name(), value_in) @@ -432,8 +399,6 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def read_Image(self, attr): #print "In ", self.get_name(), "::read_Image()" - - # Add your own code here data = self.read_dynamic_attribute(attr.get_name()) # assert isinstance(data,np.ndarray) @@ -447,15 +412,13 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def write_Image(self, attr): #print "In ", self.get_name(), "::write_Image()" - # Add your own code here value_in = attr.get_write_value(PyTango.ExtractAs.Numpy) self.write_dynamic_attribute(attr.get_name(), value_in) def read_proxy(self, attr): - # Add your own code here val = self.myattrs[attr.get_name()].read() - data = self.myattrs[attr.get_name()] + #data = self.myattrs[attr.get_name()] attr.set_value(val.value,val.dim_x, val.dim_y) def write_proxy(self, attr): @@ -476,7 +439,6 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def NewScalar(self, argin): #print "In ", self.get_name(), "::NewScalar()" - # Add your own code here (name,typ) = processInputStringArray(argin) attr = PyTango.Attr(name, typ, PyTango.AttrWriteType.READ_WRITE) @@ -494,8 +456,6 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def NewSpectrum(self, argin): #print "In ", self.get_name(), "::NewSpectrum()" - # Add your own code here - (name,typ,siz) = processInputStringArray(argin) attr = PyTango.SpectrumAttr(name, typ, @@ -517,7 +477,6 @@ class Dynamic(PyTango.Device_4Impl): #------------------------------------------------------------------ def NewImage(self, argin): #print "In ", self.get_name(), "::NewImage()" - # Add your own code here (name,typ,sizx,sizy) = processInputStringArray(argin) attr = PyTango.ImageAttr(name, typ, @@ -586,7 +545,7 @@ class Dynamic(PyTango.Device_4Impl): else: value = value_in self.myattrs[attr_name] = value - if type(value_in) not in (int,float,str,bool,long): + if type(value_in) not in (int,float,str,bool): # Only scalar values can be memorized return dict_in = {attr_name:{'__value':value_in}} @@ -607,10 +566,10 @@ class DynamicClass(PyTango.DeviceClass): # Device Properties device_property_list = { - 'XmlConfigurator': + 'ConfiguratorScript': [PyTango.DevString, - "Path to the xml config file", - [ "./xml_config.xml"] ], + "Path to the config file", + [ "./config.py"] ], 'FiltersScript': [PyTango.DevString, "Path to the python script that will be executed.", @@ -667,7 +626,7 @@ if __name__ == '__main__': 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 + except PyTango.DevFailed as e: + print('-------> Received a DevFailed exception:',e) + except Exception as e: + print('-------> An unforeseen exception occured....',e) diff --git a/src/xmlconfig.py b/src/xmlconfig.py deleted file mode 100644 index facb63f2dfa68104aa9532d60979afb200ab29c6..0000000000000000000000000000000000000000 --- a/src/xmlconfig.py +++ /dev/null @@ -1,197 +0,0 @@ -# -*- coding: utf-8 -*- -dbg_ = False -import sys -from xml.dom import minidom -from UserDict import UserDict -#rom collections import namedtuple -import traceback - -class InvalidFileError(Exception): - def __init__(self, value): - self.message = value - def __str__(self): - return repr(self.message) - - -import urllib -import StringIO - -def open_anything(source): - """URI, filename, or string --> stream - - This function lets you define parsers that take any input source - (URL, pathname to local or network file, or actual data as a string) - and deal with it in a uniform manner. Returned object is guaranteed - to have all the basic stdio read methods (read, readline, readlines). - Just .close() the object when you're done with it. - - Examples:: - - >>> from xml.dom import minidom - >>> sock = open_anything("http://localhost/kant.xml") - >>> doc = minidom.parse(sock) - >>> sock.close() - >>> sock = open_anything("c:\\inetpub\\wwwroot\\kant.xml") - >>> doc = minidom.parse(sock) - >>> sock.close() - >>> sock = open_anything("<ref id='conjunction'><text>and</text><text>or</text></ref>") - >>> doc = minidom.parse(sock) - >>> sock.close() - """ - if hasattr(source, "read"): - return source - - if source == '-': - return sys.stdin - - # try to open with urllib (if source is http, ftp, or file URL) - - try: - return urllib.urlopen(source) - except (IOError, OSError): - pass - - # try to open with native open function (if source is pathname) - try: - return open(source) - except (IOError, OSError): - pass - - # treat source as string - - return StringIO.StringIO(str(source)) - -def _get_text(nodelist): - """ Extract an string from a xml node data.""" - rc_ = [node.data for node in nodelist - if node.nodeType == node.TEXT_NODE] - return ''.join(rc_).strip().encode('ascii') - -def _get_value(node, tagname): - """ Extract the value from an xml node""" - values = node.getElementsByTagName(tagname) - if len(values) == 0: - return '' - internal_node = values[0] - return _get_text(internal_node.childNodes) - - -READ_ONLY = 0 -READ_WRITE = 1 -WRITE_ONLY = 2 -IS_COMMAND = 3 - -class XmlItem: - - def __init__(self, flag , type, handler, name, tango_name, - description="", default=None, dimension = 1, - memorized = 0 , read_function = '' , write_function = ''): - self.flag = flag - self.type = type - self.handler = handler - self.tango_name = tango_name - self.name = name - self.description = description - self.default = default - self.dimension = dimension - self.memorized = memorized - self.read_function = read_function - self.write_function = write_function - - def __str__(self): - return "Attr %s = %s/%s \n %s \n %s %d \n %s \n %s"% (self.name, self.handler, - self.name, self.description, self.default, - self.memorized, self.read_function, self.write_function) - -class ScriptXmlConfig: - """ - Parser of the XML file in python usefull class - - attributes a dict with: - - flag: read_only, write_only, read_write - - type: short, double, string, - - handler: tango attribute associated - - name: name or label of this attribute - - description: information for the attribute - - memorized: uses Tango Memorize feature, available only for scalar attributes - - default: default value ( WARNING: is loaded using eval() ) - - read_function: name of the function that will be executed for every read operation - - write_function: name of the function that will be executed for every write operation - - """ - def __init__(self, filename): - self.entries = dict() - self.doc = self._load(filename) - self._parse() - - def __str__(self): - return "DaqXmlConfig %s %s"% (str(self.attributes)) - - def _parse(self): - """Parse the xml file""" - try: - self.handle_entries(self.doc.getElementsByTagName("ATTRIBUTES_RO"),flag=READ_ONLY) - self.handle_entries(self.doc.getElementsByTagName("ATTRIBUTES_RW"),flag=READ_WRITE) - self.handle_entries(self.doc.getElementsByTagName("ATTRIBUTES_WO"),flag=WRITE_ONLY) - self.handle_entries(self.doc.getElementsByTagName("COMMANDS"),flag=IS_COMMAND) - except IndexError: - traceback.print_exc() - raise InvalidFileError( - "Failed to parse the configuration file") - @classmethod - def _load(cls, source): - """load XML input source, return parsed XML document - - - a URL of a remote XML file ("http://diveintopython.org/kant.xml") - - a filename of a local XML file ("~/diveintopython/common/py/kant.xml") - - standard input ("-") - - the actual XML document, as a string - """ - sock = open_anything(source) - try: - xmldoc = minidom.parse(sock).documentElement - except Exception, ex: - raise InvalidFileError(str(ex)) - sock.close() - return xmldoc - - def handle_entries(self, elements, flag): - - for group_of_attributes in elements: - attributes = [attribute - for attribute - in group_of_attributes.childNodes if - attribute.nodeType == 1] - for attribute in attributes: - type = _get_value(attribute, 'TYPE') - handler = _get_value(attribute,'HANDLER') - attr = handler +'/' + _get_value(attribute, 'TANGONAME') - name = attribute.nodeName - desc =_get_value(attribute, 'DESCRIPTION') - dimension_s = _get_value(attribute, 'DIMENSION') - if dimension_s == '': - dimension = 1 - elif dimension_s.find('(')>= 0: - dimension = eval(dimension_s) - else: - dimension = int(dimension_s) - memorized_s = _get_value(attribute, 'MEMORIZED') - if memorized_s == '1' and dimension == 1 : - memorized = 1 - else : - memorized = 0 - # - default_v = _get_value(attribute, 'DEFAULT') - # - read_function = _get_value(attribute, 'READ_FUNCTION') - write_function = _get_value(attribute, 'WRITE_FUNCTION') - # - attr_entry = XmlItem(flag, type,handler,name,attr,desc,default_v,dimension,memorized,read_function,write_function) - if dbg_: print attr_entry - self.entries[attr_entry.name] = attr_entry - - - - -if __name__ == "__main__": - xml = ScriptXmlConfig("./scripts/ldm_daq_conf.xml")