From 9445fb8ca064b1f74a92e1137bd031e49209c073 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 25 Feb 2011 20:08:08 +0100 Subject: [PATCH] added min/max/avg/consumption calculations to MeterInterpreter improved performance --- lib/Interpreter/AggregatorInterpreter.php | 2 +- lib/Interpreter/Interpreter.php | 12 +-- .../Iterator/DataAggregationIterator.php | 6 +- lib/Interpreter/Iterator/DataIterator.php | 15 ++-- lib/Interpreter/MeterInterpreter.php | 85 ++++++++++--------- lib/Interpreter/SensorInterpreter.php | 3 +- lib/View/CSV.php | 2 +- lib/View/JSON.php | 2 +- lib/View/JpGraph.php | 6 +- lib/View/XML.php | 2 +- 10 files changed, 72 insertions(+), 63 deletions(-) diff --git a/lib/Interpreter/AggregatorInterpreter.php b/lib/Interpreter/AggregatorInterpreter.php index 1d63c79..808ac0f 100644 --- a/lib/Interpreter/AggregatorInterpreter.php +++ b/lib/Interpreter/AggregatorInterpreter.php @@ -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) { } diff --git a/lib/Interpreter/Interpreter.php b/lib/Interpreter/Interpreter.php index d53ac5b..72952ec 100644 --- a/lib/Interpreter/Interpreter.php +++ b/lib/Interpreter/Interpreter.php @@ -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); } } diff --git a/lib/Interpreter/Iterator/DataAggregationIterator.php b/lib/Interpreter/Iterator/DataAggregationIterator.php index bc81da6..5f32e02 100644 --- a/lib/Interpreter/Iterator/DataAggregationIterator.php +++ b/lib/Interpreter/Iterator/DataAggregationIterator.php @@ -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; } } -?> \ No newline at end of file +?> diff --git a/lib/Interpreter/Iterator/DataIterator.php b/lib/Interpreter/Iterator/DataIterator.php index 03e409c..1cad3fd 100644 --- a/lib/Interpreter/Iterator/DataIterator.php +++ b/lib/Interpreter/Iterator/DataIterator.php @@ -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; + } } -?> \ No newline at end of file +?> diff --git a/lib/Interpreter/MeterInterpreter.php b/lib/Interpreter/MeterInterpreter.php index f9b8913..adb2d9a 100644 --- a/lib/Interpreter/MeterInterpreter.php +++ b/lib/Interpreter/MeterInterpreter.php @@ -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 ); } } diff --git a/lib/Interpreter/SensorInterpreter.php b/lib/Interpreter/SensorInterpreter.php index b6f5dfc..5026cf7 100644 --- a/lib/Interpreter/SensorInterpreter.php +++ b/lib/Interpreter/SensorInterpreter.php @@ -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(); diff --git a/lib/View/CSV.php b/lib/View/CSV.php index 80ea0cc..db97b34 100644 --- a/lib/View/CSV.php +++ b/lib/View/CSV.php @@ -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) { diff --git a/lib/View/JSON.php b/lib/View/JSON.php index 848f3c3..adb8c55 100644 --- a/lib/View/JSON.php +++ b/lib/View/JSON.php @@ -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) { diff --git a/lib/View/JpGraph.php b/lib/View/JpGraph.php index 3a7edd4..cbde4f9 100644 --- a/lib/View/JpGraph.php +++ b/lib/View/JpGraph.php @@ -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); diff --git a/lib/View/XML.php b/lib/View/XML.php index 70327b9..e4a3d43 100644 --- a/lib/View/XML.php +++ b/lib/View/XML.php @@ -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) {