Browse Source

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

pull/26/head
Starbeamrainbowlabs 4 years ago
parent
commit
09ab6f38d5
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
  1. 4
      Changelog.md
  2. 3
      README.md
  3. 31
      lib/SBRL/ResponseEncoder.php
  4. 12
      logic/Actions/DeviceData.php
  5. 25
      logic/Actions/ListReadingTypes.php

4
Changelog.md

@ -1,7 +1,9 @@ @@ -1,7 +1,9 @@
# Changelog
## 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
- Updated to use new database structure

3
README.md

@ -123,6 +123,7 @@ Examples: @@ -123,6 +123,7 @@ Examples:
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.
`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
@ -153,7 +154,7 @@ Parameter | Type | Meaning @@ -153,7 +154,7 @@ Parameter | Type | Meaning
`start` | datetime | The starting 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.
`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

31
lib/SBRL/ResponseEncoder.php

@ -0,0 +1,31 @@ @@ -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;
}
}

12
logic/Actions/DeviceData.php

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
namespace AirQuality\Actions;
use \SBRL\TomlConfig;
use \SBRL\ResponseEncoder;
use \AirQuality\Repositories\IMeasurementDataRepository;
use \AirQuality\Repositories\IMeasurementTypeRepository;
use \AirQuality\ApiResponseSender;
@ -117,17 +118,10 @@ class DeviceData implements IAction { @@ -117,17 +118,10 @@ class DeviceData implements IAction {
$response = json_encode($data);
break;
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_suggested_filename .= ".json";
$response = \stream_get_contents($result);
$response = ResponseEncoder::encode_csv($data);
fclose($result);
break;
}
@ -135,7 +129,7 @@ class DeviceData implements IAction { @@ -135,7 +129,7 @@ class DeviceData implements IAction {
// 4: Send response
header("content-length: " . strlen($response));
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));
echo($response);
return true;

25
logic/Actions/ListReadingTypes.php

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
namespace AirQuality\Actions;
use \SBRL\TomlConfig;
use \SBRL\ResponseEncoder;
use \AirQuality\Repositories\IMeasurementTypeRepository;
use \AirQuality\ApiResponseSender;
@ -33,6 +34,13 @@ class ListReadingTypes implements IAction { @@ -33,6 +34,13 @@ class ListReadingTypes implements IAction {
// 1: Parse & validate parameters
$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
$data = null;
@ -52,7 +60,19 @@ class ListReadingTypes implements IAction { @@ -52,7 +60,19 @@ class ListReadingTypes implements IAction {
// 3: Serialise data
$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
@ -60,7 +80,8 @@ class ListReadingTypes implements IAction { @@ -60,7 +80,8 @@ class ListReadingTypes implements IAction {
// TODO: Investigate adding a short-term (~10mins?) cache-control header here
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));
echo($response);
return true;

Loading…
Cancel
Save