diff --git a/lib/Interpreter/Interpreter.php b/lib/Interpreter/Interpreter.php index 1b9bdd5..d53ac5b 100644 --- a/lib/Interpreter/Interpreter.php +++ b/lib/Interpreter/Interpreter.php @@ -159,11 +159,11 @@ abstract class Interpreter { $sql = ''; if (isset($from)) { - $sql .= ' AND timestamp >= ' . $from; + $sql .= ' AND timestamp >= ' . $from; } if (isset($to)) { - $sql .= ' AND timestamp <= ' . $to; + $sql .= ' AND timestamp <= ' . $to; } return $sql; diff --git a/lib/Interpreter/MeterInterpreter.php b/lib/Interpreter/MeterInterpreter.php index c8a5d10..f9b8913 100644 --- a/lib/Interpreter/MeterInterpreter.php +++ b/lib/Interpreter/MeterInterpreter.php @@ -38,12 +38,12 @@ class MeterInterpreter extends Interpreter { /** * Calculates the consumption for interval speciefied by $from and $to * - * @todo reimplement according to new env + * @todo improfve workaround */ public function getConsumption() { - $sql = 'SELECT COUNT(*) FROM `data` WHERE `channel_id` = ' . $this->channel->getId() . parent::buildDateTimeFilterSQL($this->from, $this->to); + $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 + return $this->conn->fetchColumn($sql, array($this->channel->getId()), 0) / $this->channel->getProperty('resolution'); // return KWh } /** @@ -92,13 +92,13 @@ class MeterInterpreter extends Interpreter { * @todo untested * @return array with timestamp, values, and pulse count */ - public function getValues($tuples = NULL, $groupBy = NULL) { + public function getValues($tuples, $groupBy, $callback) { $pulses = parent::getData($tuples, $groupBy); $values = array(); foreach ($pulses as $pulse) { if (isset($last)) { - $values[] = $this->raw2differential($last, $pulse); + $values[] = $callback($this->raw2differential($last, $pulse)); $last = $pulse; } else { diff --git a/lib/Interpreter/SensorInterpreter.php b/lib/Interpreter/SensorInterpreter.php index 00fb815..b6f5dfc 100644 --- a/lib/Interpreter/SensorInterpreter.php +++ b/lib/Interpreter/SensorInterpreter.php @@ -37,16 +37,16 @@ class SensorInterpreter extends Interpreter { * @todo untested * @param string|integer $groupBy */ - public function getValues($tuples = NULL, $groupBy = NULL) { + public function getValues($tuples, $groupBy, $callback) { $data = parent::getData($tuples, $groupBy); $values = array(); foreach ($data as $reading) { - $values[] = array( + $values[] = $callback(array( (float) $reading[0], (float) $reading[1] / $reading[2], (int) $reading[2] - ); + )); } return $values; @@ -80,14 +80,6 @@ class SensorInterpreter extends Interpreter { 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); } - - /** - * @todo possible and/or required? - * @return float - */ - public function getConsumption() { - - } } ?> diff --git a/lib/View/CSV.php b/lib/View/CSV.php index b08bcca..80ea0cc 100644 --- a/lib/View/CSV.php +++ b/lib/View/CSV.php @@ -35,8 +35,8 @@ use Volkszaehler\Interpreter; * @todo rework */ class CSV extends View { - protected $delimiter = ';'; - protected $enclosure = '"'; + const DELIMITER = ';'; + const ENCLOSURE = '"'; protected $csv = array(); @@ -115,14 +115,19 @@ class CSV extends View { * @param Interpreter\InterpreterInterface $interpreter */ protected function addData(Interpreter\Interpreter $interpreter) { - $tuples = $interpreter->getValues($this->request->getParameter('tuples'), $this->request->getParameter('group')); - //$this->response->setHeader('Content-Disposition', 'attachment; filename="' . strtolower($interpreter->getEntity()->getProperty('title')) . '.csv"'); // TODO add time? - - foreach ($tuples as $row) { - $array = array_map(array($this, 'escape'), $row); - echo implode($this->delimiter, $row) . PHP_EOL; - } + + $tuples = $interpreter->getValues( + $this->request->getParameter('tuples'), + $this->request->getParameter('group'), + function($tuple) { + echo implode(CSV::DELIMITER, array( + $tuple[0], + View::formatNumber($tuple[1]), + $tuple[2] + )) . PHP_EOL; + } + ); } /** @@ -138,7 +143,7 @@ class CSV extends View { */ protected function escape($value) { if (is_string($value)) { - return $this->enclosure . $value . $this->enclosure; + return self::ENCLOSURE . $value . self::ENCLOSURE; } elseif (is_numeric($value)) { return $value; diff --git a/lib/View/JSON.php b/lib/View/JSON.php index 5ccf14c..848f3c3 100644 --- a/lib/View/JSON.php +++ b/lib/View/JSON.php @@ -171,7 +171,7 @@ class JSON extends View { if (count($queries) > 0) { $jsonDebug['database'] = array( 'driver' => Util\Configuration::read('db.driver'), - 'queries' => $queries + 'queries' => array_values($queries) ); } @@ -208,19 +208,31 @@ class JSON extends View { /** * Add data to output queue * - * @param Interpreter\InterpreterInterface $interpreter + * @param $interpreter */ - protected function addData(Interpreter\Interpreter $interpreter) { + protected function addData($interpreter) { $this->json['data']['uuid'] = $interpreter->getEntity()->getUuid(); - $data = $interpreter->getValues($this->request->getParameter('tuples'), $this->request->getParameter('group')); + $data = $interpreter->getValues( + $this->request->getParameter('tuples'), + $this->request->getParameter('group'), + function($tuple) { + return array( + $tuple[0], + View::formatNumber($tuple[1]), + $tuple[2] + ); + } + ); $min = $interpreter->getMin(); $max = $interpreter->getMax(); $average = $interpreter->getAverage(); + $consumption = $interpreter->getConsumption(); - if (isset($min)) $this->json['data']['min'] = $min; - if (isset($max)) $this->json['data']['max'] = $max; - if (isset($average)) $this->json['data']['average'] = $average; + $this->json['data']['min'] = $min; + $this->json['data']['max'] = $max; + $this->json['data']['average'] = View::formatNumber($average); + $this->json['data']['consumption'] = View::formatNumber($consumption); if (count($data) > 0) $this->json['data']['tuples'] = $data; } diff --git a/lib/View/View.php b/lib/View/View.php index 5003a03..9bbb599 100644 --- a/lib/View/View.php +++ b/lib/View/View.php @@ -137,6 +137,16 @@ abstract class View { throw new Exception('Unknown caching mode: ' . $mode); } } + + /** + * Round decimal numbers to given precission + * + * @param $number float the number + * @return (float|string) the formatted number + */ + public static function formatNumber($number) { + return round($number, self::PRECISSION); + } public abstract function add($object); protected abstract function render(); diff --git a/lib/View/XML.php b/lib/View/XML.php index 1fb1520..70327b9 100644 --- a/lib/View/XML.php +++ b/lib/View/XML.php @@ -75,10 +75,10 @@ class XML extends View { $this->addEntity($data); } elseif ($data instanceof \Exception) { - //$this->addException($data); + $this->addException($data); } elseif ($data instanceof Util\Debug) { - //$this->addDebug($data); + $this->addDebug($data); } elseif (is_array($data)) { $this->xmlRoot->appendChild($this->convertArray($data)); @@ -163,11 +163,11 @@ class XML extends View { protected function addDebug(Util\Debug $debug) { $xmlDebug = $this->xmlDoc->createElement('debug'); $xmlDebug->appendChild($this->xmlDoc->createElement('time', $debug->getExecutionTime())); - $xmlDebug->appendChild($this->convertArray($debug->getMessages(), 'messages')); + $xmlDebug->appendChild($this->convertArray($debug->getMessages(), 'messages', 'message')); $xmlDatabase = $this->xmlDoc->createElement('database'); $xmlDatabase->setAttribute('driver', Util\Configuration::read('db.driver')); - $xmlDatabase->appendChild($this->convertArray($debug->getQueries(), 'queries')); + $xmlDatabase->appendChild($this->convertArray($debug->getQueries(), 'queries', 'query')); $xmlDebug->appendChild($xmlDatabase); $this->xmlRoot->appendChild($xmlDebug); @@ -198,28 +198,30 @@ class XML extends View { /** * Add data to output queue * - * @param Interpreter\InterpreterInterface $interpreter + * @param $interpreter */ - protected function addData(Interpreter\InterpreterInterface $interpreter) { - $data = $interpreter->getValues($this->request->getParameter('tuples'), $this->request->getParameter('group')); + protected function addData($interpreter) { + $xmlDoc = $this->xmlDoc; $xmlData = $this->xmlDoc->createElement('data'); $xmlTuples = $this->xmlDoc->createElement('tuples'); - foreach ($data as $tuple) { - $xmlTuple = $this->xmlDoc->createElement('tuple'); - $xmlTuple->setAttribute('timestamp', $tuple[0]); // hardcoded data fields for performance optimization - $xmlTuple->setAttribute('value', $tuple[1]); - $xmlTuple->setAttribute('count', $tuple[2]); - $xmlTuples->appendChild($xmlTuple); - } - + + $data = $interpreter->getValues( + $this->request->getParameter('tuples'), + $this->request->getParameter('group'), + function($tuple) use ($xmlDoc, $xmlTuples) { + $xmlTuple = $xmlDoc->createElement('tuple'); + $xmlTuple->setAttribute('timestamp', $tuple[0]); // hardcoded data fields for performance optimization + $xmlTuple->setAttribute('value', View::formatNumber($tuple[1])); + $xmlTuple->setAttribute('count', $tuple[2]); + $xmlTuples->appendChild($xmlTuple); + } + ); + $xmlData->appendChild($this->xmlDoc->createElement('uuid', $interpreter->getEntity()->getUuid())); - $xmlData->appendChild($this->xmlDoc->createElement('count', count($data))); - $xmlData->appendChild($this->xmlDoc->createElement('first', (isset($data[0][0])) ? $data[0][0] : NULL)); - $xmlData->appendChild($this->xmlDoc->createElement('last', (isset($data[count($data)-1][0])) ? $data[count($data)-1][0] : NULL)); $xmlData->appendChild($this->xmlDoc->createElement('min', $interpreter->getMin())); $xmlData->appendChild($this->xmlDoc->createElement('max', $interpreter->getMax())); - $xmlData->appendChild($this->xmlDoc->createElement('average', $interpreter->getAverage())); - $xmlData->appendChild($this->xmlDoc->createElement('last', $interpreter->getLast())); + $xmlData->appendChild($this->xmlDoc->createElement('average', self::formatNumber($interpreter->getAverage()))); + $xmlData->appendChild($this->xmlDoc->createElement('consumption', self::formatNumber($interpreter->getConsumption()))); $xmlData->appendChild($xmlTuples); $this->xmlRoot->appendChild($xmlData); @@ -231,28 +233,25 @@ class XML extends View { * @param array the input array * @return DOMElement */ - protected function convertArray(array $array, $identifier = 'array') { - $xmlArray = $this->xmlDoc->createElement($identifier); + protected function convertArray(array $array, $identifierPlural = 'array', $identifierSingular = 'entry') { + $xmlArray = $this->xmlDoc->createElement($identifierPlural); foreach ($array as $key => $value) { - // determine tagname if (is_numeric($key)) { - if (substr($identifier, -3) == 'ies') { - $key = substr($identifier, 0, -3) . 'y'; - } - elseif (substr($identifier, -1) == 's') { - $key = substr($identifier, 0, -1); - } - else { - $key = 'index' . $key; - } + $key = $identifierSingular; } if (is_array($value)) { $xmlArray->appendChild($this->convertArray($value, $key)); } - else { - $xmlArray->appendChild($this->xmlDoc->createElement($key, (is_scalar($value)) ? $value : 'object')); + elseif (is_numeric($value)) { + $xmlArray->appendChild($this->xmlDoc->createElement($key, self::formatNumber($value))); + } + elseif (is_scalar($value)) { + $xmlArray->appendChild($this->xmlDoc->createElement($key, $value)); + } + else { // TODO required? + $xmlArray->appendChild($this->xmlDoc->createElement($key, 'object')); } } diff --git a/misc/tools/doctrine.php b/misc/tools/doctrine.php index 4ef6716..bdc566f 100644 --- a/misc/tools/doctrine.php +++ b/misc/tools/doctrine.php @@ -26,8 +26,6 @@ use Volkszaehler\Util; -// TODO replace by state class -define('VZ_VERSION', 0.2); define('VZ_DIR', realpath(__DIR__ . '/../..')); // class autoloading