Commit 8264f200 authored by Michael Ott's avatar Michael Ott

Renaming xccBulkPower once more to xccDatastorePower, refactoring LenovoXCC and IPMISensorGroup

parent d3965293
......@@ -89,7 +89,7 @@ class IPMISensorBase : public SensorBase {
undefined = 0,
raw,
sdr,
xccBulkPower
xccDatastorePower
};
uint16_t getRecordId() const { return _recordId; }
......@@ -113,8 +113,8 @@ class IPMISensorBase : public SensorBase {
return std::string("raw");
case sdr:
return std::string("sdr");
case xccBulkPower:
return std::string("xccBulkPower");
case xccDatastorePower:
return std::string("xccDatastorePower");
default:
return std::string("undefined");
}
......@@ -144,8 +144,8 @@ class IPMISensorBase : public SensorBase {
_type = raw;
} else if (boost::iequals(type, "sdr")) {
_type = sdr;
} else if (boost::iequals(type, "xccBulkPower")) {
_type = xccBulkPower;
} else if (boost::iequals(type, "xccDatastorePower")) {
_type = xccDatastorePower;
} else {
_type = undefined;
}
......
......@@ -100,29 +100,40 @@ void IPMISensorGroup::read() {
for (const auto &s : _sensors) {
try {
if (s->getType() == IPMISensorBase::sensorType::xccBulkPower) {
std::vector<reading_t> readings(3000);
LenovoXCC xcc(_entity);
int count = xcc.getBulkPower(readings);
for (int i=0; i<count; i++) {
s->storeReading(readings[i], s->getFactor());
switch (s->getType()) {
case IPMISensorBase::sensorType::xccDatastorePower: {
std::vector<reading_t> readings;
LenovoXCC xcc(_entity);
if (xcc.getDatastorePower(readings) == 0) {
for (int i=0; i<readings.size(); i++) {
s->storeReading(readings[i], s->getFactor());
}
reading = readings[2999];
}
break;
}
} else {
if (s->getType() == IPMISensorBase::sensorType::sdr) {
case IPMISensorBase::sensorType::sdr: {
std::vector<uint8_t> sdrRecord = s->getSdrRecord();
if (sdrRecord.size() == 0) {
_entity->getSdrRecord(s->getRecordId(), sdrRecord);
s->setSdrRecord(sdrRecord);
}
reading.value = _entity->readSensorRecord(sdrRecord);
} else {
s->storeReading(reading, s->getFactor());
break;
}
case IPMISensorBase::sensorType::raw: {
reading.value = readRaw(s->getRawCmd(), s->getLsb(), s->getMsb());
s->storeReading(reading, s->getFactor());
break;
}
default:
LOG(error) << _groupName << "::" << s->getName() << " undefined sensor type";
break;
}
#ifdef DEBUG
LOG(debug) << _groupName << "::" << s->getName() << " raw reading: \"" << reading.value << "\"";
LOG(debug) << _groupName << "::" << s->getName() << " reading: ts=" << reading.timestamp << " val=" << reading.value;
#endif
s->storeReading(reading, s->getFactor());
}
} catch (const std::exception &e) {
LOG(error) << _groupName << "::" << s->getName() << " could not read value: " << e.what();
continue;
......@@ -131,7 +142,7 @@ void IPMISensorGroup::read() {
}
uint64_t IPMISensorGroup::nextReadingTime() {
if ((_sensors.size() == 1) && (_sensors.front()->getType() == IPMISensorBase::sensorType::xccBulkPower)) {
if ((_sensors.size() == 1) && (_sensors.front()->getType() == IPMISensorBase::sensorType::xccDatastorePower)) {
reading_t r = _sensors.front()->getLatestValue();
uint64_t now = getTimestamp();
......@@ -150,10 +161,17 @@ uint64_t IPMISensorGroup::nextReadingTime() {
bool IPMISensorGroup::checkConfig() {
if (_sensors.size() > 1) {
for (const auto &s : _sensors) {
if (s->getType() == IPMISensorBase::sensorType::xccBulkPower) {
if (s->getType() == IPMISensorBase::sensorType::xccDatastorePower) {
LOG(error) << _groupName << " contains an XCC sensor among others, this is not possible";
return false;
}
}
}
}
for (const auto &s : _sensors) {
if (s->getType() == IPMISensorBase::sensorType::undefined) {
LOG(error) << _groupName << "::" << s->getName() << " has an undefined sensor type";
return false;
}
}
return true;
......
......@@ -22,11 +22,50 @@ void printbuf(std::string header, uint8_t *buf, int len) {
LenovoXCC::LenovoXCC(IPMIHost *host) {
_host = host;
_handle = 0;
_drift = 0;
}
LenovoXCC::~LenovoXCC() {}
int LenovoXCC::getSingleEnergy(uint64_t &timeStamp, uint64_t &energy) {
int LenovoXCC::getDatastorePower(std::vector<reading_t> &readings) {
if (openDatastore() == 0) {
uint64_t ts1, ts2;
uint8_t buf[256];
ts2 = 0;
if (_drift || getDrift() == 0) {
if ((ts1 = readDatastoreTimestamp()) > 0) {
while (ts1 != ts2) {
int i = 0;
for (int offset=16; offset < 6016; offset += 200) {
int len = readDatastoreRange(offset, 200, buf, sizeof(buf));
if (len >= 0) {
uint16_t n = (buf[5] | buf[6] << 8) / 2;
uint16_t *buf16 = (uint16_t *)&buf[7];
for (int j=0; j<n; j++) {
reading_t r;
r.timestamp = ts1 + _drift + MS_TO_NS(i * 10);
r.value = buf16[j];
readings.push_back(r);
i++;
}
}
}
// Check whether the timestamp changed during readDatastorePower() and re-read if it did
ts2 = readDatastoreTimestamp();
}
}
}
closeDatastore();
}
if (readings.size() == 3000) {
return 0;
} else {
return 1;
}
}
int LenovoXCC::readSingleEnergyRaw(uint64_t &timeStamp, uint64_t &energy) {
uint8_t buf[256];
uint8_t getSingleEnergyCmd[] = {0x00, 0x3a, 0x32, 0x04, 0x02, 0x00, 0x00, 0x00};
int len = -1;
......@@ -61,24 +100,24 @@ int LenovoXCC::getSingleEnergy(uint64_t &timeStamp, uint64_t &energy) {
return -1;
}
int64_t LenovoXCC::getDrift() {
int64_t drift = 0;
int LenovoXCC::getDrift() {
uint64_t xccTs, dummy;
uint64_t sysTs1 = getTimestamp();
if (getSingleEnergy(xccTs, dummy) == 0) {
if (readSingleEnergyRaw(xccTs, dummy) == 0) {
uint64_t sysTs2 = getTimestamp();
drift = sysTs1 + (sysTs2 - sysTs1) / 2 - xccTs;
_drift = sysTs1 + (sysTs2 - sysTs1) / 2 - xccTs;
return 0;
}
return drift;
return 1;
}
int LenovoXCC::openDatastore() {
if (_handle) {
closeDatastore();
}
uint8_t buf[256];
uint8_t getHandleCmd[] = {0x00, 0x2e, 0x90, 0x66, 0x4a, 0x00, 0x01, 0x01, 0x01, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x70, 0x77, 0x72, 0x5f, 0x6d, 0x65, 0x74, 0x65, 0x72};
int len = -1;
......@@ -174,53 +213,3 @@ uint64_t LenovoXCC::readDatastoreTimestamp() {
return 0;
}
}
int LenovoXCC::readDatastorePower(std::vector<uint16_t> &rawReadings) {
uint8_t buf[256];
try {
for (uint16_t offset = 16; offset < 6016; offset += 200) {
int len = readDatastoreRange(offset, 200, buf, sizeof(buf));
if (len >= 0) {
uint16_t n = (buf[5] | buf[6] << 8) / 2;
uint16_t *buf16 = (uint16_t *)&buf[7];
rawReadings.insert(rawReadings.end(), buf16, buf16 + n);
}
}
} catch (const std::exception &e) {
throw e;
return 1;
}
if (rawReadings.size()) {
return 0;
} else {
return -1;
}
}
int LenovoXCC::getBulkPower(std::vector<reading_t> &readings) {
if (openDatastore() == 0) {
uint64_t ts1, ts2;
std::vector<uint16_t> rawReadings;
if ((ts1 = readDatastoreTimestamp()) > 0) {
if (readDatastorePower(rawReadings) == 0) {
// Check whether the timestamp changed during readDatastorePower() and re-read if it did
ts2 = readDatastoreTimestamp();
if (ts2 > ts1) {
readDatastorePower(rawReadings);
ts1 = ts2;
}
}
closeDatastore();
}
ts1 += getDrift();
for (unsigned int i = 0; i < readings.size(); i++) {
readings[i].timestamp = ts1 + MS_TO_NS(i * 10);
readings[i].value = rawReadings[i];
// LOG(debug) << _groupName << "::" << s->getName() << " xcc: " << i << " " << reading.timestamp << " " << reading.value;
}
return (int) readings.size();
} else {
return 0;
}
}
......@@ -19,19 +19,18 @@ class LenovoXCC {
LenovoXCC(IPMIHost *host);
virtual ~LenovoXCC();
int getSingleEnergy(uint64_t &timeStamp, uint64_t &energy);
int getBulkPower(std::vector<reading_t> &readings);
int64_t getDrift();
int getDatastorePower(std::vector<reading_t> &readings);
private:
int openDatastore();
int closeDatastore();
uint64_t readDatastoreTimestamp();
int readDatastorePower(std::vector<uint16_t> &readings);
private:
int readDatastoreRange(uint32_t offset, uint16_t count, uint8_t *buf, uint16_t bufLen);
int readDatastoreRange(uint32_t offset, uint16_t count, uint8_t *buf, uint16_t bufLen);
int readSingleEnergyRaw(uint64_t &timeStamp, uint64_t &energy);
int getDrift();
IPMIHost *_host;
uint32_t _handle;
int64_t _drift;
};
#endif /* LenovoXCC_hpp */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment