ConfiguratorTemplate.h 7.88 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)

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

34
protected:
35
	typedef std::map<std::string, SGroup> sensorGroupMap_t;
36

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

40
	virtual ~ConfiguratorTemplate() {
41
42
		for (auto g : _sensorGroups) {
			delete g;
43
		}
44
		_templateSensorGroups.clear();
45
	}
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
79
		//read template groups
		boost::optional<boost::property_tree::iptree&> tempSens = cfg.get_child_optional("groupTemplates");
80
		if (tempSens) {
81
82
83
84
85
86
87
88
			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));
89
						} else {
90
							LOG(warning) << "Template group \"" << groupVal.second.data() << "\" has bad values! Ignoring...";
91
						}
92
93
94
95
96
97
98
					}
				}
			}
		}

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

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

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

Micha Mueller's avatar
Micha Mueller committed
117
		//clean up plugin specific stuff
118
119
		derivedReReadConfig();

Micha Mueller's avatar
Micha Mueller committed
120
121
122
123
124
125
		//clean up sensors and groups
		for(auto g : _sensorGroups) {
			delete g;
		}

		_sensorGroups.clear();
126
		_templateSensorGroups.clear();
127

Micha Mueller's avatar
Micha Mueller committed
128
		//back to the very beginning
129
		return readConfig(_cfgPath);
130
	}
131

132
133
134
135
136
137
138
	/**
	 * 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.
	 */
139
	void setGlobalSettings(const pluginSettings_t& pluginSettings) final {
140
141
		_mqttPrefix = pluginSettings.mqttPrefix;
		_cacheInterval = pluginSettings.cacheInterval;
142
143

		derivedSetGlobalSettings(pluginSettings);
144
145
	}

Micha Mueller's avatar
Micha Mueller committed
146
147
148
149
150
	/**
	 * Get all sensor groups
	 *
	 * @return	Vector containing pointers to all sensor groups of this plugin
	 */
151
	std::vector<SensorGroupInterface*>& getSensorGroups() {
Micha Mueller's avatar
Micha Mueller committed
152
153
154
		return _sensorGroups;
	}

155
protected:
156
157
158
159
160
	/**
	 * 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.
161
	 *
162
	 * @param sBase		The sensor base for which to set the values
163
164
165
166
	 * @param config	A boost property (sub-)tree containing the sensor values
	 *
	 * @return	True on success, false otherwise
	 */
167
168
	bool readSensorBase(SBase& sBase, boost::property_tree::iptree& config) {
		return derivedReadSensorBase(sBase, config);
169
170
171
172
173
174
175
176
177
178
179
180
181
	}

	/**
	 * 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
	 */
182
183
184
	bool readSensorGroup(SGroup& sGroup, boost::property_tree::iptree& config) {
		sGroup.setCacheInterval(_cacheInterval);
		//read in values inherited from SensorGroupInterface
185
		BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
186
			if (STRCMP(val, "interval")) {
187
				sGroup.setInterval(stoull(val.second.data()));
188
			} else if (STRCMP(val, "minValues")) {
189
190
191
192
193
194
195
196
				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";
				}
197
198
199
			}
		}

200
201
		LOG(debug) << "  Interval : " << sGroup.getInterval();
		LOG(debug) << "  minValues: " << sGroup.getMinValues();
202

203
		return derivedReadSensorGroup(sGroup, config);
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
	}

	/**
	 * 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
232
	 * base values.
233
	 *
234
235
236
237
238
239
240
241
242
243
244
245
	 * @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
	 */
	virtual bool derivedReadSensorBase(SBase& sBase, boost::property_tree::iptree& config) = 0;

	/**
	 * Pure virtual interface method, responsible for reading plugin-specific sensor
	 * group values.
	 *
	 * @param sGroup	The sensor group for which to set the values
246
247
248
249
	 * @param config	A boost property (sub-)tree containing the sensor values
	 *
	 * @return	True on success, false otherwise
	 */
250
	virtual bool derivedReadSensorGroup(SGroup& sGroup, boost::property_tree::iptree& config) = 0;
251
252
253
254

	std::string 	_cfgPath;
	std::string		_mqttPrefix;
	unsigned int	_cacheInterval;
255
	std::vector<SensorGroupInterface*> _sensorGroups;
256
	sensorGroupMap_t	_templateSensorGroups;
257
258
};

259
#endif /* SRC_CONFIGURATORTEMPLATE_H_ */