diff --git a/docs/source/State_Machine.rst b/docs/source/State_Machine.rst index 95039a0259ba3546044ecaa4e50acaad523a97e6..d193e154250d4e4643c190cf7508faa798b96cf1 100644 --- a/docs/source/State_Machine.rst +++ b/docs/source/State_Machine.rst @@ -2,36 +2,131 @@ State Machine ============= -The state machine modules implements SKA's two fundamental state machines: the -base device state machine, and the observation state machine. +The state machine module implements three fundamental SKA state +machines: + +* the admin mode state machine +* the operational state (opState, represented in TANGO devices by TANGO + state) state machine +* the observation state machine. + +Admin mode state machine +------------------------ +The admin mode state machine allows for transitions between the five +administrative modes: + +* NOT_FITTED: this is the lowest state of readiness, representing + devices that cannot be deployed without some external action, such as + plugging hardware in or updating network settings.) +* RESERVED: the device is fitted but redundant to other devices. It is + ready to take over should other devices fail. +* OFFLINE: the device has been declared by SKA operations not currently + to be used for operations (or whatever other function it provides) +* MAINTENANCE: the device cannot be used for science purposes but can be + operationed for engineering / maintenance purposes, such as testing, + debugging, etc +* ONLINE: the device can be used for science purposes. + +The admin mode state machine allows for + +* any transition between the modes NOT_FITTED, RESERVED and OFFLINE + (e.g. an unfitted device being fitted as a redundant or non-redundant + device, a redundant device taking over when another device fails, etc) +* any transition between the modes OFFLINE, MAINTENANCE and ONLINE (e.g. + an online device being taken offline or put into maintenance mode to + diagnose a fault, a faulty device moving between maintenance and + offline mode as it undergoes sporadic periods of diagnosis. + +Diagrams of the admin mode state machine are shown below. + +.. figure:: images/AdminModeStateMachine.png + :alt: Diagram of the admin mode state machine, as designed + + Diagram of the admin mode state machine, as designed + + +.. + COMMENTED OUT FOR NOW + .. figure:: images/AdminModeStateMachine_autogenerated.png + :alt: Diagram of the admin mode state machine, as implemented + + Diagram of the admin mode state machine, automatically generated from + the implementation. The equivalence of this diagram to the diagram + above demonstrates that the machine has been implemented as designed. + + +Operational state state machine +------------------------------- +The operational state (opState) machine represents the operational state +of a SKA device. It is represented in TANGO devices using the TANGO +"state", so the states used are a subset of the TANGO states: INIT, +FAULT, DISABLE, STANDBY, OFF and ON. + +* INIT: the device is currently initialising +* FAULT: the device has experienced an error from which it could not + recover. +* DISABLE: the device is in its lowest state of readiness, from which + it may take some time to become fully operational. For example, if the + device manages hardware, that hardware may be switched off. +* STANDBY: the device is unready, but can be made ready quickly. For + example, if the device manages hardware, that hardware may be in a + low-power standby mode. +* OFF: the device is fully operational but is not currently in use +* ON: the device is in use + +The operational state state machine allows for: + +* transition from INIT or FAULT into any of the three "readiness states" + DISABLE, STANDBY and OFF. +* all transitions between these three "readiness states" DISABLE, + STANDBY and OFF. +* transition between OFF and ON. + +.. figure:: images/OperationalStateStateMachine_decoupled.png + :alt: Diagram of the operational state state machine, as designed, + ignoring coupling with admin mode + + Diagram of the operational state (opState) state machine, as + designed, ignoring coupling with admin mode + +Unfortunately, operational state is inextricably coupled with admin +mode: there are admin modes that imply disablement, and operational +states such as ON should not be possible in such admin modes. + +To facilitate this, the entire operational state state machine is +accessible only when the admin mode is ONLINE or MAINTENANCE. When in +any other admin mode, the only permitted operational states are INIT, +FAULT and DISABLE. This constraint is implemented into the operational +state state machine by + +* three extra states: INIT_ADMIN, FAULT_ADMIN and DISABLED_ADMIN +* two extra transition triggers: "admin_on" and "admin_off", which allow + for transition between INIT and INIT_ADMIN; FAULT and FAULT_ADMIN; and + DISABLE and DISABLE_ADMIN. + +This implementation minimises the coupling between admin mode and +operational state, allowing the two machines to be conceptualised almost +separately. + +Diagrams of the operational state state machine are shown below. + +.. figure:: images/OperationalStateStateMachine_coupled.png + :alt: Diagram of the operational state state machine, as designed, + showing coupling with admin mode + + Diagram of the operational state (opState) state machine, as + designed, showing coupling with admin mode + +.. + COMMENTED OUT FOR NOW + .. figure:: images/OperationalStateStateMachine_coupled_autogenerated.png + :width: 80% + :alt: Diagram of the admin operational state state machine, as implemented -Base device state machine -------------------------- -The base device state machine provides basic state needed for all devices, -covering initialisation, off and on states, and a fault state. This state -machine is implemented by all SKA Tango devices that inherit from these LMC -base classes, though some devices with standby power modes may need to -implement further states. - - -.. figure:: images/device_state_diagram.png - :width: 80% - :alt: Diagram of the device state machine, taken from SKA design - documentation, showing the state machine as designed - - Diagram of the device state machine, taken from SKA design - documentation, showing the state machine as designed - - -.. figure:: images/DeviceStateMachine.png - :width: 80% - :alt: Diagram of the device state machine, automatically generated - from the state machine as specified in code. - - Diagram of the device state machine, automatically generated from the - state machine as specified in code. The equivalence of this diagram to - the diagram previous demonstrates that the machine has been - implemented as designed. + Diagram of the operational state state machine, automatically + generated from the implementation. The equivalence of this diagram + to the diagram above demonstrates that the machine has been + implemented as designed. Observation state machine @@ -39,22 +134,24 @@ Observation state machine The observation state machine is implemented by devices that manage observations (currently only subarray devices). -.. figure:: images/ADR-8.png +.. figure:: images/ObservationStateMachine_adr8.png :width: 80% - :alt: Diagram of the observation state machine, as decided and published in ADR-8. + :alt: Diagram of the observation state machine, as decided and + published in ADR-8. - Diagram of the observation state machine, as decided and published in ADR-8. + Diagram of the observation state machine, as decided and published in + ADR-8. -.. figure:: images/ObservationStateMachine.png +.. figure:: images/ObservationStateMachine_autogenerated.png :width: 80% - :alt: Diagram of the observation state machine, automatically generated from - the state machine as specified in code. + :alt: Diagram of the observation state machine, automatically + generated from the implementation Diagram of the observation state machine, automatically generated from - the state machine as specified in code. The equivalance of this - diagram to the diagram previous demonstrates that the machine has been - implemented in conformance with ADR-8. + the implementation. The equivalance of this diagram to the diagram + previous demonstrates that the machine has been implemented in + conformance with ADR-8. API --- diff --git a/docs/source/images/AdminModeStateMachine.png b/docs/source/images/AdminModeStateMachine.png new file mode 100644 index 0000000000000000000000000000000000000000..6351a89cf21b929414bfdaa2ca37028d77a32591 Binary files /dev/null and b/docs/source/images/AdminModeStateMachine.png differ diff --git a/docs/source/images/DeviceStateMachine.png b/docs/source/images/DeviceStateMachine.png deleted file mode 100644 index 805ed112bc4811383278bea4d00c88768580c7c1..0000000000000000000000000000000000000000 Binary files a/docs/source/images/DeviceStateMachine.png and /dev/null differ diff --git a/docs/source/images/ADR-8.png b/docs/source/images/ObservationStateMachine_adr8.png similarity index 100% rename from docs/source/images/ADR-8.png rename to docs/source/images/ObservationStateMachine_adr8.png diff --git a/docs/source/images/ObservationStateMachine.png b/docs/source/images/ObservationStateMachine_autogenerated.png similarity index 100% rename from docs/source/images/ObservationStateMachine.png rename to docs/source/images/ObservationStateMachine_autogenerated.png diff --git a/docs/source/images/OperationalStateStateMachine_coupled.png b/docs/source/images/OperationalStateStateMachine_coupled.png new file mode 100644 index 0000000000000000000000000000000000000000..69578bf657860094ad6a16af0eb304e3cfd5b499 Binary files /dev/null and b/docs/source/images/OperationalStateStateMachine_coupled.png differ diff --git a/docs/source/images/OperationalStateStateMachine_decoupled.png b/docs/source/images/OperationalStateStateMachine_decoupled.png new file mode 100644 index 0000000000000000000000000000000000000000..057aef047390af60da94e7d574ad6c876b8b36cd Binary files /dev/null and b/docs/source/images/OperationalStateStateMachine_decoupled.png differ diff --git a/docs/source/images/device_state_diagram.png b/docs/source/images/device_state_diagram.png deleted file mode 100644 index 839caca46bad985fb1d6b59e5e6728e2d1ca5a35..0000000000000000000000000000000000000000 Binary files a/docs/source/images/device_state_diagram.png and /dev/null differ diff --git a/src/ska/base/base_device.py b/src/ska/base/base_device.py index ab5047ad8ea67bd02274958d7da83a5fc8a1860c..f7a243544d727f8b8205a48bc1f86bb6aba037c6 100644 --- a/src/ska/base/base_device.py +++ b/src/ska/base/base_device.py @@ -421,7 +421,7 @@ class DeviceStateModel: "to_notfitted": ("admin_on", "to_notfitted"), "to_offline": ("admin_on", "to_offline"), "to_maintenance": ("admin_off", "to_maintenance"), - "to_online": ("admin_off", "to_maintenance"), + "to_online": ("admin_off", "to_online"), "init_started": ("init_started", None), "init_succeeded_disable": ("init_succeeded_disable", None), "init_succeeded_standby": ("init_succeeded_standby", None), diff --git a/src/ska/base/state_machine.py b/src/ska/base/state_machine.py index cabbe667ff447a7ad4719fabd5d8722196fada7f..6bd7d7c6e064e22a2925ba6824b1695befc8f5b8 100644 --- a/src/ska/base/state_machine.py +++ b/src/ska/base/state_machine.py @@ -222,7 +222,7 @@ class AdminModeStateMachine(Machine): states = ["RESERVED", "NOT_FITTED", "OFFLINE", "MAINTENANCE", "ONLINE"] transitions = [ { - "source": "NOT_FITTED", + "source": ["NOT_FITTED", "OFFLINE"], "trigger": "to_reserved", "dest": "RESERVED", }, @@ -232,17 +232,17 @@ class AdminModeStateMachine(Machine): "dest": "NOT_FITTED", }, { - "source": ["NOT_FITTED", "MAINTENANCE", "ONLINE"], + "source": ["RESERVED", "NOT_FITTED", "MAINTENANCE", "ONLINE"], "trigger": "to_offline", "dest": "OFFLINE", }, { - "source": "OFFLINE", + "source": ["OFFLINE", "ONLINE"], "trigger": "to_maintenance", "dest": "MAINTENANCE", }, { - "source": "OFFLINE", + "source": ["OFFLINE", "MAINTENANCE"], "trigger": "to_online", "dest": "ONLINE", }, diff --git a/tests/data/admin_mode_state_machine.json b/tests/data/admin_mode_state_machine.json index 947639ad7ad9429f6b1c5c455507a9359b61801e..099223b1fb5e0bfd432888c4854027240f8a5e65 100644 --- a/tests/data/admin_mode_state_machine.json +++ b/tests/data/admin_mode_state_machine.json @@ -7,11 +7,6 @@ "ONLINE": {} }, "transitions": [ - { - "from": "RESERVED", - "to": "NOT_FITTED", - "trigger": "to_notfitted" - }, { "from": "NOT_FITTED", "to": "RESERVED", @@ -22,6 +17,21 @@ "to": "OFFLINE", "trigger": "to_offline" }, + { + "from": "RESERVED", + "to": "NOT_FITTED", + "trigger": "to_notfitted" + }, + { + "from": "RESERVED", + "to": "OFFLINE", + "trigger": "to_offline" + }, + { + "from": "OFFLINE", + "to": "RESERVED", + "trigger": "to_reserved" + }, { "from": "OFFLINE", "to": "NOT_FITTED", @@ -42,10 +52,20 @@ "to": "OFFLINE", "trigger": "to_offline" }, + { + "from": "MAINTENANCE", + "to": "ONLINE", + "trigger": "to_online" + }, { "from": "ONLINE", "to": "OFFLINE", "trigger": "to_offline" + }, + { + "from": "ONLINE", + "to": "MAINTENANCE", + "trigger": "to_maintenance" } ] } \ No newline at end of file diff --git a/tests/data/device_state_machine.json b/tests/data/device_state_machine.json index e74847ebfe7b83ef905431a4db81f167fb002044..503c6b7487988fcc769b40cacf4d04995aea6cbf 100644 --- a/tests/data/device_state_machine.json +++ b/tests/data/device_state_machine.json @@ -91,6 +91,11 @@ "to": "INIT_OFFLINE", "trigger": "to_offline" }, + { + "from": "INIT_MAINTENANCE", + "to": "INIT_ONLINE", + "trigger": "to_online" + }, { "from": "INIT_MAINTENANCE", "to": "DISABLE_MAINTENANCE", @@ -116,6 +121,11 @@ "to": "FAULT_MAINTENANCE", "trigger": "fatal_error" }, + { + "from": "INIT_ONLINE", + "to": "INIT_MAINTENANCE", + "trigger": "to_maintenance" + }, { "from": "INIT_ONLINE", "to": "INIT_OFFLINE", @@ -156,6 +166,11 @@ "to": "INIT_MAINTENANCE", "trigger": "to_maintenance" }, + { + "from": "INIT_OFFLINE", + "to": "INIT_RESERVED", + "trigger": "to_reserved" + }, { "from": "INIT_OFFLINE", "to": "INIT_NOTFITTED", @@ -206,6 +221,11 @@ "to": "INIT_NOTFITTED", "trigger": "to_notfitted" }, + { + "from": "INIT_RESERVED", + "to": "INIT_OFFLINE", + "trigger": "to_offline" + }, { "from": "INIT_RESERVED", "to": "DISABLE_RESERVED", @@ -226,6 +246,11 @@ "to": "FAULT_OFFLINE", "trigger": "to_offline" }, + { + "from": "FAULT_MAINTENANCE", + "to": "FAULT_ONLINE", + "trigger": "to_online" + }, { "from": "FAULT_MAINTENANCE", "to": "DISABLE_MAINTENANCE", @@ -256,6 +281,11 @@ "to": "FAULT_OFFLINE", "trigger": "to_offline" }, + { + "from": "FAULT_ONLINE", + "to": "FAULT_MAINTENANCE", + "trigger": "to_maintenance" + }, { "from": "FAULT_ONLINE", "to": "DISABLE_ONLINE", @@ -291,6 +321,11 @@ "to": "FAULT_MAINTENANCE", "trigger": "to_maintenance" }, + { + "from": "FAULT_OFFLINE", + "to": "FAULT_RESERVED", + "trigger": "to_reserved" + }, { "from": "FAULT_OFFLINE", "to": "FAULT_NOTFITTED", @@ -341,6 +376,11 @@ "to": "FAULT_NOTFITTED", "trigger": "to_notfitted" }, + { + "from": "FAULT_RESERVED", + "to": "FAULT_OFFLINE", + "trigger": "to_offline" + }, { "from": "FAULT_RESERVED", "to": "DISABLE_RESERVED", @@ -361,6 +401,11 @@ "to": "DISABLE_OFFLINE", "trigger": "to_offline" }, + { + "from": "DISABLE_MAINTENANCE", + "to": "DISABLE_ONLINE", + "trigger": "to_online" + }, { "from": "DISABLE_MAINTENANCE", "to": "STANDBY_MAINTENANCE", @@ -391,6 +436,11 @@ "to": "DISABLE_OFFLINE", "trigger": "to_offline" }, + { + "from": "DISABLE_ONLINE", + "to": "DISABLE_MAINTENANCE", + "trigger": "to_maintenance" + }, { "from": "DISABLE_ONLINE", "to": "STANDBY_ONLINE", @@ -431,6 +481,11 @@ "to": "DISABLE_NOTFITTED", "trigger": "to_notfitted" }, + { + "from": "DISABLE_OFFLINE", + "to": "DISABLE_RESERVED", + "trigger": "to_reserved" + }, { "from": "DISABLE_OFFLINE", "to": "FAULT_OFFLINE", @@ -456,6 +511,11 @@ "to": "DISABLE_NOTFITTED", "trigger": "to_notfitted" }, + { + "from": "DISABLE_RESERVED", + "to": "DISABLE_OFFLINE", + "trigger": "to_offline" + }, { "from": "DISABLE_RESERVED", "to": "FAULT_RESERVED", diff --git a/tests/data/subarray_state_machine.json b/tests/data/subarray_state_machine.json index f5b6bb4e6ecc49adf935df3c85f6d0642d3a55ce..e9667844fc1c9ba9acef3b56cba6a8f9dd3549df 100644 --- a/tests/data/subarray_state_machine.json +++ b/tests/data/subarray_state_machine.json @@ -212,6 +212,11 @@ "to": "INIT_OFFLINE", "trigger": "to_offline" }, + { + "from": "INIT_MAINTENANCE", + "to": "INIT_ONLINE", + "trigger": "to_online" + }, { "from": "INIT_MAINTENANCE", "to": "DISABLE_MAINTENANCE", @@ -237,6 +242,11 @@ "to": "FAULT_MAINTENANCE", "trigger": "fatal_error" }, + { + "from": "INIT_ONLINE", + "to": "INIT_MAINTENANCE", + "trigger": "to_maintenance" + }, { "from": "INIT_ONLINE", "to": "INIT_OFFLINE", @@ -277,6 +287,11 @@ "to": "INIT_MAINTENANCE", "trigger": "to_maintenance" }, + { + "from": "INIT_OFFLINE", + "to": "INIT_RESERVED", + "trigger": "to_reserved" + }, { "from": "INIT_OFFLINE", "to": "INIT_NOTFITTED", @@ -327,6 +342,11 @@ "to": "INIT_NOTFITTED", "trigger": "to_notfitted" }, + { + "from": "INIT_RESERVED", + "to": "INIT_OFFLINE", + "trigger": "to_offline" + }, { "from": "INIT_RESERVED", "to": "DISABLE_RESERVED", @@ -347,6 +367,11 @@ "to": "FAULT_OFFLINE", "trigger": "to_offline" }, + { + "from": "FAULT_MAINTENANCE", + "to": "FAULT_ONLINE", + "trigger": "to_online" + }, { "from": "FAULT_MAINTENANCE", "to": "DISABLE_MAINTENANCE", @@ -377,6 +402,11 @@ "to": "FAULT_OFFLINE", "trigger": "to_offline" }, + { + "from": "FAULT_ONLINE", + "to": "FAULT_MAINTENANCE", + "trigger": "to_maintenance" + }, { "from": "FAULT_ONLINE", "to": "DISABLE_ONLINE", @@ -412,6 +442,11 @@ "to": "FAULT_MAINTENANCE", "trigger": "to_maintenance" }, + { + "from": "FAULT_OFFLINE", + "to": "FAULT_RESERVED", + "trigger": "to_reserved" + }, { "from": "FAULT_OFFLINE", "to": "FAULT_NOTFITTED", @@ -462,6 +497,11 @@ "to": "FAULT_NOTFITTED", "trigger": "to_notfitted" }, + { + "from": "FAULT_RESERVED", + "to": "FAULT_OFFLINE", + "trigger": "to_offline" + }, { "from": "FAULT_RESERVED", "to": "DISABLE_RESERVED", @@ -482,6 +522,11 @@ "to": "DISABLE_OFFLINE", "trigger": "to_offline" }, + { + "from": "DISABLE_MAINTENANCE", + "to": "DISABLE_ONLINE", + "trigger": "to_online" + }, { "from": "DISABLE_MAINTENANCE", "to": "STANDBY_MAINTENANCE", @@ -512,6 +557,11 @@ "to": "DISABLE_OFFLINE", "trigger": "to_offline" }, + { + "from": "DISABLE_ONLINE", + "to": "DISABLE_MAINTENANCE", + "trigger": "to_maintenance" + }, { "from": "DISABLE_ONLINE", "to": "STANDBY_ONLINE", @@ -552,6 +602,11 @@ "to": "DISABLE_NOTFITTED", "trigger": "to_notfitted" }, + { + "from": "DISABLE_OFFLINE", + "to": "DISABLE_RESERVED", + "trigger": "to_reserved" + }, { "from": "DISABLE_OFFLINE", "to": "FAULT_OFFLINE", @@ -577,6 +632,11 @@ "to": "DISABLE_NOTFITTED", "trigger": "to_notfitted" }, + { + "from": "DISABLE_RESERVED", + "to": "DISABLE_OFFLINE", + "trigger": "to_offline" + }, { "from": "DISABLE_RESERVED", "to": "FAULT_RESERVED",