[server] Add list-devices API action

This commit is contained in:
Starbeamrainbowlabs 2019-01-17 15:39:50 +00:00
parent d9420b82c4
commit f0781948f3
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
5 changed files with 105 additions and 4 deletions

View file

@ -4,11 +4,13 @@
This project contains the web interface for the ConnectedHumber air Quality Monitoring system. It is composed of 2 parts: This project contains the web interface for the ConnectedHumber air Quality Monitoring system. It is composed of 2 parts:
- A PHP-based JSON API server (entry point: api.php) - A PHP-based JSON API server (entry point: api.php) that's backed by a MariaDB server
- A Javascript client application that runs in the browser - A Javascript client application that runs in the browser
The client-side browser application is powered by [Leaflet](https://leafletjs.com/). The client-side browser application is powered by [Leaflet](https://leafletjs.com/).
Note that this project is _not_ responsible for entering data into the database. This project's purpose is simply to display the data.
## System Requirements ## System Requirements
In order to run this program, you'll need the following: In order to run this program, you'll need the following:
@ -17,6 +19,7 @@ In order to run this program, you'll need the following:
- [composer](https://getcomposer.org/) - For the server-side packages - [composer](https://getcomposer.org/) - For the server-side packages
- [Node.JS](https://nodejs.org/) - [Node.JS](https://nodejs.org/)
- [npm](https://npmjs.org/) - comes with Node.JS - used for building the client-side code - [npm](https://npmjs.org/) - comes with Node.JS - used for building the client-side code
- A [MariaDB](https://mariadb.com/) server with a database already setup with the schema data in it. Please get in contact with [ConnectedHumber](https://connectedhumber.org/) for information about the database schema and structure.
## Getting Started ## Getting Started
The client-side code requires building. Currently, no pre-built versions are available (though these can be provided upon request), so this must be done from source. A build script is available, however, which automates the process - as explained below. The client-side code requires building. Currently, no pre-built versions are available (though these can be provided upon request), so this must be done from source. A build script is available, however, which automates the process - as explained below.
@ -61,12 +64,15 @@ https://example.com/path/to/api.php?action=fetch-data&datetime=2019-01-03%2007:5
### list-devices ### list-devices
> Fetches a list of devices currently in the system. > Fetches a list of devices currently in the system.
_No additional parameters are supported by this action._ Parameter | Type | Meaning
--------------------|-----------|---------------------
`only_with_location`| bool | Optional. If present only devices with a defined location will be returned. Useful for getting a list of devices to place on a map.
Examples: Examples:
``` ```
https://example.com/path/to/api.php?action=list-devices https://example.com/path/to/api.php?action=list-devices
https://example.com/path/to/api.php?action=list-devices&only-with-location=yes
``` ```
## Notes ## Notes

View file

@ -0,0 +1,65 @@
<?php
namespace AirQuality\Actions;
use \SBRL\TomlConfig;
use \AirQuality\Repositories\IDeviceRepository;
use \AirQuality\ApiResponseSender;
use \AirQuality\Validator;
use \AirQuality\PerfFormatter;
class ListDevices implements IAction {
/** @var TomlConfig */
private $settings;
/** @var IDeviceRepository */
private $device_repo;
/** @var ApiResponseSender */
private $sender;
public function __construct(
TomlConfig $in_settings,
IDeviceRepository $in_device_repo,
ApiResponseSender $in_sender) {
$this->settings = $in_settings;
$this->device_repo = $in_device_repo;
$this->sender = $in_sender;
}
public function handle() : bool {
global $start_time;
$start_handle = microtime(true);
// 1: Parse & validate parameters
$only_with_location = !empty($_GET["only_with_location"]);
// 1: Pull data from database
$data = $this->device_repo->get_all_devices($only_with_location);
// 1.5: Validate data from database
if(empty($data)) {
http_response_code(404);
header("content-type: text/plain");
header("x-time-taken: " . PerfFormatter::format_perf_data($start_time, $start_handle, null));
echo("Error: No devices are currently present in the system.");
return false;
}
// 3: Serialise data
$start_encode = microtime(true);
$response = json_encode($data);
// 4: Send response
// Don't a cache control header, because new devices might get added at any time
// TODO: Investigate adding a short-term (~10mins?) cache-control header here
header("content-length: " . strlen($response));
header("content-type: application/json");
header("x-time-taken: " . PerfFormatter::format_perf_data($start_time, $start_handle, $start_encode));
echo($response);
return true;
}
}

View file

@ -3,5 +3,11 @@
namespace AirQuality\Repositories; namespace AirQuality\Repositories;
interface IDeviceRepository { interface IDeviceRepository {
/**
* Returns an array of all the devices in the system with basic information
* about each.
* @param bool $only_with_location Whether only devices with a defined location should be returned.
* @return array A list of devices and their basic information.
*/
public function get_all_devices($only_with_location);
} }

View file

@ -22,8 +22,33 @@ class MariaDBDeviceRepository implements IDeviceRepository {
*/ */
private $database; private $database;
/** Function that gets a static variable by it's name. Useful in preparing SQL queries. */
private $get_static;
function __construct(\AirQuality\Database $in_database) { function __construct(\AirQuality\Database $in_database) {
$this->database = $in_database; $this->database = $in_database;
$this->get_static = function($name) { return self::$$name; };
} }
public function get_all_devices($only_with_location) {
$s = $this->get_static;
$sql = "SELECT
{$s("column_device_id")},
{$s("column_device_name")},
{$s("column_lat")},
{$s("column_long")}
FROM {$s("table_name")}";
if($only_with_location)
$sql .= "\nWHERE
{$s("column_lat")} IS NOT NULL
AND {$s("column_long")} IS NOT NULL";
$sql .= ";";
return $this->database->query($sql)->fetchAll();
}
} }

View file

@ -37,7 +37,6 @@ class MariaDBMeasurementDataRepository implements IMeasurementDataRepository {
/** Function that gets a static variable by it's name. Useful in preparing SQL queries. */ /** Function that gets a static variable by it's name. Useful in preparing SQL queries. */
private $get_static; private $get_static;
private $get_static_extra; private $get_static_extra;
function __construct(Database $in_database, TomlConfig $in_settings) { function __construct(Database $in_database, TomlConfig $in_settings) {