PDUSensorGroup.cpp 4.17 KB
Newer Older
1
2
3
4
5
6
7
8
/*
 * PDUSensorGroup.cpp
 *
 *  Created on: 24.02.2018
 *      Author: Micha Mueller
 */

#include "PDUSensorGroup.h"
9
10
11
12
13

#include <sstream>

#include <boost/foreach.hpp>
#include <boost/property_tree/xml_parser.hpp>
14
15
16
17
18
19

PDUSensorGroup::PDUSensorGroup(const std::string& name) :
	SensorGroupTemplate(name) {
	_pdu = nullptr;
}

20
21
22
23
24
PDUSensorGroup::PDUSensorGroup(const PDUSensorGroup& other) :
    SensorGroupTemplate(other),
    _request(other._request),
    _pdu(other._pdu) {}

25
26
PDUSensorGroup::~PDUSensorGroup() {}

27
28
29
30
31
32
33
34
PDUSensorGroup& PDUSensorGroup::operator=(const PDUSensorGroup& other) {
  SensorGroupTemplate::operator=(other);
  _request = other._request;
  _pdu = other._pdu;

  return *this;
}

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void PDUSensorGroup::init(boost::asio::io_service& io) {
	SensorGroupTemplate::init(io);
	if(_pdu) {
		_pdu->initializeStrand(io);
	} else {
		LOG(error) << "No PDUUnit set for sensorgroup " << _groupName << "! Cannot initialize sensor.";
	}
}

void PDUSensorGroup::start() {
	if (_keepRunning) {
		//we have been started already
		LOG(info) << "Sensorgroup " << _groupName << " already running.";
		return;
	}

	if (_pdu) {
		_keepRunning = 1;
		_pendingTasks++;
		_timer->async_wait(_pdu->getStrand()->wrap(std::bind(&PDUSensorGroup::readAsync, this)));
		LOG(info) << "Sensorgroup " << _groupName << " started.";
	} else {
		LOG(error) << "No PDUUnit set for sensorgroup " << _groupName << "! Cannot start polling.";
	}
}

void PDUSensorGroup::stop() {
	_keepRunning = 0;
	//cancel any outstanding readAsync()
	_timer->cancel();
	LOG(info) << "Sensorgroup " << _groupName << " stopped.";
}

void PDUSensorGroup::read() {
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
	//send request
	std::string response;
	if (!_pdu->sendRequest(_request, response)) {
		LOG(error) << _groupName << " could not send request!";
		return;
	}

	//parse response
	boost::property_tree::ptree ptree;
	std::string xml = response.substr(response.find("<"));
	std::istringstream treeStream(xml);
	try {
		boost::property_tree::read_xml(treeStream, ptree);
	} catch (const std::exception& e) {
		LOG(error) << _groupName << " got malformed XML response";
		return;
	}

	//read values for every sensor from response
88
89
90
	reading_t reading;
	reading.timestamp = getTimestamp();

91
	for(const auto& s : _sensors) {
92
		try {
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
			std::string readStr;
			const xmlPathVector_t& xmlPath = s->getXMLPath();
			boost::property_tree::ptree node = ptree;
			for (size_t i = 0; i < xmlPath.size(); i++) {
				const std::string& path = std::get<0>(xmlPath[i]);
				const std::string& child = std::get<1>(xmlPath[i]);
				const attributesVector_t& attVec = std::get<2>(xmlPath[i]);

				unsigned matchCount;
				if (child != "") {
					BOOST_FOREACH(boost::property_tree::ptree::value_type &v, node.get_child(path)) {
						if (v.first == child) {
							matchCount = 0;
							for (size_t j = 0; j < attVec.size(); j++) {
								std::string attributeVal = v.second.get_child("<xmlattr>." + attVec[j].first).data();

								if (attributeVal != attVec[j].second) { //attribute values don't match
									break;
								} else {
									matchCount++;
								}
							}
							if (matchCount == attVec.size()) { //all attributes matched
								readStr = v.second.data();
								node = v.second;
								break;
							}
						}
					}
				} else {	//child == ""
					readStr = node.get(path, "");
					break;	//last (part of the) path
				}
			}

			if (readStr == "") {
				throw std::runtime_error("Value not found!");
			}
131
			reading.value = stoll(readStr);
132
#ifdef DEBUG
Micha Mueller's avatar
Micha Mueller committed
133
			LOG(debug) << _groupName << "::" << s->getName() << " raw reading: \"" << reading.value << "\"";
134
#endif
135
			s->storeReading(reading);
136
137
		} catch (const std::exception& e) {
			LOG(error) << _groupName << "::" << s->getName() << " could not read value: " << e.what();
138
			continue;
139
140
141
142
143
144
145
		}
	}
}

void PDUSensorGroup::readAsync() {
	read();
	if (_timer && _keepRunning) {
146
		_timer->expires_at(timestamp2ptime(nextReadingTime()));
147
148
149
150
151
		_pendingTasks++;
		_timer->async_wait(_pdu->getStrand()->wrap(std::bind(&PDUSensorGroup::readAsync, this)));
	}
	_pendingTasks--;
}
Micha Mueller's avatar
Micha Mueller committed
152
153
154
155
156
157
158
159
160

void PDUSensorGroup::printConfig(LOG_LEVEL ll) {
    if (_pdu) {
      LOG_VAR(ll) << "   PDU Unit: " << _pdu->getHost();
    } else {
      LOG_VAR(ll) << "   No Host set!";
    }
    LOG_VAR(ll) << "   Request: " << _request;
}