Commit aa8e5884dc92b4924c4b69f584697b093197c0c9

Authored by Alain Klotz
1 parent 68279fc8
Exists in dev

Grosse amélioration du XML et de la classe ConfigPyros.

Showing 2 changed files with 770 additions and 171 deletions   Show diff stats
config/config_unit_simulunit1.xml
... ... @@ -7,9 +7,12 @@ This File describes all the parameters that characterize a unit.
7 7 One parameter <param></param> is defined using the following attributes:
8 8 section, key, value, type, unit, access, comment, label, reference, timestamp
9 9  
  10 +* Mandatory
10 11 section : Category of the keyword
11 12 key : Key of the keyword
12 13 value : Useful value of the keyword
  14 +
  15 +* Optional
13 16 type : Python type to interpret the value
14 17 unit : Physical value to allow conversions
15 18 access : 0brwrwrw (rw for PI-Mount, rw for Maintenance, rw for Astronomers)
... ... @@ -23,62 +26,95 @@ timestamp : Date when the value has been last updated
23 26  
24 27 <unit alias="SimulUnit1">
25 28  
26   - <date_created>2018-04-13 00:38:14.461736</date_created>
27   - <!-- Select the unit as one unit and one or more channels -->
28   - <param section="instanciation" key="mount1" value="VirtualMount"/>
29   - <param section="instanciation" key="channel1" value="VirtualCamera"/>
  29 + <!-- Some informations about this configuration -->
  30 + <date_creation>2018-04-13 00:38:14</date_creation>
  31 + <date_last_modification>2019-02-18 16:38:00</date_last_modification>
  32 + <author_last_modification>Alain Klotz</author_last_modification>
  33 +
  34 + <!-- Select the unit as one mount and one or more channels -->
  35 + <param section="assembly" key="alias" value="PyROSDatabase" comment="database"/>
  36 + <param section="assembly" key="alias" value="VirtualMount" comment="mount"/>
  37 + <param section="assembly" key="alias" value="VirtualCamera1" comment="channel"/>
30 38  
  39 + <!-- A database definition -->
  40 + <database alias="PyROSDatabase">
  41 + <!-- Select the type of database (DBMS) -->
  42 + <param section="management" key="system" value="MySQL"/>
  43 + <!-- Access autorizations -->
  44 + <param section="access" key="host" value="127.0.0.1"/>
  45 + <param section="access" key="port" value="3306"/>
  46 + <param section="access" key="user" value="pyros"/>
  47 + <param section="access" key="pswd" value="6cacc99693b5bca5a2b9e37dbba529116d" type="str" unit="crypted1"/>
  48 + <!-- Database characteristics -->
  49 + <param section="database" key="name" value="pyros"/>
  50 + </database>
  51 +
31 52 <!-- A mount definition -->
32 53 <mount alias="VirtualMount">
  54 + <!-- General description -->
  55 + <param section="mount" key="name" value="Losmandy"/>
  56 + <param section="mount" key="home" value="IRAP" type="str" unit="" comment="Institut de Recherche en Astrophysique et Planetologie"/>
  57 + <param section="mount" key="iau_num" value="n.d" type="str" unit="" comment="Not defined"/>
33 58 <!-- Set period parameters -->
34 59 <param section="period" key="periods" value="(1, 2018, 9, 1, 2019, 3, 1), (2, 2019, 3, 1, 2019, 9, 1)" type="int" unit=""/>
35 60 <param section="period" key="sun_elev_night" value="-10" type="float" unit="deg"/>
36 61 <param section="partner" key="partners" value="(1, 'PAA', 45, 'Partner_A'), (1, 'PAB', 22, 'Partner_B'), (1, 'PAC', 33, 'Partner_C')" type="int" unit=""/>
37   - <!-- Set site parameters -->
38   - <param section="localization" key="home" value="GPS 1.477083 E 43.81667 150" type="str" unit=""/>
39   - <param section="localization" key="name" value="IRAP" type="str" unit="" comment="Institut de Recherche en Astrophysique et Planetologie"/>
40   - <param section="localization" key="iau_num" value="n.d" type="str" unit="" comment="Not defined"/>
  62 + <!-- Set device controller agent -->
  63 + <param section="MountPointing" key="agent" value="TelescopeSimulator" comment="Value must be the alias of the controller agent"/>
41 64 <!-- Set mount paramters for simulations and scheduler -->
42   - <param section="mount" key="axe_type" value="hadec" type="str" unit=""/>
43   - <param section="mount" key="ha_liminf" value="-90" type="float" unit="Angle"/>
44   - <param section="mount" key="ha_limsup" value="90" type="float" unit="Angle"/>
45   - <param section="mount" key="dec_liminf" value="-30" type="float" unit="Angle"/>
46   - <param section="mount" key="dec_limsup" value="89.7" type="float" unit="Angle"/>
47   - <param section="mount" key="ha_vel_profile" value="scurve" type="str" unit=""/>
48   - <param section="mount" key="dec_vel_profile" value="scurve" type="str" unit=""/>
  65 + <param section="MountPointing" key="home" value="GPS 1.477083 E 43.81667 150" type="str" unit=""/>
  66 + <param section="MountPointing" key="axe_type" value="hadec" type="str" unit=""/>
  67 + <param section="MountPointing" key="ha_liminf" value="-90" type="float" unit="Angle"/>
  68 + <param section="MountPointing" key="ha_limsup" value="90" type="float" unit="Angle"/>
  69 + <param section="MountPointing" key="dec_liminf" value="-30" type="float" unit="Angle"/>
  70 + <param section="MountPointing" key="dec_limsup" value="89.7" type="float" unit="Angle"/>
  71 + <param section="MountPointing" key="ha_vel_profile" value="scurve" type="str" unit=""/>
  72 + <param section="MountPointing" key="dec_vel_profile" value="scurve" type="str" unit=""/>
