ConfiguratorTemplate.h 8.65 KB
Newer Older
1
/*
2
 * ConfiguratorTemplate.h
3
4
5
6
7
 *
 *  Created on: 13.01.2018
 *      Author: Micha Mueller
 */

8
9
#ifndef SRC_CONFIGURATORTEMPLATE_H_
#define SRC_CONFIGURATORTEMPLATE_H_
10

11
#include "ConfiguratorInterface.h"
12

13
14
#include "SensorBase.h"
#include "SensorGroupTemplate.h"
15

16
17
18
19
20
21
#include <map>

#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
22

23
24
#define STRCMP(node,str) boost::iequals(node.first,str)

25
26
27
28
29
30
#define CONFIG		boost::property_tree::iptree& config
#define ATTRIBUTES	BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) { \
						if (false) {}
#define ADD(name,setter)	else if (boost::iequals(val.first, name)) { sBase.setter(val.second.data()); }
#define END			} return true;

Micha Mueller's avatar
Micha Mueller committed
31
/**
32
 * Non-virtual interface template for the configurators.
Micha Mueller's avatar
Micha Mueller committed
33
 */
34
template <class SBase, class SGroup, class SEntity = void>
35
class ConfiguratorTemplate : public ConfiguratorInterface {
36
	//the template shall only be instantiated for classes which derive from SensorBase/SensorGroup
37
	static_assert(std::is_base_of<SensorBase, SBase>::value, "SBase must derive from SensorBase!");
38
	static_assert(std::is_base_of<SensorGroupTemplate, SGroup>::value, "SGroup must derive from SensorGroupTemplate!");
39

40
protected:
41
42
	typedef std::map<std::string, SGroup> sGroupMap_t;
	typedef std::map<std::string, SEntity> sEntityMap_t;
43

44
public:
45
46
47
48
49
50
51
	ConfiguratorTemplate() :
		_entityName("entity"),
		_groupName("group"),
		_sensorName("sensor"),
		_cfgPath(""),
		_mqttPrefix(""),
		_cacheInterval(900000) {}
52

53
	virtual ~ConfiguratorTemplate() {
54
55
		for (auto g : _sensorGroups) {
			delete g;
56
		}
57
		_templateSensorGroups.clear();
58
		_templateSensorEntitys.clear();
59
	}
60

Micha Mueller's avatar
Micha Mueller committed
61
62
	/**
	 * Read in the given configuration
63
	 *
Micha Mueller's avatar
Micha Mueller committed
64
	 * @param	cfgPath Path to the config-file
65
66
	 *
	 * @return	True on success, false otherwise
Micha Mueller's avatar
Micha Mueller committed
67
	 */
68
	bool readConfig(std::string cfgPath) final {
69
		_cfgPath = cfgPath;
70
71
72
73
74

		boost::property_tree::iptree cfg;
		boost::property_tree::read_info(cfgPath, cfg);

		//read global variables (if present overwrite those from global.conf)
75
76
77
		boost::optional<boost::property_tree::iptree&> globalVals = cfg.get_child_optional("global");
		if (globalVals) {
			BOOST_FOREACH(boost::property_tree::iptree::value_type &global, cfg.get_child("global")) {
78
				if (STRCMP(global, "mqttprefix")) {
79
80
81
82
83
					_mqttPrefix = global.second.data();
					if (_mqttPrefix[_mqttPrefix.length()-1] != '/') {
						_mqttPrefix.append("/");
					}
					LOG(debug) << "  Using own MQTT-Prefix " << _mqttPrefix;
84
				} else if (STRCMP(global, "cacheInterval")) {
85
86
87
					_cacheInterval = stoul(global.second.data());
					LOG(debug) << "  Using own caching interval " << _cacheInterval << " [s]";
					_cacheInterval *= 1000;
88
89
90
91
				}
			}
		}

92
93
		//read template groups
		boost::optional<boost::property_tree::iptree&> tempSens = cfg.get_child_optional("groupTemplates");
94
		if (tempSens) {
95
96
97
98
99
100
101
102
			BOOST_FOREACH(boost::property_tree::iptree::value_type &groupVal, cfg.get_child("groupTemplates")) {
				if (STRCMP(groupVal, "group")) {
					LOG(debug) << "Template Group \"" << groupVal.second.data() << "\"";
					if (!groupVal.second.empty()) {
						//TODO
						SGroup group(groupVal.second.data());
						if(readSensorGroup(group, groupVal.second)) {
							_templateSensorGroups.insert(std::pair<std::string, SGroup>(group.getName(), group));
103
						} else {
104
							LOG(warning) << "Template group \"" << groupVal.second.data() << "\" has bad values! Ignoring...";
105
						}
106
107
108
109
110
111
112
					}
				}
			}
		}

		//read in plugin specific stuff (including actual sensors)
		return derivedReadConfig(cfg);
113
114
115
116
	}

