Data-driven applications
Using the mechanisms described in the Objects and References and in the Object configuration sections, together with a special syntax, the framework is capable of instantiating a tree of objects based on a configuration stream (e.g. a file).
Syntax
The Initialise
method of the ReferenceContainer will look for any name starting with the character +
.
When the +
character is found, the property Class=LIB::CLASS
shall exist in the subtree. LIB
is the name of the shared library holding the compiled CLASS
.
The CLASS
shall inherit from Object
and shall implement the macros defined in the Objects section.
If LIB
is not defined, it is assumed that the class was already registered (e.g. because it was statically linked) or that the name of the library is equal to the name of the class.
This process is recursively repeated and a tree of Objects is built. The name of the Object is automatically set to the name of the node.
In the following example, an object named A
, of type AClass
, would be created, together with another object of type AClass
, named B
, and with an object of type CClass
named C
. It is assumed that the AClass
inherits from ReferenceContainer
and that, as a consequence, calling Get(0)
on the instance named B
would return a Reference
to C
.
+A = {
Class = AClass
}
+B = {
Class = AClass
+C = {
Class = ALIB::CClass
}
}
The ObjectRegistryDatabase is a ReferenceContainer
which offers a database to hold and link all the Objects
defined in a given configuration stream.
The Find
method can be used to find any of the instantiated Objects
in the tree.
A dot . is used as the path separator.
...
ObjectRegistryDatabase *ord = ObjectRegistryDatabase::Instance();
ReferenceT<CClass> obj = ord->Find("B.C");
if (obj.IsValid()) {
...
If the node name starts with a $
, besides implementing the same behaviour described before for the +
, it will also set the node as a search domain.
This means that when using the ObjectRegistryDatabase Find
method, the :
symbol will allow to perform searches related to a given root domain. For example:
+A = {
Class = AClass
$B = {
Class = BClass
+C = {
Class = CClass
+E = {
Class = EClass
}
}
+D = {
Class = DClass
+F = {
Class = CClass
}
}
}
}
Would allow to Find C
, C.E
, D
and D.F
, using B
as the root domain (see the example below).
Note
Other characters can also be set as a identifiers for the new Object creation and for the setting of a given Object as the root domain. See the methods AddBuildToken
, RemoveBuildToken
, IsBuildToken
, AddDomainToken
, RemoveDomainToken
and IsDomainToken
in ReferenceContainer.
Reading C structures
If a C struct
has been registered in the ClassRegistryDatabase it is possible to directly map the contents of a configuration node to the registered structure (see example below).
To read/write a registered structure an AnyType which describes the registered type must be created:
struct AStruct {
float32 f1;
float32 f2;
};
///Register the struct with the required macros.
AStruct aStruct1;
AStruct aStruct2;
ClassRegistryItem * registeredStructClassProperties = ClassRegistryDatabase::Instance()->Find("AStruct");
...
ClassUID registeredStructUID = registeredStructClassProperties->GetUniqueIdentifier();
TypeDescriptor registeredStructTypeDescriptor(false, registeredStructUID);
AnyType registeredStructAnyType1 = AnyType(registeredStructTypeDescriptor, 0u, &aStruct1);
AnyType registeredStructAnyType2 = AnyType(registeredStructTypeDescriptor, 0u, &aStruct2);
...
data.Read("AStruct1", registeredStructAnyType1);
data.Read("AStruct2", registeredStructAnyType2);
...
if (aStruct1.f1 == aStruct2.f1) {
...
Note
Only the types and structure of the configuration tree must match with the types and structure of the C struct
, i.e. the names are ignored.
Reading data-driven C structures
The IntrospectionStructure class can also be used to dynamically create and register structures using a standard configuration file.
+Types = {
Class = ReferenceContainer
+GainFromIntroStructure = {
Class = IntrospectionStructure
gain1 = {
Type = float32
NumberOfElements = {1}
}
gain2 = {
Type = float32
NumberOfElements = {1}
}
gain3 = {
Type = float32
NumberOfElements = {6}
}
}
+GainsFromIntroStructure = {
Class = IntrospectionStructure
lowGains = {
Type = GainFromIntroStructure
}
...
Preprocessing
The MARTe configuration files can be preprocessed using the C
preprocessor directives (e.g. #include
and #define
).
This strategy can be used to write modular configuration settings (see example below). Note that the files must first be processed with a Makefile.inc
and a Makefile.cfg
, following the MARTe Makefile structure:
#Named of the unit files to be compiled. It will generate files named *_Gen.cfg (e.g. RTApp-6_Gen.cfg)
OBJSX=RTApp-6.x
#Location of the Build directory where the configuration file will be written to
BUILD_DIR?=.
#Location of the MakeDefaults directory.
#Note that the MARTe2_DIR environment variable
#must have been exported before
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
CFLAGS += -DENABLE_WEB_BROWSING
all: $(OBJS)
echo $(OBJS)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
export TARGET=cfg
include Makefile.inc
Postprocessing
As of v1.7.0, the StandardParser also allows to post-process and assign simple mathematical expressions to nodes in the tree. The syntax is NODE=(OUTPUT_VAR_TYPE|EXPRESSION), where OUTPUT_VAR_TYPE is the output variable type (e.g. uint32) and EXPRESSION is the mathematical expression to be executed.
The variables in the expression can reference to other nodes in the configuration tree, noting that the expressions are executed in order (top to bottom) and that the names in the node path cannot include the + sign.
int a =3;
Parameters = {
T1_FREQUENCY = (uint32)10000
T2_FREQUENCY = (uint32)1
SAMPLES = (uint32|"Parameters.T1_FREQUENCY / Parameters.T2_FREQUENCY")
}
+TestApp = {
Class = RealTimeApplication
+Functions = {
Class = ReferenceContainer
+GAMTimer = {
Class = IOGAM
InputSignals = {
Time = {
Frequency = (uint32|"(uint32)2 * Parameters.T1_FREQUENCY")
...
Examples
The following example shows how to load an application from a configuration file.
Note that Objects can be nested inside other Objects (provided that the container Object inherits from ReferenceContainer and that it calls ReferenceContainer::Initialise on its Initialise method).
1/**
2 * @file ConfigurationExample4.cpp
3 * @brief Source file for class ConfigurationExample4
4 * @date 14/03/2018
5 * @author Andre' Neto
6 *
7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
8 * the Development of Fusion Energy ('Fusion for Energy').
9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
11 * You may not use this work except in compliance with the Licence.
12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
13 *
14 * @warning Unless required by applicable law or agreed to in writing,
15 * software distributed under the Licence is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17 * or implied. See the Licence permissions and limitations under the Licence.
18
19 * @details This source file contains the definition of all the methods for
20 * the class ConfigurationExample4 (public, protected, and private). Be aware that some
21 * methods, such as those inline could be defined on the header file, instead.
22 */
23
24#define DLL_API
25
26/*---------------------------------------------------------------------------*/
27/* Standard header includes */
28/*---------------------------------------------------------------------------*/
29
30/*---------------------------------------------------------------------------*/
31/* Project header includes */
32/*---------------------------------------------------------------------------*/
33#include "AdvancedErrorManagement.h"
34#include "ClassRegistryDatabase.h"
35#include "ConfigurationDatabase.h"
36#include "ErrorLoggerExample.h"
37#include "Matrix.h"
38#include "Object.h"
39#include "ObjectRegistryDatabase.h"
40#include "Reference.h"
41#include "ReferenceT.h"
42#include "StandardParser.h"
43#include "StreamString.h"
44#include "Vector.h"
45
46/*---------------------------------------------------------------------------*/
47/* Static definitions */
48/*---------------------------------------------------------------------------*/
49
50/*---------------------------------------------------------------------------*/
51/* Method definitions */
52/*---------------------------------------------------------------------------*/
53namespace MARTe2Tutorial {
54
55/**
56 * Configuration structures
57 */
58struct Gains {
59 MARTe::float32 gain1;
60 MARTe::float32 gain2;
61};
62
63struct Waveforms {
64 MARTe::float32 *times;
65 MARTe::float32 *values;
66};
67
68/**
69 * @brief A MARTe::Object that will be inserted (data-driven) inside the ControllerEx1.
70 */
71class ReferenceEx1: public MARTe::Object {
72public:
73 CLASS_REGISTER_DECLARATION()
74
75ReferenceEx1 () {
76 waveform.times = NULL;
77 waveform.values = NULL;
78 }
79
80 virtual ~ReferenceEx1 () {
81 if (waveform.times != NULL) {
82 delete [] waveform.times;
83 }
84 if (waveform.values != NULL) {
85 delete [] waveform.values;
86 }
87 if (GetName() != NULL) {
88 REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing"
89 " at %s [%s]. The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
90 }
91 }
92
93 /**
94 * Read the waveform properties
95 * Times = {0 0.1 0.2 1}
96 * Values = {1 2 3 4}
97 */
98 virtual bool Initialise(MARTe::StructuredDataI &data) {
99 using namespace MARTe;
100 bool ok = Object::Initialise(data);
101
102 if (ok) {
103 ok = ReadArray(data, "Times", waveform.times);
104 }
105 if (ok) {
106 ok = ReadArray(data, "Values", waveform.values);
107 }
108
109 return ok;
110 }
111
112private:
113 bool ReadArray(MARTe::StructuredDataI &data, const MARTe::char8 * const arrayName, MARTe::float32 *&dest) {
114 using namespace MARTe;
115 if (dest != NULL) {
116 delete [] dest;
117 }
118
119 AnyType arrayDescription = data.GetType(arrayName);
120 bool ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
121 uint32 numberOfElements = 0u;
122 if (ok) {
123 numberOfElements = arrayDescription.GetNumberOfElements(0u);
124 ok = (numberOfElements > 0u);
125 if (!ok) {
126 REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array with name %s", arrayName);
127 }
128 }
129 if (ok) {
130 dest = new float32[numberOfElements];
131 Vector<float32> readVector(dest, numberOfElements);
132 ok = data.Read(arrayName, readVector);
133 if (ok) {
134 REPORT_ERROR(ErrorManagement::Information, "Array set to %f", readVector);
135 }
136 else {
137 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the array with name %s", arrayName);
138 }
139 }
140 return ok;
141 }
142
143 Waveforms waveform;
144};
145CLASS_REGISTER(ReferenceEx1, "")
146
147/**
148 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
149 */
150class ControllerEx1: public MARTe::ReferenceContainer {
151public:
152 CLASS_REGISTER_DECLARATION()
153
154 /**
155 * @brief NOOP.
156 */
157ControllerEx1 () {
158
159 }
160
161 virtual ~ControllerEx1 () {
162 if (GetName() != NULL) {
163 REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
164 "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
165 }
166 }
167
168 /**
169 * Read all the properties which are organised inside a tree
170 * Gains = {
171 * Low = {
172 * Gain1 = -1.0;
173 * Gain2 = -3.0;
174 * }
175 * High = {
176 * Gain1 = 7.0;
177 * Gain2 = 9.0;
178 * }
179 * }
180 * +SlowReference = {
181 * Class = ReferenceEx1
182 * Times = {0 0.1 0.2 1}
183 * Values = {1 2 3 4}
184 * }
185 * +FastReference = {
186 * Class = ReferenceEx1
187 * Times = {0 0.1 0.2 1}
188 * Values = {1 4 8 12}
189 * }
190 */
191 virtual bool Initialise(MARTe::StructuredDataI &data) {
192 using namespace MARTe;
193 bool ok = ReferenceContainer::Initialise(data);
194 if (ok) {
195 //Move in the tree
196 ok = data.MoveRelative("Gains");
197 if (!ok) {
198 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains section");
199 }
200 }
201 if (ok) {
202 ok = data.MoveRelative("Low");
203 if (!ok) {
204 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains.Low section");
205 }
206 }
207 if (ok) {
208 ok = data.Read("Gain1", lowGains.gain1);
209 if (ok) {
210 REPORT_ERROR(ErrorManagement::Information, "Gains.Low.Gain1 = %f", lowGains.gain1);
211 }
212 else {
213 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain1");
214 }
215 }
216 if (ok) {
217 ok = data.Read("Gain2", lowGains.gain2);
218 if (ok) {
219 REPORT_ERROR(ErrorManagement::Information, "Gains.Low.Gain1 = %f", lowGains.gain2);
220 }
221 else {
222 }
223 }
224 if (ok) {
225 ok = data.MoveToAncestor(1u);
226 if (!ok) {
227 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move back to the Gains section");
228 }
229 }
230 if (ok) {
231 ok = data.MoveRelative("High");
232 if (!ok) {
233 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains.High section");
234 }
235 }
236 if (ok) {
237 ok = data.Read("Gain1", highGains.gain1);
238 if (ok) {
239 REPORT_ERROR(ErrorManagement::Information, "Gains.High.Gain1 = %f", highGains.gain1);
240 }
241 else {
242 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain1");
243 }
244 }
245 if (ok) {
246 ok = data.Read("Gain2", highGains.gain2);
247 if (ok) {
248 REPORT_ERROR(ErrorManagement::Information, "Gains.High.Gain1 = %f", highGains.gain2);
249 }
250 else {
251 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain2");
252 }
253 }
254
255 if (ok) {
256 //Check if the waveforms were declared
257 slowWaveform = Get(0);
258 ok = slowWaveform.IsValid();
259 if (!ok) {
260 REPORT_ERROR(ErrorManagement::ParametersError, "Could not find the SlowWaveform");
261 }
262 }
263
264 if (ok) {
265 //Check if the waveforms were declared
266 fastWaveform = Get(1);
267 ok = fastWaveform.IsValid();
268 if (!ok) {
269 REPORT_ERROR(ErrorManagement::ParametersError, "Could not find the FastWaveform");
270 }
271 }
272
273 return ok;
274 }
275
276 /**
277 * A list of properties.
278 */
279 Gains lowGains;
280 Gains highGains;
281 MARTe::ReferenceT<ReferenceEx1> slowWaveform;
282 MARTe::ReferenceT<ReferenceEx1> fastWaveform;
283};
284
285CLASS_REGISTER(ControllerEx1, "")
286
287}
288
289int main(int argc, char **argv) {
290 using namespace MARTe;
291 using namespace MARTe2Tutorial;
292 SetErrorProcessFunction(&ErrorProcessExampleFunction);
293
294 StreamString configurationCfg = ""
295 "+ControllerInstance1 = {\n"
296 " Class = ControllerEx1\n"
297 " Gains = {\n"
298 " Low = {\n"
299 " Gain1 = -1.0\n"
300 " Gain2 = -3.0\n"
301 " }\n"
302 " High = {\n"
303 " Gain1 = 7.0\n"
304 " Gain2 = 9.0\n"
305 " }\n"
306 " }\n"
307 " +SlowWaveform = {\n"
308 " Class = ReferenceEx1\n"
309 " Times = {0 0.1 0.2 1}\n"
310 " Values = {1 2 3 4}\n"
311 " }\n"
312 " +FastWaveform = {\n"
313 " Class = ReferenceEx1\n"
314 " Times = {0 0.1 0.2 1}\n"
315 " Values = {1 4 6 8}\n"
316 " }\n"
317 "}";
318
319 REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s",
320 configurationCfg.Buffer());
321 ConfigurationDatabase cdb;
322 StreamString err;
323 //Force the string to be seeked to the beginning.
324 configurationCfg.Seek(0LLU);
325 StandardParser parser(configurationCfg, cdb, &err);
326 bool ok = parser.Parse();
327 if (ok) {
328 //After parsing the tree is pointing at the last leaf
329 cdb.MoveToRoot();
330 ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
331 }
332 else {
333 StreamString errPrint;
334 errPrint.Printf("Failed to parse %s", err.Buffer());
335 REPORT_ERROR_STATIC(ErrorManagement::ParametersError,
336 errPrint.Buffer());
337 }
338
339 if (ok) {
340 REPORT_ERROR_STATIC(ErrorManagement::Information,
341 "Successfully loaded the configuration file");
342 }
343
344 return 0;
345}
This example highlights how the Find method can be used to search for Objects in the ObjectRegistryDatabase. Note how the reference G.H is found with respect to B.
1/**
2 * @file ConfigurationExample5.cpp
3 * @brief Source file for class ConfigurationExample5
4 * @date 14/03/2018
5 * @author Andre' Neto
6 *
7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
8 * the Development of Fusion Energy ('Fusion for Energy').
9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
11 * You may not use this work except in compliance with the Licence.
12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
13 *
14 * @warning Unless required by applicable law or agreed to in writing,
15 * software distributed under the Licence is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17 * or implied. See the Licence permissions and limitations under the Licence.
18
19 * @details This source file contains the definition of all the methods for
20 * the class ConfigurationExample5 (public, protected, and private). Be aware that some
21 * methods, such as those inline could be defined on the header file, instead.
22 */
23
24#define DLL_API
25
26/*---------------------------------------------------------------------------*/
27/* Standard header includes */
28/*---------------------------------------------------------------------------*/
29
30/*---------------------------------------------------------------------------*/
31/* Project header includes */
32/*---------------------------------------------------------------------------*/
33#include "AdvancedErrorManagement.h"
34#include "ClassRegistryDatabase.h"
35#include "ConfigurationDatabase.h"
36#include "ErrorLoggerExample.h"
37#include "JsonParser.h"
38#include "Matrix.h"
39#include "Object.h"
40#include "ObjectRegistryDatabase.h"
41#include "Reference.h"
42#include "ReferenceT.h"
43#include "StandardParser.h"
44#include "StreamString.h"
45#include "Vector.h"
46
47/*---------------------------------------------------------------------------*/
48/* Static definitions */
49/*---------------------------------------------------------------------------*/
50
51/*---------------------------------------------------------------------------*/
52/* Method definitions */
53/*---------------------------------------------------------------------------*/
54
55int main(int argc, char **argv) {
56 using namespace MARTe;
57 SetErrorProcessFunction(&ErrorProcessExampleFunction);
58
59 StreamString configurationCfg = ""
60 "+A = {\n"
61 " Class = ReferenceContainer\n"
62 " $B = {\n"
63 " Class = ReferenceContainer\n"
64 " +C = {"
65 " Class = ReferenceContainer\n"
66 " +F = {"
67 " Class = ReferenceContainer\n"
68 " }\n"
69 " }\n"
70 " +G = {"
71 " Class = ReferenceContainer\n"
72 " +H = {"
73 " Class = ReferenceContainer\n"
74 " }\n"
75 " }\n"
76 " }\n"
77 " +D = {\n"
78 " Class = ReferenceContainer\n"
79 " +E = {\n"
80 " Class = ReferenceContainer\n"
81 " }\n"
82 " }\n"
83 "}\n";
84
85 REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s",
86 configurationCfg.Buffer());
87 ConfigurationDatabase cdb;
88 StreamString err;
89 //Force the string to be seeked to the beginning.
90 configurationCfg.Seek(0LLU);
91 StandardParser parser(configurationCfg, cdb, &err);
92 bool ok = parser.Parse();
93 ObjectRegistryDatabase *ord = ObjectRegistryDatabase::Instance();
94 if (ok) {
95 //After parsing the tree is pointing at the last leaf
96 cdb.MoveToRoot();
97 ok = ord->Initialise(cdb);
98 }
99 else {
100 StreamString errPrint;
101 errPrint.Printf("Failed to parse %s", err.Buffer());
102 REPORT_ERROR_STATIC(ErrorManagement::ParametersError,
103 errPrint.Buffer());
104 }
105
106 if (ok) {
107 //Find A.D.E
108 const char8 * const path = "A.D.E";
109 ReferenceT<ReferenceContainer> rc = ord->Find(path);
110 ok = rc.IsValid();
111 if (ok) {
112 REPORT_ERROR_STATIC(ErrorManagement::Information, "Found %s", path);
113 }
114 else {
115 REPORT_ERROR_STATIC(ErrorManagement::FatalError,
116 "Could not find %s !", path);
117 }
118 }
119 if (ok) {
120 //Find A.B.E
121 const char8 * const path = "A.B.E";
122 ReferenceT<ReferenceContainer> rc = ord->Find(path);
123 ok = !rc.IsValid();
124 if (ok) {
125 REPORT_ERROR_STATIC(ErrorManagement::Information,
126 "Could not find %s as expected", path);
127 }
128 else {
129 REPORT_ERROR_STATIC(ErrorManagement::FatalError,
130 "Should not have found %s !", path);
131 }
132 }
133 if (ok) {
134 //Find D.E as relative path to F
135 const char8 * const path = "A.B.C.F";
136 ReferenceT<ReferenceContainer> rc = ord->Find(path);
137 ok = rc.IsValid();
138 if (ok) {
139 REPORT_ERROR_STATIC(ErrorManagement::Information, "Found %s", path);
140 //: Moves up to the next domain (which $B)
141 const char8 * const path = ":G.H";
142 //Note that the search is relative to rc (which is currently @ A.B.C.F)
143 rc = ord->Find(path, rc);
144 ok = rc.IsValid();
145 if (ok) {
146 REPORT_ERROR_STATIC(ErrorManagement::Information, "Found %s",
147 path);
148 }
149 else {
150 REPORT_ERROR_STATIC(ErrorManagement::FatalError,
151 "Could not find %s !", path);
152 }
153 }
154 else {
155 REPORT_ERROR_STATIC(ErrorManagement::FatalError,
156 "Could not find %s !", path);
157 }
158 }
159
160 return 0;
161}
This example shows how to read and write directly from a registered C struct
:
1/**
2 * @file ConfigurationExample6.cpp
3 * @brief Source file for class ConfigurationExample6
4 * @date 08/04/2018
5 * @author Andre' Neto
6 *
7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
8 * the Development of Fusion Energy ('Fusion for Energy').
9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
11 * You may not use this work except in compliance with the Licence.
12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
13 *
14 * @warning Unless required by applicable law or agreed to in writing,
15 * software distributed under the Licence is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17 * or implied. See the Licence permissions and limitations under the Licence.
18
19 * @details This source file contains the definition of all the methods for
20 * the class ConfigurationExample6 (public, protected, and private). Be aware that some
21 * methods, such as those inline could be defined on the header file, instead.
22 */
23
24#define DLL_API
25
26/*---------------------------------------------------------------------------*/
27/* Standard header includes */
28/*---------------------------------------------------------------------------*/
29
30/*---------------------------------------------------------------------------*/
31/* Project header includes */
32/*---------------------------------------------------------------------------*/
33#include "AdvancedErrorManagement.h"
34#include "ClassRegistryDatabase.h"
35#include "ClassRegistryItemT.h"
36#include "ConfigurationDatabase.h"
37#include "ErrorLoggerExample.h"
38#include "IntrospectionT.h"
39#include "Matrix.h"
40#include "Object.h"
41#include "ObjectRegistryDatabase.h"
42#include "Reference.h"
43#include "ReferenceT.h"
44#include "StandardParser.h"
45#include "StreamString.h"
46#include "Vector.h"
47
48/*---------------------------------------------------------------------------*/
49/* Static definitions */
50/*---------------------------------------------------------------------------*/
51namespace MARTe2Tutorial {
52
53/**
54 * Configuration structures
55 */
56struct Gain {
57 MARTe::float32 gain1;
58 MARTe::float32 gain2;
59 MARTe::float32 gain3[6];
60};
61struct Gains {
62 struct Gain lowGains;
63 struct Gain highGains;
64};
65
66DECLARE_CLASS_MEMBER(Gain, gain1, float32, "", "");
67DECLARE_CLASS_MEMBER(Gain, gain2, float32, "", "");
68DECLARE_CLASS_MEMBER(Gain, gain3, float32, "[6]", "");
69
70static const MARTe::IntrospectionEntry* GainStructEntries[] = { &Gain_gain1_introspectionEntry,
71 &Gain_gain2_introspectionEntry, &Gain_gain3_introspectionEntry, 0 };
72
73DECLARE_STRUCT_INTROSPECTION(Gain, GainStructEntries)
74
75DECLARE_CLASS_MEMBER(Gains, lowGains, Gain, "", "");
76DECLARE_CLASS_MEMBER(Gains, highGains, Gain, "", "");
77static const MARTe::IntrospectionEntry* GainsStructEntries[] = { &Gains_lowGains_introspectionEntry,
78 &Gains_highGains_introspectionEntry, 0 };
79
80DECLARE_STRUCT_INTROSPECTION(Gains, GainsStructEntries)
81
82/**
83 * @brief A MARTe::Object class that will read directly read its configuration from a structure.
84 */
85class ControllerEx1: public MARTe::ReferenceContainer {
86public:
87 CLASS_REGISTER_DECLARATION()
88
89 /**
90 * @brief NOOP.
91 */
92ControllerEx1 () {
93
94 }
95
96 virtual ~ControllerEx1 () {
97 if (GetName() != NULL) {
98 REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
99 "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
100 }
101 }
102
103 /**
104 * Read all the properties from the Gains struct (names must match the ones of the struct!
105 * Gains1 = {
106 * lowGain = {
107 * Gain1 = -1.0
108 * Gain2 = -3.0
109 * Gain3 = {-9.0, -8.0, -7.0, -6.0, -5.0, -4.0}
110 * }
111 * High = {
112 * Gain1 = 7.0
113 * Gain2 = 9.0
114 * }
115 * }
116 * Gains2 = {
117 * lowGain = {
118 * Gain1 = -1.1
119 * Gain2 = -3.1
120 * Gain3 = {-9.1, -8.1, -7.1, -6.1, -5.1, -4.1}
121 * }
122 * High = {
123 * Gain1 = 7.1
124 * Gain2 = 9.1
125 * Gain3 = {9.1, 8.1, 7.1, 6.1, 5.1, 4.1}"
126 * }
127 * }
128 */
129 virtual bool Initialise(MARTe::StructuredDataI &data) {
130 using namespace MARTe;
131 bool ok = ReferenceContainer::Initialise(data);
132 ClassRegistryItem *gainsStructClassRegistryItem = NULL_PTR(ClassRegistryItem *);
133 if (ok) {
134 //Search for the registered structure
135 gainsStructClassRegistryItem = ClassRegistryDatabase::Instance()->Find("Gains");
136 }
137 const ClassProperties *gainsStructClassProperties = NULL_PTR(ClassProperties *);
138 if (ok) {
139 gainsStructClassProperties = gainsStructClassRegistryItem->GetClassProperties();
140 }
141 ClassUID gainsStructClassUID;
142 AnyType gainsAnyType;
143 if (ok) {
144 gainsStructClassUID = gainsStructClassProperties->GetUniqueIdentifier();
145 //Encapsulate the AnyType
146
147 TypeDescriptor gainsTypeDescriptor(false, gainsStructClassUID);
148 gainsAnyType = AnyType(gainsTypeDescriptor, 0u, &gains1);
149 ok = data.Read("Gains1", gainsAnyType);
150 if (ok) {
151 gainsAnyType = AnyType(gainsTypeDescriptor, 0u, &gains2);
152 ok = data.Read("Gains2", gainsAnyType);
153 if (!ok) {
154 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gains2 structure");
155 }
156 }
157 else {
158 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gains1 structure");
159 }
160 }
161
162 if (ok) {
163 REPORT_ERROR(ErrorManagement::Information, "Gains 1 low gains");
164 PrintGains(&gains1.lowGains);
165 REPORT_ERROR(ErrorManagement::Information, "Gains 1 high gains");
166 PrintGains(&gains1.highGains);
167 REPORT_ERROR(ErrorManagement::Information, "Gains 2 low gains");
168 PrintGains(&gains2.lowGains);
169 REPORT_ERROR(ErrorManagement::Information, "Gains 2 high gains");
170 PrintGains(&gains2.highGains);
171 }
172
173 return ok;
174 }
175
176private:
177 void PrintGains(Gain *gainToPrint) {
178 using namespace MARTe;
179 REPORT_ERROR(ErrorManagement::Information, "Gain1 %f", gainToPrint->gain1);
180 REPORT_ERROR(ErrorManagement::Information, "Gain2 %f", gainToPrint->gain2);
181 REPORT_ERROR(ErrorManagement::Information, "Gain3 %f", gainToPrint->gain3);
182 }
183
184 /**
185 * A list of properties.
186 */
187 Gains gains1;
188 Gains gains2;
189};
190
191CLASS_REGISTER(ControllerEx1, "")
192
193}
194/*---------------------------------------------------------------------------*/
195/* Method definitions */
196/*---------------------------------------------------------------------------*/
197
198int main(int argc, char **argv) {
199 using namespace MARTe;
200 using namespace MARTe2Tutorial;
201 SetErrorProcessFunction(&ErrorProcessExampleFunction);
202
203 StreamString configurationCfg = ""
204 "+ControllerInstance1 = {\n"
205 " Class = ControllerEx1\n"
206 " Gains1 = {\n"
207 " lowGains = {\n"
208 " Gain1 = -1.0\n"
209 " Gain2 = -3.0\n"
210 " Gain3 = {-9.0, -8.0, -7.0, -6.0, -5.0, -4.0}\n"
211 " }\n"
212 " highGains = {\n"
213 " Gain1 = 7.0\n"
214 " Gain2 = 9.0\n"
215 " Gain3 = {9.0, 8.0, 7.0, 6.0, 5.0, 4.0}\n"
216 " }\n"
217 " }\n"
218 " Gains2 = {\n"
219 " lowGains = {\n"
220 " Gain1 = -1.0\n"
221 " Gain2 = -3.0\n"
222 " Gain3 = {-9.1, -8.1, -7.1, -6.1, -5.1, -4.1}\n"
223 " }\n"
224 " highGains = {\n"
225 " Gain1 = 7.0\n"
226 " Gain2 = 9.0\n"
227 " Gain3 = {9.1, 8.1, 7.1, 6.1, 5.1, 4.1}\n"
228 " }\n"
229 " }\n"
230 "}";
231
232 REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
233 ConfigurationDatabase cdb;
234 StreamString err;
235 //Force the string to be seeked to the beginning.
236 configurationCfg.Seek(0LLU);
237 StandardParser parser(configurationCfg, cdb, &err);
238 bool ok = parser.Parse();
239 if (ok) {
240 //After parsing the tree is pointing at the last leaf
241 cdb.MoveToRoot();
242 ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
243 }
244 else {
245 StreamString errPrint;
246 errPrint.Printf("Failed to parse %s", err.Buffer());
247 REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
248 }
249
250 if (ok) {
251 REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the configuration file");
252 }
253
254 //Write a structure to a ConfigurationDatabase
255 ClassRegistryItem *gainsStructClassRegistryItem = NULL_PTR(ClassRegistryItem *);
256 if (ok) {
257 gainsStructClassRegistryItem = ClassRegistryDatabase::Instance()->Find("Gains");
258 }
259 AnyType gainsAnyType;
260 const ClassProperties *gainsStructClassProperties = NULL_PTR(ClassProperties *);
261 if (ok) {
262 gainsStructClassProperties = gainsStructClassRegistryItem->GetClassProperties();
263 }
264 if (ok) {
265 ConfigurationDatabase cdb;
266 Gains gainsExample;
267 gainsExample.lowGains.gain1 = 1;
268 gainsExample.lowGains.gain2 = 2;
269 gainsExample.lowGains.gain3[0] = -1;
270 gainsExample.lowGains.gain3[5] = 1;
271 gainsExample.highGains.gain1 = -1;
272 gainsExample.highGains.gain2 = -2;
273 gainsExample.highGains.gain3[0] = 1;
274 gainsExample.highGains.gain3[5] = -1;
275
276 ClassUID gainsStructClassUID = gainsStructClassProperties->GetUniqueIdentifier();
277 //Encapsulate the AnyType
278
279 TypeDescriptor gainsTypeDescriptor(false, gainsStructClassUID);
280 gainsAnyType = AnyType(gainsTypeDescriptor, 0u, &gainsExample);
281 ok = cdb.Write("DumpStruct", gainsAnyType);
282 if (ok) {
283 cdb.MoveToRoot();
284 REPORT_ERROR_STATIC(ErrorManagement::Information, "Wrote structure %!", cdb);
285 }
286 }
287 return 0;
288}
Similar to the example below but the structures are registered using the configuration file:
1/**
2 * @file ConfigurationExample7.cpp
3 * @brief Source file for class ConfigurationExample7
4 * @date 08/04/2018
5 * @author Andre' Neto
6 *
7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
8 * the Development of Fusion Energy ('Fusion for Energy').
9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
11 * You may not use this work except in compliance with the Licence.
12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
13 *
14 * @warning Unless required by applicable law or agreed to in writing,
15 * software distributed under the Licence is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17 * or implied. See the Licence permissions and limitations under the Licence.
18
19 * @details This source file contains the definition of all the methods for
20 * the class ConfigurationExample7 (public, protected, and private). Be aware that some
21 * methods, such as those inline could be defined on the header file, instead.
22 */
23
24#define DLL_API
25
26/*---------------------------------------------------------------------------*/
27/* Standard header includes */
28/*---------------------------------------------------------------------------*/
29
30/*---------------------------------------------------------------------------*/
31/* Project header includes */
32/*---------------------------------------------------------------------------*/
33#include "AdvancedErrorManagement.h"
34#include "ClassRegistryDatabase.h"
35#include "ClassRegistryItemT.h"
36#include "ConfigurationDatabase.h"
37#include "ErrorLoggerExample.h"
38#include "IntrospectionT.h"
39#include "Matrix.h"
40#include "Object.h"
41#include "ObjectRegistryDatabase.h"
42#include "Reference.h"
43#include "ReferenceT.h"
44#include "StandardParser.h"
45#include "StreamString.h"
46#include "Vector.h"
47
48/*---------------------------------------------------------------------------*/
49/* Static definitions */
50/*---------------------------------------------------------------------------*/
51namespace MARTe2Tutorial {
52
53/**
54 * Configuration structures
55 */
56#ifdef __GNUC__
57struct __attribute__((__packed__)) GainFromIntroStructure {
58 MARTe::float32 gain1;
59 MARTe::float32 gain2;
60 MARTe::float32 gain3[6];
61};
62struct __attribute__((__packed__)) GainsFromIntroStructure {
63 struct GainFromIntroStructure lowGains[2];
64 struct GainFromIntroStructure highGains;
65};
66#endif
67
68#ifdef _MSC_VER
69#pragma pack(push,1)
70struct GainFromIntroStructure {
71 MARTe::float32 gain1;
72 MARTe::float32 gain2;
73 MARTe::float32 gain3[6];
74};
75struct GainsFromIntroStructure {
76 struct GainFromIntroStructure lowGains[2];
77 struct GainFromIntroStructure highGains;
78};
79#pragma pack(pop)
80#endif
81
82/**
83 * @brief A MARTe::Object class that will read directly read its configuration from a structure.
84 */
85class ControllerEx1: public MARTe::ReferenceContainer {
86public:
87 CLASS_REGISTER_DECLARATION()
88
89 /**
90 * @brief NOOP.
91 */
92ControllerEx1 () {
93
94 }
95
96 virtual ~ControllerEx1 () {
97 if (GetName() != NULL) {
98 REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at %s [%s]. "
99 "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
100 }
101 }
102
103 /**
104 * Read all the properties from the Gains struct (names must match the ones of the struct!
105 * Gains1 = {
106 * lowGain[0] = {
107 * Gain1 = -1.0
108 * Gain2 = -3.0
109 * Gain3 = {-9.0, -8.0, -7.0, -6.0, -5.0, -4.0}
110 * }
111 * lowGain[1] = {
112 * Gain1 = -2.0
113 * Gain2 = -6.0
114 * Gain3 = {-18.0, -16.0, -14.0, -12.0, -10.0, -8.0}
115 * }
116 * High = {
117 * Gain1 = 7.0
118 * Gain2 = 9.0
119 * }
120 * }
121 * Gains2 = {
122 * lowGain = {
123 * Gain1 = -1.1
124 * Gain2 = -3.1
125 * Gain3 = {-9.1, -8.1, -7.1, -6.1, -5.1, -4.1}
126 * }
127 * High = {
128 * Gain1 = 7.1
129 * Gain2 = 9.1
130 * Gain3 = {9.1, 8.1, 7.1, 6.1, 5.1, 4.1}"
131 * }
132 * }
133 */
134 virtual bool Initialise(MARTe::StructuredDataI &data) {
135 using namespace MARTe;
136 bool ok = ReferenceContainer::Initialise(data);
137 ClassRegistryItem *gainsStructClassRegistryItem = NULL_PTR(ClassRegistryItem *);
138 if (ok) {
139 //Search for the registered structure
140 gainsStructClassRegistryItem = ClassRegistryDatabase::Instance()->Find("GainsFromIntroStructure");
141 }
142 const ClassProperties *gainsStructClassProperties = NULL_PTR(ClassProperties *);
143 if (ok) {
144 gainsStructClassProperties = gainsStructClassRegistryItem->GetClassProperties();
145 }
146 ClassUID gainsStructClassUID;
147 AnyType gainsAnyType;
148 if (ok) {
149 gainsStructClassUID = gainsStructClassProperties->GetUniqueIdentifier();
150 //Encapsulate the AnyType
151
152 TypeDescriptor gainsTypeDescriptor(false, gainsStructClassUID);
153 gainsAnyType = AnyType(gainsTypeDescriptor, 0u, &gains1);
154 ok = data.Read("Gains1", gainsAnyType);
155 if (ok) {
156 gainsAnyType = AnyType(gainsTypeDescriptor, 0u, &gains2);
157 ok = data.Read("Gains2", gainsAnyType);
158 if (!ok) {
159 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gains2 structure");
160 }
161 }
162 else {
163 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gains1 structure");
164 }
165 }
166
167 if (ok) {
168 REPORT_ERROR(ErrorManagement::Information, "Gains 1 low[0] gains");
169 PrintGains(&gains1.lowGains[0]);
170 REPORT_ERROR(ErrorManagement::Information, "Gains 1 low[1] gains");
171 PrintGains(&gains1.lowGains[1]);
172 REPORT_ERROR(ErrorManagement::Information, "Gains 1 high gains");
173 PrintGains(&gains1.highGains);
174 REPORT_ERROR(ErrorManagement::Information, "Gains 2 low[0] gains");
175 PrintGains(&gains2.lowGains[0]);
176 REPORT_ERROR(ErrorManagement::Information, "Gains 2 low[1] gains");
177 PrintGains(&gains2.lowGains[1]);
178 REPORT_ERROR(ErrorManagement::Information, "Gains 2 high gains");
179 PrintGains(&gains2.highGains);
180 }
181
182 return ok;
183 }
184
185private:
186 void PrintGains(GainFromIntroStructure *gainToPrint) {
187 using namespace MARTe;
188 float32 gain1 = gainToPrint->gain1;
189 float32 gain2 = gainToPrint->gain2;
190 float32 gain3[6] = {gainToPrint->gain3[0], gainToPrint->gain3[1], gainToPrint->gain3[2], gainToPrint->gain3[3], gainToPrint->gain3[4], gainToPrint->gain3[5]};
191 REPORT_ERROR(ErrorManagement::Information, "Gain1 %f", gain1);
192 REPORT_ERROR(ErrorManagement::Information, "Gain2 %f", gain2);
193 REPORT_ERROR(ErrorManagement::Information, "Gain3 %f", gain3);
194 }
195
196 /**
197 * A list of properties.
198 */
199 GainsFromIntroStructure gains1;
200 GainsFromIntroStructure gains2;
201};
202
203CLASS_REGISTER(ControllerEx1, "")
204
205}
206/*---------------------------------------------------------------------------*/
207/* Method definitions */
208/*---------------------------------------------------------------------------*/
209
210int main(int argc, char **argv) {
211 using namespace MARTe;
212 using namespace MARTe2Tutorial;
213 SetErrorProcessFunction(&ErrorProcessExampleFunction);
214
215 StreamString configurationCfg = ""
216 "+Types = {\n"
217 " Class = ReferenceContainer\n"
218 " +GainFromIntroStructure = {\n"
219 " Class = IntrospectionStructure\n"
220 " gain1 = {\n"
221 " Type = float32\n"
222 " NumberOfElements = {1}\n"
223 " }\n"
224 " gain2 = {\n"
225 " Type = float32\n"
226 " NumberOfElements = {1}\n"
227 " }\n"
228 " gain3 = {\n"
229 " Type = float32\n"
230 " NumberOfElements = {6}\n"
231 " }\n"
232 " }\n"
233 " +GainsFromIntroStructure = {\n"
234 " Class = IntrospectionStructure\n"
235 " lowGains = {\n"
236 " Type = GainFromIntroStructure\n"
237 " NumberOfElements = {2}\n"
238 " }\n"
239 " highGains = {\n"
240 " Type = GainFromIntroStructure\n"
241 " }\n"
242 " }\n"
243 "}\n"
244 "+ControllerInstance1 = {\n"
245 " Class = ControllerEx1\n"
246 " Gains1 = {\n"
247 " lowGains[0] = {\n"
248 " Gain1 = -1.0\n"
249 " Gain2 = -3.0\n"
250 " Gain3 = {-9.0, -8.0, -7.0, -6.0, -5.0, -4.0}\n"
251 " }\n"
252 " lowGains[1] = {\n"
253 " Gain1 = -2.0\n"
254 " Gain2 = -6.0\n"
255 " Gain3 = {-18.0, -16.0, -14.0, -12.0, -10.0, -8.0}\n"
256 " }\n"
257 " highGains = {\n"
258 " Gain1 = 7.0\n"
259 " Gain2 = 9.0\n"
260 " Gain3 = {9.0, 8.0, 7.0, 6.0, 5.0, 4.0}\n"
261 " }\n"
262 " }\n"
263 " Gains2 = {\n"
264 " lowGains[0] = {\n"
265 " Gain1 = -1.0\n"
266 " Gain2 = -3.0\n"
267 " Gain3 = {-9.1, -8.1, -7.1, -6.1, -5.1, -4.1}\n"
268 " }\n"
269 " lowGains[1] = {\n"
270 " Gain1 = -2.0\n"
271 " Gain2 = -6.0\n"
272 " Gain3 = {-18.2, -16.2, -14.2, -12.2, -10.2, -8.2}\n"
273 " }\n"
274 " highGains = {\n"
275 " Gain1 = 7.0\n"
276 " Gain2 = 9.0\n"
277 " Gain3 = {9.1, 8.1, 7.1, 6.1, 5.1, 4.1}\n"
278 " }\n"
279 " }\n"
280 "}";
281
282 REPORT_ERROR_STATIC(ErrorManagement::Information, "Loading CFG:\n%s", configurationCfg.Buffer());
283 ConfigurationDatabase cdb;
284 StreamString err;
285 //Force the string to be seeked to the beginning.
286 configurationCfg.Seek(0LLU);
287 StandardParser parser(configurationCfg, cdb, &err);
288 bool ok = parser.Parse();
289 if (ok) {
290 //After parsing the tree is pointing at the last leaf
291 cdb.MoveToRoot();
292 ok = ObjectRegistryDatabase::Instance()->Initialise(cdb);
293 }
294 else {
295 StreamString errPrint;
296 errPrint.Printf("Failed to parse %s", err.Buffer());
297 REPORT_ERROR_STATIC(ErrorManagement::ParametersError, errPrint.Buffer());
298 }
299
300 if (ok) {
301 REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully loaded the configuration file");
302 }
303
304 //Write a structure to a ConfigurationDatabase
305 ClassRegistryItem *gainsStructClassRegistryItem = NULL_PTR(ClassRegistryItem *);
306 if (ok) {
307 gainsStructClassRegistryItem = ClassRegistryDatabase::Instance()->Find("GainsFromIntroStructure");
308 }
309 AnyType gainsAnyType;
310 const ClassProperties *gainsStructClassProperties = NULL_PTR(ClassProperties *);
311 if (ok) {
312 gainsStructClassProperties = gainsStructClassRegistryItem->GetClassProperties();
313 }
314 if (ok) {
315 ConfigurationDatabase cdb;
316 GainsFromIntroStructure gainsExample;
317 gainsExample.lowGains[0].gain1 = 1;
318 gainsExample.lowGains[0].gain2 = 2;
319 gainsExample.lowGains[1].gain3[0] = -1;
320 gainsExample.lowGains[1].gain3[5] = 1;
321 gainsExample.highGains.gain1 = -1;
322 gainsExample.highGains.gain2 = -2;
323 gainsExample.highGains.gain3[0] = 1;
324 gainsExample.highGains.gain3[5] = -1;
325
326 ClassUID gainsStructClassUID = gainsStructClassProperties->GetUniqueIdentifier();
327 //Encapsulate the AnyType
328
329 TypeDescriptor gainsTypeDescriptor(false, gainsStructClassUID);
330 gainsAnyType = AnyType(gainsTypeDescriptor, 0u, &gainsExample);
331 ok = cdb.Write("DumpStruct", gainsAnyType);
332 if (ok) {
333 cdb.MoveToRoot();
334 REPORT_ERROR_STATIC(ErrorManagement::Information, "Wrote structure %!", cdb);
335 }
336 }
337 return 0;
338}
Instructions on how to compile and execute the example can be found here.
Example on how to preprocess complex configuration files:
1#ifdef ENABLE_WEB_BROWSING
2#include "RTApp-6-Web.cfg"
3#endif
4#include "RTApp-6-StateMachine.cfg"
5#include "RTApp-6-RTApp.cfg"
1#############################################################
2#
3# Copyright 2015 F4E | European Joint Undertaking for ITER
4# and the Development of Fusion Energy ('Fusion for Energy')
5#
6# Licensed under the EUPL, Version 1.1 or - as soon they
7# will be approved by the European Commission - subsequent
8# versions of the EUPL (the "Licence");
9# You may not use this work except in compliance with the
10# Licence.
11# You may obtain a copy of the Licence at:
12#
13# http://ec.europa.eu/idabc/eupl
14#
15# Unless required by applicable law or agreed to in
16# writing, software distributed under the Licence is
17# distributed on an "AS IS" basis,
18# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
19# express or implied.
20# See the Licence for the specific language governing
21# permissions and limitations under the Licence.
22#
23#############################################################
24
25#Named of the unit files to be compiled
26OBJSX=RTApp-6.x
27
28#Location of the Build directory where the configuration file will be written to
29BUILD_DIR?=.
30
31#Location of the MakeDefaults directory.
32#Note that the MARTe2_DIR environment variable
33#must have been exported before
34MARTe2_MAKEDEFAULT_DIR?=$(MARTe2_DIR)/MakeDefaults
35
36include $(MARTe2_MAKEDEFAULT_DIR)/MakeStdLibDefs.$(TARGET)
37
38CFLAGS += -DENABLE_WEB_BROWSING
39
40all: $(OBJS)
41 echo $(OBJS)
42
43include $(MARTe2_MAKEDEFAULT_DIR)/MakeStdLibRules.$(TARGET)
Example with post-processing of variables:
1Parameters = {
2 T1_FREQUENCY = (uint32)10000
3 T2_FREQUENCY = (uint32)1
4 SAMPLES = (uint32|"Parameters.T1_FREQUENCY / Parameters.T2_FREQUENCY")
5}
6$TestApp = {
7 Class = RealTimeApplication
8 +Functions = {
9 Class = ReferenceContainer
10 +GAMTimer = {
11 Class = IOGAM
12 InputSignals = {
13 Counter = {
14 DataSource = Timer
15 Type = uint32
16 }
17 Time = {
18 Frequency = (uint32|"Parameters.T1_FREQUENCY")
19 DataSource = Timer
20 Type = uint32
21 }
22 }
23 OutputSignals = {
24 Counter = {
25 DataSource = DDB1
26 Type = uint32
27 }
28 Time = {
29 DataSource = DDB1
30 Type = uint32
31 }
32 }
33 }
34 +GAMFixed1 = {
35 Class = FixedGAMExample1
36 Gain = 2
37 InputSignals = {
38 Counter = {
39 DataSource = DDB1
40 Type = uint32
41 }
42 }
43 OutputSignals = {
44 GainCounter = {
45 DataSource = DDB1
46 Type = uint32
47 }
48 }
49 }
50 +GAMT1ToT2 = {
51 Class = IOGAM
52 InputSignals = {
53 Counter = {
54 DataSource = DDB1
55 Type = uint32
56 }
57 GainCounter = {
58 DataSource = DDB1
59 Type = uint32
60 }
61 State1_Thread1_CycleTime = {
62 Alias = State1.Thread1_CycleTime
63 DataSource = Timings
64 Type = uint32
65 }
66 GAMTimer_ReadTime = {
67 DataSource = Timings
68 Type = uint32
69 }
70 GAMTimer_ExecTime = {
71 DataSource = Timings
72 Type = uint32
73 }
74 GAMTimer_WriteTime = {
75 DataSource = Timings
76 Type = uint32
77 }
78 GAMFixed1_ReadTime = {
79 DataSource = Timings
80 Type = uint32
81 }
82 GAMFixed1_ExecTime = {
83 DataSource = Timings
84 Type = uint32
85 }
86 GAMFixed1_WriteTime = {
87 DataSource = Timings
88 Type = uint32
89 }
90 }
91 OutputSignals = {
92 Counter = {
93 DataSource = RTThreadSynch
94 Type = uint32
95 }
96 GainCounter = {
97 DataSource = RTThreadSynch
98 Type = uint32
99 }
100 State1_Thread1_CycleTime = {
101 DataSource = RTThreadSynch
102 Type = uint32
103 }
104 GAMTimer_ReadTime = {
105 DataSource = RTThreadSynch
106 Type = uint32
107 }
108 GAMTimer_ExecTime = {
109 DataSource = RTThreadSynch
110 Type = uint32
111 }
112 GAMTimer_WriteTime = {
113 DataSource = RTThreadSynch
114 Type = uint32
115 }
116 GAMFixed1_ReadTime = {
117 DataSource = RTThreadSynch
118 Type = uint32
119 }
120 GAMFixed1_ExecTime = {
121 DataSource = RTThreadSynch
122 Type = uint32
123 }
124 GAMFixed1_WriteTime = {
125 DataSource = RTThreadSynch
126 Type = uint32
127 }
128 }
129 }
130 +GAMT2FromT1 = {
131 Class = IOGAM
132 InputSignals = {
133 Counter = {
134 DataSource = RTThreadSynch
135 Samples = (uint32|"Parameters.SAMPLES")
136 Type = uint32
137 }
138 GainCounter = {
139 DataSource = RTThreadSynch
140 Samples = (uint32|"Parameters.SAMPLES")
141 Type = uint32
142 }
143 State1_Thread1_CycleTime = {
144 DataSource = RTThreadSynch
145 Samples = (uint32|"Parameters.SAMPLES")
146 Type = uint32
147 }
148 GAMTimer_ReadTime = {
149 DataSource = RTThreadSynch
150 Samples = (uint32|"Parameters.SAMPLES")
151 Type = uint32
152 }
153 GAMTimer_ExecTime = {
154 DataSource = RTThreadSynch
155 Samples = (uint32|"Parameters.SAMPLES")
156 Type = uint32
157 }
158 GAMTimer_WriteTime = {
159 DataSource = RTThreadSynch
160 Samples = (uint32|"Parameters.SAMPLES")
161 Type = uint32
162 }
163 GAMFixed1_ReadTime = {
164 DataSource = RTThreadSynch
165 Samples = (uint32|"Parameters.SAMPLES")
166 Type = uint32
167 }
168 GAMFixed1_ExecTime = {
169 DataSource = RTThreadSynch
170 Samples = (uint32|"Parameters.SAMPLES")
171 Type = uint32
172 }
173 GAMFixed1_WriteTime = {
174 DataSource = RTThreadSynch
175 Samples = (uint32|"Parameters.SAMPLES")
176 Type = uint32
177 }
178 }
179 OutputSignals = {
180 Counter = {
181 DataSource = DDB2
182 NumberOfElements = 10000
183 Type = uint32
184 }
185 GainCounter = {
186 DataSource = DDB2
187 NumberOfElements = 10000
188 Type = uint32
189 }
190 State1_Thread1_CycleTime = {
191 DataSource = DDB2
192 NumberOfElements = 10000
193 Type = uint32
194 }
195 GAMTimer_ReadTime = {
196 DataSource = DDB2
197 NumberOfElements = 10000
198 Type = uint32
199 }
200 GAMTimer_ExecTime = {
201 DataSource = DDB2
202 NumberOfElements = 10000
203 Type = uint32
204 }
205 GAMTimer_WriteTime = {
206 DataSource = DDB2
207 NumberOfElements = 10000
208 Type = uint32
209 }
210 GAMFixed1_ReadTime = {
211 DataSource = DDB2
212 NumberOfElements = 10000
213 Type = uint32
214 }
215 GAMFixed1_ExecTime = {
216 DataSource = DDB2
217 NumberOfElements = 10000
218 Type = uint32
219 }
220 GAMFixed1_WriteTime = {
221 DataSource = DDB2
222 NumberOfElements = 10000
223 Type = uint32
224 }
225 }
226 }
227 +GAMDisplay = {
228 Class = IOGAM
229 InputSignals = {
230 Counter = {
231 DataSource = DDB2
232 Ranges = {{0, 10}}
233 Type = uint32
234 }
235 GainCounter = {
236 DataSource = DDB2
237 Ranges = {{0, 10}}
238 Type = uint32
239 }
240 State1_Thread1_CycleTime = {
241 DataSource = DDB2
242 Ranges = {{0, 10}}
243 Type = uint32
244 }
245 GAMTimer_ReadTime = {
246 DataSource = DDB2
247 Ranges = {{0, 10}}
248 Type = uint32
249 }
250 GAMTimer_ExecTime = {
251 DataSource = DDB2
252 Ranges = {{0, 10}}
253 Type = uint32
254 }
255 GAMTimer_WriteTime = {
256 DataSource = DDB2
257 Ranges = {{0, 10}}
258 Type = uint32
259 }
260 GAMFixed1_ReadTime = {
261 DataSource = DDB2
262 Ranges = {{0, 10}}
263 Type = uint32
264 }
265 GAMFixed1_ExecTime = {
266 DataSource = DDB2
267 Ranges = {{0, 10}}
268 Type = uint32
269 }
270 GAMFixed1_WriteTime = {
271 DataSource = DDB2
272 Ranges = {{0, 10}}
273 Type = uint32
274 }
275 }
276 OutputSignals = {
277 Counter = {
278 DataSource = LoggerDataSource
279 NumberOfElements = 11
280 Type = uint32
281 }
282 GainCounter = {
283 DataSource = LoggerDataSource
284 NumberOfElements = 11
285 Type = uint32
286 }
287 State1_Thread1_CycleTime = {
288 DataSource = LoggerDataSource
289 NumberOfElements = 11
290 Type = uint32
291 }
292 GAMTimer_ReadTime = {
293 DataSource = LoggerDataSource
294 NumberOfElements = 11
295 Type = uint32
296 }
297 GAMTimer_ExecTime = {
298 DataSource = LoggerDataSource
299 NumberOfElements = 11
300 Type = uint32
301 }
302 GAMTimer_WriteTime = {
303 DataSource = LoggerDataSource
304 NumberOfElements = 11
305 Type = uint32
306 }
307 GAMFixed1_ReadTime = {
308 DataSource = LoggerDataSource
309 NumberOfElements = 11
310 Type = uint32
311 }
312 GAMFixed1_ExecTime = {
313 DataSource = LoggerDataSource
314 NumberOfElements = 11
315 Type = uint32
316 }
317 GAMFixed1_WriteTime = {
318 DataSource = LoggerDataSource
319 NumberOfElements = 11
320 Type = uint32
321 }
322 }
323 }
324 }
325 +Data = {
326 Class = ReferenceContainer
327 DefaultDataSource = DDB2
328 +DDB1 = {
329 Class = GAMDataSource
330 }
331 +DDB2 = {
332 Class = GAMDataSource
333 }
334 +LoggerDataSource = {
335 Class = LoggerDataSource
336 }
337 +RTThreadSynch = {
338 Class = RealTimeThreadSynchronisation
339 Timeout = 10000 //Timeout in ms to wait for the thread to cycle.
340 }
341 +Timings = {
342 Class = TimingDataSource
343 }
344 +Timer = {
345 Class = LinuxTimer
346 SleepNature = "Default"
347 Signals = {
348 Counter = {
349 Type = uint32
350 }
351 Time = {
352 Type = uint32
353 }
354 }
355 }
356 }
357 +States = {
358 Class = ReferenceContainer
359 +State1 = {
360 Class = RealTimeState
361 +Threads = {
362 Class = ReferenceContainer
363 +Thread1 = {
364 Class = RealTimeThread
365 CPUs = 0x2
366 Functions = {GAMTimer GAMFixed1 GAMT1ToT2}
367 }
368 +Thread2 = {
369 Class = RealTimeThread
370 CPUs = 0x1
371 Functions = {GAMT2FromT1 GAMDisplay}
372 }
373
374 }
375 }
376 }
377 +Scheduler = {
378 Class = GAMScheduler
379 TimingDataSource = Timings
380 }
381}