Skip to content
Snippets Groups Projects
Commit 2cf8e623 authored by Dennis Goeries's avatar Dennis Goeries
Browse files

Document schema injection

See merge request !3
parents 10d83e4f 903edb68
No related branches found
No related tags found
1 merge request!3Document schema injection
Schema Injection
================
A schema injection is a modification of a device schema, to bring further
properties visible outside or to update attributes of existing properties
(such as the maximum size of a vector). Any number and types of properties can
be injected, whether parameters or slots.
In this example, we will define a slot that adds a boolean `injectedProperty`.
Begin by defining a slot that will call the `extend` function:
.. code-block:: Python
from karabo.bound import BOOL_ELEMENT, PythonDevice, SLOT_ELEMENT
class MyDevice(PythonDevice):
@staticmethod
def expectedParameters(expected):
(
SLOT_ELEMENT(expected).key('extend')
.displayedName('Extend')
.description('Extend the schema and introduce a new boolean property')
.commit(),
)
# Register the slot in the device schema
def onInitialization(self):
self.KARABO_SLOT(self.extend)
There are two methods to injecting properties: `appendSchema` and `updateSchema`,
both inherited from :class:`karabo.bound.PythonDevice`.
:func:`appendSchema` will add properties to the device, and can be called any
number of time.
:func:`updateSchema` will take the the original schema of the device, and add
the new one to the device. However, it will discard what has been previously
appended or updated!
Nonetheless, if :func:`appendSchema` is called after :func:`updateSchema`, then
the parameters from both injections are kept.
If :func:`updateSchema` is called with an empty schema, then the device will be
reset to its original schema, as defined in :func:`MyDevice.expectedParameters`.
This works, as internally, a device keeps three schemas: its `static` schema,
as defined in `expectedParameters`, the `injected` schema, which is modified on
injections, and the `full` schema, the combination of both which is exposed to
the rest of the ecosystem.
.. code-block:: Python
from karabo.bound import BOOL_ELEMENT, DAQPolicy, Schema
def extend(self):
# Define a new Schema object
schema = Schema()
# Then populate that new Schema
(
BOOL_ELEMENT(schema).key('injectedProperty')
.displayedName('Hello')
.description('A fresh property')
.daqPolicy(DAQPolicy.OMIT)
.readOnly().initialValue(True)
.commit()
# Finally, append the schema to our existing device
self.appendSchema(schema) # Or self.updateSchema(schema)
Once a device has been modified, either of these log messages will be given::
INFO MyDevice : Schema updated
INFO MyDevice : Schema appended
Re-injecting a property, such as `injectedProperty`, will keep its current value
if possible. However, with different types, an error will be raised if the
value cannot be cast e.g. going from `UINT32_ELEMENT` to `INT16_ELEMENT` with a
value out of bound.
Check Whether A Property Exists
-------------------------------
If your device has an update loop, you can either use flags to check
whether schema injection has already been done, or use :func:`getFullSchema`:
.. code-block:: Python
def update(self):
if self.getFullSchema().has("injectedProperty"):
self.set("injectedProperty", not self.get("injectedProperty"))
Injected Properties and DAQ
---------------------------
Injected Properties and the DAQ need some ground rules in order to record these
properties correctly.
In order for the DAQ to record injected properties, the DAQ needs to request the
updated schema again, using the Run Controller's :func:`applyConfiguration` slot.
This can be prone to operator errors, and therefore it is recommended that only
properties injected at instantiation to be recorded.
However, a common need for Schema updates is to specify the `maxSize` attribute
fo vector or table elements, as the DAQ only supports fixed length arrays, of
which the size has to be predefined.
For that, there is the special function :func:`karabo.bound.PythonDevice.appendSchemaMaxSize`
which, given a property path and the new length, will update the schema
accordingly.
Such a vector:
.. code-block:: Python
from karabo.bound import NODE_ELEMENT, VECTOR_INT32_ELEMENT
@staticmethod
def expectedParameters(expected):
(
NODE_ELEMENT(expected).key('node').commit(),
VECTOR_INT32_ELEMENT(expected').key('node.vector')
.displayedName('Vector')
.readOnly()
.maxSize(5)
.commit(),
)
Can have its `maxSize` be redefined as follows:
.. code-block:: Python
self.appendSchemaMaxSize('node.vector', 50)
If several updates are made, then it is recommended to set `emitFlag` to false for
all vectors apart of the last one. Only a single update will be then sent:
.. code-block:: Python
self.appendSchemaMaxSize('node.vector0', 50, emitFlag=False)
self.appendSchemaMaxSize('node.vector1', 50, emitFlag=False)
self.appendSchemaMaxSize('node.vector2', 50)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment