diff --git a/lib/Interpreter/MeterInterpreter.php b/lib/Interpreter/MeterInterpreter.php index 30c83bc..b242c1e 100644 --- a/lib/Interpreter/MeterInterpreter.php +++ b/lib/Interpreter/MeterInterpreter.php @@ -76,8 +76,12 @@ class MeterInterpreter extends Interpreter { * @return float 3600: 3600 s/h; 1000: ms -> s */ public function getAverage() { - $delta = ($this->getConsumption()) ? $this->last[0] - $this->first[0] : 1; // prevent division by zero - return (3600 * 1000 * $this->getConsumption()) / $delta; + if ($consumption = $this->getConsumption()) { + return (3600 * 1000 * $consumption) / ($this->last[0] - $this->first[0]); + } + else { // prevents division by zero + return 0; + } } /** diff --git a/lib/Interpreter/SensorInterpreter.php b/lib/Interpreter/SensorInterpreter.php index 5dbee57..52c94c2 100644 --- a/lib/Interpreter/SensorInterpreter.php +++ b/lib/Interpreter/SensorInterpreter.php @@ -33,48 +33,83 @@ use Volkszaehler\Util; class SensorInterpreter extends Interpreter { - public function processData($callback) { - $data = parent::getData(); - - $values = array(); - foreach ($data as $reading) { - $values[] = $callback(array( - (float) $reading[0], - (float) $reading[1] / $reading[2], - (int) $reading[2] - )); - } - - return $values; + protected $consumption = NULL; // in Wms (Watt milliseconds) + protected $min = NULL; + protected $max = NULL; + protected $first = NULL; + protected $last = NULL; + + /** + * Calculates the consumption + * + * @return float total consumption in Wh + */ + public function getConsumption() { + return $this->consumption / 3600000; // convert to Wh } /** - * Fetch the smallest value from database - * @internal doesn't fits the SQL standard + * Get minimum + * * @return array (0 => timestamp, 1 => value) */ public function getMin() { - $min = $this->conn->fetchArray('SELECT timestamp, value FROM data WHERE channel_id = ?' . parent::buildDateTimeFilterSQL($this->from, $this->to) . ' ORDER BY value ASC LIMIT 1', array($this->channel->getId())); - return ($min) ? array_map('floatval', $min) : NULL; + return ($this->min) ? array_map('floatval', array_slice($this->min, 0 , 2)) : NULL; } /** - * Fetch the greatest value from the database - * @internal doesn't fits the SQL standard + * Get maximum + * * @return array (0 => timestamp, 1 => value) */ public function getMax() { - $max = $this->conn->fetchArray('SELECT timestamp, value FROM data WHERE channel_id = ?' . parent::buildDateTimeFilterSQL($this->from, $this->to) . ' ORDER BY value DESC LIMIT 1', array($this->channel->getId())); - return ($max) ? array_map('floatval', $max) : NULL; + return ($this->max) ? array_map('floatval', array_slice($this->max, 0 , 2)) : NULL; } /** - * Fetch the average value from the database - * @internal doesn't fits the SQL standard - * @return float + * Get Average + * + * @return float 3600: 3600 s/h; 1000: ms -> s */ public function getAverage() { - return (float) $this->conn->fetchColumn('SELECT AVG(value) FROM data WHERE channel_id = ?' . parent::buildDateTimeFilterSQL($this->from, $this->to), array($this->channel->getId()), 0); + if ($consumption = $this->getConsumption()) { + return (3600 * 1000 * $consumption) / ($this->last[0] - $this->first[0]); + } + else { // prevents division by zero + return 0; + } + } + + public function processData($callback) { + $data = parent::getData(); + $tuples = array(); + + $last = $data->rewind(); + $next = $data->next(); + + while ($data->valid()) { + $tuple = $callback(array( + (float) $next[0], + (float) $next[1] / $next[2], + (int) $next[2] + )); + + if (is_null($this->max) || $tuple[1] > $this->max[1]) { + $this->max = $tuple; + } + + if (is_null($this->min) || $tuple[1] < $this->min[1]) { + $this->min = $tuple; + } + + $this->consumption += $next[1] * ($next[0] - $last[0]); + + $tuples[] = $tuple; + $last = $next; + $next = $data->next(); + } + + return $tuples; } } diff --git a/lib/View/JSON.php b/lib/View/JSON.php index 590b2e2..a9bfd94 100644 --- a/lib/View/JSON.php +++ b/lib/View/JSON.php @@ -214,6 +214,7 @@ class JSON extends View { $min = $interpreter->getMin(); $max = $interpreter->getMax(); $average = $interpreter->getAverage(); + $consumption = $interpreter->getConsumption(); $from = $interpreter->getFrom(); $to = $interpreter->getTo(); @@ -229,8 +230,8 @@ class JSON extends View { $this->json['data']['max'] = $max; if (isset($average)) $this->json['data']['average'] = View::formatNumber($average); - if ($interpreter instanceof Interpreter\MeterInterpreter) - $this->json['data']['consumption'] = View::formatNumber($interpreter->getConsumption()); + if (isset($consumption)) + $this->json['data']['consumption'] = View::formatNumber($consumption); $this->json['data']['count'] = count($data); if (($interpreter->getTupleCount() > 0 || is_null($interpreter->getTupleCount())) && count($data) > 0) $this->json['data']['tuples'] = $data; diff --git a/lib/View/XML.php b/lib/View/XML.php index 3b60853..c7798c3 100644 --- a/lib/View/XML.php +++ b/lib/View/XML.php @@ -243,6 +243,7 @@ class XML extends View { $min = $interpreter->getMin(); $max = $interpreter->getMax(); $average = $interpreter->getAverage(); + $consumption = $interpreter->getConsumption(); $from = $interpreter->getFrom(); $to = $interpreter->getTo(); @@ -258,8 +259,8 @@ class XML extends View { $xmlData->appendChild($this->xmlDoc->createElement('max', $max)); if (isset($average)) $xmlData->appendChild($this->xmlDoc->createElement('average', View::formatNumber($average))); - if ($interpreter instanceof Interpreter\MeterInterpreter) - $xmlData->appendChild($this->xmlDoc->createElement('consumption', View::formatNumber($interpreter->getConsumption()))); + if (isset($consumption)) + $xmlData->appendChild($this->xmlDoc->createElement('consumption', View::formatNumber($consumption))); $xmlData->appendChild($this->xmlDoc->createElement('count', count($data))); if (($interpreter->getTupleCount() > 0 || is_null($interpreter->getTupleCount())) && count($data) > 0) $xmlData->appendChild($xmlTuples);