From e14321af8bb2911edd2d0168e10a7247947b9034 Mon Sep 17 00:00:00 2001 From: dorian Date: Mon, 15 Jul 2019 20:29:19 +0200 Subject: [PATCH] restructured api internally --- README.md | 6 +- api/blueweather.php | 268 +++++++++++++++++++++++++++++++++++++++++ api/example.config.php | 19 +++ api/json.php | 140 +-------------------- 4 files changed, 296 insertions(+), 137 deletions(-) create mode 100644 api/blueweather.php create mode 100644 api/example.config.php diff --git a/README.md b/README.md index 962fa3d..c322a0e 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,15 @@ A (hopefully soon) fully featured selft-hosted web interface and server-backend # State of development - interface and backend planned +- readonly dashboard is working # API docs ## get locations triggered by setting no GET parameter at all ### Parameters - +no parameters + ### Tags - id - locationname @@ -59,3 +61,5 @@ triggered by setting GET parameter 'locId' to a vaild location id - range (actual range of present measvalues) - from - to + + diff --git a/api/blueweather.php b/api/blueweather.php new file mode 100644 index 0000000..66a49d4 --- /dev/null +++ b/api/blueweather.php @@ -0,0 +1,268 @@ + + * @license GPLV3 gpl.com + * @link itsblue.de + */ + +class BlueWeather +{ + private $_config; + private $_con; + + /** + * Constructor + * + * @param mixed $_config config array containing some stuff + * + * @return void + */ + public function __construct($_config) + { + $this->_config = $_config; + $this->_con = mysqli_connect( + $_config['dbhost'], + $_config['dbuser'], + $_config['dbpassword'], + $_config['dbname'] + ); + + if (!$this->_con) { + echo "Error connecting to database: " . mysqli_connect_error(); + http_response_code(500); + die(); + } + + } + + + /** + * Function to login users + * + * @param string $username username + * @param string $password passowrd + * + * @return string '' or session token + */ + public function loginUser($username, $password) + { + $sql = "SELECT * FROM `users` + WHERE`username`=\"".$this->_con->real_escape_string($username)."\""; + $result = $this->_con->query($sql); + + // only one row will be returned + $data = $result->fetch_assoc(); + + if (!password_verify($password, $data['password'])) { + return ""; + } + + //generate random token + $length = 10; + $str = ""; + $characters = array_merge(range('A', 'Z'), range('a', 'z'), range('0', '9')); + $max = count($characters) - 1; + for ($i = 0; $i < $length; $i++) { + $rand = mt_rand(0, $max); + $str .= $characters[$rand]; + } + $token_hash = password_hash($str, PASSWORD_DEFAULT); + + $sql = 'INSERT INTO `sessions` (userId, session) + VALUES ("'. $data['id'] .'", "'. $token_hash .'")'; + + if (!$this->_con->query($sql)) { + return ""; + } + + return $token_hash; + } + + // -------------------- + // - getter functions - + // -------------------- + + /** + * Function to get all locations from the database + * + * @return mixed (array with all locations) + */ + public function getAllLocations() + { + // get all locations + $sql = "SELECT * FROM `locations`"; + $result = $this->_con->query($sql); + + //loop through the returned data + while ($row = $result->fetch_assoc()) { + $locations[] = $row; + } + + return $locations; + } + + /** + * Function to get the data of a specific location + * + * @param int $locId id of the location to return data of + * @param mixed $range contains 'from' and 'to' as unix timestamps + * @param int $maxVals maximum measvals to be transmitted; if more are + * present in the timespan, the avarage will be calculated + * + * @return mixed object with all information about the location (see docs) + */ + function getLocationData($locId, $range, $maxVals) + { + $sql = "SELECT * FROM `locations` + WHERE`id`=$locId"; + $result = $this->_con->query($sql); + + // only one row will be returned + $data = $result->fetch_assoc(); + + if (!isset($range['from']) || $range['from'] === "") { + $range['from'] = time() - 24 * 60 * 60; + } + + if (!isset($range['to']) || $range['to'] === "") { + $range['to'] = time(); + } + + // get all measvalues of given location + $sql = "SELECT M.measvalue,M.sensorid,M.timestamp FROM measvalues M + JOIN sensors S ON M.sensorid = S.id + JOIN locations L ON S.locationid=L.id + WHERE L.id=$locId AND M.timestamp > " . $range['from'] . + "AND M.timestamp < " . $range['to'] . " + ORDER BY timestamp ASC"; + + $result = $this->_con->query($sql); + + while ($row = $result->fetch_assoc()) { + $measvalues[] = $row; + } + + // get all sensors of given location + $sql = "SELECT * FROM `sensors` + WHERE `locationid` = $locId"; + + $result = $this->_con->query($sql); + + //loop through the returned data + while ($row = $result->fetch_assoc()) { + unset($row['locationid']); // remove locId as it is redundant + $sensors[] = $row; + } + + // get all value types + $sql = "SELECT * FROM `valuetypes`"; + + $result = $this->_con->query($sql); + + //loop through the returned data + while ($row = $result->fetch_assoc()) { + foreach ($sensors as $sensor) { + if ($sensor['valuetypeid'] == $row['id']) { + $valuetypes[] = $row; + break; + } + } + } + + if (isset($maxVals) && $maxVals > 0 && count($measvalues) > $maxVals) { + // build the new measvalues array with respect to maxVals for each sensor + + $finalMeasvals = array(); + + foreach ($sensors as $sensor) { + + // get all measvalues of the current sensor + $rawMeasvalsOfThisSensor = array(); + $finalMeasvalsOfThisSensor = array(); + + foreach ($measvalues as $measvalue) { + if ($measvalue["sensorid"] === $sensor["id"]) { + array_push($rawMeasvalsOfThisSensor, $measvalue); + } + } + + // always sum up the same amount of values to get a new array + // which doesn't have more than $maxVals values + $countOfValuesForAvarage = intval( + round(count($rawMeasvalsOfThisSensor) / $maxVals, 0) + ); + + $takenValuesForNextSum = 0; + $tmpMeasvalueSum = 0; + $tmpTimestampSum = 0; + + for ($i = 0; $i < count($rawMeasvalsOfThisSensor); $i++) { + // loop through all measvals of the sensor + $measvalue = $rawMeasvalsOfThisSensor[$i]; + + if ($measvalue["sensorid"] === $sensor["id"]) { + $tmpMeasvalueSum += $measvalue["measvalue"]; + $tmpTimestampSum += $measvalue["timestamp"]; + $takenValuesForNextSum += 1; + } + if ($takenValuesForNextSum === $countOfValuesForAvarage || $i === count($rawMeasvalsOfThisSensor) - 1) { + array_push( + $finalMeasvalsOfThisSensor, + array( + "measvalue" => round( + $tmpMeasvalueSum / $takenValuesForNextSum, 2 + ), + "timestamp" => round( + $tmpTimestampSum / $takenValuesForNextSum, 0 + ), + "sensorid" => $sensor["id"] + ) + ); + + $takenValuesForNextSum = 0; + $tmpMeasvalueSum = 0; + $tmpTimestampSum = 0; + } + } + + // insert the new vals of this sensor into the global new vals + $finalMeasvals = array_merge( + $finalMeasvals, $finalMeasvalsOfThisSensor + ); + } + + $measvalues = $finalMeasvals; + } + + // find actual range + $min = null; + $max = null; + + foreach ($measvalues as $value) { + if ($value['timestamp'] < $min || !isset($min)) { + $min = $value['timestamp']; + } else if ($value['timestamp'] > $max || !isset($max)) { + $max = $value['timestamp']; + } + } + + // add sensors and value types to data object + $data['measvalues'] = $measvalues; + $data['sensors'] = $sensors; + $data['valuetypes'] = $valuetypes; + $data['range'] = array('from' => $min, 'to' => $max); + + return $data; + } + + +} + +?> \ No newline at end of file diff --git a/api/example.config.php b/api/example.config.php new file mode 100644 index 0000000..f4854d4 --- /dev/null +++ b/api/example.config.php @@ -0,0 +1,19 @@ + + * @license GPLV3 gpl.com + * @link itsblue.de + */ + +$config['dbhost'] = ''; +$config['dbname'] = ''; +$config['dbuser'] = ''; +$config['dbpassword'] = ''; + +?> diff --git a/api/json.php b/api/json.php index 847c1db..45ab14b 100644 --- a/api/json.php +++ b/api/json.php @@ -17,19 +17,12 @@ */ require_once './config.php'; - - +require_once './blueweather.php'; header('Content-Type: application/json'); header('Access-Control-Allow-Origin: *'); -$con = mysqli_connect($config['dbhost'], $config['dbuser'], $config['dbpassword'], $config['dbname']); -if (!$con) { - echo "

