updated docs

This commit is contained in:
Steffen Vogel 2010-07-29 00:04:33 +02:00
parent f59aa6c0e4
commit 63ff53ec73
27 changed files with 233 additions and 88 deletions

View file

@ -1,6 +1,6 @@
<?php
/**
* backend bootstrapping entrypoint
* Backend bootstrapping entrypoint
*
* @author Steffen Vogel <info@steffenvogel.de>
* @copyright Copyright (c) 2010, The volkszaehler.org project

View file

@ -26,7 +26,7 @@ namespace Volkszaehler\Controller;
use \Volkszaehler\Model;
/**
* channel controller
* Channel controller
*
* @author Steffen Vogel <info@steffenvogel.de>
* @package default
@ -34,9 +34,10 @@ use \Volkszaehler\Model;
class ChannelController extends Controller {
/**
* get channels by filter
* Get channels by filter
*
* @todo authentification/indentification
* @todo implement filters
*/
public function get() {
$dql = 'SELECT c FROM Volkszaehler\Model\Channel c';
@ -62,7 +63,7 @@ class ChannelController extends Controller {
}
/**
* add channel
* Add channel
*
* @todo validate input and throw exceptions
*/
@ -82,7 +83,7 @@ class ChannelController extends Controller {
}
/**
* delete channel
* Delete channel by uuid
*
* @todo authentification/indentification
*/
@ -95,7 +96,7 @@ class ChannelController extends Controller {
}
/**
* edit channel properties
* Edit channel properties
*
* @todo authentification/indentification
* @todo to be implemented

View file

@ -24,7 +24,7 @@
namespace Volkszaehler\Controller;
/**
* controller superclass for all controllers
* Controller superclass for all controllers
*
* @author Steffen Vogel <info@steffenvogel.de>
* @package default
@ -34,7 +34,10 @@ abstract class Controller {
protected $em;
/**
* constructor
* Constructor
*
* @param View $view
* @param EntityManager $em
*/
public function __construct(\Volkszaehler\View\View $view, \Doctrine\ORM\EntityManager $em) {
$this->view = $view;
@ -42,7 +45,7 @@ abstract class Controller {
}
/**
* run controller actions
* Run controller actions
*
* @param string $action runs the action if class method is available
*/

View file

@ -24,11 +24,10 @@
namespace Volkszaehler\Controller;
use Volkszaehler\Model;
use Volkszaehler\Util;
/**
* data controller
* Data controller
*
* @author Steffen Vogel <info@steffenvogel.de>
* @todo call via redirect from Controller\Channel
@ -37,7 +36,7 @@ use Volkszaehler\Util;
class DataController extends Controller {
/**
* query for data
* Query for data by given channel or group
*
* @todo authentification/indentification
* @todo use uuids for groups or channels
@ -72,7 +71,7 @@ class DataController extends Controller {
}
/**
* log new readings
* Log new readings with logger interfaces
*
* @todo authentification/indentification
*/

View file

@ -24,7 +24,7 @@
namespace Volkszaehler\Controller;
/**
* group controller
* Group controller
*
* @author Steffen Vogel (info@steffenvogel.de)
* @package default
@ -34,7 +34,7 @@ use Volkszaehler\Model;
class GroupController extends Controller {
/**
* get groups by filter
* Get groups by filter
*
* @todo filter to root groups when using recursion
*/
@ -63,7 +63,9 @@ class GroupController extends Controller {
}
/**
* add new group as child of a parent group
* Add new group as child of a parent group
*
* @todo add parent validation to model?
*/
public function add() {
$ugid = $this->view->request->getParameter('ugid');

View file

@ -23,17 +23,25 @@
namespace Volkszaehler;
/**
* @author Steffen Vogel <info@steffenvogel.de>
*/
use Doctrine\DBAL;
/**
* @author Steffen Vogel <info@steffenvogel.de>
* @package default
*/
class DataAggregationIterator extends DataIterator {
protected $packageSize; // count of readings in tuple
protected $aggregatedSize; // total readings
protected $aggregatedKey = -1;
public function __construct(DBAL\Statement $stmt, $size, $tuples) {
/**
* Constructor
*
* @param \PDOStatement $stmt
* @param unknown_type $size
* @param unknown_type $tuples
*/
public function __construct(\PDOStatement $stmt, $size, $tuples) {
parent::__construct($stmt, $size);
if ($tuples < $this->size) { // return $tuples values
@ -47,7 +55,7 @@ class DataAggregationIterator extends DataIterator {
}
/**
* aggregate data
* Aggregate data
*/
public function next() {
$current = array (0, 0);
@ -71,14 +79,26 @@ class DataAggregationIterator extends DataIterator {
$this->current[2] = $this->packageSize;
}
/**
* @return array with data
*/
public function current() {
return $this->current;
}
/**
* @return integer the nth data row
*/
public function key() {
return $this->aggregatedKey;
}
/**
* Rewind the iterator
*
* Should only be called once
* PDOStatements doest support rewind()
*/
public function rewind() {
parent::rewind();
@ -90,7 +110,7 @@ class DataAggregationIterator extends DataIterator {
}
/**
* getter & setter
* Getter & setter
*/
public function getPackageSize() { return $this->packageSize; }
}

View file

@ -23,49 +23,75 @@
namespace Volkszaehler;
/**
* @author Steffen Vogel <info@steffenvogel.de>
*/
use Doctrine\DBAL;
/**
* @author Steffen Vogel <info@steffenvogel.de>
* @package default
*/
class DataIterator implements \Iterator, \Countable {
protected $current;
protected $key; // incrementing key
protected $pdoStmt; // PDOStatement
protected $stmt; // PDOStatement
protected $size; // total readings in PDOStatement
public function __construct(DBAL\Statement $stmt, $size) {
/**
* Constructor
*
* @param \PDOStatement $stmt
* @param unknown_type $size
*/
public function __construct(\PDOStatement $stmt, $size) {
$this->size = $size;
$this->pdoStmt = $stmt->getWrappedStatement();
$this->pdoStmt->setFetchMode(\PDO::FETCH_NUM);
$this->stmt = $stmt;
$this->stmt->setFetchMode(\PDO::FETCH_NUM);
}
/**
* @return array with data
*/
public function current() {
return $this->current;
}
/**
* Fetch next row from database
*/
public function next() {
$this->key++;
$this->current = $this->pdoStmt->fetch();
$this->current = $this->stmt->fetch();
}
/**
* @return integer the nth data row
*/
public function key() {
return $this->key;
}
/**
* @return boolean do we have another row in the resultset?
*/
public function valid() {
return (boolean) $this->current;
}
/**
* NoRewindIterator
* Rewind the iterator
*
* Should only be called once
* PDOStatements doest support rewind()
*/
public function rewind() {
$this->key = 0;
$this->current = $this->pdoStmt->fetch();
$this->current = $this->stmt->fetch();
}
/**
* @return integer
*/
public function count() { return $this->size; }
}

View file

@ -29,16 +29,16 @@ use Volkszaehler\Controller;
use Volkszaehler\Util;
/**
* backend dispatcher
* Backend dispatcher
*
* this class acts as a frontcontroller to route incomming requests
* This class acts as a frontcontroller to route incomming requests
*
* @package default
* @author Steffen Vogel <info@steffenvogel.de>
*/
class Dispatcher {
/**
* @var \Doctrine\ORM\EntityManager Doctrine Model
* @var \Doctrine\ORM\EntityManager Doctrine EntityManager
*/
protected $em;
@ -68,18 +68,24 @@ class Dispatcher {
);
/**
* constructor
* Constructor
*/
public function __construct() {
// create HTTP request & response (needed to initialize view & controller)
$request = new HTTP\Request();
$response = new HTTP\Response();
if (!($format = $request->getParameter('format'))) {
if ($format = $request->getParameter('format')) {
$format = strtolower($format);
}
else {
$format = 'json'; // default view
}
if (!($controller = $request->getParameter('controller'))) {
if ($controller = $request->getParameter('controller')) {
$controller = strtolower($controller);
}
else {
throw new \Exception('no controller specified');
}
@ -124,7 +130,7 @@ class Dispatcher {
}
// initialize controller
$controllerClassName = 'Volkszaehler\Controller\\' . ucfirst($request->getParameter('controller')) . 'Controller';
$controllerClassName = 'Volkszaehler\Controller\\' . ucfirst($controller) . 'Controller';
if (!(Util\ClassLoader::classExists($controllerClassName)) || !is_subclass_of($controllerClassName, '\Volkszaehler\Controller\Controller')) {
throw new \Exception('\'' . $controllerClassName . '\' is not a valid controller');
}
@ -132,7 +138,7 @@ class Dispatcher {
}
/**
* execute application
* Execute application
*/
public function run() {
if ($this->view->request->getParameter('action')) {
@ -155,7 +161,7 @@ class Dispatcher {
}
/**
* factory for doctrines entitymanager
* Factory for doctrines entitymanager
*
* @todo create extra singleton class?
*/

View file

@ -26,9 +26,27 @@ namespace Volkszaehler\Interpreter;
use Doctrine\ORM;
use Volkszaehler\Model;
/**
* Group interpreter
*
* The GroupInterpreter is used to aggregate multiple channels with the same
* indicator
*
* @author Steffen Vogel <info@steffenvogel.de>
* @package default
*
*/
class GroupInterpreter {
protected $channelInterpreter;
/**
* Constructor
*
* @param Model\Group $group should only contain channels with the same indicator
* @param ORM\EntityManager $em
* @param integer $from timestamp in ms since 1970
* @param integer $to timestamp in ms since 1970
*/
public function __construct(Model\Group $group, ORM\EntityManager $em, $from, $to) {
foreach ($group->getChannels() as $channel) {
if (isset($indicator) && $indicator != $channel->getIndicator) {
@ -43,15 +61,20 @@ class GroupInterpreter {
}
/**
* Just a passthrough to the channel interpreters
*
* @param string|integer $groupBy
* @todo to be implemented
* @return array of values
*/
public function getValues($groupBy = NULL) {
}
/**
* Just a passthrough to the channel interpreters
*
* @return array with the smallest value
*/
public function getMin() {
$min = current($this->channelInterpreter)->getMax();
@ -65,7 +88,9 @@ class GroupInterpreter {
}
/**
* Just a passthrough to the channel interpreters
*
* @return array with the biggest value
*/
public function getMax() {
$max = current($this->channelInterpreter)->getMax();
@ -79,7 +104,9 @@ class GroupInterpreter {
}
/**
* Just a passthrough to the channel interpreters
*
* @return float average value
*/
public function getAverage() {
$sum = 0;

View file

@ -42,7 +42,7 @@ interface InterpreterInterface {
}
/**
* interpreter superclass for all interpreters
* Interpreter superclass for all interpreters
*
* @author Steffen Vogel <info@steffenvogel.de>
* @package default
@ -56,9 +56,12 @@ abstract class Interpreter implements InterpreterInterface {
protected $to;
/**
* Constructor
*
* @param $channel
* @param $em
* @param Channel $channel
* @param EntityManager $em
* @param integer $from timestamp in ms since 1970
* @param integer $to timestamp in ms since 1970
*/
public function __construct(\Volkszaehler\Model\Channel $channel, \Doctrine\ORM\EntityManager $em, $from = NULL, $to = NULL) {
$this->channel = $channel;
@ -69,11 +72,10 @@ abstract class Interpreter implements InterpreterInterface {
}
/**
* Get raw data
*
* @param integer $from timestamp in ms since 1970
* @param integer $to timestamp in ms since 1970
* @param mixed $groupBy
* @todo split in two functions
* @param string|integer $groupBy
* @return Volkszaehler\DataIterator
*/
protected function getData($groupBy = NULL) {
// get dbal connection from EntityManager
@ -98,8 +100,7 @@ abstract class Interpreter implements InterpreterInterface {
$rowCount = $conn->fetchColumn($sqlRowCount, $params, 0);
$stmt = $conn->prepare('SELECT ' . $sqlFields . $sqlFrom . $sqlWhere . $sqlGroupBy . $sqlOrderBy);
$stmt->execute($params);
$stmt = $conn->executeQuery('SELECT ' . $sqlFields . $sqlFrom . $sqlWhere . $sqlGroupBy . $sqlOrderBy, $params);
if ($sqlGroupBy || is_null($groupBy)) { // aggregation by sql or skip it
return new Volkszaehler\DataIterator($stmt, $rowCount);
@ -114,10 +115,10 @@ abstract class Interpreter implements InterpreterInterface {
}
/**
* builds sql query part for grouping data by date functions
* Builds sql query part for grouping data by date functions
*
* @param string $groupBy
* @return string $sql the sql part
* @return string the sql part
* @todo make compatible with: MSSql (Transact-SQL), Sybase, Firebird/Interbase, IBM, Informix, MySQL, Oracle, DB2, PostgreSQL, SQLite
*/
protected static function buildGroupBySQL($groupBy) {
@ -157,6 +158,13 @@ abstract class Interpreter implements InterpreterInterface {
}
}
/**
* Build sql query part to filter specified time interval
*
* @param integer $from timestamp in ms since 1970
* @param integer $to timestamp in ms since 1970
* @return string the sql part
*/
protected static function buildTimeFilterSQL($from = NULL, $to = NULL) {
$sql = '';

View file

@ -24,7 +24,7 @@
namespace Volkszaehler\Interpreter;
/**
* meter interpreter
* Meter interpreter
*
* @package default
* @author Steffen Vogel (info@steffenvogel.de)
@ -35,7 +35,7 @@ use Volkszaehler;
class MeterInterpreter extends Interpreter {
/**
* calculates the consumption for interval speciefied by $from and $to
* Calculates the consumption for interval speciefied by $from and $to
*
* @todo untested
*/
@ -68,7 +68,7 @@ class MeterInterpreter extends Interpreter {
}
/**
* @return Ambigous <mixed, unknown>
* @return array
*/
public function getMax() {
$data = $this->getData();
@ -84,20 +84,21 @@ class MeterInterpreter extends Interpreter {
/**
* @todo calculate timeinterval if no params were given
* @return float
*/
public function getAverage() {
return $this->getConsumption() / ($this->to - $this->from) / 1000; // return W
}
/**
* just a passthrough of raw data
* Just a passthrough of raw data
*/
public function getPulses($groupBy = NULL) {
return parent::getData($groupBy);
}
/**
* raw pulses to power conversion
* Raw pulses to power conversion
*
* @todo untested
* @return array with timestamp and values in [W]
@ -114,8 +115,8 @@ class MeterInterpreter extends Interpreter {
$values[] = array(
(int) ($pulse[0] - $delta / 2), // timestamp
round($pulse[1] * (3600000 / (($this->channel->getResolution() / 1000) * $delta)), 5), // value
$pulse[2]
$pulse[1] * (3600000 / (($this->channel->getResolution() / 1000) * $delta)), // value
(isset($pulse[2])) ? $pulse[2] : 1
);
}
else {

View file

@ -24,7 +24,7 @@
namespace Volkszaehler\Interpreter;
/**
* sensor interpreter
* Sensor interpreter
*
* @package default
* @author Steffen Vogel <info@steffenvogel.de>
@ -33,6 +33,7 @@ class SensorInterpreter extends Interpreter {
/**
* @todo untested
* @param string|integer $groupBy
*/
public function getValues($groupBy = NULL) {
$data = parent::getData($groupBy);
@ -52,6 +53,7 @@ class SensorInterpreter extends Interpreter {
/**
* @todo adapt to doctrine orm
* @todo untested
* @return array
*/
public function getMin() {
return $this->dbh->query('SELECT value, timestamp FROM data WHERE channel_id = ' . (int) $this->id . self::buildFilterTime($this->from, $this->to) . ' ORDER BY value ASC', 1)->current();
@ -60,6 +62,7 @@ class SensorInterpreter extends Interpreter {
/**
* @todo adapt to doctrine orm
* @todo untested
* @return array
*/
public function getMax() {
return $this->dbh->query('SELECT value, timestamp FROM data WHERE channel_id = ' . (int) $this->id . self::buildFilterTime($this->from, $this->to) . ' ORDER BY value DESC', 1)->current();
@ -68,6 +71,7 @@ class SensorInterpreter extends Interpreter {
/**
* @todo adapt to doctrine orm
* @todo untested
* @return float
*/
public function getAverage() {
return $this->dbh->query('SELECT AVG(value) AS value FROM data WHERE channel_id = ' . (int) $this->id . self::buildFilterTime($this->from, $this->to))->current();
@ -75,6 +79,7 @@ class SensorInterpreter extends Interpreter {
/**
* @todo to be implemented
* @return float
*/
public function getConsumption() {

View file

@ -24,7 +24,7 @@
namespace Volkszaehler\Logger;
/**
* logger for the Flukso.net API
* Logger for the Flukso.net API
*
* @package default
* @link http://www.flukso.net

View file

@ -28,7 +28,7 @@ use Doctrine\ORM;
use Volkszaehler\Model;
/**
* interface for parsing diffrent logging APIs (google, flukso etc..)
* Interface for parsing diffrent logging APIs (google, flukso etc..)
*
* @author Steffen Vogel <info@steffenvogel.de>
* @package default
@ -45,15 +45,29 @@ interface LoggerInterface {
public function getVersion();
}
/**
*
* @author Steffen Vogel <info@steffenvogel.de>
*
*/
abstract class Logger implements LoggerInterface {
protected $request;
protected $em;
/**
* Constructor
*
* @param HTTP\Request $request
* @param ORM\EntityManager $em
*/
public function __construct(HTTP\Request $request, ORM\EntityManager $em) {
$this->request = $request;
$this->em = $em;
}
/**
*
*/
public function log() {
$data = $this->getData();

View file

@ -27,7 +27,7 @@ use Volkszaehler\Model;
use Doctrine\ORM;
/**
* logger for the the original volkszaehler.org prototype based on ethersex's watchasync
* Logger for the the original volkszaehler.org prototype based on ethersex's watchasync
*
* @package default
* @link http://github.com/ethersex/ethersex/blob/master/services/watchasync
@ -67,7 +67,7 @@ class PrototypeLogger extends Logger {
}
/*
* just some documentation
* Just some documentation
*
* /httplog/httplog.php?port=<port>&uuid=<uuid>&time=<unixtimestamp>
*

View file

@ -50,6 +50,9 @@ class VzLogger extends Logger {
$data = new Model\Data($channel, $value, $ts);
}
/**
* @return string the version
*/
public function getVersion() {
return $this->request->getParameter('version');
}

View file

@ -86,7 +86,7 @@ class Channel extends Entity {
}
/**
* add a new data to the database
* Add a new data to the database
* @todo move to Logger\Logger?
*/
public function addData(\Volkszaehler\Model\Data $data) {
@ -94,13 +94,29 @@ class Channel extends Entity {
}
/**
* obtain channels data interpreter to calculate statistical information
* Obtain channel interpreter to obtain data and statistical information for a given time interval
*
* @param Doctrine\ORM\EntityManager $em
* @param integer $from timestamp in ms since 1970
* @param integer $to timestamp in ms since 1970
* @return Interpreter
*/
public function getInterpreter(\Doctrine\ORM\EntityManager $em, $from, $to) {
$interpreterClassName = 'Volkszaehler\Interpreter\\' . ucfirst($this->getType()) . 'Interpreter';
return new $interpreterClassName($this, $em, $from, $to);
}
/**
* Validate
*
* @PrePersist @PreUpdate
*/
protected function validate() {
if ($this->getResolution() <= 0 && $this->getType() == 'meter') {
throw new Exception('resolution has to be a positive integer');
}
}
/**
* getter & setter
*/

View file

@ -26,7 +26,7 @@ namespace Volkszaehler\Model;
use Volkszaehler\Util;
/**
* entity superclass for all models with database persistance
* Entity superclass for all models with database persistance
*
* @author Steffen Vogel <info@steffenvogel.de>
* @package default
@ -49,7 +49,7 @@ abstract class Entity {
}
/**
* getter & setter
* Getter & setter
*/
public function getId() { return $this->id; } // read only
public function getUuid() { return $this->uuid; } // read only

View file

@ -24,11 +24,8 @@
namespace Volkszaehler\Model;
use Volkszaehler\Interpreter;
use Doctrine\ORM;
use Doctrine\Common\Collections;
use Doctrine\Common\Collections\ArrayCollection;
/**

View file

@ -25,9 +25,9 @@
namespace Volkszaehler\Util;
/**
* class loader for volkszaehler and vendor libraries
* Classloader for volkszaehler and vendor libraries
*
* namespace is mapped to the filesystem structure
* Namespace is mapped to the filesystem structure
*
* @package util
* @author Roman Borschel <roman@code-factory.org>

View file

@ -24,7 +24,7 @@
namespace Volkszaehler\Util;
/**
* static configuration class for loading and storing the configuration to the disk
* Static configuration class for loading and storing the configuration to the disk
*
* @package util
* @author Steffen Vogel <info@steffenvogel.de>

View file

@ -26,7 +26,7 @@ namespace Volkszaehler\Util;
use Doctrine\DBAL\Logging;
/**
* static debugging class
* Static debugging class
*
* @package util
* @author Steffen Vogel <info@steffenvogel.de>

View file

@ -30,12 +30,12 @@ use Volkszaehler\Model;
/**
* JSON view
*
* also used for data
*
* @package default
* @author Steffen Vogel <info@steffenvogel.de>
*/
class JSON extends View {
const PRECISSION = 5;
protected $json = array();
protected $padding = FALSE;
@ -63,18 +63,21 @@ class JSON extends View {
$jsonChannel['unit'] = $channel->getUnit();
$jsonChannel['name'] = $channel->getName();
$jsonChannel['description'] = $channel->getDescription();
$jsonChannel['resolution'] = (int) $channel->getResolution();
$jsonChannel['cost'] = (float) $channel->getCost();
if ($channel->getType() == 'meter') {
$jsonChannel['resolution'] = (int) $channel->getResolution();
$jsonChannel['cost'] = (float) $channel->getCost();
}
if (isset($data)) {
$jsonChannel['data'] = $data;
$jsonChannel['data'] = self::convertData($data);
}
$this->json['channels'][] = $jsonChannel;
}
public function addGroup(Model\Group $group, $recursive = FALSE) {
$this->json['groups'][] = $this->toJson($group, $recursive);
$this->json['groups'][] = self::convertJson($group, $recursive);
}
public function addDebug(Util\Debug $debug) {
@ -99,7 +102,7 @@ class JSON extends View {
);
}
protected function toJson(Model\Group $group, $recursive = FALSE) {
protected static function convertGroup(Model\Group $group, $recursive = FALSE) {
$jsonGroup = array();
$jsonGroup['uuid'] = (string) $group->getUuid();
@ -122,6 +125,20 @@ class JSON extends View {
return $jsonGroup;
}
protected static function convertData($data) {
$jsonData = array();
foreach ($data as $reading) {
$jsonData[] = array(
(int) $reading[0],
(float) round($reading[1], JSON::PRECISSION),
(int) $reading[2]
);
}
return $jsonData;
}
public function renderResponse() {
$json = json_encode($this->json);

View file

@ -31,9 +31,9 @@ require_once \Volkszaehler\BACKEND_DIR . '/lib/vendor/JpGraph/jpgraph_scatter.ph
require_once \Volkszaehler\BACKEND_DIR . '/lib/vendor/JpGraph/jpgraph_date.php';
/**
* plotting and graphing of data on the server side
* Plotting and graphing of data on the server side
*
* this view uses the JpGraph PHP5 plotting library
* This view uses the JpGraph PHP5 plotting library
*
* @package default
* @author Steffen Vogel <info@steffenvogel.de>

View file

@ -28,7 +28,7 @@ use Volkszaehler\Util;
use Volkszaehler\Model;
/**
* Plain Text view
* Plain text view
*
* @author Steffen Vogel <info@steffenvogel.de>
* @package default

View file

@ -40,7 +40,7 @@ interface ViewInterface {
}
/**
* superclass for all view classes
* Superclass for all view classes
*
* @package default
* @author Steffen Vogel <info@steffenvogel.de>

View file

@ -1,8 +1,8 @@
<?php
/**
* configuration template
* Configuration template
*
* you should use this file to obtain your custom configuration
* You should use this file to obtain your custom configuration
* new parameters should be documented
*
* @copyright Copyright (c) 2010, The volkszaehler.org project