49 73 </mount>
50 74  
51 75 <!-- A channel definition -->
52   - <channel alias="VirtualCamera">
53   - <!-- Set a name to the camera -->
54   - <param section="channel" key="name" value="VirtualCam" type="str" unit=""/>
55   - <!-- Parameters of the channel for the web form for a plan -->
56   - <param section="channel" key="plan" value="'filter': 'filters symbols', 'binning': 'detector binnings', 'exptime': 'detector exptime_mini exptime_maxi', 'nb_images': 'int 1 Inf', 'shutter': 'shutters', 'delay': 'float 0 Inf'" type="dict" unit=""/>
  76 + <channel alias="VirtualCamera1">
  77 + <!-- General description -->
  78 + <param section="channel" key="name" value="Takahshi + Atik"/>
  79 + <!-- Set device controller agent -->
  80 + <param section="DetectorSensor" key="agent" value="CameraSimulator" comment="Value must be the alias of the controller agent"/>
  81 + <param section="DetectorShutter" key="agent" value="CameraSimulator" comment="Value must be the alias of the controller agent"/>
  82 + <param section="DetectorTimer" key="agent" value="CameraSimulator" comment="Value must be the alias of the controller agent"/>
  83 + <param section="FilterSelector" key="agent" value="CameraSimulator" comment="Value must be the alias of the controller agent"/>
  84 + <param section="DetectorFocus" key="agent" value="TelescopeSimulator" comment="Value must be the alias of the controller agent"/>
  85 + <!-- Camera properties for plans and for simulations -->
  86 + <param section="DetectorSensor" key="name" value="Atik 460" type="str" unit=""/>
  87 + <param section="DetectorSensor" key="serial_number" value="S/N67Y" type="str" unit=""/>
  88 + <param section="DetectorSensor" key="sensor_type" value="CCD" type="str" unit=""/>
  89 + <param section="DetectorSensor" key="efficiency" value="0.9" type="float" unit=""/>
  90 + <param section="DetectorSensor" key="binnings" value="(1, 1), (2, 2), (3, 3), (4,4)" type="list" unit=""/>
  91 + <param section="DetectorSensor" key="exptime_mini" value="0.1" type="float" unit="sec"/>
  92 + <param section="DetectorSensor" key="exptime_maxi" value="1000" type="float" unit="sec"/>
  93 + <param section="DetectorSensor" key="readouttime" value="10" type="float" unit="sec"/>
  94 + <param section="DetectorSensor" key="nbcells1" value="4096" type="int" unit=""/>
  95 + <param section="DetectorSensor" key="cellsize1" value="15" type="float" unit="mu"/>
  96 + <param section="DetectorSensor" key="nbcells2" value="4096" type="int" unit=""/>
  97 + <param section="DetectorSensor" key="cellsize2" value="15" type="float" unit="mu"/>
  98 + <param section="DetectorSensor" key="readoutnoise" value="7.5" type="float" unit="electrons"/>
  99 + <param section="DetectorSensor" key="gain" value="2.5" type="float" unit="electrons/adu"/>
  100 + <param section="DetectorSensor" key="temperature" value="-50" type="float" unit="degC"/>
  101 + <param section="DetectorSensor" key="thermic_signal" value="0.05" type="float" unit="electrons/s"/>
  102 + <!-- Shutter properties for plans and for simulations -->
  103 + <param section="DetectorShutter" key="mode" value="synchro, openned, closed" type="str" unit=""/>
  104 + <param section="DetectorShutter" key="delayopening" value="60" type="int" unit="us"/>
  105 + <param section="DetectorShutter" key="delayclosing" value="30" type="int" unit="us"/>
  106 + <!-- Filter properties for plans and for simulations -->
  107 + <param section="FilterSelector" key="symbols" value="B g r i gri" type="str" unit=""/>
  108 + <param section="FilterSelector" key="efficiencies" value="0.75 0.85 0.85 0.85 0.85 0.85" type="float" unit=""/>
  109 + <param section="FilterSelector" key="lambda_mins" value="0.37 0.40 0.55 0.70 0.40" type="float" unit="mu"/>
  110 + <param section="FilterSelector" key="lambda_maxs" value="0.50 0.55 0.70 0.80 0.80" type="float" unit="mu"/>
  111 + <param section="FilterSelector" key="positions" value="0 60 120 180 240" type="float" unit="deg"/>
57 112 <!-- Optical design of the channel for simulations -->
  113 + <param section="optic" key="name" value="Takahashi epsilon" type="str" unit=""/>
  114 + <param section="optic" key="serial_number" value="875432" type="str" unit=""/>
58 115 <param section="optic" key="aperdiam" value="0.16" type="float" unit="m"/>
59 116 <param section="optic" key="focleneq" value="0.53" type="float" unit="m"/>
60 117 <param section="optic" key="efficiency" value="0.68" type="float" unit=""/>
61   - <!-- List of optical filters for plans and for simulations -->
62   - <param section="filters" key="symbols" value="B g r i gri" type="str" unit=""/>
63   - <param section="filters" key="efficiencies" value="0.75 0.85 0.85 0.85 0.85 0.85" type="float" unit=""/>
64   - <param section="filters" key="lambda_mins" value="0.37 0.40 0.55 0.70 0.40" type="float" unit="mu"/>
65   - <param section="filters" key="lambda_maxs" value="0.50 0.55 0.70 0.80 0.80" type="float" unit="mu"/>
66   - <!-- Camera properties for plans and for simulations -->
67   - <param section="detector" key="sensor_type" value="CCD" type="str" unit=""/>
68   - <param section="detector" key="efficiency" value="0.9" type="float" unit=""/>
69   - <param section="detector" key="binnings" value="(1, 1), (2, 2), (3, 3), (4,4)" type="int" unit=""/>
70   - <param section="detector" key="exptime_mini" value="0.1" type="float" unit="sec"/>
71   - <param section="detector" key="exptime_maxi" value="1000" type="float" unit="sec"/>
72   - <param section="detector" key="readouttime" value="10" type="float" unit="sec"/>
73   - <param section="detector" key="shutters" value="synchro, openned, closed" type="str" unit=""/>
74   - <param section="detector" key="nbcells1" value="4096" type="int" unit=""/>
75   - <param section="detector" key="cellsize1" value="15" type="float" unit="mu"/>
76   - <param section="detector" key="nbcells2" value="4096" type="int" unit=""/>
77   - <param section="detector" key="cellsize2" value="15" type="float" unit="mu"/>
78   - <param section="detector" key="readoutnoise" value="7.5" type="float" unit="electrons"/>
79   - <param section="detector" key="gain" value="2.5" type="float" unit="electrons/adu"/>
80   - <param section="detector" key="temperature" value="-50" type="float" unit="degC"/>
81   - <param section="detector" key="thermic_signal" value="0.05" type="float" unit="electrons/s"/>
82 118 <!-- Atmospheric conditions for simulations -->
83 119 <param section="atmosphere" key="temperature" value="300" type="float" unit="Kelvin"/>
84 120 <param section="atmosphere" key="pressure" value="101325" type="float" unit="Pascal"/>
... ... @@ -87,14 +123,117 @@ timestamp : Date when the value has been last updated
87 123 <param section="atmosphere" key="transparency" value="0.8" type="float" unit="0b110101"/>
88 124 <!-- Define the horizon line for scheduler -->
89 125 <param section="horizon" key="amer_list" value="(0, 10), (50, 15), (60,10)" type="tuple" unit="Angle"/>
  126 + <!-- Plan description of this channel for the web form and observations -->
  127 + <plan>
  128 + <param section="form" key="filter" label="Filter" default_value="" element="input" element_attribute=''/>
  129 + <param section="form" key="binning" label="Binning" default_value="" element="select" element_attribute="" options="param detector binnings"/>
  130 + <param section="form" key="exptime" label="Exposure time (s)" default_value="1" element="range" element_attribute='min="0.1" max="100"'/>
  131 + <param section="form" key="nb_images" label="Number image" default_value="1" element="range" element_attribute='min="1" max="10000"'/>
  132 + <param section="form" key="shutter" label="Shutter mode" default_value="1" element="select" element_attribute="" options="param detector shutter_mode"/>
  133 + <param section="form" key="delay" label="Delay start (s)" default_value="0" element="range" element_attribute='min="0" max="100"'/>
  134 + </plan>
