added universal format routine for all output modes
improved rendering performance of all output modes
This commit is contained in:
parent
4456c43263
commit
443081f9a0
8 changed files with 87 additions and 71 deletions
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
use Volkszaehler\Util;
|
||||
|
||||
// TODO replace by state class
|
||||
define('VZ_VERSION', 0.2);
|
||||
define('VZ_DIR', realpath(__DIR__ . '/../..'));
|
||||
|
||||
// class autoloading
|
||||
|
|
Loading…
Add table
Reference in a new issue