Object configuration
Objects are configured using inputs from a (tree) database. The access to this database is abstracted by the StructuredDataI interface.
The StructuredDataI offers methods to navigate the tree, create new nodes and read/write values from/to the tree leafs. Note that the StructuredDataI does not prescribe the configuration language of the database implementation (which can be e.g. XML, JSON, …).
Using the Object Initialise method the class implementation is expected to query the database, verify the values and assign them to its members.
...
virtual bool Initialise(MARTe::StructuredDataI &data) {
bool ok = Object::Initialise(data);
if (ok) {
ok = data.Read("Gain1", gain1);
...
The ConfigurationDatabase offers a read/write implementation of the StructuredDataI and is used internally in the core of the framework.
...
ConfigurationDatabase cdb;
cdb.Write("Gain1", 2);
...
Reading values
The StructuredDataI::Read
method accepts an AnyType and will automatically convert the value stored in the database into the target type (i.e. the type of the variable passed in the Read).
The return value should always be checked. It will fail if the type cannot be converted or if the variable does not exist in the database.
To read multi-dimensional values, the memory must be allocated beforehand. As a consequence, the type and dimension of the variable to be read must be known. This is achieved by querying the type StructuredDataI::GetType("NAME_OF_THE_LEAF_TO_QUERY");
.
...
AnyType arrayDescription = data.GetType("Modes");
ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
//The leaf exists
if (ok) {
numberOfElements = arrayDescription.GetNumberOfElements(0u);
...
if (ok) {
...
modesArray = new StreamString[numberOfElements];
Vector<StreamString> readVector(modesArray, numberOfElements);
ok = data.Read("Modes", readVector);
...
Warning
The StructuredDataI::GetType
method does not return any memory/value and shall only be used to query information about the type.
For matrices a similar strategy applies:
...
AnyType arrayDescription = data.GetType("Model");
ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
...
if (ok) {
numberOfDimensions = arrayDescription.GetNumberOfDimensions();
ok = (numberOfDimensions == 2u);
...
numberOfRows = arrayDescription.GetNumberOfElements(1u);
numberOfCols = arrayDescription.GetNumberOfElements(0u);
...
if (ok) {
Matrix<float32> modelMatrix(numberOfRows, numberOfCols);
ok = data.Read("Model", modelMatrix);
...
Reading values with the StructuredDataIHelper
As of v1.7.0 of MARTe2, the StructuredDataIHelper facilitates the reading and validation of configuration values. In particular, it allows to:
Read arrays and matrices without having to query for their size:
virtual bool Initialise(MARTe::StructuredDataI &data) {
bool ok = Object::Initialise(data);
StructuredDataIHelper helper(data, this);
...
MARTe::int32 *referencesArray;
if (ok) {
uint32 nOfReferences = 0u;
ok = helper.ReadArray("References", referencesArray, nOfReferences);
}
...
MARTe::float32 **model;
if (ok) {
uint32 modelCols = 0u;
ok = helper.ReadMatrix("Model", model, modelRows, modelCols);
}
...
Automatically assign default values for parameters that are not defined:
virtual bool Initialise(MARTe::StructuredDataI &data) {
bool ok = Object::Initialise(data);
StructuredDataIHelper helper(data, this);
...
//Assign default of 1.7 to gain2
ok = helper.Read("Gain2", gain2, 1.7);
...
Read “enum-like” types:
virtual bool Initialise(MARTe::StructuredDataI &data) {
bool ok = Object::Initialise(data);
StructuredDataIHelper helper(data, this);
...
const char8 * controllerTypesStr[] = {"C1", "C2", "C3"};
uint32 controllerTypes[] = {1, 2, 3};
ok = helper.ReadEnum("ControllerType", controllerType, controllerTypesStr, controllerTypes);
...
Validate parameters against simple mathematical expressions:
virtual bool Initialise(MARTe::StructuredDataI &data) {
bool ok = Object::Initialise(data);
StructuredDataIHelper helper(data, this);
...
if (ok) {
ok = helper.ReadValidated("Gain3", gain3, "(Gain3 > (float32)(-3.0)) && (Gain3 <= (float32)(0.0))");
}
Examples
The following example shows how to read parameters (including arrays and matrices).
1/**
2 * @file ConfigurationExample1.cpp
3 * @brief Source file for class ConfigurationExample1
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 ConfigurationExample1 (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 "Reference.h"
40#include "ReferenceT.h"
41#include "StreamString.h"
42#include "Vector.h"
43
44/*---------------------------------------------------------------------------*/
45/* Static definitions */
46/*---------------------------------------------------------------------------*/
47
48/*---------------------------------------------------------------------------*/
49/* Method definitions */
50/*---------------------------------------------------------------------------*/
51namespace MARTe2Tutorial {
52/**
53 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
54 */
55class ControllerEx1: public MARTe::Object {
56public:
57 CLASS_REGISTER_DECLARATION()
58
59 /**
60 * @brief NOOP.
61 */
62 ControllerEx1 () {
63 gain1 = 0u;
64 gain2 = 0.f;
65 mode = "";
66 referencesArray = NULL;
67 modesArray = NULL;
68 }
69
70 virtual ~ControllerEx1 () {
71 using namespace MARTe;
72 if (referencesArray != NULL) {
73 delete [] referencesArray;
74 }
75 if (modesArray != NULL) {
76 delete [] modesArray;
77 }
78 if (GetName() != NULL) {
79 REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references pointing at %s [%s]. "
80 "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
81 }
82 }
83
84 /**
85 * Read all the properties
86 */
87 virtual bool Initialise(MARTe::StructuredDataI &data) {
88 using namespace MARTe;
89 bool ok = Object::Initialise(data);
90 if (ok) {
91 ok = data.Read("Gain1", gain1);
92 if (ok) {
93 REPORT_ERROR(ErrorManagement::Information, "gain1 set to %d", gain1);
94 }
95 else {
96 REPORT_ERROR(ErrorManagement::ParametersError, "The Gain1 property shall be set");
97 }
98 }
99 if (ok) {
100 ok = data.Read("Gain2", gain2);
101 if (ok) {
102 REPORT_ERROR(ErrorManagement::Information, "gain2 set to %f", gain2);
103 }
104 else {
105 REPORT_ERROR(ErrorManagement::ParametersError, "The Gain2 property shall be set");
106 }
107 }
108
109 if (ok) {
110 mode = "";
111 ok = data.Read("Mode", mode);
112 if (ok) {
113 REPORT_ERROR(ErrorManagement::Information, "mode set to %s", mode.Buffer());
114 }
115 else {
116 REPORT_ERROR(ErrorManagement::ParametersError, "The Mode property shall be set");
117 }
118 }
119
120 if (ok) {
121 AnyType arrayDescription = data.GetType("References");
122 ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
123 uint32 numberOfElements = 0u;
124 if (ok) {
125 numberOfElements = arrayDescription.GetNumberOfElements(0u);
126 ok = (numberOfElements > 0u);
127 if (!ok) {
128 REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array");
129 }
130 }
131 if (ok) {
132 //Reconfiguration...
133 if (referencesArray != NULL) {
134 delete [] referencesArray;
135 }
136 referencesArray = new int32[numberOfElements];
137 Vector<int32> readVector(referencesArray, numberOfElements);
138 ok = data.Read("References", readVector);
139 if (ok) {
140 REPORT_ERROR(ErrorManagement::Information, "referencesArray set to %d", readVector);
141 }
142 else {
143 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the References");
144 }
145 }
146 }
147
148 if (ok) {
149 AnyType arrayDescription = data.GetType("Modes");
150 ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
151 uint32 numberOfElements = 0u;
152 if (ok) {
153 numberOfElements = arrayDescription.GetNumberOfElements(0u);
154 ok = (numberOfElements > 0u);
155 if (!ok) {
156 REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array");
157 }
158 }
159 if (ok) {
160 //Reconfiguration...
161 if (modesArray != NULL) {
162 delete [] modesArray;
163 }
164 modesArray = new StreamString[numberOfElements];
165 Vector<StreamString> readVector(modesArray, numberOfElements);
166 ok = data.Read("Modes", readVector);
167 if (ok) {
168 uint32 i;
169 for (i=0u; i<numberOfElements; i++) {
170 REPORT_ERROR(ErrorManagement::Information, "modesArray[%d] set to %s", i,readVector[i].Buffer());
171 }
172 }
173 else {
174 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Modes");
175 }
176 }
177 }
178
179 if (ok) {
180 AnyType arrayDescription = data.GetType("Model");
181 ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
182 uint32 numberOfDimensions = 0u;
183 if (ok) {
184 numberOfDimensions = arrayDescription.GetNumberOfDimensions();
185 ok = (numberOfDimensions == 2u);
186 if (!ok) {
187 REPORT_ERROR(ErrorManagement::ParametersError, "Model is not a Matrix");
188 }
189 }
190 uint32 numberOfRows = 0u;
191 uint32 numberOfCols = 0u;
192 if (ok) {
193 numberOfRows = arrayDescription.GetNumberOfElements(1u);
194 numberOfCols = arrayDescription.GetNumberOfElements(0u);
195 ok = (numberOfRows > 0u);
196 if (!ok) {
197 REPORT_ERROR(ErrorManagement::ParametersError, "No rows defined in the matrix");
198 }
199 }
200 if (ok) {
201 ok = (numberOfCols > 0u);
202 if (!ok) {
203 REPORT_ERROR(ErrorManagement::ParametersError, "No columns defined in the matrix");
204 }
205 }
206 if (ok) {
207 Matrix<float32> modelMatrix(numberOfRows, numberOfCols);
208 ok = data.Read("Model", modelMatrix);
209 if (ok) {
210 REPORT_ERROR(ErrorManagement::Information, "modelMatrix set to %f", modelMatrix);
211 }
212 else {
213 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the References");
214 }
215 }
216 }
217
218 return ok;
219 }
220
221 /**
222 * A list of properties.
223 */
224 MARTe::uint32 gain1;
225 MARTe::float32 gain2;
226 MARTe::StreamString mode;
227 MARTe::int32 *referencesArray;
228 MARTe::StreamString *modesArray;
229};
230
231CLASS_REGISTER(ControllerEx1, "")
232
233}
234
235int main(int argc, char **argv) {
236 using namespace MARTe;
237 using namespace MARTe2Tutorial;
238 SetErrorProcessFunction(&ErrorProcessExampleFunction);
239
240 CCString className1 = "ControllerEx1";
241
242 int32 int32Arr[] = { -1, 2, -3, 4, -5 };
243 const char8 *stringArr[] = { "A", "BB", "CCC", "DDDD", "EEEEE" };
244 float32 float32Mat[3][2] = { { -1.0, 2.3 }, { 4.7, -3.2 }, { -7.1, 5.6 } };
245
246 ReferenceT<ControllerEx1> ref1(className1,
247 GlobalObjectsDatabase::Instance()->GetStandardHeap());
248 //Automatically generate a new object instance based on the class name and on the correct Heap
249 //and with the template reference.
250 if (ref1.IsValid()) {
251 ref1->SetName("ControllerInstance1");
252 REPORT_ERROR_STATIC(ErrorManagement::Information,
253 "Successfully created an instance of %s", className1.GetList());
254 //Write a valid configuration.
255 {
256 ConfigurationDatabase cdb;
257 cdb.Write("Gain1", 2);
258 cdb.Write("Gain2", 1.5);
259 cdb.Write("Mode", "ASTRING");
260 cdb.Write("Modes", stringArr);
261 cdb.Write("References", int32Arr);
262 cdb.Write("Model", float32Mat);
263
264 if (ref1->Initialise(cdb)) {
265 REPORT_ERROR_STATIC(ErrorManagement::Information,
266 "Successfully configured instance of %s",
267 ref1->GetName());
268 } else {
269 REPORT_ERROR_STATIC(ErrorManagement::FatalError,
270 "Failed to configure instance of %s", ref1->GetName());
271 }
272 }
273 //Write an invalid configuration
274 {
275 ConfigurationDatabase cdb;
276 cdb.Write("Gain1", 2);
277 cdb.Write("Gain2", 1.5);
278 cdb.Write("Mode", "ASTRING");
279 cdb.Write("Modes", stringArr);
280 cdb.Write("References", int32Arr);
281 cdb.Write("Model", int32Arr);
282 if (!ref1->Initialise(cdb)) {
283 REPORT_ERROR_STATIC(ErrorManagement::Information,
284 "As expected failed to reconfigure instance of %s",
285 ref1->GetName());
286 }
287 }
288 }
289
290 return 0;
291}
This is a similar example, highlighting structured configurations.
1/**
2 * @file ConfigurationExample2.cpp
3 * @brief Source file for class ConfigurationExample2
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 ConfigurationExample2 (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 "Object.h"
38#include "Reference.h"
39#include "ReferenceT.h"
40#include "StreamString.h"
41#include "Vector.h"
42
43/*---------------------------------------------------------------------------*/
44/* Static definitions */
45/*---------------------------------------------------------------------------*/
46
47/*---------------------------------------------------------------------------*/
48/* Method definitions */
49/*---------------------------------------------------------------------------*/
50namespace MARTe2Tutorial {
51
52/**
53 * Configuration structures
54 */
55struct Gains {
56 MARTe::float32 gain1;
57 MARTe::float32 gain2;
58};
59
60struct Waveforms {
61 MARTe::float32 *times;
62 MARTe::float32 *values;
63};
64
65/**
66 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
67 */
68class ControllerEx1: public MARTe::Object {
69public:
70 CLASS_REGISTER_DECLARATION()
71
72 /**
73 * @brief NOOP.
74 */
75ControllerEx1 () {
76 slowWaveform.times = NULL;
77 slowWaveform.values = NULL;
78 fastWaveform.times = NULL;
79 fastWaveform.values = NULL;
80
81 }
82
83 virtual ~ControllerEx1 () {
84 if (slowWaveform.times != NULL) {
85 delete [] slowWaveform.times;
86 }
87 if (slowWaveform.values != NULL) {
88 delete [] slowWaveform.values;
89 }
90 if (fastWaveform.times != NULL) {
91 delete [] fastWaveform.times;
92 }
93 if (fastWaveform.values != NULL) {
94 delete [] fastWaveform.values;
95 }
96 if (GetName() != NULL) {
97 REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "No more references pointing at "
98 "%s [%s]. The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
99 }
100 }
101
102 /**
103 * Read all the properties which are organised inside a tree
104 * Gains = {
105 * Low = {
106 * Gain1 = -1.0;
107 * Gain2 = -3.0;
108 * }
109 * High = {
110 * Gain1 = 7.0;
111 * Gain2 = 9.0;
112 * }
113 * }
114 * References = {
115 * Slow = {
116 * Waveform = {
117 * Times = {0 0.1 0.2 1}
118 * Values = {1 2 3 4}
119 * }
120 * }
121 * Fast = {
122 * Waveform = {
123 * Times = {0 0.1 0.2 1}
124 * Values = {1 2 3 4}
125 * }
126 * }
127 * }
128 */
129 virtual bool Initialise(MARTe::StructuredDataI &data) {
130 using namespace MARTe;
131 bool ok = Object::Initialise(data);
132 if (ok) {
133 //Move in the tree
134 ok = data.MoveRelative("Gains");
135 if (!ok) {
136 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains section");
137 }
138 }
139 if (ok) {
140 ok = data.MoveRelative("Low");
141 if (!ok) {
142 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains.Low section");
143 }
144 }
145 if (ok) {
146 ok = data.Read("Gain1", lowGains.gain1);
147 if (ok) {
148 REPORT_ERROR(ErrorManagement::Information, "Gains.Low.Gain1 = %f", lowGains.gain1);
149 }
150 else {
151 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain1");
152 }
153 }
154 if (ok) {
155 ok = data.Read("Gain2", lowGains.gain2);
156 if (ok) {
157 REPORT_ERROR(ErrorManagement::Information, "Gains.Low.Gain1 = %f", lowGains.gain2);
158 }
159 else {
160 }
161 }
162 if (ok) {
163 ok = data.MoveToAncestor(1u);
164 if (!ok) {
165 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move back to the Gains section");
166 }
167 }
168 if (ok) {
169 ok = data.MoveRelative("High");
170 if (!ok) {
171 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the Gains.High section");
172 }
173 }
174 if (ok) {
175 ok = data.Read("Gain1", highGains.gain1);
176 if (ok) {
177 REPORT_ERROR(ErrorManagement::Information, "Gains.High.Gain1 = %f", highGains.gain1);
178 }
179 else {
180 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain1");
181 }
182 }
183 if (ok) {
184 ok = data.Read("Gain2", highGains.gain2);
185 if (ok) {
186 REPORT_ERROR(ErrorManagement::Information, "Gains.High.Gain1 = %f", highGains.gain2);
187 }
188 else {
189 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the Gain2");
190 }
191 }
192 if (ok) {
193 //Move to the ancestor
194 ok = data.MoveToAncestor(2u);
195 if (!ok) {
196 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move back to the References section");
197 }
198 }
199 if (ok) {
200 ok = data.MoveRelative("References.Slow.Waveform");
201 if (!ok) {
202 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the References.Slow.Waveform section");
203 }
204 }
205 if (ok) {
206 ok = ReadArray(data, "Times", slowWaveform.times);
207 }
208 if (ok) {
209 ok = ReadArray(data, "Values", slowWaveform.values);
210 }
211 //Move back to the parent
212 if (ok) {
213 ok = data.MoveToAncestor(2u);
214 }
215 if (ok) {
216 ok = data.MoveRelative("Fast.Waveform");
217 if (!ok) {
218 REPORT_ERROR(ErrorManagement::ParametersError, "Could not move to the References.fast.Waveform section");
219 }
220 }
221 if (ok) {
222 ok = ReadArray(data, "Times", fastWaveform.times);
223 }
224 if (ok) {
225 ok = ReadArray(data, "Values", fastWaveform.values);
226 }
227
228 return ok;
229 }
230
231private:
232 bool ReadArray(MARTe::StructuredDataI &data, const MARTe::char8 * const arrayName, MARTe::float32 *&dest) {
233 using namespace MARTe;
234 if (dest != NULL) {
235 delete [] dest;
236 }
237
238 AnyType arrayDescription = data.GetType(arrayName);
239 bool ok = arrayDescription.GetDataPointer() != NULL_PTR(void *);
240 uint32 numberOfElements = 0u;
241 if (ok) {
242 numberOfElements = arrayDescription.GetNumberOfElements(0u);
243 ok = (numberOfElements > 0u);
244 if (!ok) {
245 REPORT_ERROR(ErrorManagement::ParametersError, "No elements defined in the array with name %s", arrayName);
246 }
247 }
248 if (ok) {
249 dest = new float32[numberOfElements];
250 Vector<float32> readVector(dest, numberOfElements);
251 ok = data.Read(arrayName, readVector);
252 if (ok) {
253 REPORT_ERROR(ErrorManagement::Information, "Array set to %f", readVector);
254 }
255 else {
256 REPORT_ERROR(ErrorManagement::ParametersError, "Could not read the array with name %s", arrayName);
257 }
258 }
259 return ok;
260 }
261
262 /**
263 * A list of properties.
264 */
265 Gains lowGains;
266 Gains highGains;
267 Waveforms slowWaveform;
268 Waveforms fastWaveform;
269};
270
271CLASS_REGISTER(ControllerEx1, "")
272
273}
274
275int main(int argc, char **argv) {
276 using namespace MARTe;
277 using namespace MARTe2Tutorial;
278 SetErrorProcessFunction(&ErrorProcessExampleFunction);
279
280 CCString className1 = "ControllerEx1";
281
282 float32 times1[] = { 0.0, 0.2, 1 };
283 float32 values1[] = { 1.0, -1.0, 1.0 };
284 float32 times2[] = { 0.0, 0.5, 1 };
285 float32 values2[] = { 0.0, 1.0, 0.0 };
286
287 ReferenceT<ControllerEx1> ref1(className1,
288 GlobalObjectsDatabase::Instance()->GetStandardHeap());
289 //Automatically generate a new object instance based on the class name and on the correct Heap and with the template reference.
290 if (ref1.IsValid()) {
291 ref1->SetName("ControllerInstance1");
292 REPORT_ERROR_STATIC(ErrorManagement::Information,
293 "Successfully created an instance of %s", className1.GetList());
294 //Write a valid configuration.
295 {
296 ConfigurationDatabase cdb;
297 //Create the structure nodes
298 cdb.CreateAbsolute("Gains.Low");
299 cdb.Write("Gain1", 1.0);
300 cdb.Write("Gain2", -1.0);
301 cdb.CreateAbsolute("Gains.High");
302 cdb.Write("Gain1", 5.0);
303 cdb.Write("Gain2", -5.0);
304 cdb.CreateAbsolute("References.Slow.Waveform");
305 cdb.Write("Times", times1);
306 cdb.Write("Values", values1);
307 cdb.CreateAbsolute("References.Fast.Waveform");
308 cdb.Write("Times", times2);
309 cdb.Write("Values", values2);
310 //Move back again to the root of the tree
311 cdb.MoveToRoot();
312
313 //Print the configuration
314 REPORT_ERROR_STATIC(ErrorManagement::Information,
315 "Going to load the following configuration\n%s", cdb);
316 //Need to move back after the printf
317 cdb.MoveToRoot();
318 if (ref1->Initialise(cdb)) {
319 REPORT_ERROR_STATIC(ErrorManagement::Information,
320 "Successfully configured instance of %s",
321 ref1->GetName());
322 } else {
323 REPORT_ERROR_STATIC(ErrorManagement::FatalError,
324 "Failed to configure instance of %s", ref1->GetName());
325 }
326 }
327 //Write an invalid configuration
328 {
329 ConfigurationDatabase cdb;
330 //Create the structure nodes with a typo: Gain (not Gains)
331 cdb.CreateAbsolute("Gain.Low");
332 cdb.Write("Gain1", 1.0);
333 cdb.Write("Gain2", -1.0);
334 cdb.CreateAbsolute("Gain.High");
335 cdb.Write("Gain1", 5.0);
336 cdb.Write("Gain2", -5.0);
337 cdb.CreateAbsolute("References.Slow.Waveform");
338 cdb.Write("Times", times1);
339 cdb.Write("Values", values1);
340 cdb.CreateAbsolute("References.Fast.Waveform");
341 cdb.Write("Times", times2);
342 cdb.Write("Values", values2);
343 //Move back again to the root of the tree
344 cdb.MoveToRoot();
345
346 //Print the configuration
347 REPORT_ERROR_STATIC(ErrorManagement::Information,
348 "Going to load the following configuration\n%s", cdb);
349
350 if (!ref1->Initialise(cdb)) {
351 REPORT_ERROR_STATIC(ErrorManagement::Information,
352 "As expected failed to configure instance of %s",
353 ref1->GetName());
354 }
355 }
356 }
357
358 return 0;
359}
The following example shows how the reading of parameters can be simplified with the StructuredDataIHelper.
1/**
2 * @file ConfigurationExample8.cpp
3 * @brief Source file for class ConfigurationExample8
4 * @date 27/06/2022
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 ConfigurationExample8 (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 "Reference.h"
40#include "ReferenceT.h"
41#include "StreamString.h"
42#include "StructuredDataIHelper.h"
43#include "Vector.h"
44
45/*---------------------------------------------------------------------------*/
46/* Static definitions */
47/*---------------------------------------------------------------------------*/
48
49/*---------------------------------------------------------------------------*/
50/* Method definitions */
51/*---------------------------------------------------------------------------*/
52namespace MARTe2Tutorial {
53/**
54 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
55 */
56class ControllerEx1: public MARTe::Object {
57public:
58 CLASS_REGISTER_DECLARATION()
59
60 /**
61 * @brief NOOP.
62 */
63 ControllerEx1 () {
64 gain1 = 0u;
65 gain2 = 0.f;
66 gain3 = -1.0f;
67 controllerType = 0u;
68 mode = "";
69 referencesArray = NULL;
70 modesArray = NULL;
71 model = NULL;
72 modelRows = 0u;
73 }
74
75 virtual ~ControllerEx1 () {
76 using namespace MARTe;
77 if (referencesArray != NULL) {
78 delete [] referencesArray;
79 }
80 if (modesArray != NULL) {
81 delete [] modesArray;
82 }
83 if (model != NULL) {
84 for (uint32 i=0; i<modelRows; i++) {
85 delete [] model[i];
86 }
87 delete [] model;
88 }
89
90 if (GetName() != NULL) {
91 REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references pointing at %s [%s]. "
92 "The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
93 }
94 }
95
96 /**
97 * Read all the properties
98 */
99 virtual bool Initialise(MARTe::StructuredDataI &data) {
100 using namespace MARTe;
101 bool ok = Object::Initialise(data);
102 StructuredDataIHelper helper(data, this);
103 if (ok) {
104 ok = helper.Read("Gain1", gain1);
105 }
106 if (ok) {
107 //Read with default
108 ok = helper.Read("Gain2", gain2, 1.7);
109 }
110 if (ok) {
111 ok = helper.Read("Mode", mode);
112 }
113 if (ok) {
114 const char8 * controllerTypesStr[] = {"C1", "C2", "C3"};
115 uint32 controllerTypes[] = {1, 2, 3};
116 ok = helper.ReadEnum("ControllerType", controllerType, controllerTypesStr, controllerTypes);
117 }
118
119 if (ok) {
120 uint32 nOfReferences = 0u;
121 //Reconfiguration...
122 if (referencesArray != NULL) {
123 delete [] referencesArray;
124 referencesArray = NULL;
125 }
126 ok = helper.ReadArray("References", referencesArray, nOfReferences);
127 }
128
129 if (ok) {
130 uint32 nOfModes = 0u;
131 //Reconfiguration...
132 if (modesArray != NULL) {
133 delete [] modesArray;
134 modesArray = NULL;
135 }
136 ok = helper.ReadArray("Modes", modesArray, nOfModes);
137 }
138
139 if (ok) {
140 //Reconfiguration...
141 if (model != NULL) {
142 for (uint32 i=0; i<modelRows; i++) {
143 delete [] model[i];
144 }
145 delete [] model;
146 model = NULL;
147 }
148
149 uint32 modelCols = 0u;
150 ok = helper.ReadMatrix("Model", model, modelRows, modelCols);
151 }
152
153 if (ok) {
154 ok = helper.ReadValidated("Gain3", gain3, "(Gain3 > (float32)(-3.0)) && (Gain3 <= (float32)(0.0))");
155 }
156
157 return ok;
158 }
159
160 /**
161 * A list of properties.
162 */
163 MARTe::uint32 gain1;
164 MARTe::uint32 modelRows;
165 MARTe::uint32 controllerType;
166 MARTe::float32 gain2;
167 MARTe::float32 gain3;
168 MARTe::StreamString mode;
169 MARTe::int32 *referencesArray;
170 MARTe::StreamString *modesArray;
171 MARTe::float32 **model;
172};
173
174CLASS_REGISTER(ControllerEx1, "")
175
176}
177
178int main(int argc, char **argv) {
179 using namespace MARTe;
180 using namespace MARTe2Tutorial;
181 SetErrorProcessFunction(&ErrorProcessExampleFunction);
182
183 CCString className1 = "ControllerEx1";
184
185 int32 int32Arr[] = { -1, 2, -3, 4, -5 };
186 const char8 *stringArr[] = { "A", "BB", "CCC", "DDDD", "EEEEE" };
187 float32 float32Mat[3][2] = { { -1.0, 2.3 }, { 4.7, -3.2 }, { -7.1, 5.6 } };
188
189 ReferenceT<ControllerEx1> ref1(className1,
190 GlobalObjectsDatabase::Instance()->GetStandardHeap());
191 //Automatically generate a new object instance based on the class name and on the correct Heap
192 //and with the template reference.
193 if (ref1.IsValid()) {
194 ref1->SetName("ControllerInstance1");
195 REPORT_ERROR_STATIC(ErrorManagement::Information,
196 "Successfully created an instance of %s", className1.GetList());
197 //Write a valid configuration.
198 {
199 ConfigurationDatabase cdb;
200 cdb.Write("Gain1", 2);
201 cdb.Write("Gain3", -2.0);
202 cdb.Write("Mode", "ASTRING");
203 cdb.Write("ControllerType", "C3");
204 cdb.Write("Modes", stringArr);
205 cdb.Write("References", int32Arr);
206 cdb.Write("Model", float32Mat);
207
208 if (ref1->Initialise(cdb)) {
209 REPORT_ERROR_STATIC(ErrorManagement::Information,
210 "Successfully configured instance of %s",
211 ref1->GetName());
212 } else {
213 REPORT_ERROR_STATIC(ErrorManagement::FatalError,
214 "Failed to configure instance of %s", ref1->GetName());
215 }
216 }
217 //Write an invalid configuration - missing compulsory parameter
218 {
219 ConfigurationDatabase cdb;
220 cdb.Write("Gain1", 2);
221 cdb.Write("Gain2", 1.5);
222 cdb.Write("Gain3", -2.0);
223 cdb.Write("ControllerType", "C3");
224 cdb.Write("Modes", stringArr);
225 cdb.Write("References", int32Arr);
226 cdb.Write("Model", float32Mat);
227 if (!ref1->Initialise(cdb)) {
228 REPORT_ERROR_STATIC(ErrorManagement::Information,
229 "As expected failed to reconfigure instance of %s",
230 ref1->GetName());
231 }
232 }
233 //Write a configuration without a parameter that is out of range
234 {
235 ConfigurationDatabase cdb;
236 cdb.Write("Gain1", 2);
237 cdb.Write("Gain2", 1.5);
238 cdb.Write("Gain3", 2.0);
239 cdb.Write("ControllerType", "C3");
240 cdb.Write("Mode", "ASTRING");
241 cdb.Write("Modes", stringArr);
242 cdb.Write("References", int32Arr);
243 cdb.Write("Model", float32Mat);
244 if (!ref1->Initialise(cdb)) {
245 REPORT_ERROR_STATIC(ErrorManagement::Information,
246 "As expected failed to reconfigure instance of %s",
247 ref1->GetName());
248 }
249 }
250
251 }
252
253 return 0;
254}
Instructions on how to compile and execute the example can be found here.