======================================= Mpod device code implementation details ======================================= Details of the code implementation are given. The idea is to get the reader to the a level where coding solutions can be understood and changes can be made efficiently. Updating property values ------------------------ The device.py bound api base class inherited by mpod.py does not, apologies if wrong, impose a policy of not sending 'unchanged' property values. Hence, mpod.py overwrites set() with a version that removes unchanged properties from the (key, value or hash) input parameters before calling the base class set(). An 'unchanged' channel (V,I) value is defined by the channel state. When the channel has reached a constant state (ON or OFF, TRIPPED, ERROR) values are defined to be 'unchanged'. In other states property value changes are not 'unchanged' and will be updated. Special treatment of some ISEG HV channel properties ---------------------------------------------------- OutputSupervisionMinSenseVoltage, OutputSupervisionMaxSenseVoltage and OutputSupervisionMaxPower properties are reported as "not-a-number" (nan). As such their values, if any, cannot be read or set. This constellation is probably related to f/w and h/w of HV channels - there is no sense measurement and power is not an issue for very low current HV channels. The same read/set issues are present when snmpget/set tools are used, therefore the problem is unlikely to be psynmp or the related karabo s/w implementation. OutputSupervisionMaxTerminalVoltage for negative supplies can only be read and set as a positive number. This is also seen when using snmpget/get. :: $ pwd /home/xbeam/cy_caslab_work/snmp/ireasoning/mibbrowser $ snmpget -v 2c -M mibs -m WIENER-CRATE-MIB -c guru exflqr18568 outputConfigMaxTerminalVoltage.u1 WIENER-CRATE-MIB::outputConfigMaxTerminalVoltage.u1 = Opaque: Float: -10000.000000 V $ snmpget -v 2c -M mibs -m WIENER-CRATE-MIB -c guru exflqr18568 outputSupervisionMaxTerminalVoltage.u1 WIENER-CRATE-MIB::outputSupervisionMaxTerminalVoltage.u1 = Opaque: Float: 10000.000000 V $ snmpset -v 2c -M mibs -m WIENER-CRATE-MIB -c guru exflqr18568 outputSupervisionMaxTerminalVoltage.u1 F -10000.0 WIENER-CRATE-MIB::outputSupervisionMaxTerminalVoltage.u1 = Opaque: Float: 10000.000000 V $ snmpset -v 2c -M mibs -m WIENER-CRATE-MIB -c guru exflqr18568 outputSupervisionMaxTerminalVoltage.u1 F -5000.0 WIENER-CRATE-MIB::outputSupervisionMaxTerminalVoltage.u1 = Opaque: Float: 10000.000000 V $ snmpget -v 2c -M mibs -m WIENER-CRATE-MIB -c guru exflqr18568 outputSupervisionMaxTerminalVoltage.u1 WIENER-CRATE-MIB::outputSupervisionMaxTerminalVoltage.u1 = Opaque: Float: 10000.000000 V The side-effect of this is that outputConfigMaxTerminalVoltage (the channel's maximum output voltage which is fixed by the manufacturer has -ve or +ve parity) absolute value is used as the maxInc limit on outputSupervisionMaxTerminalVoltage with the minInc value set to 0.0. ``Target voltage`` maxInc and minInc limit values are set to the value of outputSupervisionMaxTerminalVoltage with the sign defined by outputConfigMaxTerminalVoltage. Special treatment of V and I set values, their s/w limits and h/w actions ------------------------------------------------------------------------- This section describes how: * s/w limit properties are used to limit the maximum and minimum settable values of ``Target voltage`` and ``Maximum current`` properties via their maxInc and minInc attribute. * s/w limits can be used to define the threshold V or I value which when exceeded will cause the controller's f/w to act on the channel output, e.g. to turn the channel OFF. This activity is referred to as supervision-behaviour in the mpod manual. Channel supervision-behaviour is easier to understand by breaking it down into two parts: * the supervisor evaluates *if channel-value exceeds threshold-value* clauses for fault conditions: * MinSenseVoltageFailure - LV channels * MaxSenseVoltageFailure - LV channels * MaxTerminalVoltageFailure - LV and HV channels * MaxCurrentFailure - LV and HV channels * MaxTemperatureFailure - LV and HV(?) channels * MaxPowerFailure - LV channels * InhibitFailure - LV channels * TimeoutFailure - LV(?) and HV channels * the action performed if the clause is True can be: * ignore * channelOff * groupOff * crateOff The supervisor continuously evaluates all clauses of all channels and ``supervisionBehaviorCheckBox`` should be used to set the action required per channel to avoid unexpected behaviour. As indicated not all clauses apply to both LV and HV (no 4-wire sense measurement, etc) channels and where not applicable their actions should be set to *ignore*. The above discussion exposes a triple property partition * operation properties, the values of which the operator would like to set * ``Target voltage`` is the operator specified channel target voltage when the channel is ON. * ``Maximum current`` is the operator specified maximum current the channel can drive when ON. * applied limit properties, which define maxInc, minInc, and behaviour * ``s/w (max) applied V limit`` is the s/w limit of the channel sense voltage * ``s/w (max abs) applied V limit`` is the s/w limit of the channel terminal voltage * ``s/w (max) applied I limit`` is the s/w limit of the channel current * supply maximum properties fixed by the board h/w capabilities * ``h/w (max) supplied V limit`` is the maximum channel voltage the supply h/w can deliver. * ``h/w (max) supplied I limit`` is the maximum channel current the supply h/w can deliver. * ``SupervisionBehavior in words`` lists all actions applied to the channel. Note that MinSenseVoltageFailure channel maxInc, minInc attribute setting is not yet implemented in mpod.py. ``Maximum current`` LV and HV channel maxInc, minInc attribute and behaviour value sources: +----------------------+------------------------------+-----------------------+ |**LimitSource** |**Property attribute set** |**to value of** | +----------------------+------------------------------+-----------------------+ | VENDOR | supervisionMaxCurrent MaxInc | configMaxCurrent | + +------------------------------+-----------------------+ | | supervisionMaxCurrent MinInc | 0.0 | + +------------------------------+-----------------------+ | | current MaxInc | configMaxCurrent | + +------------------------------+-----------------------+ | | current MinInc | 0.0 | +----------------------+------------------------------+-----------------------+ | USER | supervisionMaxCurrent MaxInc | configMaxCurrent | + +------------------------------+-----------------------+ | | supervisionMaxCurrent MinInc | 0.0 | + +------------------------------+-----------------------+ | | current MaxInc | supervisionMaxCurrent | + +------------------------------+-----------------------+ | | current MinInc | 0.0 | +----------------------+------------------------------+-----------------------+ ``Target voltage`` LV channel maxInc, minInc attribute and behaviour value sources: +----------------------+------------------------------------+----------------------------+ |**LimitSource** |**Property attribute set** |**to value of** | +----------------------+------------------------------------+----------------------------+ | VENDOR | supervisionMaxSenseVoltage MaxInc | configMaxSenseVoltage | + +------------------------------------+----------------------------+ | | supervisionMaxSenseVoltage MinInc | 0.0 | + +------------------------------------+----------------------------+ | | voltage MaxInc | configMaxSenseVoltage | + +------------------------------------+----------------------------+ | | voltage MinInc | 0.0 | +----------------------+------------------------------------+----------------------------+ | USER | supervisionMaxSenseVoltage MaxInc | configMaxSenseVoltage | + +------------------------------------+----------------------------+ | | supervisionMaxSenseVoltage MinInc | 0.0 | + +------------------------------------+----------------------------+ | | voltage MaxInc | supervisionMaxSenseVoltage | + +------------------------------------+----------------------------+ | | voltage MinInc | 0.0 | +----------------------+------------------------------------+----------------------------+ ``Target voltage`` HV channel behaviour value sources: +----------------------+--------------------------------------+---------------------------------------+ |**LimitSource** |**Property attribute set** |**to value of** | +----------------------+--------------------------------------+---------------------------------------+ | VENDOR | supervisionMaxTerminalVoltage MaxInc | fabs(configMaxTerminalVoltage) + 0.15 | + +--------------------------------------+---------------------------------------+ | | supervisionMaxTerminalVoltage MinInc | -0.15 | +----------------------+--------------------------------------+---------------------------------------+ | USER | supervisionMaxTerminalVoltage MaxInc | fabs(configMaxTerminalVoltage) + 0.01 | + +--------------------------------------+---------------------------------------+ | | supervisionMaxTerminalVoltage MinInc | -0.01 | +----------------------+--------------------------------------+---------------------------------------+ ``Target voltage`` HV -ve channel maxInc and minInc value sources: +----------------------+---------------------------+---------------------------------------------------+ |**LimitSource** |**Property attribute set** |**to value of** | +----------------------+---------------------------+---------------------------------------------------+ | VENDOR | voltage MaxInc | 0.01 | + +---------------------------+---------------------------------------------------+ | | voltage MinInc | -1.0 * fabs(configMaxTerminalVoltage) + 0.01 | +----------------------+---------------------------+---------------------------------------------------+ | USER | voltage MaxInc | 0.01 | + +---------------------------+---------------------------------------------------+ | | voltage MaxInc | -1.0 * fabs(supervisionMaxTerminalVoltage) + 0.01 | +----------------------+---------------------------+---------------------------------------------------+ ``Target voltage`` HV +ve channel maxInc and minInc value sources: +----------------------+---------------------------+-------------------------------------+ |**LimitSource** |**Property attribute set** |**to value of** | +----------------------+---------------------------+-------------------------------------+ | VENDOR | voltage MaxInc | fabs(configMaxTerminalVoltage) | + +---------------------------+-------------------------------------+ | | voltage MinInc | -0.01 | +----------------------+---------------------------+-------------------------------------+ | USER | voltage MaxInc | fabs(supervisionMaxTerminalVoltage) | + +---------------------------+-------------------------------------+ | | voltage MaxInc | -0.01 | +----------------------+--------------------+--------------------------------------------+ Controlling maxInc and minInc attribute setting whilst STARTING ``````````````````````````````````````````````````````````````` Processing in the STARTING state provides two phases during which attributes can be set. * Phase 1. immediately following crate board channel discovery when the crate's currently set values, i.e. those in NVRAM, are used. * Phase 2. later when a saved configuration is loading, which may not have the same values set as those previously found in NVRAM. Which attribute values are set when mpod.py enters ACTIVE is controlled by properties shown in the picture of mpod.py's configuration view below. Phase 1 control is via ``V limit source`` and ``I limit source``, where * NONE - sets no attributes * VENDOR - sets supply maximum property values to both operation and applied limit properties * USER - sets applied limit properties to operation, and supply maximum values to applied mimit properties. Phase 2 control is via ``Loadfile limit source``, where * NONE = do not update attribute values * USER = set values found in the configuration load file Phase 2 is disabled if ``Load channel configs`` is False. |vi_attributes| Controlling maxInc and minInc attribute setting whilst ACTIVE ````````````````````````````````````````````````````````````` GUI and CLI client requested value changes to operation and applied limit properties mpod.py use preReconfigure() code to insert maxInc and minInc attributes according according to the USER definition shown in the tables above. Loading a configuration file applies maxInc, minInc attribute and behaviour value sources as in STARTING Phase 2. Whilst ACTIVE the value of ``Load channel configs`` is ignored. .. |vi_attributes| image:: VI_attribute_insertion.png Controlling behaviour settings during STARTING and whilst ACTIVE ```````````````````````````````````````````````````````````````` The values of a s/w applied property is not controlled by property flags. The Phase 1 NVRAM value found is used unless updated by Phase 2 or GUI/CLU requests. More importantly the behaviour action follows the same pattern. Special treatment of LV channel User Config settings ---------------------------------------------------- Control of LV channel voltage regulation and external interlock is performed through setting or clearing bits in a f/w RW integer. The s/w device uses the ChannelUserConfig (derived from MpodCsrBitEnum(Enum)) to manipulate the set and clear: :: >>> from enum import Enum, unique >>> from mpodConstants import * >>> [print(x) for x in ChannelUserConfig] name bitNoOffRampdown mask 0x1 rbox 0x1 rdef 0x0 rest 0xfffffffe desc "Bit 0: No voltage rampdown at switch off" name bitRegulation1to30m mask 0x2 rbox 0xe rdef 0x8 rest 0xfffffff1 desc "Bit 1: Output regulation for 1 to 30 meter cables" name bitRegulationAbove30m mask 0x4 rbox 0xe rdef 0x8 rest 0xfffffff1 desc "Bit 2: Output regulation for 30+ meter cables" name bitRegulationOutputVoltage mask 0x8 rbox 0xe rdef 0x8 rest 0xfffffff1 desc "Bit 3: Output regulation for short or no cables (sense loopback)" name bitExternalInhibitEnabled mask 0x10 rbox 0x10 rdef 0x0 rest 0xffffffef desc "Bit 4: External inhibit enabled" name bitDisableGlobalInhibit mask 0x20 rbox 0x20 rdef 0x0 rest 0xffffffdf desc "Bit 5: Disable global inhibit" name bitAutomaticPowerOn mask 0x40 rbox 0x40 rdef 0x0 rest 0xffffffbf desc "Bit 6: Automatically power on after main switch on" .. warning:: Bit 3 should be set when cables less than 1 meter and when no cables are connected. Additionally connecting longer cables at the supply but not at the load can cause unexpected behaviour if the the 4-wire sense measurement lines are not connected directly at the load connector as the sense feedback is then broken. .. note:: The Mpod manual definitions for Bit 1 thru 3 are strange and their implementation in the s/w device is as follows. The setting where Bit 1 and 2 are both set is not allowed - the manual states that this setting should not be used, the s/w does not allow both to be set. The setting where Bit 1 and 2 are both clear is for cables of less than 1 meter, the s/w does not allow both to be clear, instead Bit 4 has to be used. Bits 1 thru 3 requiring radio-box functionality, one and only one must be set. Bits 0 and 4-6 require check-box functionality. It would be attractive to do both selections in a combined GUI-client widget sending the resulting integer to the client, but this is not supported in the GUI and might be difficult in a CLI-client. Instead the following s/w device properties are used to emulate radio- and check-box functionality: * ``userConfig``, a readOnly integer containing the bit settings written to and read from the crate controller. * ``userConfigCheckBox``, a node of reconfigurable booleans one per user bit definition. This requires additional device side code * preReconfigure() - bit value change requests are caught, their content (set or clear) are integrated into ``userConfig``, with bit 3 set if bits 1 and 2 are clear. If ``userConfig`` changes, then both it and additionally changed bits, i.e. bit 3, are added to the incoming hash for setting on preConfiguration return. The changed ``userConfig`` is also sent to the f/w. * preReconfigure() - the bit handling implemented should provide similar results for CLI- and GUI-clients. The single action of clearing a radio-box bit can have a side-effect of setting a default bit. Setting or clearing multiple bits is implemented by blocking all changes to separate channels together. * pollingmpod() - the read ``userConfig`` value is decomposed into all ``userConfigCheckBox`` property values. All are set. Note that no attempt is made to apply a correct bit 1 thru 3 (radio-box) setting, this is delegated to the configuration application stage. .. warning:: In initial device s/w versions only ``userConfig`` was present and consequently reconfigurable, but with the introduction of ``userConfigCheckBox`` it is now readOnly. Special treatment of HV and LV channel Supervision Behavior settings -------------------------------------------------------------------- Control of how the controller f/w reacts when channel properties exceed or undercut threshold values is controlled by the ``supervisionBehavior`` status word. Two bit fields are associated with the channels reaction to MinSenseVoltage, MaxSenseVoltage, MaxTerminalVoltage, MaxCurrent, MaxTemperature, MaxPower, Inhibit and Timeout failures. For LV channels the 2 bit fields have the following meaning: 0x0 = ignore failure, 0x1 = switch channel off, 0x2 = switch all channels with the same group number off, and 0x3 = switch off the complete crate. For HV channels 0x0 = ignore, 0x1 = switch channel off by ramping down, 0x2 = switch channel off with 'Emergency off', and 0x3 switch entire board off with 'Emergency off'. A similar implementation route has been taken by expanding the 2-bit field values into 4 check-box booleans, using s/w device properties * ``supervisionBehavior``, a readOnly integer containing the bit settings written to and read from the crate controller. * ``supervisionBehaviorCheckBox``, a node of reconfigurable booleans one per user action definition. Controlling channel property exposure and whether readOnly or reconfigurable ---------------------------------------------------------------------------- Channel property schema definition functions are in ``vchannel.py``. Which definition, readonly (RO) or reconfigurable (RW), is used for a LV or HV channel and whether it is exposed (applied) is determined by the ``type`` property setting before application instantiation. The value of ``type`` selects which (defined by an expert) list of properties are used. The ``type`` property lists are defined in the ChannelViews class in ``mpodViewables.py``. The definitions used in ``vchannel.py`` and ``mpodViewables.py`` allow the lists of properties to be built without error if an auto-complete editor is used based on the schema insertion function name which is a concatenation of the key name of the property, whether it is readOnly or reconfigurable, and whether it is applied to LV or HV channels. Lists containing voltage_RO_HV will result in readOnly 'voltage' key properties appearing in a HV channel configurator panel view. The s/w device's channel schemas are rebuilt according to the property list chosen and injected during transition through the STARTING state by ``mpodRebuildSchema()`` which additionally adds dependencies and must-be-present properties, removes identical duplicates, and removes lesser precedence property definitions (as required). Required property dependencies are added into the list immediately before the property requiring them. Must-be-properties are added to the tail of the list. Duplicate properties have their tail end instance removed. Lesser precedence (RO) are removed keeping the higher precedence (RW) properties. The ordering of adding and removing properties aims at producing a GUI-client configurator panel which should be as close as possible to that aimed at by the specifier of the list. Simple awk scripts are useful if internals of ``mpodViewables.py`` require modification due to changes in ``vchannel.py`` follow. :: $ grep 'def sf' vchannel.py | awk -F ' ' '{print $2}' | awk -F '(' '{print $1}' | awk -F '_' '{print $2"_"$3"_"$4}' | awk -F '_' '/_LV/ {print " "$0" = (sf_"$0", \""$1"\", True, False, [], None)"; next}; /_HV/ {print " "$0" = (sf_"$0", \""$1"\", False, True, [], None)"; next}' | sort produces output like :: voltage_RO_HV = (sf_voltage_RO_HV, "voltage", False, True, [], None) voltage_RO_LV = (sf_voltage_RO_LV, "voltage", True, False, [], None) which can be pasted directly into ``mpodViewables.py``. Similarly, for imports :: $ grep 'def sf' vchannel.py | awk -F ' ' '{print $2}' | awk -F '(' '{print " "$1","}' | sort The decision to itemize property schema definitions and provide ``type`` lists of properties results partially from the lack of access authorization limits to the UI-Clients 'who-sees-what' property access mechanism. If the latter appears then the special treatment outlined here may collapse into a single list. Channel ON/OFF 'switch' and 'operator' differences -------------------------------------------------- ``switch`` and ``operator`` properties (displayed names "Switch" and "Operator's switch", respectively) are used to request change of channel state, i.e. turn ON, OFF, etc. The channel ``operator`` property shadows the ``switch`` property and provides a text version ('off', 'on',...) of the latter (0, 1,...). UI-Client changes to either are applied automatically to the other. There is however a difference, ``switch`` is directly coupled to the RW register of the channel's f/w and is updated on every poll cycle and currently ``switch`` updates are not applied to ``operator``. The reason lies in the different handling of actions initiated. LV and HV channel ``switch`` stable state values are 0 and 1 indicating OFF and ON, respectively, but when turn ON or OFF actions are requested the following is found: * For LV channels: * To turn an ON channel OFF requires setting ``switch`` = 0, the request is granted, but the f/w sets ``switch`` back to 1 until the channel is OFF. * For HV channels: * the value of ``switch`` remains as requested throughout the action Not applying ``switch`` f/w updates to ``operator`` provides the operator with a WYSIWYG view of the last channel request action and alignment of ``switch`` and ``operator`` is required only on entering the ACTIVE state.