ConfiguratorTemplate.h 8.08 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
15
16
#include "headers/SensorBase.h"
#include "headers/SingleSensor.h"
#include "headers/SensorGroupTemplate.h"

17
18
19
20
21
22
#include <map>

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

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

Micha Mueller's avatar
Micha Mueller committed
26
/**
27
 * Non-virtual interface template for the configurators.
Micha Mueller's avatar
Micha Mueller committed
28
 */
29
template <typename SBase, typename S>
30
class ConfiguratorTemplate : public ConfiguratorInterface {
31
32
33
	//the template shall only be instantiated for classes which derive from SensorBase/SingleSensor
	static_assert(std::is_base_of<SingleSensor, S>::value, "S must derive from Sensor!");
	static_assert(std::is_base_of<SensorBase, SBase>::value, "SBase must derive from SensorBase!");
34

35
protected:
36
37
	typedef std::map<std::string, S> sensorMap_t;

38
public:
39
	ConfiguratorTemplate() : _cacheInterval(900000) {}
40

41
	virtual ~ConfiguratorTemplate() {
42
43
44
45
		for (auto s : _sensors) {
			delete s;
		}
	}
46

Micha Mueller's avatar
Micha Mueller committed
47
48
	/**
	 * Read in the given configuration
49
	 *
Micha Mueller's avatar
Micha Mueller committed
50
	 * @param	cfgPath Path to the config-file
51
52
	 *
	 * @return	True on success, false otherwise
Micha Mueller's avatar
Micha Mueller committed
53
	 */
54
	bool readConfig(std::string cfgPath) final {
55
		_cfgPath = cfgPath;
56
57
58
59
60

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

		//read global variables (if present overwrite those from global.conf)
61
62
63
		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")) {
64
				if (STRCMP(global, "mqttprefix")) {
65
66
67
68
69
					_mqttPrefix = global.second.data();
					if (_mqttPrefix[_mqttPrefix.length()-1] != '/') {
						_mqttPrefix.append("/");
					}
					LOG(debug) << "  Using own MQTT-Prefix " << _mqttPrefix;
70
				} else if (STRCMP(global, "cacheInterval")) {
71
72
73
					_cacheInterval = stoul(global.second.data());
					LOG(debug) << "  Using own caching interval " << _cacheInterval << " [s]";
					_cacheInterval *= 1000;
74
75
76
77
78
				}
			}
		}

		//read template sensors
79
80
81
		boost::optional<boost::property_tree::iptree&> tempSens = cfg.get_child_optional("sensorTemplates");
		if (tempSens) {
			BOOST_FOREACH(boost::property_tree::iptree::value_type &sensorVal, cfg.get_child("sensorTemplates")) {
82
				if (STRCMP(sensorVal, "sensor")) {
83
84
85
					LOG(debug) << "Template Sensor \"" << sensorVal.second.data() << "\"";
					if (!sensorVal.second.empty()) {
						S sensor(sensorVal.second.data());
86
						if(readSingleSensor(sensor, sensorVal.second)) {
87
88
89
90
							_templateSensors.insert(std::pair<std::string, S>(sensor.getName(), sensor));
						} else {
							LOG(warning) << "Template sensor \"" << sensorVal.second.data() << "\" has bad values! Ignoring...";
						}
91
92
93
94
95
96
97
					}
				}
			}
		}

		//read in plugin specific stuff (including actual sensors)
		return derivedReadConfig(cfg);
98
99
100
101
	}

	/**
	 * Clear internal storage and read in the configuration again.
102
103
	 *
	 * @return	True on success, false otherwise
104
	 */
105
	bool reReadConfig() final {
Micha Mueller's avatar
Micha Mueller committed
106
		//bring everything to a halt
107
		for (auto s : _sensors) {
108
			s->stop();
109
		}
Micha Mueller's avatar
Micha Mueller committed
110
		for(auto g : _sensorGroups) {
111
			g->stop();
Micha Mueller's avatar
Micha Mueller committed
112
113
114
115
116
117
118
119
120
		}

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

Micha Mueller's avatar
Micha Mueller committed
122
		//clean up plugin specific stuff
123
124
		derivedReReadConfig();

Micha Mueller's avatar
Micha Mueller committed
125
		//clean up sensors and groups
126
127
128
		for (auto s : _sensors) {
			delete s;
		}
Micha Mueller's avatar
Micha Mueller committed
129
130
131
132
		for(auto g : _sensorGroups) {
			delete g;
		}

133
		_sensors.clear();
Micha Mueller's avatar
Micha Mueller committed
134
		_sensorGroups.clear();
135
136
		_templateSensors.clear();

Micha Mueller's avatar
Micha Mueller committed
137
		//back to the very beginning
138
		return readConfig(_cfgPath);
139
	}
140

141
142
143
144
145
146
147
	/**
	 * 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.
	 */
148
	void setGlobalSettings(const pluginSettings_t& pluginSettings) final {
149
150
		_mqttPrefix = pluginSettings.mqttPrefix;
		_cacheInterval = pluginSettings.cacheInterval;
151
152

		derivedSetGlobalSettings(pluginSettings);
153
154
	}

155
156
157
158
159
	/**
	 * Get all sensors
	 *
	 * @return	Vector containing pointers to all sensors of this plugin
	 */
160
	std::vector<SingleSensor*>& getSensors() final {
161
162
163
		return _sensors;
	}

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

173
protected:
174
175
	/**
	 * Non-virtual interface method for class-internal use only.
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
	 * Reads and sets the values for a SingleSensor. This is only a
	 * convenience function and only calls readSensorBase() and
	 * readSensorInterface() itself.
	 *
	 * @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
	 */
	bool readSingleSensor(S& sensor, boost::property_tree::iptree& config) {
		return (readSensorBase(sensor, config) | readSensorInterface(sensor, config));
	}

	/**
	 * 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.
194
195
196
197
198
199
	 *
	 * @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
	 */
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
	bool readSensorBase(SBase& sensor, boost::property_tree::iptree& config) {
		return derivedReadSensorBase(sensor, config);
	}

	/**
	 * 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
	 */
	bool readSensorInterface(SensorInterface& sensor, boost::property_tree::iptree& config) {
		//read in values inherited from SensorInterface
217
		BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
218
			if (STRCMP(val, "interval")) {
219
				sensor.setInterval(stoull(val.second.data()));
220
			} else if (STRCMP(val, "minValues")) {
221
222
223
224
225
226
227
228
				sensor.setMinValues(stoull(val.second.data()));
			}
		}
		sensor.setCacheInterval(_cacheInterval);

		LOG(debug) << "  Interval : " << sensor.getInterval();
		LOG(debug) << "  minValues: " << sensor.getMinValues();

229
230
		/* return derivedReadSensorInterface(sensor, config); */
		return true;
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
	}

	/**
	 * 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
259
	 * base values.
260
261
262
263
264
265
	 *
	 * @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
	 */
266
	virtual bool derivedReadSensorBase(SBase& sensor, boost::property_tree::iptree& config) = 0;
267
268
269
270

	std::string 	_cfgPath;
	std::string		_mqttPrefix;
	unsigned int	_cacheInterval;
271
272
	std::vector<SingleSensor*> _sensors;
	std::vector<SensorGroupInterface*> _sensorGroups;
273
	sensorMap_t		_templateSensors;
274
275
};

276
#endif /* SRC_CONFIGURATORTEMPLATE_H_ */