IPMISensorGroup.cpp 3.19 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * IPMISingleSensor.cpp
 *
 *  Created on: 18 Jan 2017
 *      Author: Michael Ott (original), Micha Müller
 */

#include "IPMISensorGroup.h"
#include "IPMIHost.h"

#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>
#include <boost/regex.hpp>
#include <boost/bind.hpp>
#include <boost/lockfree/spsc_queue.hpp>

#include <iostream>
#include <exception>
#include <chrono>

IPMISensorGroup::IPMISensorGroup(const std::string& name) :
		SensorGroupTemplate(name) {
	_host = nullptr;
}

26 27 28 29
IPMISensorGroup::IPMISensorGroup(const IPMISensorGroup& other) :
    SensorGroupTemplate(other),
    _host(other._host) {}

30 31
IPMISensorGroup::~IPMISensorGroup() {}

32 33 34 35 36 37 38
IPMISensorGroup& IPMISensorGroup::operator=(const IPMISensorGroup& other) {
  SensorGroupTemplate::operator=(other);
  _host = other._host;

  return *this;
}

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
void IPMISensorGroup::init(boost::asio::io_service& io) {
	SensorGroupTemplate::init(io);
	if (_host) {
		_host->initializeStrand(io);
	} else {
		LOG(error)<< "No host set for sensorgroup " << _groupName << "! Cannot initialize sensor.";
	}
}

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

	if (_host) {
		_keepRunning = 1;
		_pendingTasks++;
		_timer->async_wait(_host->getStrand()->wrap(boost::bind(&IPMISensorGroup::readAsync, this)));
		LOG(info) << "Sensorgroup " << _groupName << " started.";
	} else {
61
		LOG(error) << "No host set for sensorgroup " << _groupName << "! Cannot start polling.";
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
		return;
	}
}

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

void IPMISensorGroup::read() {
	reading_t reading;
	reading.timestamp = getTimestamp();

77
	for(const auto& s : _sensors) {
78 79
		try {
			if (s->getRecordId() != 0) { /* recordId was set */
80 81 82 83 84
			    std::vector<uint8_t> sdrRecord = s->getSdrRecord();
			    if (sdrRecord.size() == 0) {
				_host->getSdrRecord(s->getRecordId(), sdrRecord);
				s->setSdrRecord(sdrRecord);
			    }
85
			    reading.value = _host->readSensorRecord(sdrRecord);
86
			} else { /* use raw command */
87
				reading.value = _host->sendRawCmd(s->getRawCmd(), s->getLsb(), s->getMsb());
88
			}
89
#ifdef DEBUG
Micha Müller's avatar
Micha Müller committed
90
			LOG(debug) << _groupName << "::" << s->getName() << " raw reading: \"" << reading.value << "\"";
91
#endif
92
			s->storeReading(reading, s->getFactor());
93 94
		} catch (const std::exception& e) {
			LOG(error) << _groupName << "::" << s->getName() << " could not read value: " << e.what();
95
		    continue;
96 97 98 99 100 101 102 103 104 105
		}
	}
}

void IPMISensorGroup::readAsync() {
	uint64_t now = getTimestamp();
	if (now >= _host->getDelayNextReadUntil()) {
		read();
	}
	if (_timer && _keepRunning) {
106
		uint64_t next = nextReadingTime();
107 108 109 110 111 112 113 114 115
		while (next < _host->getDelayNextReadUntil()) {
			next += MS_TO_NS(_interval);
		}
		_timer->expires_at(timestamp2ptime(next));
		_pendingTasks++;
		_timer->async_wait(_host->getStrand()->wrap(boost::bind(&IPMISensorGroup::readAsync, this)));
	}
	_pendingTasks--;
}
Micha Müller's avatar
Micha Müller committed
116 117 118

void IPMISensorGroup::printConfig(LOG_LEVEL ll) {
    if (_host) {
119
      LOG_VAR(ll) << "            Host: " << _host->getHostName();
Micha Müller's avatar
Micha Müller committed
120
    } else {
121
      LOG_VAR(ll) << "            No Host set!";
Micha Müller's avatar
Micha Müller committed
122 123
    }
}