Configuration by Value
In certain scenarios, the ability to dynamically assign values to Monitors/Recorders proves to be a valuable and efficient feature. Consider a situation where distinct triggers necessitate monitoring speeds at different thresholds—detecting speeds around 50 km/h in one instance and speeds around 130 km/h in another. Instead of creating separate, hard-coded monitors for each trigger, our system offers a more intelligent approach. Users can create a versatile monitor that accepts speed as a configurable parameter. This means that a single monitor can be easily adapted to various speed thresholds by providing different values as arguments. This not only streamlines the monitoring setup but also enhances the system’s adaptability, allowing users to customize monitoring criteria on-the-fly. By embracing parameterized monitors, our system empowers users with a flexible and efficient solution for diverse monitoring requirements.
Usage
These classes can be directly used in the main method of your custom monitor. They provide an updateValue
method to supply the value we want to track and do the check.
In this example, every time the speed is between the values we defined in the monitor configuration, a signal is triggered.
If your usage is outside of the scope of these predefined classes, the following instructions will help you implement your custom value configurable monitor.
Functional components
Origin of ValueConfigurations
All ValueConfiguration
are read by the agent Kernel
from the systemConf.json
file and stored until a agent (Monitor or Recorder) connects to the agent Kernel
.
Run-time
Upon Identification
, the agent receives a ValueConfiguration
message and has to parse it.
To do so, any Agent in need of value configuration should implement the method handleValueConfiguration
This method should return a pointer on an object inheriting from ValueConfiguration
to store the value received in the command.
We provide a small collection of ValueConfiguration
classes:
ValueConfigurationDouble
to store a double.ValueConfigurationString
to store a string.ValueConfigurationDoubleInterval
to store an interval of double.ValueConfigurationBoolean
to store a boolean.ValueConfigurationThreshold
to store a custom object representing a comparison to a value.ValueConfigurationZone
to store a zone from a map.
You can create your own class inheriting from ValueConfiguration
to store a more complex value.
The handleValueConfiguration
method is given two arguments:
cmd
is the full configuration command received by the agent.header
is the same command but pre-parsed with the following variable :valid
A boolean at true if the command was formatted the right way. False otherwise.uuid
Agent UUID.cvUuid
The UUID of the configuration value that is associated with the value.name
Name of the configuration value.type
Type of value that should be used by Agents to determine how to handle the value.params
The unparsed value to be handled by the Agent.
The ValueConfiguration
object returned by handleValueConfiguration
is then added into the Agent variable _valueConfigurations
.
Sample of handleValueConfiguration
See handleValueConfiguration
method in sampleIntervalMonitor.cpp
:
Here we start by checking if the header.type
is “interval” as this Agent needs speed interval configuration.
Then we instantiate the appropriate ValueConfigurationDoubleInterval
that will parse the value contained inside the header.params
.
If our value configuration is valid we can return it so the agent can now use it.
Otherwise, we return nullptr
.
You can now use those configurations while using your Agent :
You can create a method in your Monitor to determine if the Dataflow you are monitoring activate or not your Monitor.
See void updateValue(double inputValue)
method in sampleIntervalMonitor.cpp
:
Here we browse all _valueConfigurations
list and check the name to be sure it is a “interval” as our Monitor only takes intervals.
We cast the ValueConfiguration in the right type (here ValueConfigurationDoubleInterval
) and check the pointer is not null.
From here we have access to the values of the ValueConfigurationDoubleInterval
via its methods getLowValue()
and getHighValue()
.
Then we check if the given inputValue is inside one interval of a valueConfiguration. If true, it calls signalOn
giving the timestamp and the uuid of the valueConfiguration (CV-XXXXX) :
When you decide the condition is no longer met, you can call signalOff
giving the same arguments.
You can create a method in your Monitor to determine if the Dataflow you are monitoring activate or not your Monitor.
See void updateValue(double inputValue)
method in sampleIntervalMonitor.cpp
:
Here we browse all _valueConfigurations
list and check the name to be sure it is a “interval” as our Monitor only takes intervals.
We cast the ValueConfiguration in the right type (here ValueConfigurationDoubleInterval
) and check the pointer is not null.
From here we have access to the values of the ValueConfigurationDoubleInterval
via its methods getLowValue()
and getHighValue()
.
Then we check if the given inputValue is inside one interval of a valueConfiguration. If true, it calls signalOn
giving the timestamp and the uuid of the valueConfiguration (CV-XXXXX) :
When you decide the condition is no longer met, you can call signalOff
giving the same arguments.
See generateRequestedFilePaths
method in sampleRecorderValueConf.cpp
:
On Recorders, all you need to do is to browse all _valueConfigurations
inside generateRequestedFilePaths
method to know what is requested from your Recorder in the query.
Comparing the query uuid
field to the value configurations cvUuid
field to get the right value(s).
Cast it to the right type and get the value you need to know what to record.
Samples
Here are the descriptions of our different value configurable samples:
SampleMonitorValueConf
The sampleMonitorValueConf
also demonstrates a simple usage of the monitor to notify the core of an event of interest (eg. boolean transition from true to false) using the signalOnOff() method.
But it overrides the Agent’s method handleValueConfiguration
that is called when receiving a value configuration from the agent Kernel
.
- The sample’s implementation of
handleValueConfiguration
, it only prints the value configuration. - The sample is designed to work with any configurable-by-value conditions.
The UUID of the monitor can be set by passing it as a command line argument:
When run, the Monitor gets initialized, connects to Core with D-UUID
, sends the signal with CV-UUID
and stops.
SampleIntervalMonitor
The sampleIntervalMonitor
demonstrates how to create a Configurable-by-Value Monitor that notifies the core of an event of interest for the speed-interval
field name.
This is the perfect sample to understand the Configurable-by-Value feature.
- The sample is designed to work only with
speed-interval
configurable-by-value named conditions and uses theCV-UUID
provided byagent Kernel
in system configuration during its exchanges. - This sample manages a state machine for every ValueConfiguration interval and change its state whenever the speed value gets in and out the interval. Once initialized, it runs as follows:
- A new speed is generated every second
- The method updateValue(speed) is called whenever a new speed is received
- It determine if the new value of speed change of state of any ValueConfiguratiion currently managed, eg. gets in and out the speed-interval passed as ValueConfiguration
- It notifies the Core of a state change calling either
signalOn()
orsignalOff()
with theCV-UUID
The UUID of the Monitor can be set by passing it as a command line argument:
sampleRecorderValueConf
The sampleRecorderValueConf
demonstrates how to create a Configurable-by-Value Recorder that generates a file with different content based on the ValueConfiguration it is called upon in the event query.
- This sample requires this Recorder to be defined as Configurable-by-value in the configuration on Heex Cloud.
- This sample is designed to work with
camera
configurable-by-value.
The UUID of the Recorder can be set by passing it as a command line argument:
When run:
- The recorder gets initialized, connects to Core with
R-UUID
. - Then it exposes the Context Values and Event Recording Part generation to the Core for identifiers
SV-UUID
. - It stops only on SIGKILL (Ctrl-C).