	/**
	 * Clear internal storage and read in the configuration again.
117
118
	 *
	 * @return	True on success, false otherwise
119
	 */
120
	bool reReadConfig() final {
Micha Mueller's avatar
Micha Mueller committed
121
122
		//bring everything to a halt
		for(auto g : _sensorGroups) {
123
			g->stop();
Micha Mueller's avatar
Micha Mueller committed
124
125
126
127
128
129
		}

		//wait until everything is halted
		for(auto g : _sensorGroups) {
			g->wait();
		}
130

Micha Mueller's avatar
Micha Mueller committed
131
		//clean up plugin specific stuff
132
133
		derivedReReadConfig();

Micha Mueller's avatar
Micha Mueller committed
134
135
136
137
138
139
		//clean up sensors and groups
		for(auto g : _sensorGroups) {
			delete g;
		}

		_sensorGroups.clear();
140
		_templateSensorGroups.clear();
141

Micha Mueller's avatar
Micha Mueller committed
142
		//back to the very beginning
143
		return readConfig(_cfgPath);
144
	}
145

146
147
148
149
150
151
152
	/**
	 * Sets internal variables with the ones provided by pluginSettings.
	 * This method should be called once after constructing a configurator
	 * to provide him with the global default values.
	 *
	 * @param pluginSettings	Struct with global default settings for the plugins.
	 */
153
	void setGlobalSettings(const pluginSettings_t& pluginSettings) final {
154
155
		_mqttPrefix = pluginSettings.mqttPrefix;
		_cacheInterval = pluginSettings.cacheInterval;
156
157

		derivedSetGlobalSettings(pluginSettings);
158
159
	}

Micha Mueller's avatar
Micha Mueller committed
160
161
162
163
164
	/**
	 * Get all sensor groups
	 *
	 * @return	Vector containing pointers to all sensor groups of this plugin
	 */
165
	std::vector<SensorGroupInterface*>& getSensorGroups() {
Micha Mueller's avatar
Micha Mueller committed
166
167
168
		return _sensorGroups;
	}

169
protected:
170
171
172
173
174
	/**
	 * Non-virtual interface method for class-internal use only.
	 * Reads and sets the common base values of a sensor (currently none),
	 * then calls the corresponding derived function to read plugin specific
	 * values.
175
	 *
176
	 * @param sBase		The sensor base for which to set the values
177
178
179
180
	 * @param config	A boost property (sub-)tree containing the sensor values
	 *
	 * @return	True on success, false otherwise
	 */
181
	bool readSensorBase(SBase& sBase, boost::property_tree::iptree& config) {
182
		return sensorBase(sBase, config);
183
184
185
186
187
188
189
190
191
192
193
194
195
	}

	/**
	 * Non-virtual interface method for class-internal use only.
	 * Reads and sets the common base values of a SensorInterface, then calls
	 * the corresponding derived function to read in plugin specific values
	 * (currently none).
	 *
	 * @param sensor	The sensor for which to set the values
	 * @param config	A boost property (sub-)tree containing the sensor values
	 *
	 * @return	True on success, false otherwise
	 */
196
197
198
	bool readSensorGroup(SGroup& sGroup, boost::property_tree::iptree& config) {
		sGroup.setCacheInterval(_cacheInterval);
		//read in values inherited from SensorGroupInterface
199
		BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
200
			if (STRCMP(val, "interval")) {
201
				sGroup.setInterval(stoull(val.second.data()));
202
			} else if (STRCMP(val, "minValues")) {
203
204
205
206
207
208
209
210
				sGroup.setMinValues(stoull(val.second.data()));
			} else if (STRCMP(val, "sensor")) {
				SBase* sensor = new SBase(val.second.data());
				if (readSensorBase(*sensor, val.second)) {
					sGroup.pushBackSensor(sensor);
				} else {
					LOG(warning) << "Sensor " << sGroup.getGroupName() << "::" << sensor->getName() << " could not be read! Omitting";
				}
211
212
213
			}
		}

214
215
		LOG(debug) << "  Interval : " << sGroup.getInterval();
		LOG(debug) << "  minValues: " << sGroup.getMinValues();
216

217
218
219
220
221
		return sensorGroup(sGroup, config);
	}

	bool readSensorEntity(SEntity& sEntity, boost::property_tree::iptree& config) {
		return sensorEntity(sEntity, config);
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
	}

	/**
	 * Pure virtual interface method, responsible for reading the plugin-specific
	 * configuration part.
	 *
	 * @param cfg	The (root) boost property tree from the plugins configuration file
	 *
	 * @return	True on success, false otherwise
	 */
	virtual bool derivedReadConfig(boost::property_tree::iptree& cfg) = 0;

	/**
	 * Pure virtual interface method, responsible for the plugin specific part if
	 * re-reading the config.
	 */
	virtual void derivedReReadConfig() = 0;

	/**
	 * Pure virtual interface method, responsible for setting global values specifically
	 * for its plugin.
	 *
	 * @param pluginSettings	The struct with global default plugin settings
	 */
	virtual void derivedSetGlobalSettings(const pluginSettings_t& pluginSettings) = 0;

	/**
	 * Pure virtual interface method, responsible for reading plugin-specific sensor
250
	 * base values.
251
	 *
252
253
254
255
256
	 * @param sBase		The sensor base for which to set the values
	 * @param config	A boost property (sub-)tree containing the sensor values
	 *
	 * @return	True on success, false otherwise
	 */
257
	virtual bool sensorBase(SBase& sBase, boost::property_tree::iptree& config) = 0;
258
259
260
261
262
263

	/**
	 * Pure virtual interface method, responsible for reading plugin-specific sensor
	 * group values.
	 *
	 * @param sGroup	The sensor group for which to set the values
264
265
266
267
	 * @param config	A boost property (sub-)tree containing the sensor values
	 *
	 * @return	True on success, false otherwise
	 */
268
269
270
271
272
273
274
	virtual bool sensorGroup(SGroup& sGroup, boost::property_tree::iptree& config) = 0;

	virtual bool sensorEntity(SEntity& sEntity, boost::property_tree::iptree& config) = 0;

	std::string		_entityName;
	std::string		_groupName;
	std::string		_sensorName;
275
276
277
278

	std::string 	_cfgPath;
	std::string		_mqttPrefix;
	unsigned int	_cacheInterval;
279
	std::vector<SensorGroupInterface*> _sensorGroups;
280
281
	sGroupMap_t		_templateSensorGroups;
	sEntityMap_t	_templateSensorEntitys;
282
283
};

284
#endif /* SRC_CONFIGURATORTEMPLATE_H_ */