90 135 </channel>
91 136  
92 137 <!-- A computer definition -->
93 138 <computer alias="Computer1">
  139 + <!-- Access -->
  140 + <param section="local" key="hostname" value="titanium" comment="returned by import socket;print(socket.gethostname())"/>
  141 + <param section="local" key="ip" value="192.168.0.1"/>
  142 + <param section="global" key="hostname" value="titanium.irap.omp.eu"/>
  143 + <param section="global" key="www_port" value="80"/>
  144 + <!-- Agents to launch on this computer -->
  145 + <param section="agent_to_launch" key="alias" value="AgentX"/>
  146 + <param section="agent_to_launch" key="alias" value="Monitoring"/>
  147 + <param section="agent_to_launch" key="alias" value="TelescopeSimulator"/>
  148 + <param section="agent_to_launch" key="alias" value="CameraSimulator"/>
  149 + </computer>
  150 +
  151 + <!-- A computer definition -->
  152 + <computer alias="Computer2">
94 153 <!-- Access autorizations -->
95   - <param section="access" key="mysql_host" value="127.0.0.1"/>
96   - <param section="access" key="mysql_user" value="pyros"/>
97   - <param section="access" key="mysql_pswd" value="DjangoPyros"/>
  154 + <param section="local" key="hostname" value="etienne" comment="returned by import socket;print(socket.gethostname())"/>
  155 + <param section="local" key="ip" value="192.168.0.1"/>
  156 + <param section="global" key="hostname" value="etienne.irap.omp.eu"/>
  157 + <param section="global" key="www_port" value="80"/>
  158 + <!-- Agents to launch on this computer -->
  159 + <param section="agent_to_launch" key="alias" value="AgentX"/>
  160 + <param section="agent_to_launch" key="alias" value="Monitoring"/>
  161 + <param section="agent_to_launch" key="alias" value="TelescopeSimulator"/>
  162 + <param section="agent_to_launch" key="alias" value="CameraSimulator"/>
98 163 </computer>
99 164  
100   -</unit>
101 165 \ No newline at end of file
  166 + <!-- A computer definition -->
  167 + <computer alias="Computer3">
  168 + <!-- Access autorizations -->
  169 + <param section="local" key="hostname" value="patrick" comment="returned by import socket;print(socket.gethostname())"/>
  170 + <param section="local" key="ip" value="192.168.0.1"/>
  171 + <param section="global" key="hostname" value="etienne.irap.omp.eu"/>
  172 + <param section="global" key="www_port" value="80"/>
  173 + <!-- Agents to launch on this computer -->
  174 + <param section="agent_to_launch" key="alias" value="AgentX"/>
  175 + <param section="agent_to_launch" key="alias" value="Monitoring"/>
  176 + <param section="agent_to_launch" key="alias" value="TelescopeSimulator"/>
  177 + <param section="agent_to_launch" key="alias" value="CameraSimulator"/>
  178 + </computer>
  179 +
  180 + <!-- An agent definition -->
  181 + <agent alias="Superagent1">
  182 + <!-- -->
  183 + <param section="general" key="startmode" value="RUN"/>
  184 + <!-- Where is the code to launch ? Concatenation of path0_filename + path1_filename + tail_filename -->
  185 + <param section="code" key="path0_filename" value="$PYROS"/>
  186 + <param section="code" key="path1_filename" value="../pyros_simulunit1/src/superagent1"/>
  187 + <param section="code" key="tail_filename" value="SuperAgent1.py"/>
  188 + </agent>
  189 +
  190 + <!-- An agent definition -->
  191 + <agent alias="AgentX">
  192 + <!-- -->
  193 + <param section="general" key="startmode" value="IDLE"/>
  194 + <!-- Where is the code to launch ? Concatenation of path0_filename + path1_filename + tail_filename -->
  195 + <param section="code" key="path0_filename" value="$PYROS"/>
  196 + <param section="code" key="path1_filename" value="src/agentx"/>
  197 + <param section="code" key="tail_filename" value="AgentX.py"/>
  198 + </agent>
  199 +
  200 + <!-- An agent definition -->
  201 + <agent alias="AgentY">
  202 + <!-- -->
  203 + <param section="general" key="startmode" value="RUN"/>
  204 + <!-- Where is the code to launch ? Concatenation of path0_filename + path1_filename + tail_filename -->
  205 + <param section="code" key="path0_filename" value="$PYROS"/>
  206 + <param section="code" key="path1_filename" value="../pyros_simulunit1/src/agenty"/>
  207 + <param section="code" key="tail_filename" value="AgentY.py"/>
  208 + </agent>
  209 +
  210 + <!-- An agent definition -->
  211 + <agent alias="TelescopeSimulator">
  212 + <!-- -->
  213 + <param section="general" key="startmode" value="RUN"/>
  214 + <!-- Where is the code to launch ? Concatenation of path0_filename + path1_filename + tail_filename -->
  215 + <param section="code" key="path0_filename" value="$PYROS"/>
  216 + <param section="code" key="path1_filename" value="src/telescopesimulator"/>
  217 + <param section="code" key="tail_filename" value="TelescopeSimulator.py"/>
  218 + </agent>
  219 +
  220 + <!-- An agent definition -->
  221 + <agent alias="CameraSimulator">
  222 + <!-- -->
  223 + <param section="general" key="startmode" value="RUN"/>
  224 + <!-- Where is the code to launch ? Concatenation of path0_filename + path1_filename + tail_filename -->
  225 + <param section="code" key="path0_filename" value="$PYROS"/>
  226 + <param section="code" key="path1_filename" value="src/camerasimulator"/>
  227 + <param section="code" key="tail_filename" value="CameraSimulator.py"/>
  228 + </agent>
  229 +
  230 + <!-- An agent definition -->
  231 + <agent alias="Monitoring">
  232 + <!-- -->
  233 + <param section="general" key="startmode" value="RUN"/>
  234 + <!-- Where is the code to launch ? Concatenation of path0_filename + path1_filename + tail_filename -->
  235 + <param section="code" key="path0_filename" value="$PYROS"/>
  236 + <param section="code" key="path1_filename" value="src/monitoring"/>
  237 + <param section="code" key="tail_filename" value="start_agent_monitoring.py"/>
  238 + </agent>
  239 +
  240 +</unit>
... ...
config/configpyros.py
... ... @@ -2,31 +2,404 @@
2 2 # ----------------------------------------------------------------------------------------------------
3 3 # Parameter attributes = section, key, value, type, unit, access, comment, label, reference, timestamp
4 4 # ----------------------------------------------------------------------------------------------------
  5 +"""
  6 +Example of
  7 +config = ConfigPyros()
  8 +config.set_configfile('/tmp/myconfig.xml')
  9 +stmod = config.get_paramvalue('angentX','general','startmode')
  10 +"""
  11 +# ----------------------------------------------------------------------------------------------------
  12 +
