Skip to main content

Preprocessor directives

Preprocessor directives

Preprocessor directives can be used to influence the functions of the Math Module Compiler, the processing of variables, and the execution of the code. Preprocessor directives must be placed at the beginning of a line in the formula text and end with the first line break that is not hidden in a bracket level. Comments can be inserted according to known rules.

The directives are marked by a # character followed by an identifier. Which parameters follow the directive and how they are formatted depends on the function. Possible formats are, for example:

#directiveA <parameter>
#directiveB <name>[<parameter>](<parameter>){<code>}
#directiveC <key>, <key>=<value>, …

Insert formula text "#include"

This directive can be used to insert formula text from a resource or an external file. The syntax used determines which source is addressed.

#include "aResource"
#include 'aResource'
#include <aFile>

The resource specified as a string is incorporated into the source code, taking into account the decoder specified there, or as text.

The file specified in <…> is included in the source code. Absolute and relative paths are permitted, whereby relative paths are searched for starting from fixed directories (search paths). Elements in %...% are replaced by the corresponding value of the environment variable.

Search paths under WINDOWS:

  • %USERPROFILE%/mm_lib/

  • %LOCALAPPDATA%/optimeas.osg.com/mm_lib/

  • %APPDATA%/optimeas.osg.com/mm_lib/

Search paths under LINUX/YOCTO:

  • /sdi/config/mm_lib/

  • /sdi/apps/smartcore/mm_lib/

  • /var/lib/mm_lib/

  • /usr/local/lib/mm_lib/

  • /usr/lib/mm_lib/

Remove time reference "#timeless"

As described in the introduction, the Math module always processes data from the various smartCORE sources in a time-correct manner. This ensures that, for example, a current and voltage signal are correlated with each other for the purpose of calculating power.

However, there are also data sources that only provide new values extremely rarely. These could be, for example, measurement data from a weather station, which may only be queried every 10 minutes and written to the smartCORE channels, or data from a timetable that is only queried and updated once a day by a server.

Data transferred from smartCORE to the Math module times out after the adjustable time inputTimeoutS and is then continued to be used with this time offset and the last pending value, even though its validity has not been confirmed by more recent measurements or queries. As a result, all dependent calculations are still executed at the correct time but are delayed by this time span.

This delay can have adverse effects on the display of MQTT data in the cloud or on control tasks.

With the functions

can be used to query the various states of an input variable. If no smartCORE channel could be connected or if this channel does not yet provide any data, a default value is assigned, which can be set using the macro #property <channel>, default=<var>.

To resolve the time reference of certain input channels for the Math module, the directive #timeless can be used. The channel names can be passed to the directive in a list separated by commas. If the names contain characters other than those permitted for an identifier, they must be enclosed in '...' or "...". The use of the $'...' syntax is not permitted, as only one attribute of the channel is set here.

#timeless <varName>, <varName2>, ...

The input channels marked in this way are then always valid from the beginning to the end of the respective calculation interval evaluationTimeMs relative to the respective system time.

Timeless Schema

In the example shown, the formula set is calculated at times t0,t_0, t1,t_1, and t2.Uptotimet_2. Up to time t_0,onlythevalue, only the value y_0wassetonthechannel.Uptotimewas set on the channel. Up to timet_1,thesignalsourcedeliversthedatapoints, the signal source delivers the data points y_1, y_2andandy_3.Thedatapoints. The data points y_4andandy_5arenotproduceduntiltimeare not produced until timet_2,eventhoughtheirtimestampisbefore, even though their timestamp is before t_1$.

The data set immediately preceding the channel is always used for the start of the interval, regardless of how old it is. For the interval ]t0,t1]]t_0,t_1], this means the data point y1y_1, and for the interval ]t1,t2]]t_1,t_2], the data point y5y_5.

If new data values happen to fall within the current calculation interval and have already been entered there in time, they are taken into account with their times. For the interval ]t0,t1]]t_0,t_1], these are the data points y2y_2 and y3y_3.

The validity of the most recent data set available (here y3y_3) is automatically extended until the end of the interval (here t1t_1), so that this channel cannot ultimately delay any calculations that depend on it.

The price for this is that short signal changes that fall within this extended validity range may no longer be included in the calculations. In the example, the data point y4y_4 is "overlooked" because it lies in a time interval that has already been supplemented by the automatic mechanism. However, assuming and provided that these channels rarely supply data, this should not be a problem.

Setting properties of a variable "#property" 1

This preprocessor directive can be used to set properties and meta information for an input or output variable.

#property <channel>, <key>=<value>, ...
ArgumentTypeDescription
channel<str>The channel name must be specified as the first argument. If it contains special characters such as spaces or commas, it must be enclosed in quotation marks. The use of the $'...' syntax is not permitted, as only channel properties are set here.
key<str>The name of the property, see table below
value<var>The new value of the property (variant)

The following table lists the possible and permitted properties and their values:

PropertyTypeDescription
default<var>The default value assigned to a variable until the first data values arrive from the smartCORE channel. This makes it possible to respond to delayed data streams in the Math module.
timeless<bool>This enables or disables the timeless feature for this channel. This corresponds to the macro #timeless.

Definition of functions "#define"

| | timeless | <bool> | This turns the timeless feature on or off for this channel. This co

Under Construction This function is currently being developed.

#define <newFunction>(<argsList>)[<options>]{<code>}

Debug information "#dump"

warning

For Debugging Only This preprocessor directive is intended solely for diagnostic and development purposes. It produces a large amount of informal output in the smartCORE log file and should therefore only be used for short periods of time.

The parameter of the #dump directive is a comma-separated list of keys or key-value pairs and affects the subsequent formula text:

#dump <key>, <key>=<value>, ...
KeyValueDescription
treeOutputs the translated object tree. See below for interpretation.
node<uint>Adds a specific object node for continuous monitoring (2, 3).
var<str>Adds a regex expression to select channel names whose accesses are to be logged (2)
trace<enum>Enables data flow output for
- in inputs,
- out outputs, or
- io both data directions
.
clearClears all dump settings for the following code section.

Examples:

#dump tree
#dump node=5, node=9
#dump var='Temp.*', trace=out

Output of the object tree

The output of the object tree using #dump tree provides detailed information on the functional relationships of the defined formula set. The evaluation is reserved for expert optiMEAS employees.

        +---o   [0]: sequencer, bareImpl, op: ';' listOfArgs
> out: nullptr
+---o [1]: operatorNode, followInputs, op: '=' orderR2L
| > out: { n:'duration', s:[upLnk, wrVar], *rd[0], *wr[1], h:'=', empty}
| +---o [2]: operatorNode, followInputs, op: '*' orderL2R
| | > out: { n:'', s:[upLnk], *rd[1], *wr[2], h:'*', empty}
| | +---o [3]: varPoolSource, followInputs
| | | > var: { n:'wv2', s:[rdVar], *rd[3], empty}
| | | > out: { n:'', s:[upLnk], *rd[2], *wr[3], empty}
| | +---o [4]: constValueNode, constValue
| | | > out: { n:'', s:[upLnk, const], *rd[2], *wr[4], [1]={t: INF, d: TrustedTimestamp }, [0]={t: 0, d: (cScalar, cInt) 59}}

Trace outputs for a data flow connection element (out: or var:, channel or TS_Stream) have the following compact structure:

{ n:'duration', s:[upLnk, wrVar], *rd[0], *wr[1], h:'=', [9]={t: 48, d: (cScalar, cDbl) 54.978065}, ... [0]={t: 20, d: (cScalar, cDbl) 0.000000}}

This means:

AbbreviationFlagsDescription
n:'...'The name of the channel, if it is a variable
s:[]Status flags of the channel
upLnkUp-link, connection from a subnode to the parent node
rdVarRead variable, input variable, provided by smartCORE and read only
wrVarWrite variable, output variable, can be fed back into the smartCORE
inzInitializer, has an initializing node
constConstant value, the value does not change during runtime.
discrDiscrete evaluation, this channel is calculated in discrete sampling steps
ev@0Evaluate at Start, the discrete channel has been initialized
evDTEvaluate Delta-T, one sampling step has been calculated for the discrete channel.
explExplicit name, variable was defined with the $'…' syntax and must exist in smartCORE
fldEField element, channel feeds a specific data field in a multidimensional structure (vector, matrix, etc.)
privPrivate, a variable that was created by a function block and is used exclusively by it
propProperties were set on the variable with #property.
noTnoTime, this channel has been marked as #timeless and is always valid until the end of the calculation interval.
nRecNoRecursion, this variable must not be used in a recursion loop.
noChThis channel could not be connected to a smartCORE channel as input. => Assigned as a constant value by default. See also isConnected()
noDThe input channel is still empty, no data from the smartCORE. See also isEmpty()
tmoTimeout for input data if the channel is still empty (noD) or has not been marked as #timeless. See also isTimeout()
tmoTimeout for input data, provided that the channel is still empty (noD) or
*rd[]The indices of the object nodes that access the channel in read mode
*wr[]The index of the object node that accesses the channel in write mode
*@0[]The index of the object node that performs the initialization of the discrete channel.
h:'...'Reference to the function of the writing node, e.g., '*' or 'sin(…)'
[n]={}The stored sample at the most recent position n (corresponds to the number of entries - 1) with...
t:Timestamp in ns since 01/01/1070, INF (infinite) or NAV (not available)
d:Data value with (structure, type) value or TrustedTimestamp, i.e., the preceding value remains valid until this point in time. The point in time can grow monotonically in each calculation interval.
[0]={}the stored sample at the oldest position (optional)

Track calculation process "#monitor"

| | the stored sample at the oldest position (optional)

For Debugging Only WARNING! This preprocessor directive is intended for diagnostic and development purposes only. It produces a large amount of informal output in the smartCORE log file and should therefore only be used for short periods of time.

Monitoring the internal buffers "#warn"

For Debugging Only WARNING! This preprocessor directive is intended for diagnostic and development purposes only. It produces a large amount of informal output in the smartCORE log file and should therefore only be used for short periods of time. In addition, this option generates additional CPU load and may only be used temporarily under supervision !!!

The parameter of the #warn directive is a comma-separated list of keys or key-value pairs and affects the subsequent formula text:

KeyValueDescription
maxbuflen<uint>Monitors the maximum number of data records in a data queue. A warning is issued if the limit is exceeded. The limit is raised by 25% of maxbuflen for the following message.
timeout<dbl>Monitors the time interval between the first data sample and the execution time. A warning is issued if this time is greater than the set value in s.
clearClears all warning settings for the following code section.

Examples:

#warn maxBufLen=10, timeout=1000
// Formula text for monitoring
#warn clea

Footnotes

  1. Available from catalog version 10 onwards.

  2. Option can be specified multiple times. | 2

  3. Node numbers from the object tree