Fatal internal Error! :-/

"; - echo "Error connecting to database: " . mysqli_connect_error(); - http_response_code(500); - exit(); -} +$blueweather = new BlueWeather($config); if (isset($_GET['locId'])) { // get data of given location @@ -38,134 +31,9 @@ if (isset($_GET['locId'])) { $range['to'] = $con->real_escape_string($_GET['range']['to']); $maxVals = $con->real_escape_string($_GET['maxVals']); - $sql = "SELECT * FROM `locations` - WHERE`id`=$locId"; - $result = $con->query($sql); - - // only one row will be returned - $data = $result->fetch_assoc(); - - if (!isset($range['from']) || $range['from'] === "") { - $range['from'] = time() - 24 * 60 * 60; - } - - if (!isset($range['to']) || $range['to'] === "") { - $range['to'] = time(); - } - - // get all measvalues of given location - $sql = "SELECT M.measvalue,M.sensorid,M.timestamp FROM measvalues M - JOIN sensors S ON M.sensorid = S.id - JOIN locations L ON S.locationid=L.id - WHERE L.id=$locId AND M.timestamp > " . $range['from'] . " AND M.timestamp < " . $range['to'] . " - ORDER BY timestamp ASC"; - - $result = $con->query($sql); - - while ($row = $result->fetch_assoc()) { - $measvalues[] = $row; - } - - // get all sensors of given location - $sql = "SELECT * FROM `sensors` - WHERE `locationid` = $locId"; - - $result = $con->query($sql); - - //loop through the returned data - while ($row = $result->fetch_assoc()) { - unset($row['locationid']); // remove locId as it is redundant - $sensors[] = $row; - } - - // get all value types - $sql = "SELECT * FROM `valuetypes`"; - - $result = $con->query($sql); - - //loop through the returned data - while ($row = $result->fetch_assoc()) { - foreach ($sensors as $sensor) { - if ($sensor['valuetypeid'] == $row['id']) { - $valuetypes[] = $row; - break; - } - } - } - - if (isset($maxVals) && $maxVals > 0 && count($measvalues) > $maxVals) { - // build the new measvalues array with respect to maxVals for each sensor - - $finalMeasvals = array(); - - foreach ($sensors as $sensor) { - - - $rawMeasvalsOfThisSensor = array(); - $finalMeasvalsOfThisSensor = array(); - - foreach ($measvalues as $measvalue) { - if ($measvalue["sensorid"] === $sensor["id"]) { - array_push($rawMeasvalsOfThisSensor, $measvalue); - } - } - - $countOfValuesForAvarage = intval(round(count($rawMeasvalsOfThisSensor) / $maxVals, 0)); - - $takenValuesForNextSum = 0; - $tmpMeasvalueSum = 0; - $tmpTimestampSum = 0; - - for ($i = 0; $i < count($rawMeasvalsOfThisSensor); $i++) { - $measvalue = $rawMeasvalsOfThisSensor[$i]; - if ($measvalue["sensorid"] === $sensor["id"]) { - $tmpMeasvalueSum += $measvalue["measvalue"]; - $tmpTimestampSum += $measvalue["timestamp"]; - $takenValuesForNextSum += 1; - } - if ($takenValuesForNextSum === $countOfValuesForAvarage || $i === count($rawMeasvalsOfThisSensor) - 1) { - array_push($finalMeasvalsOfThisSensor, array("measvalue" => round($tmpMeasvalueSum / $takenValuesForNextSum, 2), "timestamp" => round($tmpTimestampSum / $takenValuesForNextSum, 0), "sensorid" => $sensor["id"])); - - $takenValuesForNextSum = 0; - $tmpMeasvalueSum = 0; - $tmpTimestampSum = 0; - } - } - - - //print_r($finalMeasvalsOfThisSensor); - - $finalMeasvals = array_merge($finalMeasvals, $finalMeasvalsOfThisSensor); - } - - $measvalues = $finalMeasvals; - } - - // find actual range - $min; - $max; - foreach ($measvalues as $value) { - if ($value['timestamp'] < $min || !isset($min)) { - $min = $value['timestamp']; - } else if ($value['timestamp'] > $max || !isset($max)) { - $max = $value['timestamp']; - } - } - - // add sensors and value types to data object - $data['measvalues'] = $measvalues; - $data['sensors'] = $sensors; - $data['valuetypes'] = $valuetypes; - $data['range'] = array('from' => $min, 'to' => $max); + $data = getLocationData($locId, $range, $maxVals); } else { - // get all locations - $sql = "SELECT * FROM `locations`"; - $result = $con->query($sql); - - //loop through the returned data - while ($row = $result->fetch_assoc()) { - $data[] = $row; - } + $data = $blueweather->getAllLocations(); } http_response_code(200);