5 13 from lxml import etree
6 14 import os
  15 +import socket
  16 +import random
7 17  
8 18 class ConfigPyros:
9 19  
10 20 # === Constants
11 21 NO_ERROR = 0
12   - ERR_FILE_NOT_EXISTS = 100
13   - ERR_LOAD_ERROR = 200
14   - ERR_TAG_ROOT_IS_NOT_UNIT = 201
15   - ERR_TAG_ROOT_HAS_NO_ATTRIBUTE_ALIAS = 202
  22 +
  23 + ERR_FILE_NOT_EXISTS = 101
  24 + ERR_XML_FILE_ERROR = 102
  25 +
  26 + ERR_A_SUBTAG_UNIT_HAVE_NO_ATTRIBUTE_ALIAS = 301
  27 + ERR_ASSEMBLED_ALIAS_NOT_DEFINED = 302
  28 + ERR_NO_MOUNT_ASSEMBLED = 303
  29 + ERR_ONLY_ONE_MOUNT_CAN_BE_ASSEMBLED = 304
  30 + ERR_NO_CHANNEL_ASSEMBLED = 305
  31 + ERR_NO_DATABASE_ASSEMBLED = 306
16 32  
17 33 # === Private variables
18 34 _last_errno = NO_ERROR
  35 + _last_errparam1 = ""
  36 + # --- XML file
