API: Add format parameter to list-reading-types action

This commit is contained in:
Starbeamrainbowlabs 2019-02-24 17:07:09 +00:00
parent 75e26f4960
commit 09ab6f38d5
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
5 changed files with 62 additions and 13 deletions

View file

@ -1,7 +1,9 @@
# Changelog # Changelog
## v0.4 - 24th February 2019 (unreleased) ## v0.4 - 24th February 2019 (unreleased)
- [API] Added new `format` GET parameter to `device-data` action. - [API] Added new `format` GET parameter to the following actions:
- `device-data`
- `list-reading-types`
## v0.3.3 - 20th February 2019 ## v0.3.3 - 20th February 2019
- Updated to use new database structure - Updated to use new database structure

View file

@ -123,6 +123,7 @@ Examples:
Parameter | Type | Meaning Parameter | Type | Meaning
--------------------|-----------|--------------------- --------------------|-----------|---------------------
`device-id` | int | Optional. If specified, this filters the list of measurement types to list only those reported by the device with the specified id. `device-id` | int | Optional. If specified, this filters the list of measurement types to list only those reported by the device with the specified id.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
``` ```
https://example.com/path/to/api.php?action=list-reading-types https://example.com/path/to/api.php?action=list-reading-types
@ -153,7 +154,7 @@ Parameter | Type | Meaning
`start` | datetime | The starting datetime. `start` | datetime | The starting datetime.
`end` | datetime | The ending datetime. `end` | datetime | The ending datetime.
`average-seconds` | int | Optional. If specified, readings will be grouped into lumps of this many seconds and averaged. For example a value of 3600 (1 hour) will return 1 data point per hour, with the value of each point an average of all the readings for that hour. `average-seconds` | int | Optional. If specified, readings will be grouped into lumps of this many seconds and averaged. For example a value of 3600 (1 hour) will return 1 data point per hour, with the value of each point an average of all the readings for that hour.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json` `format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
### changelog ### changelog

View file

@ -0,0 +1,31 @@
<?php
namespace SBRL;
/**
* Serialises an object to a variety of formats.
*/
class ResponseEncoder
{
/**
* Encodes an array of associative arrays to CSV.
* @param array $data The data to encode.
* @return string The data encoded to csv.
*/
public static function encode_csv($data) {
if(empty($data))
return "";
$result = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
fputcsv($result, array_keys($data[0]));
foreach($data as $row)
fputcsv($result, array_values($row));
rewind($result);
$response = \stream_get_contents($result);
fclose($result);
return $response;
}
}

View file

@ -3,6 +3,7 @@
namespace AirQuality\Actions; namespace AirQuality\Actions;
use \SBRL\TomlConfig; use \SBRL\TomlConfig;
use \SBRL\ResponseEncoder;
use \AirQuality\Repositories\IMeasurementDataRepository; use \AirQuality\Repositories\IMeasurementDataRepository;
use \AirQuality\Repositories\IMeasurementTypeRepository; use \AirQuality\Repositories\IMeasurementTypeRepository;
use \AirQuality\ApiResponseSender; use \AirQuality\ApiResponseSender;
@ -117,17 +118,10 @@ class DeviceData implements IAction {
$response = json_encode($data); $response = json_encode($data);
break; break;
case "csv": case "csv":
$result = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
fputcsv($result, array_keys($data[0]));
foreach($data as $row)
fputcsv($result, array_values($row));
rewind($result);
$response_type = "text/csv"; $response_type = "text/csv";
$response_suggested_filename .= ".json"; $response_suggested_filename .= ".json";
$response = \stream_get_contents($result); $response = ResponseEncoder::encode_csv($data);
fclose($result);
break; break;
} }
@ -135,7 +129,7 @@ class DeviceData implements IAction {
// 4: Send response // 4: Send response
header("content-length: " . strlen($response)); header("content-length: " . strlen($response));
header("content-type: $response_type"); header("content-type: $response_type");
header("content-disposition: inline; filename=data.csv"); header("content-disposition: inline; filename=$response_suggested_filename");
header("x-time-taken: " . PerfFormatter::format_perf_data($start_time, $start_handle, $start_encode)); header("x-time-taken: " . PerfFormatter::format_perf_data($start_time, $start_handle, $start_encode));
echo($response); echo($response);
return true; return true;

View file

@ -3,6 +3,7 @@
namespace AirQuality\Actions; namespace AirQuality\Actions;
use \SBRL\TomlConfig; use \SBRL\TomlConfig;
use \SBRL\ResponseEncoder;
use \AirQuality\Repositories\IMeasurementTypeRepository; use \AirQuality\Repositories\IMeasurementTypeRepository;
use \AirQuality\ApiResponseSender; use \AirQuality\ApiResponseSender;
@ -33,6 +34,13 @@ class ListReadingTypes implements IAction {
// 1: Parse & validate parameters // 1: Parse & validate parameters
$device_id = !empty($_GET["device-id"]) ? intval($_GET["device-id"]) : null; $device_id = !empty($_GET["device-id"]) ? intval($_GET["device-id"]) : null;
$format = $_GET["format"] ?? "json";
if(!in_array($format, ["json", "csv"])) {
$this->sender->send_error_plain(406,
"Error: The format '$format' isn't recognised. Valid formats: " . implode(", ", $format) . "."
);
exit;
}
// 1: Pull data from database // 1: Pull data from database
$data = null; $data = null;
@ -52,7 +60,19 @@ class ListReadingTypes implements IAction {
// 3: Serialise data // 3: Serialise data
$start_encode = microtime(true); $start_encode = microtime(true);
$response = json_encode($data); $response = null;
$response_type = "application/octet-stream";
$response_suggested_filename = "data-" . date(\DateTime::ATOM) . "";
switch($format) {
case "json":
$response_type = "application/json";
$response = json_encode($data);
break;
case "csv":
$response_type = "text/csv";
$response = ResponseEncoder::encode_csv($data);
break;
}
// 4: Send response // 4: Send response
@ -60,7 +80,8 @@ class ListReadingTypes implements IAction {
// TODO: Investigate adding a short-term (~10mins?) cache-control header here // TODO: Investigate adding a short-term (~10mins?) cache-control header here
header("content-length: " . strlen($response)); header("content-length: " . strlen($response));
header("content-type: application/json"); header("content-type: $response_type");
header("content-disposition: inline; filename=$response_suggested_filename");
header("x-time-taken: " . PerfFormatter::format_perf_data($start_time, $start_handle, $start_encode)); header("x-time-taken: " . PerfFormatter::format_perf_data($start_time, $start_handle, $start_encode));
echo($response); echo($response);
return true; return true;