added min/max/avg/consumption calculations to MeterInterpreter
improved performance
This commit is contained in:
parent
b2b6f357a9
commit
9445fb8ca0
10 changed files with 72 additions and 63 deletions
|
@ -78,7 +78,7 @@ class AggregatorInterpreter {
|
|||
* @todo to be implemented
|
||||
* @return array of values
|
||||
*/
|
||||
public function getValues($tuples = NULL, $groupBy = NULL) {
|
||||
public function processData($tuples = NULL, $groupBy = NULL) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ abstract class Interpreter {
|
|||
|
||||
protected $from;
|
||||
protected $to;
|
||||
|
||||
protected $rows;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -72,7 +74,7 @@ abstract class Interpreter {
|
|||
* @param string|integer $groupBy
|
||||
* @return Volkszaehler\DataIterator
|
||||
*/
|
||||
protected function getData($tuples = NULL, $groupBy = NULL) {
|
||||
protected function getData($count = NULL, $groupBy = NULL) {
|
||||
// prepare sql
|
||||
$sql['from'] = ' FROM data';
|
||||
$sql['where'] = ' WHERE channel_id = ?' . self::buildDateTimeFilterSQL($this->from, $this->to);
|
||||
|
@ -90,17 +92,17 @@ abstract class Interpreter {
|
|||
}
|
||||
|
||||
// get total row count for grouping
|
||||
$rowCount = $this->conn->fetchColumn($sql['rowCount'], array($this->channel->getId()), 0);
|
||||
$this->rows = $this->conn->fetchColumn($sql['rowCount'], array($this->channel->getId()), 0);
|
||||
|
||||
// query for data
|
||||
$stmt = $this->conn->executeQuery('SELECT ' . $sql['fields'] . $sql['from'] . $sql['where'] . $sql['groupBy'] . $sql['orderBy'], array($this->channel->getId()));
|
||||
|
||||
// return iterators
|
||||
if ($sql['groupBy'] || is_null($tuples) || $rowCount < $tuples) {
|
||||
return new Iterator\DataIterator($stmt, $rowCount);
|
||||
if ($sql['groupBy'] || is_null($count) || $this->rows < $count) {
|
||||
return new Iterator\DataIterator($stmt, $this->rows);
|
||||
}
|
||||
else {
|
||||
return new Iterator\DataAggregationIterator($stmt, $rowCount, $tuples);
|
||||
return new Iterator\DataAggregationIterator($stmt, $this->rows, $count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,8 +64,8 @@ class DataAggregationIterator implements \Iterator, \Countable {
|
|||
$current[2] += $tuple[2];
|
||||
}
|
||||
|
||||
$this->current = $current;
|
||||
$this->key++;
|
||||
return $this->current = $current;
|
||||
}
|
||||
|
||||
public function rewind() {
|
||||
|
@ -75,7 +75,7 @@ class DataAggregationIterator implements \Iterator, \Countable {
|
|||
for ($i = 0; $i < $skip; $i++) {
|
||||
$this->iterator->next();
|
||||
}
|
||||
$this->next();
|
||||
return $this->next();
|
||||
}
|
||||
|
||||
public function valid() {
|
||||
|
@ -91,4 +91,4 @@ class DataAggregationIterator implements \Iterator, \Countable {
|
|||
public function current() { return $this->current; }
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
namespace Volkszaehler\Interpreter\Iterator;
|
||||
|
||||
use Volkszaehler\Util;
|
||||
|
||||
use Doctrine\DBAL;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +31,7 @@ use Doctrine\DBAL;
|
|||
* @package default
|
||||
*/
|
||||
class DataIterator implements \Iterator, \Countable {
|
||||
protected $current;
|
||||
protected $current; // the current data
|
||||
protected $key; // key
|
||||
protected $stmt; // PDOStatement
|
||||
protected $size; // total readings in PDOStatement
|
||||
|
@ -45,7 +44,6 @@ class DataIterator implements \Iterator, \Countable {
|
|||
*/
|
||||
public function __construct(\PDOStatement $stmt, $size) {
|
||||
$this->size = $size;
|
||||
|
||||
$this->stmt = $stmt;
|
||||
$this->stmt->setFetchMode(\PDO::FETCH_NUM);
|
||||
}
|
||||
|
@ -62,7 +60,7 @@ class DataIterator implements \Iterator, \Countable {
|
|||
*/
|
||||
public function next() {
|
||||
$this->key++;
|
||||
$this->current = $this->stmt->fetch();
|
||||
return $this->current = $this->stmt->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,13 +85,16 @@ class DataIterator implements \Iterator, \Countable {
|
|||
*/
|
||||
public function rewind() {
|
||||
$this->key = 0;
|
||||
$this->current = $this->stmt->fetch();
|
||||
return $this->current = $this->stmt->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total num of rows
|
||||
* @return integer
|
||||
*/
|
||||
public function count() { return $this->size; }
|
||||
public function count() {
|
||||
return $this->size;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
|
|
@ -35,50 +35,43 @@ use Volkszaehler\Util;
|
|||
|
||||
class MeterInterpreter extends Interpreter {
|
||||
|
||||
protected $min = NULL;
|
||||
protected $max = NULL;
|
||||
protected $consumption = NULL;
|
||||
protected $resolution;
|
||||
|
||||
/**
|
||||
* Calculates the consumption for interval speciefied by $from and $to
|
||||
*
|
||||
* @todo improfve workaround
|
||||
* Calculates the consumption
|
||||
* @return float total consumption
|
||||
*/
|
||||
public function getConsumption() {
|
||||
$sql = 'SELECT COUNT(*) FROM `data` WHERE `channel_id` = ?' . parent::buildDateTimeFilterSQL($this->from, $this->to);
|
||||
|
||||
return $this->conn->fetchColumn($sql, array($this->channel->getId()), 0) / $this->channel->getProperty('resolution'); // return KWh
|
||||
if (is_null($this->consumption)) throw new \Excpetion('Data has to be processed first!');
|
||||
|
||||
return $this->consumption / $this->resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum
|
||||
* @return array (0 => timestamp, 1 => value)
|
||||
* @todo reimplement according to new env
|
||||
*/
|
||||
public function getMin() {
|
||||
/*$data = $this->getData();
|
||||
|
||||
$min = current($data);
|
||||
foreach ($data as $reading) {
|
||||
if ($reading['value '] < $min['value']) {
|
||||
$min = $reading;
|
||||
}
|
||||
}
|
||||
return $min;*/
|
||||
if (is_null($this->min)) throw new \Excpetion('Data has to be processed first!');
|
||||
|
||||
return $this->min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximum
|
||||
* @return array (0 => timestamp, 1 => value)
|
||||
* @todo reimplement according to new env
|
||||
*/
|
||||
public function getMax() {
|
||||
/*$data = $this->getData();
|
||||
|
||||
$max = current($data);
|
||||
foreach ($data as $reading) {
|
||||
if ($reading['value '] > $max['value']) {
|
||||
$max = $reading;
|
||||
}
|
||||
}
|
||||
return $max;*/
|
||||
if (is_null($this->max)) throw new \Excpetion('Data has to be processed first!');
|
||||
|
||||
return $this->max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Average
|
||||
* @return float
|
||||
*/
|
||||
public function getAverage() {
|
||||
|
@ -92,21 +85,37 @@ class MeterInterpreter extends Interpreter {
|
|||
* @todo untested
|
||||
* @return array with timestamp, values, and pulse count
|
||||
*/
|
||||
public function getValues($tuples, $groupBy, $callback) {
|
||||
$pulses = parent::getData($tuples, $groupBy);
|
||||
public function processData($count, $groupBy, $callback) {
|
||||
$this->resolution = $this->channel->getProperty('resolution');
|
||||
$this->consumption = 0;
|
||||
|
||||
$pulses = parent::getData($count, $groupBy);
|
||||
|
||||
$values = array();
|
||||
foreach ($pulses as $pulse) {
|
||||
if (isset($last)) {
|
||||
$values[] = $callback($this->raw2differential($last, $pulse));
|
||||
$last = $pulse;
|
||||
$tuples = array();
|
||||
$last = $pulses->rewind();
|
||||
$next = $pulses->next();
|
||||
$next = $pulses->current();
|
||||
|
||||
while ($pulses->valid()) {
|
||||
Util\Debug::log('after valid()', $last, $next);
|
||||
$tuple = $callback($this->raw2differential($last, $next));
|
||||
|
||||
if (is_null($this->max) || $tuple[1] > $this->max[1]) {
|
||||
$this->max = $tuple;
|
||||
}
|
||||
else {
|
||||
$last = $pulse;
|
||||
|
||||
if (is_null($this->min) || $tuple[1] < $this->min[1]) {
|
||||
$this->min = $tuple;
|
||||
}
|
||||
|
||||
$this->consumption += $tuple[2];
|
||||
|
||||
$tuples[] = $tuple;
|
||||
$last = $next;
|
||||
$next = $pulses->next();
|
||||
}
|
||||
|
||||
return $values;
|
||||
return $tuples;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,8 +129,8 @@ class MeterInterpreter extends Interpreter {
|
|||
|
||||
return array(
|
||||
($next[0] - $delta / 2), // timestamp
|
||||
$next[1] * (3600000 / (($this->channel->getProperty('resolution') / 1000) * $delta)), // value
|
||||
$next[2]
|
||||
$next[1] * (3600000 / (($this->resolution / 1000) * $delta)), // value
|
||||
$next[2] // num of pulses
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,10 +34,9 @@ use Volkszaehler\Util;
|
|||
class SensorInterpreter extends Interpreter {
|
||||
|
||||
/**
|
||||
* @todo untested
|
||||
* @param string|integer $groupBy
|
||||
*/
|
||||
public function getValues($tuples, $groupBy, $callback) {
|
||||
public function processData($tuples, $groupBy, $callback) {
|
||||
$data = parent::getData($tuples, $groupBy);
|
||||
|
||||
$values = array();
|
||||
|
|
|
@ -117,7 +117,7 @@ class CSV extends View {
|
|||
protected function addData(Interpreter\Interpreter $interpreter) {
|
||||
//$this->response->setHeader('Content-Disposition', 'attachment; filename="' . strtolower($interpreter->getEntity()->getProperty('title')) . '.csv"'); // TODO add time?
|
||||
|
||||
$tuples = $interpreter->getValues(
|
||||
$tuples = $interpreter->processData(
|
||||
$this->request->getParameter('tuples'),
|
||||
$this->request->getParameter('group'),
|
||||
function($tuple) {
|
||||
|
|
|
@ -213,7 +213,7 @@ class JSON extends View {
|
|||
protected function addData($interpreter) {
|
||||
$this->json['data']['uuid'] = $interpreter->getEntity()->getUuid();
|
||||
|
||||
$data = $interpreter->getValues(
|
||||
$data = $interpreter->processData(
|
||||
$this->request->getParameter('tuples'),
|
||||
$this->request->getParameter('group'),
|
||||
function($tuple) {
|
||||
|
|
|
@ -112,9 +112,7 @@ class JpGraph extends View {
|
|||
$this->graph->xaxis->SetLabelAngle(45);
|
||||
$this->graph->xaxis->SetLabelFormatCallback(function($label) { return date('j.n.y G:i', $label); });
|
||||
|
||||
if (function_exists('imageantialias')) {
|
||||
$this->graph->img->SetAntiAliasing();
|
||||
}
|
||||
$this->graph->img->SetAntiAliasing(function_exists('imageantialias'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,7 +142,7 @@ class JpGraph extends View {
|
|||
* @param $data
|
||||
*/
|
||||
public function addData(Interpreter\InterpreterInterface $interpreter){
|
||||
$data = $interpreter->getValues($this->width/4);
|
||||
$data = $interpreter->processData($this->width/4);
|
||||
|
||||
if (count($data) > 0) {
|
||||
$count = count($this->channels);
|
||||
|
|
|
@ -205,7 +205,7 @@ class XML extends View {
|
|||
$xmlData = $this->xmlDoc->createElement('data');
|
||||
$xmlTuples = $this->xmlDoc->createElement('tuples');
|
||||
|
||||
$data = $interpreter->getValues(
|
||||
$data = $interpreter->processData(
|
||||
$this->request->getParameter('tuples'),
|
||||
$this->request->getParameter('group'),
|
||||
function($tuple) use ($xmlDoc, $xmlTuples) {
|
||||
|
|
Loading…
Add table
Reference in a new issue