19 37 _config_filename = ""
20 38 _config_filename_mtime = 0
21 39 _config_filename_need_to_be_read = True
22   - _unit_component_params = []
23   - _unit_component_params_valid = False
  40 + # --- XML structure
  41 + _tags_to_scan = None
  42 + # --- XML contents
  43 + _config_contents_valid = False
  44 + _tree = None
  45 + _root = None
  46 + _unit_subtags = None
  47 + _tag_aliases = None
  48 + _assemblies = None
  49 + # --- Computer infos
  50 + _hostname = None
  51 + _this_computer_alias = None
  52 +
  53 +# =====================================================================
  54 +# =====================================================================
  55 +# Private methods
  56 +# =====================================================================
  57 +# =====================================================================
  58 +
  59 + def _configfile_verify(self):
  60 + """ Update parameters of the configuration file (existing, modification date)
  61 + """
  62 + self._config_filename_need_to_be_read = False
  63 + self._last_errno = self.NO_ERROR
  64 + if os.path.isfile(self._config_filename):
  65 + # --- verify the date of last modification of the file
  66 + config_filename_mtime = os.path.getmtime(self._config_filename)
  67 + if config_filename_mtime > self._config_filename_mtime:
  68 + self._config_filename_need_to_be_read = True
  69 + #### self._config_filename_mtime = config_filename_mtime
  70 + else:
  71 + self._last_errno = self.ERR_FILE_NOT_EXISTS
  72 +
  73 + def _parse_xml2lists(self, verbose:bool = False):
  74 + """ Transform the DOM XML structure into usable lists for PyROS
  75 + """
  76 +
  77 + if (verbose==True):
  78 + print("============== Subtags of <unit> Information with attribute alias")
  79 +
  80 + unit_subtags = []
  81 + tags_to_scan = ['']
  82 + xpath = '/unit' + '/*'
  83 + for elem in self._root.xpath(xpath):
  84 + if str(type(elem)) != "<class 'lxml.etree._Element'>":
  85 + continue
  86 + if elem.tag in unit_subtags:
  87 + continue
  88 + if elem.attrib.get('alias',None) == None:
  89 + continue
  90 + unit_subtags.append(elem.tag)
  91 + tags_to_scan.append(elem.tag)
  92 + if (verbose==True):
  93 + print("<{}> subtags = {}".format(xpath, unit_subtags))
  94 +
  95 + # --- verify the presence of at less one of the following subtag of <unit>
  96 + mandatory_tags = ['', 'database', 'mount', 'channel', 'computer', 'agent']
  97 + for mandatory_tag in mandatory_tags:
  98 + if mandatory_tag not in tags_to_scan:
  99 + self._last_errno = self.ERR_A_SUBTAG_UNIT_HAVE_NO_ATTRIBUTE_ALIAS
  100 + if mandatory_tag == '':
  101 + self._last_errparam1 = 'unit'
  102 + else:
  103 + self._last_errparam1 = mandatory_tag
  104 + return False
  105 +
  106 + # --- Get all aliases of subtags of <unit>
  107 + # --- Set the tag_aliases dictionnary of lists
  108 + tag_aliases = {}
  109 + for tag in tags_to_scan:
  110 +
  111 + if tag == "":
  112 + xpath = '/unit'
  113 + tag = 'unit'
  114 + else:
  115 + xpath = '/unit/' + tag
  116 + if (verbose==True):
  117 + print("============== Aliases of <" + tag + ">")
  118 +
  119 + attrib_key_to_get = 'alias'
  120 + aliases = config.get_attribute_level0(xpath,attrib_key_to_get)
  121 + if (verbose==True):
  122 + print("<{} {}> = {}".format(xpath, attrib_key_to_get, aliases))
  123 + if aliases == [None]:
  124 + self._last_errno = self.ERR_TAG_MOUNT_HAVE_NO_ATTRIBUTE_ALIAS
  125 + return False
  126 + tag_aliases[tag] = aliases
  127 +
  128 + if (verbose==True):
  129 + print("============== Unit all alias intantiations in one list")
  130 +
  131 + # --- get all the assemblies
  132 + xpath = '/unit'
  133 + attrib_to_select = {'alias': (tag_aliases['unit'])[0]}
  134 + tag_to_get = "param"
  135 + tag_attrib_to_select = {'section': 'assembly', 'key': 'alias'}
  136 + tag_attrib_key_to_get = 'value'
  137 + assembled_aliases = config.get_attribute_level1(xpath,attrib_to_select,tag_to_get,tag_attrib_to_select,tag_attrib_key_to_get)
  138 + if (verbose==True):
  139 + print("{} <{} {}> = {}".format(attrib_to_select, tag_to_get, tag_attrib_to_select, assembled_aliases))
  140 +
  141 + if (verbose==True):
  142 + print("============== Unit alias intantiations in dictionnary of tags")
  143 +
  144 + # --- Set the assembly dictionnary of lists
  145 + assemblies = {}
  146 + for assembled_alias in assembled_aliases:
  147 + als = []
  148 + for tag in tags_to_scan:
  149 + if tag == '':
  150 + continue
  151 + #print("tag = {}".format(tag))
  152 + #print("assembled_alias = {}".format(assembled_alias))
  153 + #print("tag_aliases[tag] = {}".format(tag_aliases[tag]))
  154 + if assembled_alias in tag_aliases[tag]:
  155 + als.append(assembled_alias)
  156 + the_tag = tag
  157 + #print("n = {}".format(n))
  158 + if len(als) == 0:
  159 + self._last_errno = self.ERR_ASSEMBLED_ALIAS_NOT_DEFINED
  160 + self._last_errparam1 = tag
  161 + return False
  162 + else:
  163 + assemblies[the_tag] = als
  164 + if (verbose==True):
  165 + print("assemblies = {}".format(assemblies))
  166 +
  167 + # --- check the number of mounts assembled
  168 + if 'mount' in assemblies.keys():
  169 + if (len(assemblies['mount']) > 1):
  170 + if (verbose==True):
  171 + print("Error: Only one mount can be assembled")
  172 + self._last_errno = self.ERR_ONLY_ONE_MOUNT_CAN_BE_ASSEMBLED
  173 + return False
  174 + else:
  175 + if (verbose==True):
  176 + print("Error: No mount assembled")
  177 + self._last_errno = self.ERR_NO_MOUNT_ASSEMBLED
  178 + return False
  179 +
  180 + # --- check the number of channels assembled
  181 + if 'channel' not in assemblies.keys():
  182 + if (verbose==True):
  183 + print("Error: No channel assembled")
  184 + self._last_errno = self.ERR_NO_CHANNEL_ASSEMBLED
  185 + return False
  186 +
  187 + # --- Chack the computer infos
  188 + if (verbose==True):
  189 + print("============== Unit all alias intantiations in one list")
  190 +
  191 + # --- get all the assemblies
  192 + this_computer_alias = None
  193 + hostname = socket.gethostname()
  194 + aliases = tag_aliases['computer']
  195 + xpath = '/unit/computer'
  196 + tag_to_get = "param"
  197 + tag_attrib_to_select = {'section': 'local', 'key': 'hostname'}
  198 + tag_attrib_key_to_get = 'value'
  199 + for alias in aliases:
  200 + attrib_to_select = {'alias': alias}
  201 + hname = config.get_attribute_level1(xpath,attrib_to_select,tag_to_get,tag_attrib_to_select,tag_attrib_key_to_get)
  202 + if hname[0] == hostname:
  203 + this_computer_alias = alias
  204 +
  205 + # --- Everything was OK until this point. Validate the XML
  206 + self._unit_subtags = unit_subtags
  207 + self._tags_to_scan = tags_to_scan
  208 + self._tag_aliases = tag_aliases
  209 + self._assemblies = assemblies
  210 + self._this_computer_alias = this_computer_alias
  211 +
  212 + return True
  213 +
  214 + def _alias2xpath(self, alias, subtag=""):
  215 + #print("alias={}".format(alias))
  216 + tag = self.get_unit_subtag(alias)
  217 + #print("tag={}".format(tag))
  218 + if tag == 'unit':
  219 + xpath = '/unit'
  220 + elif tag == None:
  221 + return None
  222 + else:
  223 + xpath = '/unit/' + tag
  224 + if subtag != "":
  225 + xpath += '/' + subtag
  226 + return xpath
  227 +
  228 + def _encode(self, texte:str, method:str = 'crypted1', phrase:str = "(Af%"):
  229 + if method == 'crypted1':
  230 + lphrase = len(phrase)
  231 + plus = random.randint(1,9)
  232 + for i in range(plus):
  233 + texte += chr(random.randint(32,255))
  234 + texte += chr(ord(str(plus)))
  235 + texte_hexa_codeds = ""
  236 + for i in range(len(texte)):
  237 + phrase_deci = ord(phrase[i%lphrase])+i
  238 + texte_deci = ord(texte[i])
  239 + #texte_hexa = hex(texte_deci)
  240 + texte_deci_coded = (texte_deci + phrase_deci)%256
  241 + texte_hexa_coded = "{0:#0{1}x}".format(texte_deci_coded,4)
  242 + texte_hexa_codeds += texte_hexa_coded[2:4]
  243 + #print("{} raw={} {} {} coded={} {}".format(i,texte[i],texte_deci,phrase_deci,texte_deci_coded,texte_hexa_coded))
  244 + return texte_hexa_codeds
  245 + else:
  246 + return texte
  247 +
  248 + def _decode(self, crypted:str, method:str = 'crypted1', phrase:str = "(Af%"):
  249 + if method == 'crypted1':
  250 + if crypted == '':
  251 + return ''
  252 + lphrase = len(phrase)
  253 + texte_hexa_codeds = crypted
  254 + texte = ""
  255 + for i in range(int(len(texte_hexa_codeds)/2)):
  256 + phrase_deci = ord(phrase[i%lphrase])+i
  257 + texte_hexa_coded = '0x'+texte_hexa_codeds[2*i:2*i+2]
  258 + texte_deci_coded = int(texte_hexa_coded,16)
  259 + texte_deci = (texte_deci_coded - phrase_deci + 256)%256
  260 + texte += chr(texte_deci)
  261 + #print("{} coded={} raw={} {}".format(i,texte_hexa_coded,texte_deci,chr(texte_deci)))
  262 + plus = int(texte[-1])
  263 + texte = texte[0:-1-plus]
  264 + return texte
  265 + else:
  266 + return crypted
  267 +
  268 +# =====================================================================
  269 +# =====================================================================
  270 +# Methods for experimented users
  271 +# =====================================================================
  272 +# =====================================================================
  273 +
  274 + def get_attribute_level0(self, xpath:str, attrib_key_to_get:str):
  275 + """ Read a list of values ['d', 'e'] from the following XML structure:
  276 + <a>
  277 + <b "c"="d">
  278 + ...
  279 + </b>
  280 + <b "c"="e">
  281 + ...
  282 + </b>
  283 + </a>
  284 + Select the path: xpath = '/a/b'
  285 + Select key attribute: attrib_key_to_get = 'c'
  286 + Call the method:
  287 + result = ConfigPyros.get_attribute_level0(xpath,attrib_to_select,tag_to_get,tag_attrib_to_select tag_attrib_key_to_get)
  288 + """
  289 + if self._config_contents_valid == False:
  290 + return ""
  291 + root = self._root
  292 + #
  293 + # 1) get the path of /unit/agent with a given attribute
  294 + # --
  295 + attrib_value_to_gets = []
  296 + for elem in root.xpath(xpath):
  297 + if str(type(elem)) != "<class 'lxml.etree._Element'>":
  298 + continue
  299 + attrib_value_to_gets.append( elem.attrib.get(attrib_key_to_get,None) )
  300 + return attrib_value_to_gets
