mirror of
https://github.com/bjango/istatserverlinux.git
synced 2025-10-22 07:28:08 +00:00
Initial commit
This commit is contained in:
748
src/stats/StatsSensors.cpp
Normal file
748
src/stats/StatsSensors.cpp
Normal file
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* Copyright 2016 Bjango Pty Ltd. All rights reserved.
|
||||
* Copyright 2010 William Tisäter. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of the copyright holder may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL WILLIAM TISÄTER BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StatsSensors.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef HAVE_LIBSENSORS
|
||||
#if SENSORS_API_VERSION >= 0x0400 /* libsensor 4 */
|
||||
|
||||
void StatsSensors::update_libsensors(long long sampleID)
|
||||
{
|
||||
int a, b, c, num;
|
||||
const sensors_chip_name * chip;
|
||||
const sensors_feature * features;
|
||||
const sensors_subfeature * subfeatures;
|
||||
|
||||
a = num = 0;
|
||||
|
||||
while ((chip = sensors_get_detected_chips(NULL, &a)))
|
||||
{
|
||||
b = 0;
|
||||
while ((features = sensors_get_features(chip, &b)))
|
||||
{
|
||||
c = 0;
|
||||
while ((subfeatures = sensors_get_all_subfeatures(chip, features, &c)))
|
||||
{
|
||||
if (subfeatures->type == SENSORS_SUBFEATURE_FAN_INPUT ||
|
||||
subfeatures->type == SENSORS_SUBFEATURE_CURR_INPUT ||
|
||||
subfeatures->type == SENSORS_SUBFEATURE_POWER_INPUT ||
|
||||
subfeatures->type == SENSORS_SUBFEATURE_IN_INPUT ||
|
||||
subfeatures->type == SENSORS_SUBFEATURE_VID ||
|
||||
subfeatures->type == SENSORS_SUBFEATURE_TEMP_INPUT)
|
||||
{
|
||||
|
||||
//if (chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
|
||||
// printf ("%s-isa-%04x", chip->prefix, chip->addr);
|
||||
//else
|
||||
// printf ("%s\n", chip->prefix);
|
||||
//fflush(stdout);
|
||||
|
||||
|
||||
char *label = sensors_get_label(chip, features);
|
||||
stringstream key;
|
||||
key << label << "_" << sensorType(subfeatures->type);
|
||||
|
||||
if(createSensor(key.str()) == 1)
|
||||
{
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).key == key.str())
|
||||
{
|
||||
(*cur).method = 1;
|
||||
(*cur).chip = chip->addr;
|
||||
(*cur).sensor = features->number;
|
||||
(*cur).label = string(label);
|
||||
(*cur).kind = sensorType(subfeatures->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double value;
|
||||
sensors_get_value(chip, subfeatures->number, &value);
|
||||
|
||||
processSensor(key.str(), sampleID, value);
|
||||
|
||||
free(label);
|
||||
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int StatsSensors::sensorType(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case SENSORS_SUBFEATURE_FAN_INPUT:
|
||||
return 2;
|
||||
break;
|
||||
case SENSORS_SUBFEATURE_CURR_INPUT:
|
||||
return 4;
|
||||
break;
|
||||
case SENSORS_SUBFEATURE_POWER_INPUT:
|
||||
return 5;
|
||||
break;
|
||||
case SENSORS_SUBFEATURE_IN_INPUT:
|
||||
case SENSORS_SUBFEATURE_VID:
|
||||
return 3;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#elif SENSORS_API_VERSION < 0x0400 /* libsensor 3 and earlier */
|
||||
|
||||
void StatsSensors::update_libsensors(long long sampleID)
|
||||
{
|
||||
int a, b, c, num;
|
||||
const sensors_chip_name * chip;
|
||||
const sensors_feature_data * features;
|
||||
|
||||
a = num = 0;
|
||||
|
||||
while ((chip = sensors_get_detected_chips(&a)))
|
||||
{
|
||||
b = c = 0;
|
||||
|
||||
while ((features = sensors_get_all_features(*chip, &b, &c)))
|
||||
{
|
||||
if ((!memcmp(features->name, "fan", 3) && features->name[4]=='\0') || (!memcmp(features->name, "temp", 3) && features->name[5]=='\0')){
|
||||
stringstream key;
|
||||
key << num;
|
||||
|
||||
if(createSensor(key.str()) == 1)
|
||||
{
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).key == key.str())
|
||||
{
|
||||
(*cur).method = 1;
|
||||
(*cur).chip = chip->addr;
|
||||
(*cur).sensor = features->number;
|
||||
if(!memcmp(features->name, "fan", 3) && features->name[4]=='\0')
|
||||
(*cur).kind = 2;
|
||||
else
|
||||
(*cur).kind = 0;
|
||||
|
||||
char *label;
|
||||
sensors_get_label(*chip, (*cur).sensor, &label);
|
||||
(*cur).label = string(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double value;
|
||||
sensors_get_feature(*chip, features->number, &value);
|
||||
|
||||
processSensor(key.str(), sampleID, value);
|
||||
|
||||
num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBSENSORS
|
||||
void StatsSensors::init_libsensors()
|
||||
{
|
||||
#if SENSORS_API_VERSION >= 0x0400 /* libsensor 4 */
|
||||
sensors_init(NULL);
|
||||
libsensors_ready = true;
|
||||
#else
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen("/etc/sensors.conf", "r")) == NULL)
|
||||
return;
|
||||
|
||||
if (sensors_init(fp) != 0) {
|
||||
libsensors_ready = false;
|
||||
fclose(fp);
|
||||
}
|
||||
libsensors_ready = true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void StatsSensors::init_dev_cpu()
|
||||
{
|
||||
#if defined(HAVE_SYSCTLBYNAME)
|
||||
int x;
|
||||
for(x=0;x<32;x++)
|
||||
{
|
||||
stringstream key;
|
||||
key << "dev.cpu." << x << ".temperature";
|
||||
|
||||
size_t len;
|
||||
long buf;
|
||||
len = sizeof(buf);
|
||||
|
||||
if (sysctlbyname(key.str().c_str(), &buf, &len, NULL, 0) >= 0)
|
||||
{
|
||||
createSensor(key.str());
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).key == key.str())
|
||||
{
|
||||
stringstream label;
|
||||
label << "CPU " << x;
|
||||
(*cur).label = label.str();
|
||||
(*cur).method = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StatsSensors::init_acpi_thermal()
|
||||
{
|
||||
#if defined(HAVE_SYSCTLBYNAME)
|
||||
int x;
|
||||
for(x=0;x<32;x++)
|
||||
{
|
||||
stringstream key;
|
||||
key << "hw.acpi.thermal.tz" << x << ".temperature";
|
||||
|
||||
size_t len;
|
||||
long buf;
|
||||
len = sizeof(buf);
|
||||
|
||||
if (sysctlbyname(key.str().c_str(), &buf, &len, NULL, 0) >= 0)
|
||||
{
|
||||
createSensor(key.str());
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).key == key.str())
|
||||
{
|
||||
stringstream label;
|
||||
label << "Thermal Zone " << x;
|
||||
(*cur).label = label.str();
|
||||
(*cur).method = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StatsSensors::init_acpi_freq()
|
||||
{
|
||||
#if defined(HAVE_SYSCTLBYNAME)
|
||||
int x;
|
||||
for(x=0;x<32;x++)
|
||||
{
|
||||
stringstream key;
|
||||
key << "dev.cpu." << x << ".freq";
|
||||
|
||||
size_t len;
|
||||
long buf;
|
||||
len = sizeof(buf);
|
||||
|
||||
if (sysctlbyname(key.str().c_str(), &buf, &len, NULL, 0) >= 0)
|
||||
{
|
||||
createSensor(key.str());
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).key == key.str())
|
||||
{
|
||||
stringstream label;
|
||||
label << "CPU " << x << " Frequency";
|
||||
(*cur).label = label.str();
|
||||
(*cur).method = 5;
|
||||
(*cur).kind = 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StatsSensors::init_qnap()
|
||||
{
|
||||
int temp;
|
||||
|
||||
char *systempfile=(char*)"/proc/tsinfo/systemp";
|
||||
FILE *systempfp;
|
||||
if ((systempfp=fopen(systempfile, "r"))==NULL) {
|
||||
return;
|
||||
}
|
||||
if (fscanf(systempfp, "%d", &temp)!=1) {
|
||||
fclose(systempfp);
|
||||
return;
|
||||
}
|
||||
fclose(systempfp);
|
||||
|
||||
createSensor("qnap");
|
||||
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
(*cur).label = "Temperature";
|
||||
(*cur).method = 3;
|
||||
}
|
||||
}
|
||||
|
||||
void StatsSensors::update_qnap(long long sampleID)
|
||||
{
|
||||
char *systempfile=(char*)"/proc/tsinfo/systemp";
|
||||
FILE *systempfp;
|
||||
int systemp;
|
||||
if ((systempfp=fopen(systempfile, "r"))==NULL)
|
||||
return;
|
||||
else {
|
||||
fseek(systempfp, 0l, 0);
|
||||
if (fscanf(systempfp, "%d", &systemp) == 1){
|
||||
processSensor("qnap", sampleID, systemp);
|
||||
}
|
||||
fclose(systempfp);
|
||||
}
|
||||
}
|
||||
|
||||
void StatsSensors::update_dev_cpu(long long sampleID)
|
||||
{
|
||||
#if defined(HAVE_SYSCTLBYNAME)
|
||||
if(_items.size() == 0)
|
||||
return;
|
||||
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).method != 2)
|
||||
continue;
|
||||
|
||||
size_t len;
|
||||
int buf;
|
||||
len = sizeof(buf);
|
||||
|
||||
if (sysctlbyname((*cur).key.c_str(), &buf, &len, NULL, 0) >= 0)
|
||||
{
|
||||
double value = (buf - 2732) / 10.0f;
|
||||
processSensor((*cur).key, sampleID, value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StatsSensors::update_acpi_thermal(long long sampleID)
|
||||
{
|
||||
#if defined(HAVE_SYSCTLBYNAME)
|
||||
if(_items.size() == 0)
|
||||
return;
|
||||
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).method != 4)
|
||||
continue;
|
||||
|
||||
size_t len;
|
||||
int buf;
|
||||
len = sizeof(buf);
|
||||
|
||||
if (sysctlbyname((*cur).key.c_str(), &buf, &len, NULL, 0) >= 0)
|
||||
{
|
||||
double value = (buf - 2732) / 10.0f;
|
||||
processSensor((*cur).key, sampleID, value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StatsSensors::update_acpi_freq(long long sampleID)
|
||||
{
|
||||
#if defined(HAVE_SYSCTLBYNAME)
|
||||
if(_items.size() == 0)
|
||||
return;
|
||||
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).method != 5)
|
||||
continue;
|
||||
|
||||
size_t len;
|
||||
int buf;
|
||||
len = sizeof(buf);
|
||||
|
||||
if (sysctlbyname((*cur).key.c_str(), &buf, &len, NULL, 0) >= 0)
|
||||
{
|
||||
processSensor((*cur).key, sampleID, (double)buf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
Methods
|
||||
|
||||
1 = libsensors
|
||||
2 = dev.cpu.(x).temperature
|
||||
3 = qnap
|
||||
4 = hw.acpi.thermal.tz(x).temperature"
|
||||
5 = dev.cpu.(x).freq
|
||||
|
||||
*/
|
||||
|
||||
void StatsSensors::init()
|
||||
{
|
||||
_init();
|
||||
|
||||
#ifdef HAVE_LIBSENSORS
|
||||
init_libsensors();
|
||||
#endif
|
||||
|
||||
init_dev_cpu();
|
||||
init_qnap();
|
||||
init_acpi_thermal();
|
||||
init_acpi_freq();
|
||||
}
|
||||
|
||||
void StatsSensors::update(long long sampleID)
|
||||
{
|
||||
#ifdef HAVE_LIBSENSORS
|
||||
if(libsensors_ready == true)
|
||||
update_libsensors(sampleID);
|
||||
#endif
|
||||
|
||||
update_qnap(sampleID);
|
||||
update_dev_cpu(sampleID);
|
||||
update_acpi_thermal(sampleID);
|
||||
update_acpi_freq(sampleID);
|
||||
|
||||
#ifdef USE_SQLITE
|
||||
if(historyEnabled == true)
|
||||
{
|
||||
if(_items.size() > 0)
|
||||
{
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).recordedValueChanged)
|
||||
{
|
||||
string sql = "UPDATE sensor_limits SET low = ?, high = ? where uuid = ?";
|
||||
|
||||
DatabaseItem dbItem = _database.databaseItem(sql);
|
||||
sqlite3_bind_double(dbItem._statement, 1, (*cur).lowestValue);
|
||||
sqlite3_bind_double(dbItem._statement, 2, (*cur).highestValue);
|
||||
sqlite3_bind_text(dbItem._statement, 3, (*cur).key.c_str(), -1, SQLITE_STATIC);
|
||||
databaseQueue.push_back(dbItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int StatsSensors::createSensor(string key)
|
||||
{
|
||||
if(_items.size() > 0)
|
||||
{
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
sensor_info sensor = *cur;
|
||||
if(sensor.key == key){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sensor_info item;
|
||||
item.key = key;
|
||||
item.lowestValue = -1;
|
||||
item.highestValue = 0;
|
||||
|
||||
#ifdef USE_SQLITE
|
||||
if(historyEnabled == true)
|
||||
{
|
||||
string sql = "select * from sensor_limits where uuid = ?";
|
||||
DatabaseItem query = _database.databaseItem(sql);
|
||||
sqlite3_bind_text(query._statement, 1, key.c_str(), -1, SQLITE_STATIC);
|
||||
|
||||
bool hasRow = false;
|
||||
while(query.next())
|
||||
{
|
||||
hasRow = true;
|
||||
item.lowestValue = query.doubleForColumn("low");
|
||||
item.highestValue = query.doubleForColumn("high");
|
||||
}
|
||||
|
||||
if(!hasRow){
|
||||
string sql = "insert into sensor_limits (uuid) values(?)";
|
||||
DatabaseItem dbItem = _database.databaseItem(sql);
|
||||
sqlite3_bind_text(dbItem._statement, 1, key.c_str(), -1, SQLITE_STATIC);
|
||||
dbItem.executeUpdate();
|
||||
}
|
||||
|
||||
int x;
|
||||
for(x=1;x<8;x++)
|
||||
{
|
||||
string table = databasePrefix + tableAtIndex(x);
|
||||
double sampleID = 0;
|
||||
if(samples[x].size() > 0)
|
||||
sampleID = samples[x][0].sampleID;
|
||||
|
||||
string sql = "select * from " + table + " where sample >= @sample AND uuid = ? order by sample asc limit 602";
|
||||
DatabaseItem query = _database.databaseItem(sql);
|
||||
sqlite3_bind_double(query._statement, 1, sampleID - 602);
|
||||
sqlite3_bind_text(query._statement, 2, key.c_str(), -1, SQLITE_STATIC);
|
||||
|
||||
while(query.next())
|
||||
{
|
||||
sensor_data sample;
|
||||
sample.value = query.doubleForColumn("value");
|
||||
sample.sampleID = (long long)query.doubleForColumn("sample");
|
||||
sample.time = query.doubleForColumn("time");
|
||||
item.samples[x].push_front(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_items.insert(_items.begin(), item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void StatsSensors::processSensor(string key, long long sampleID, double value)
|
||||
{
|
||||
if(ready == 0)
|
||||
return;
|
||||
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
if((*cur).key == key){
|
||||
sensor_data data;
|
||||
data.value = value;
|
||||
data.sampleID = sampleIndex[0].sampleID;
|
||||
data.time = sampleIndex[0].time;
|
||||
|
||||
(*cur).samples[0].push_front(data);
|
||||
if ((*cur).samples[0].size() > HISTORY_SIZE)
|
||||
(*cur).samples[0].pop_back();
|
||||
|
||||
bool changed = false;
|
||||
(*cur).recordedValueChanged = false;
|
||||
|
||||
if(value > (*cur).highestValue){
|
||||
(*cur).highestValue = value;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if(value < (*cur).lowestValue || (*cur).lowestValue == -1){
|
||||
(*cur).lowestValue = value;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
(*cur).recordedValueChanged = changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StatsSensors::_init()
|
||||
{
|
||||
initShared();
|
||||
ready = 0;
|
||||
|
||||
#ifdef USE_SQLITE
|
||||
if(historyEnabled == true)
|
||||
{
|
||||
databaseType = 1;
|
||||
databasePrefix = "sensors_";
|
||||
|
||||
int x;
|
||||
for(x=1;x<8;x++)
|
||||
{
|
||||
string table = databasePrefix + tableAtIndex(x) + "_id";
|
||||
if(!_database.tableExists(table))
|
||||
{
|
||||
string sql = "create table " + table + " (sample double PRIMARY KEY NOT NULL, time double NOT NULL DEFAULT 0, empty integer NOT NULL DEFAULT 0)";
|
||||
DatabaseItem dbItem = _database.databaseItem(sql);
|
||||
dbItem.executeUpdate();
|
||||
}
|
||||
|
||||
table = databasePrefix + tableAtIndex(x);
|
||||
if(!_database.tableExists(table))
|
||||
{
|
||||
string sql = "create table " + table + " (sample double NOT NULL, time double NOT NULL DEFAULT 0, uuid varchar(255) NOT NULL, value double NOT NULL DEFAULT 0)";
|
||||
DatabaseItem dbItem = _database.databaseItem(sql);
|
||||
dbItem.executeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
string table = "sensor_limits";
|
||||
if(!_database.tableExists(table))
|
||||
{
|
||||
string sql = "create table sensor_limits (uuid varchar(255) NOT NULL, low double NOT NULL DEFAULT 0, high double NOT NULL DEFAULT 0)";
|
||||
DatabaseItem dbItem = _database.databaseItem(sql);
|
||||
dbItem.executeUpdate();
|
||||
}
|
||||
loadPreviousSamples();
|
||||
fillGaps();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_SQLITE
|
||||
void StatsSensors::loadPreviousSamples()
|
||||
{
|
||||
loadPreviousSamplesAtIndex(1);
|
||||
loadPreviousSamplesAtIndex(2);
|
||||
loadPreviousSamplesAtIndex(3);
|
||||
loadPreviousSamplesAtIndex(4);
|
||||
loadPreviousSamplesAtIndex(5);
|
||||
loadPreviousSamplesAtIndex(6);
|
||||
loadPreviousSamplesAtIndex(7);
|
||||
}
|
||||
|
||||
void StatsSensors::loadPreviousSamplesAtIndex(int index)
|
||||
{
|
||||
|
||||
string table = databasePrefix + tableAtIndex(index) + "_id";
|
||||
double sampleID = sampleIdForTable(table);
|
||||
|
||||
string sql = "select * from " + table + " where sample >= @sample order by sample asc limit 602";
|
||||
DatabaseItem query = _database.databaseItem(sql);
|
||||
sqlite3_bind_double(query._statement, 1, sampleID - 602);
|
||||
|
||||
while(query.next())
|
||||
{
|
||||
sample_data sample;
|
||||
sample.sampleID = (long long)query.doubleForColumn("sample");
|
||||
sample.time = query.doubleForColumn("time");
|
||||
samples[index].insert(samples[index].begin(), sample);
|
||||
}
|
||||
if(samples[index].size() > 0)
|
||||
{
|
||||
sampleIndex[index].sampleID = samples[index][0].sampleID;
|
||||
sampleIndex[index].time = samples[index][0].time;
|
||||
sampleIndex[index].nextTime = sampleIndex[index].time + sampleIndex[index].interval;
|
||||
}
|
||||
}
|
||||
|
||||
void StatsSensors::updateHistory()
|
||||
{
|
||||
int x;
|
||||
for (x = 1; x < 8; x++)
|
||||
{
|
||||
if(sampleIndex[0].time >= sampleIndex[x].nextTime)
|
||||
{
|
||||
double now = get_current_time();
|
||||
double earlistTime = now - (HISTORY_SIZE * sampleIndex[x].interval);
|
||||
while(sampleIndex[x].nextTime < now)
|
||||
{
|
||||
sampleIndex[x].sampleID = sampleIndex[x].sampleID + 1;
|
||||
sampleIndex[x].time = sampleIndex[x].nextTime;
|
||||
sampleIndex[x].nextTime = sampleIndex[x].nextTime + sampleIndex[x].interval;
|
||||
|
||||
if(sampleIndex[x].time < earlistTime)
|
||||
continue;
|
||||
|
||||
if(_items.size() > 0)
|
||||
{
|
||||
for (vector<sensor_info>::iterator cur = _items.begin(); cur != _items.end(); ++cur)
|
||||
{
|
||||
sensor_data sample = historyItemAtIndex(x, (*cur));
|
||||
|
||||
(*cur).samples[x].push_front(sample);
|
||||
if ((*cur).samples[x].size() > HISTORY_SIZE) (*cur).samples[x].pop_back();
|
||||
|
||||
if(sample.empty)
|
||||
continue;
|
||||
|
||||
string table = databasePrefix + tableAtIndex(x);
|
||||
string sql = "insert into " + table + " (sample, time, value, uuid) values(?, ?, ?, ?)";
|
||||
|
||||
DatabaseItem dbItem = _database.databaseItem(sql);
|
||||
sqlite3_bind_double(dbItem._statement, 1, (double)sample.sampleID);
|
||||
sqlite3_bind_double(dbItem._statement, 2, sample.time);
|
||||
sqlite3_bind_double(dbItem._statement, 3, sample.value);
|
||||
sqlite3_bind_text(dbItem._statement, 4, (*cur).key.c_str(), -1, SQLITE_STATIC);
|
||||
databaseQueue.push_back(dbItem);
|
||||
//dbItem.executeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
string table = databasePrefix + tableAtIndex(x) + "_id";
|
||||
string sql = "insert into " + table + " (empty, sample, time) values(?, ?, ?)";
|
||||
|
||||
DatabaseItem dbItem = _database.databaseItem(sql);
|
||||
sqlite3_bind_int(dbItem._statement, 1, 0);
|
||||
sqlite3_bind_double(dbItem._statement, 2, (double)sampleIndex[x].sampleID);
|
||||
sqlite3_bind_double(dbItem._statement, 3, sampleIndex[x].time);
|
||||
databaseQueue.push_back(dbItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sensor_data StatsSensors::historyItemAtIndex(int index, sensor_info item)
|
||||
{
|
||||
sensor_data sample;
|
||||
double value = 0;
|
||||
|
||||
std::deque<sensor_data> from = item.samples[sampleIndex[index].historyIndex];
|
||||
double minimumTime = sampleIndex[index].time - sampleIndex[index].interval;
|
||||
double maximumTime = sampleIndex[index].time;
|
||||
if(sampleIndex[index].historyIndex == 0)
|
||||
maximumTime += 0.99;
|
||||
|
||||
int count = 0;
|
||||
if(from.size() > 0)
|
||||
{
|
||||
for (deque<sensor_data>::iterator cursample = from.begin(); cursample != from.end(); ++cursample)
|
||||
{
|
||||
if ((*cursample).time > maximumTime){
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*cursample).time < minimumTime)
|
||||
break;
|
||||
|
||||
value += (*cursample).value;
|
||||
count++;
|
||||
}
|
||||
if (count > 0 && value > 0)
|
||||
{
|
||||
value /= count;
|
||||
}
|
||||
}
|
||||
|
||||
sample.value = value;
|
||||
sample.sampleID = sampleIndex[index].sampleID;
|
||||
sample.time = sampleIndex[index].time;
|
||||
sample.empty = false;
|
||||
if(count == 0)
|
||||
sample.empty = true;
|
||||
|
||||
return sample;
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user