=============================================== How to use a device with inheritable admin mode =============================================== The ``ska-tango-base`` package provides :class:`.HeritableAdminModeMixin` that can be used to make a Tango device using the :class:`~._base_interface.BaseInterface` have an admin mode that can be automatically inherited from some parent device. All that is required by the Tango device developer to make this feature available is to inherit from the mixin. For example, the following is a minimal device with an inherited admin mode. .. code:: python class MyDevice(stb.future.HeritableAdminModeMixin, stb.future.BaseInterface): def init_device(self) -> None: super().init_device() self.init_completed() The rest of this guide discusses how users of the Tango device can set up and utilise admin mode inheritance. Configuring a parent -------------------- In order to use admin mode inheritance you must specify _where_ to inherit from, this is done by setting the :attr:`.ParentTRL` property. The value of the setting can be retrieved from the device via the read-only :attr:`.parentTRL` attribute. As with all properties, the device will not be notified if they are changed in the database and the setting can be reloaded from the database using the :func:`!Init()` command. For example, .. code:: shell-session In [1]: dp = DeviceProxy("foo/bar/1") In [2]: dp.parentTRL Out[2]: 'my/parent/1' In [3]: db = tango.Database() In [4]: db.put_device_property("foo/bar/1", {'ParentTRL': ['my/parent/2']}) In [5]: dp.parentTRL Out[5]: 'my/parent/1' In [6]: dp.Init() In [7]: dp.parentTRL Out[7]: 'my/parent/2' The :attr:`.ParentTRL` of a device can be empty (the default), in which case admin mode inheritance cannot be used. The INHERIT set-point --------------------- Devices supporting admin mode inheritance have an additional enum label, ``"INHERIT"`` compared to those that do not. .. code:: shell-session In [8]: dp.get_attribute_config("adminMode").enum_labels Out[8]: ['ONLINE', 'ENGINEERING', 'INHERIT'] This additional value cannot be read from the device, but can be used as a set-point to instruct the device to inherit from its parent. PyTango will allow you to set this using the string literal ``"INHERIT"``, the :class:`~ska_control_model.future.AdminMode` enumeration does not have this value. .. code:: shell-session In [9]: dp.adminMode = "INHERIT" In [9]: dp.adminMode Out[9]: The set-point can be read back using the index operator provided by PyTango to do a raw :func:`!read_attributes` invocation. Unfortanately, this will be the raw value which can be converted to a string using the :attr:`!enum_labels` found in the attribute configuration. .. code:: shell-session In [10]: dp["adminMode"].w_value Out[10]: 2 In [11]: dp.get_attribute_config("adminMode").enum_labels[2] Out[11]: 'INHERIT' It is also possible to determine if admin mode inheritance is active by reading the :attr:`inheritAdminMode ` attribute. .. code:: shell-session In [12]: dp.inheritAdminMode Out[12]: True If your device does not have a :attr:`.ParentTRL` set then setting the admin mode to ``"INHERIT"`` will be rejected: .. code:: shell-session In [13]: db.put_device_property("foo/bar/1", {'ParentTRL': ['']}) In [14]: dp.Init() In [15]: dp.adminMode = "INHERIT" STB_NotSupported: 'INHERIT' is not supported: No ParentTRL set (For more detailed information type: tango_error) Just as with the :class:`~._base_interface.BaseInterface`, the :attr:`.HeritableAdminModeMixin.adminMode` attribute is memorized, meaning the set-point is saved to the database and re-applied whenever the device server is restarted or the device is re-initialised. The default :attr:`~.HeritableAdminModeMixin.adminMode` set-point is ``"ENGINEERING"`` for devices with an empty :attr:`.ParentTRL` and ``"INHERIT"`` for devices with a non-empty :attr:`.ParentTRL`. .. warning:: If the memorized :attr:`~.HeritableAdminModeMixin.adminMode` is ``"INHERIT"`` and the :attr:`.ParentTRL` is empty when the device server is started then the :attr:`~.HeritableAdminModeMixin.adminMode` will always return an exception when read: .. code:: shell-session In [16]: dp.adminMode STB_NotSupported: 'INHERIT' is not supported: No ParentTRL set (For more detailed information type: tango_error) This can be cleared by either assigning ``"ONLINE"`` or ``"ENGINEERING"`` to the :attr:`~.HeritableAdminModeMixin.adminMode` or by providing a :attr:`.ParentTRL` and re-initialising the device with the :func:`!Init()` command. Similarly, if your device is re-initialised with the :func:`!Init()` command with an invalid database configuration, the :attr:`~.HeritableAdminModeMixin.adminMode` set-point will be rejected and the default of ``"ENGINEERING"`` will be used. Connection status reporting --------------------------- While your device is inheriting its admin mode, it will monitor the health of the connection to the parent device. The status of this connection can be retrieved via the :attr:`.parentConnectionStatus` attribute: .. code:: shell-session In [17]: dp.parentConnectionStatus Out[17]: This will return a :class:`~ska_control_model.CommunicationStatus` that will be: - :class:`DISABLED ` if the admin mode is not being inherited - :class:`ESTABLISHED ` if the admin mode is being inherited and we have recieved a value from the parent device - :class:`NOT_ESTABLISHED ` if the admin mode is being inherited but we have received error events while trying to monitor the parent device Initially, while the connection status is :class:`NOT_ESTABLISHED ` the admin mode will be reported as the last known good value: .. code:: shell-session In [18]: dp.parentConnectionStatus Out[18]: In [19]: dp.adminMode Out[19]: After a continuous period of failing to monitor the parent device the :attr:`.parentConnectionStatus` attribute will report a qulaity factor of :class:`ATTR_ALARM ` and the :attr:`~.HeritableAdminModeMixin.adminMode` will report a quality factor of :class:`ATTR_INVALID ` and therefore have no value: .. code:: shell-session In [20]: dp["parentConnectionStatus"].quality Out[20]: In [21]: dp["adminMode"].quality Out[21]: In [22]: dp.parentConnectionStatus Out[22]: In [23]: print(dp.adminMode) None .. warning:: Unfortunately, due to limitations in Tango the write value of the :attr:`~.HeritableAdminModeMixin.adminMode` will also be ``None``, however, the :attr:`.inheritAdminMode` boolean will still correctly report ``True``: .. code:: shell-session In [24]: print(dp["adminMode"].w_value) None In [25]: dp.inheritAdminMode Out[25]: True When :attr:`.parentConnectionStatus` has a quality factor of :class:`ATTR_ALARM `, setting the device's admin mode to ``"ONLINE"`` or ``"ENGINEERING"`` will stop the device from attempting to communicate with its parent and will clear the alarm: .. code:: shell-session In [26]: dp.adminMode = "ONLINE" In [27]: dp.parentConnectionStatus Out[27]: In [28]: dp.adminMode Out[28]: The time it takes for the parent connection to trigger an alarm is configured with the :attr:`.ParentConnectionTimeout` property and can be read from the device with the :attr:`.parentConnectionTimeout` attribute. As always, :func:`!Init()` is requried to reload this setting from the datbase: .. code:: shell-session In [29]: dp.parentConnectionTimeout Out[29]: 60.0 In [30]: db.put_device_property("foo/bar/1", {'ParentConnectionTimeout': ['10']}) In [31]: dp.Init() In [32]: dp.parentConnectionTimeout Out[32]: 10.0