24 301  
  302 + def get_attribute_level1(self, xpath:str, attrib_to_select:dict, tag_to_get:str, tag_attrib_to_select:dict, tag_attrib_key_to_get:str):
  303 + """ Read a value 'k' from the following XML structure:
  304 + <a>
  305 + <b "c"="d">
  306 + <e "f"="g" "h"="i" "j"="k"/>
  307 + </b>
  308 + </a>
  309 + Select the path: xpath = '/a/b'
  310 + Select the attribute dictionary: attrib_to_select = {'c': 'd'}
  311 + Select tag: tag_to_get = "e"
  312 + Select tag attribute dictionary: tag_attrib_to_select = {'f': 'g', 'h': 'i'}
  313 + Select key attribute: tag_attrib_key_to_get = 'j'
  314 + Call the method:
  315 + result = ConfigPyros.get_attribute_level1(xpath,attrib_to_select,tag_to_get,tag_attrib_to_select tag_attrib_key_to_get)
  316 + """
  317 + if self._config_contents_valid == False:
  318 + return ""
  319 + root = self._root
  320 + tree = self._tree
  321 + #
  322 + # 1) get the path of /a/b with a given attribute c="d"
  323 + # --
  324 + #print("============== xpath {}".format(xpath))
  325 + nb = 0
  326 + for elem in root.xpath(xpath):
  327 + if str(type(elem)) != "<class 'lxml.etree._Element'>":
  328 + continue
  329 + nbitems = len(attrib_to_select)
  330 + nb = 0
  331 + for key in attrib_to_select.keys():
  332 + value = attrib_to_select[key]
  333 + vxml = elem.attrib.get(key,None)
  334 + #print("key={} value={} vxml={}".format(key,value,vxml))
  335 + if value == vxml:
  336 + nb += 1
  337 + #print("nb={} nbitems={}".format(nb,nbitems))
  338 + if nb == nbitems:
  339 + path = tree.getpath(elem)
  340 + #print("tree.getpath(elem) = {}".format(tree.getpath(elem)))
  341 + if nb==0:
  342 + nb = 1
  343 + break
  344 + #
  345 + # 2) get the list of params correspondong to the selected 'b'
  346 + attrib_value_to_gets = []
  347 + if nb==0:
  348 + return attrib_value_to_gets
  349 + #print("---------------")
  350 + for elem in root.xpath(path+"/*"):
  351 + if str(type(elem)) != "<class 'lxml.etree._Element'>":
  352 + continue
  353 + #print(" elem.tag= {}".format(elem.tag))
  354 + if elem.tag == tag_to_get:
  355 + if tag_attrib_to_select == "" and tag_attrib_key_to_get == "":
  356 + attrib_value_to_gets.append(elem.attrib)
  357 + #print(" elem.attrib = {}".format(elem.attrib))
  358 + else:
  359 + nbitems = len(tag_attrib_to_select)
  360 + #print(" elem.attrib = {}".format(elem.attrib))
  361 + nb = 0
  362 + for key in tag_attrib_to_select.keys():
  363 + value = tag_attrib_to_select[key]
  364 + vxml = elem.attrib.get(key,None)
  365 + #print("key={} value={} vxml={}".format(key,value,vxml))
  366 + if value == vxml:
  367 + nb += 1
  368 + #print("nb={} nbitems={}".format(nb,nbitems))
  369 + if nb == nbitems:
  370 + if tag_attrib_key_to_get == "":
  371 + attrib_value_to_gets.append( elem.attrib )
  372 + else:
  373 + attrib_value_to_gets.append( elem.attrib.get(tag_attrib_key_to_get,None) )
  374 + return attrib_value_to_gets
  375 +
  376 +# =====================================================================
  377 +# =====================================================================
  378 +# Methods for users
  379 +# =====================================================================
  380 +# =====================================================================
  381 +
25 382 def get_last_errno(self):
26 383 """ Get the last error code
27 384 """
28 385 return self._last_errno
29   -
  386 +
  387 + def get_last_errmsg(self):
  388 + """ Get the last error message
  389 + """
  390 + msg = "Unknown error"
  391 + if self._last_errno == self.NO_ERROR: msg = "No error"
  392 + elif self._last_errno == self.ERR_FILE_NOT_EXISTS: msg = "File does not exists"
  393 + elif self._last_errno == self.ERR_XML_FILE_ERROR: msg = "XML file error"
  394 + elif self._last_errno == self.ERR_A_SUBTAG_UNIT_HAVE_NO_ATTRIBUTE_ALIAS: msg = "Tags <{}> have no attribute alias".format(self._last_errparam1)
  395 + elif self._last_errno == self.ERR_ASSEMBLED_ALIAS_NOT_DEFINED: msg = "Instantiated {} not defined in a <{}>".format(self._last_errparam1,self._last_errparam1)
  396 + elif self._last_errno == self.ERR_NO_MOUNT_ASSEMBLED: msg = "No mount assembled"
  397 + elif self._last_errno == self.ERR_ONLY_ONE_MOUNT_CAN_BE_ASSEMBLED: msg = "Only one mount can be assembled"
  398 + elif self._last_errno == self.ERR_NO_CHANNEL_ASSEMBLED: msg = "No channel assembled"
  399 + elif self._last_errno == self.ERR_NO_DATABASE_ASSEMBLED: msg = "No database assembled"
  400 +
  401 + return msg
  402 +
30 403 def set_configfile(self, config_filename:str ):
31 404 """ To set the config file name
32 405  
... ... @@ -36,8 +409,9 @@ class ConfigPyros:
36 409 if config_filename == "" or config_filename != self._config_filename:
37 410 self._config_filename = config_filename
38 411 self._config_filename_mtime = 0
39   - self._unit_component_params_valid = False
40   - self._unit_component_params = []
  412 + self._config_contents_valid = False
  413 + self._tree = None
  414 + self._root = None
41 415 self._configfile_verify()
42 416 return
43 417  
... ... @@ -46,22 +420,7 @@ class ConfigPyros:
46 420 """
47 421 return self._config_filename
48 422  
49   - def _configfile_verify(self):
50   - """ Update parameters of the configuration file (existing, modification date)
51   - """
52   - self._config_filename_need_to_be_read = False
53   - self._last_errno = self.NO_ERROR
54   - if os.path.isfile(self._config_filename):
55   - # --- verify the date of last modification of the file
56   - config_filename_mtime = os.path.getmtime(self._config_filename)
57   - if config_filename_mtime > self._config_filename_mtime:
58   - self._config_filename_need_to_be_read = True
59   - #### self._config_filename_mtime = config_filename_mtime
60   - else:
61   - self._last_errno = self.ERR_FILE_NOT_EXISTS
62   -
63   -
64   - def load(self, verbose:bool = False):
  423 + def load(self, verbose:bool = False, force:bool = False):
65 424 """ To load the config file if necessary
66 425  
67 426 :Example:
... ... @@ -69,134 +428,235 @@ class ConfigPyros:
69 428 ConfigPyros().load()
70 429 """
71 430  
  431 + # --- Verify the existence and the last modification of the XML file
72 432 self._configfile_verify()
73 433 errno = self.get_last_errno()
74 434 if errno != self.NO_ERROR:
  435 + if (verbose==True):
  436 + print("Load Error = {}".format(errno))
75 437 return
76   - if self._config_filename_need_to_be_read == False:
  438 + if self._config_filename_need_to_be_read == False and force == False:
77 439 return
78 440  
79 441 # --- Read the configuration file and parse it
80 442 self._last_errno = self.NO_ERROR
81   - unit_component_params = []
82 443 try:
  444 + # --- Save the current tree and root as '_old'
  445 + self._tree_old = self._tree
  446 + self._root_old = self._root
  447 +
  448 + # --- Parse the XML file into DOM
83 449 tree = etree.parse(self._config_filename)
  450 +
84 451 # --- Get root from the tree
85 452 root = tree.getroot()
86 453  
87   - # === Verify the root tag is 'unit'
88   - verify_unit = root.tag
89   - if (verify_unit != "unit"):
90   - self._last_errno = self.ERR_TAG_ROOT_IS_NOT_UNIT
91   - return
92   -
93   - # === Get the alias value of the root tag 'unit'
94   - alias_unit = root.attrib['alias']
95   - if (alias_unit == ""):
96   - self._last_errno = self.ERR_TAG_ROOT_HAS_NO_ATTRIBUTE_ALIAS
97   - return
98   -
99   - # === Get the mount aliases
100   - alias_mounts = []
101   - for elem in root.xpath("/unit/mount"):
102   - # print(elem.tag, elem.attrib)
103   - alias_mounts.append(elem.attrib['alias'])
104   - if (verbose==True):
105   - print("alias_mounts = {}".format(alias_mounts))
  454 + # --- Set the new tree and root
  455 + self._tree = tree
  456 + self._root = root
106 457  
107   - # === Get the channel aliases
108   - alias_channels = []
109   - for elem in root.xpath("/unit/channel"):
110   - # print(elem.tag, elem.attrib)
111   - alias_channels.append(elem.attrib['alias'])
112   - if (verbose==True):
113   - print("alias_channels = {}".format(alias_channels))
114   -
115   - # === Get the association of channels for this mount
116   - unit_components = []
117   - for elem in root:
118   - if elem.tag == "param":
119   - attributes = elem.attrib
120   - if attributes['section'] != "instanciation":
121   - continue
122   - alias_param_unit = attributes['value']
123   - for alias_mount in alias_mounts:
124   - if alias_param_unit == alias_mount:
125   - key = attributes['key']
126   - dico = {'tag':'mount','instanciation':key,'alias':alias_param_unit}
127   - unit_components.append(dico)
128   - for alias_channel in alias_channels:
129   - if alias_param_unit == alias_channel:
130   - key = attributes['key']
131   - dico = {'tag':'channel','instanciation':key,'alias':alias_param_unit}
132   - unit_components.append(dico)
133   - if (verbose==True):
134   - print("unit_components = {}".format(unit_components))
135   -
136   - # === Get detailed informations about the unit components
137   - for unit_component in unit_components:
138   - tag = unit_component['tag']
139   - instanciation = unit_component['instanciation']
140   - alias = unit_component['alias']
141   - params = []
142   - for elem in root:
143   - if (elem.tag == tag) and (elem.attrib['alias'] == alias):
144   - for el in elem:
145   - if (el.tag == "param"):
146   - params.append(el.attrib)
147   - unit_component_params.append({'component':tag, 'instanciation':instanciation, 'alias':alias, 'params':params})
148   - if (verbose==True):
149   - print("unit_component_params = {}".format(unit_component_params))
150   - self._unit_component_params = unit_component_params
151   - self._unit_component_params_valid = True
152   - self._config_filename_mtime = os.path.getmtime(self._config_filename)
  458 + # --- Parse the DOM into usable lists
  459 + self._config_contents_valid = True
  460 + valid = self._parse_xml2lists(verbose)
  461 +
  462 + # --- Validation step
  463 + if valid == True:
  464 + self._config_filename_mtime = os.path.getmtime(self._config_filename)
  465 + else:
  466 + # --- Se the current tree and root from '_old'
  467 + self._config_contents_valid = False
  468 + self._tree = self._tree_old
  469 + self._root = self._root_old
  470 +
153 471 except:
154   - self._last_errno = self.ERR_LOAD_ERROR
  472 + self._last_errno = self.ERR_XML_FILE_ERROR
155 473 return
156   -
157   - def get_paramvalue(self, instanciation:str, section:str, key:str):
158   - if self._unit_component_params_valid == False:
  474 +
  475 + def get_unit_subtags(self):
  476 + if self._config_contents_valid == False:
  477 + return ""
  478 + return self._unit_subtags
  479 +
  480 + def get_aliases(self, unit_subtag):
  481 + if self._config_contents_valid == False:
159 482 return ""
160   - unit_component_params = self._unit_component_params
161   - paramvalue = ""
162   - for unit_component_param in unit_component_params:
163   - component_instanciation = unit_component_param['instanciation']
164   - if (component_instanciation == instanciation):
165   - for param in unit_component_param['params']:
166   - param_section = param['section']
167   - param_key = param['key']
168   - if (param_section == section) and (param_key == key):
169   - paramvalue = param['value']
170   - break
171   - if (paramvalue != ""):
172   - break
173   - return paramvalue
  483 + return self._tag_aliases[unit_subtag]
  484 +
  485 + def get_unit_subtag(self, alias):
  486 + if self._config_contents_valid == False:
  487 + return ""
  488 + for unit_subtag in self._tag_aliases:
  489 + aliases = self.get_aliases(unit_subtag)
  490 + #print("alias={} in aliases={}".format(alias,aliases))
  491 + if alias in aliases:
  492 + return unit_subtag
  493 + return None
174 494  
  495 + def get_params(self, alias, subtag=""):
  496 + """ Select the tag corresponding to alias
  497 + Return the list of dictionaries of all attributes
  498 + """
  499 + if self._config_contents_valid == False:
  500 + return ""
  501 + # --- search the tag from its alias
  502 + xpath = self._alias2xpath(alias, subtag)
  503 + attrib_to_select = {'alias': alias}
  504 + tag_to_get = "param"
  505 + tag_attrib_to_select = ""
  506 + tag_attrib_key_to_get = ""
  507 + #print("get_params alias={} subtag={} xpath={}".format(alias,subtag,xpath))
  508 + value = config.get_attribute_level1(xpath,attrib_to_select,tag_to_get,tag_attrib_to_select,tag_attrib_key_to_get)
  509 + #print("{} <{} {}> = {}".format(attrib_to_select, tag_to_get, tag_attrib_to_select, value))
  510 + if (len(value)>0):
  511 + return value
  512 + return None
  513 +
  514 + def get_param(self, alias, section, key, subtag=""):
  515 + """ Select the tag corresponding to alias, and <param> tag with attributes section=, key=
  516 + Return the dictionary of all attributes
  517 + """
  518 + if self._config_contents_valid == False:
  519 + return ""
  520 + # --- search the tag from its alias
  521 + xpath = self._alias2xpath(alias, subtag)
  522 + attrib_to_select = {'alias': alias}
  523 + tag_to_get = "param"
  524 + tag_attrib_to_select = {'section': section, 'key': key}
  525 + tag_attrib_key_to_get = ""
  526 + #print("get_param alias={} subtag={} xpath={}".format(alias,subtag,xpath))
  527 + value = config.get_attribute_level1(xpath,attrib_to_select,tag_to_get,tag_attrib_to_select,tag_attrib_key_to_get)
  528 + #print("{} <{} {}> = {}".format(attrib_to_select, tag_to_get, tag_attrib_to_select, value))
  529 + if (len(value)>0):
  530 + return value[0]
  531 + return None
  532 +
  533 + def get_paramvalue(self, alias, section, key, subtag=""):
  534 + """ Select the tag corresponding to alias, and <param> tag with attributes section=, key=
  535 + Return only the value=
  536 + """
  537 + if self._config_contents_valid == False:
  538 + return ""
  539 + # --- search the tag from its alias
  540 + xpath = self._alias2xpath(alias, subtag)
  541 + attrib_to_select = {'alias': alias}
  542 + tag_to_get = "param"
  543 + tag_attrib_to_select = {'section': section, 'key': key}
  544 + tag_attrib_key_to_get = 'value'
  545 + #print("get_paramvalue alias={} subtag={} xpath={}".format(alias,subtag,xpath))
  546 + value = config.get_attribute_level1(xpath,attrib_to_select,tag_to_get,tag_attrib_to_select,tag_attrib_key_to_get)
  547 + #print("{} <{} {}> = {}".format(attrib_to_select, tag_to_get, tag_attrib_to_select, value))
  548 + if (len(value)>0):
  549 + return value[0]
  550 + return None
  551 +
  552 + def get_plan(self, alias):
  553 + """ Select the tag corresponding to alias, and <param> tag with attributes section=, key=
  554 + Return the dictionary of all attributes
  555 + """
  556 + if self._config_contents_valid == False:
  557 + return ""
  558 + # --- search the tag from its alias
  559 + subtag = 'plan'
  560 + xpath = self._alias2xpath(alias, subtag)
  561 + #attrib_to_select = {'alias': 'current'}
  562 + attrib_to_select = {}
  563 + tag_to_get = "param"
  564 + tag_attrib_to_select = ""
  565 + tag_attrib_key_to_get = ""
  566 + #print("get_plan alias={} subtag={} xpath={}".format(alias,subtag,xpath))
  567 + value = config.get_attribute_level1(xpath,attrib_to_select,tag_to_get,tag_attrib_to_select,tag_attrib_key_to_get)
  568 + #print("{} <{} {}> = {}".format(attrib_to_select, tag_to_get, tag_attrib_to_select, value))
  569 + if (len(value)>0):
  570 + return value
  571 + return None
  572 +
  573 + def get_computer_alias(self):
  574 + if self._config_contents_valid == False:
  575 + return ""
  576 + return self._this_computer_alias
  577 +
  578 + def encode(self, text:str, method:str = 'crypted1'):
  579 + return self._encode(text,method)
  580 +
  581 + def decode(self, crypted:str, method:str = 'crypted1'):
  582 + return self._decode(crypted,method)
  583 +
  584 +# =====================================================================
  585 +# =====================================================================
  586 +# Special methods
  587 +# =====================================================================
  588 +# =====================================================================
  589 +
175 590 def __init__(self, config_filename:str = ""):
176 591 self._last_errno = self.NO_ERROR
177 592 self._unit_component_params = []
178 593 self.set_configfile(config_filename)
  594 +
  595 +# =====================================================================
  596 +# =====================================================================
  597 +# Test if main
  598 +# =====================================================================
  599 +# =====================================================================
179 600  
180 601 if __name__ == "__main__":
  602 + cwd = os.getcwd()
181 603 # --- Set the filename of the configuration
182   - config_filename = 'c:/srv/develop/pyros/config/config_unit_simulunit1.xml'
183   - #config_filename = '/PROJECTS/GFT/SOFT/PYROS_SOFT/CURRENT/config/config_unit_simulunit1.xml'
  604 + config_filename = cwd + '/config_unit_simulunit1.xml'
  605 + print("config_filename = {}\n".format(config_filename))
  606 +
184 607 # --- Instanciate an object for configuration
185   - config = ConfigPyros(config_filename)
186   - #config.set_configfile(config_filename)
  608 + config = ConfigPyros()
  609 + config.set_configfile(config_filename)
  610 +
187 611 if config.get_last_errno() != config.NO_ERROR:
188   - print("Error code = {}".format(config.get_last_errno()))
  612 +
  613 + print("Error {}. {}".format(config.get_last_errno(),config.get_last_errmsg()))
  614 +
189 615 else:
  616 +
190 617 # --- Load the configuration file if needed only (i.e. modified)
191 618 config.load()
192   - # --- get the parameter value of <mount1/localization/home>
193   - instanciation = 'mount1'
194   - section = 'localization'
195   - key = 'home'
196   - paramvalue = config.get_paramvalue(instanciation, section, key)
197   - print("paramvalue <{}/{}/{}> = {}".format(instanciation, section, key,paramvalue))
198   - #
199   - #print("unit_component_params = {}".format(unit_component_params))
200   - #component = unit_component_params[0]
201   - #params = component['params']
202   - #print("params = {}".format(params))
  619 +
  620 + if config.get_last_errno() != config.NO_ERROR:
  621 +
  622 + print("Error {}. {}".format(config.get_last_errno(),config.get_last_errmsg()))
  623 +
  624 + else:
  625 +
  626 + # --- Get the home of the mount[0]
  627 + mount_alias = config.get_aliases('mount')[0]
  628 + home = config.get_param(mount_alias,'MountPointing','home')
  629 + print("home= {}\n".format(home))
  630 +
  631 + # --- Get the serial number of the optics of the channel[0]
  632 + channel_alias = config.get_aliases('channel')[0]
  633 + optsn = config.get_paramvalue(channel_alias,'optic','serial_number')
  634 + print("Serial number {}\n".format(optsn))
  635 +
  636 + # --- Get the startmode of the AgentX
  637 + agent_alias = 'AgentX'
  638 + stmod = config.get_paramvalue(agent_alias,'general','startmode')
  639 + print("startmode {}\n".format(stmod))
  640 +
  641 + # --- Get all the assembly of this unit[0] (mount + channels)
  642 + unit_alias = config.get_aliases('unit')[0]
  643 + params = config.get_params(unit_alias)
  644 + print("params {} = {}\n".format(unit_alias,params))
  645 +
  646 + # --- Get the plan parameters for web pages of the channel[0]
  647 + channel_alias = config.get_aliases('channel')[0]
  648 + plans = config.get_plan(channel_alias)
  649 + print("Plan form = {}\n".format(plans))
  650 +
  651 + # --- Get the alias of this computer
  652 + print("Alias of this computer = {}\n".format(config.get_computer_alias()))
  653 +
  654 + # --- Get the password of the database
  655 + database_alias = config.get_aliases('database')[0]
  656 + paswds = config.get_param(database_alias,'access','pswd')
  657 + if paswds.get('unit',None) == 'crypted1':
  658 + paswd = config.decode(paswds['value'])
  659 + else:
  660 + paswd = paswds['value']
  661 + print("db paswd = {}\n".format(paswd))
  662 +
203 663 \ No newline at end of file
... ...