make json api more idiomatic

* camelCase
* lose the "days":null in the overall cameras dict
This commit is contained in:
Scott Lamb 2017-10-09 21:58:44 -07:00
parent 5bb3dde74e
commit 1e4d7d5ad9
3 changed files with 60 additions and 56 deletions

View File

@ -29,18 +29,18 @@ A `GET` request on this URL returns basic information about all cameras. The
attributes about each camera:
* `uuid`: in text format
* `short_name`: a short name (typically one or two words)
* `shortName`: a short name (typically one or two words)
* `description`: a longer description (typically a phrase or paragraph)
* `retain_bytes`: the configured total number of bytes of completed
* `retainBytes`: the configured total number of bytes of completed
recordings to retain.
* `min_start_time_90k`: the start time of the earliest recording for this
* `minStartTime90k`: the start time of the earliest recording for this
camera, in 90kHz units since 1970-01-01 00:00:00 UTC.
* `max_end_time_90k`: the end time of the latest recording for this
* `maxEndTime90k`: the end time of the latest recording for this
camera, in 90kHz units since 1970-01-01 00:00:00 UTC.
* `total_duration_90k`: the total duration recorded, in 90 kHz units.
This is no greater than `max_end_time_90k - max_start_time_90k`; it
* `totalDuration90k`: the total duration recorded, in 90 kHz units.
This is no greater than `maxEndTime90k - maxStartTime90k`; it
will be lesser if there are gaps in the recorded data.
* `total_sample_file_bytes`: the total number of bytes of sample data (the
* `totalSampleFileBytes`: the total number of bytes of sample data (the
`mdat` portion of a `.mp4` file).
Example response:
@ -50,13 +50,13 @@ Example response:
"cameras": [
{
"uuid": "fd20f7a2-9d69-4cb3-94ed-d51a20c3edfe",
"short_name": "driveway",
"shortName": "driveway",
"description": "Hikvision DS-2CD2032 overlooking the driveway from east",
"retain_bytes": 536870912000,
"min_start_time_90k": 130888729442361,
"max_end_time_90k": 130985466591817,
"total_duration_90k": 96736169725,
"total_sample_file_bytes": 446774393937,
"retainBytes": 536870912000,
"minStartTime90k": 130888729442361,
"maxEndTime90k": 130985466591817,
"totalDuration90k": 96736169725,
"totalSampleFileBytes": 446774393937,
},
...
],
@ -71,12 +71,12 @@ list of calendar days (in the server's time zone) with data in the server's
time zone. The `days` entry is a object mapping `YYYY-mm-dd` to a day object
with the following attributes:
* `total_duration_90k` is the total duration recorded during that day.
* `totalDuration90k` is the total duration recorded during that day.
If a recording spans a day boundary, some portion of it is accounted to
each day.
* `start_time_90k` is the start of that calendar day in the server's time
* `startTime90k` is the start of that calendar day in the server's time
zone.
* `end_time_90k` is the end of that calendar day in the server's time zone.
* `endTime90k` is the end of that calendar day in the server's time zone.
It is usually 24 hours after the start time. It might be 23 hours or 25
hours during spring forward or fall back, respectively.
@ -89,23 +89,23 @@ Example response:
{
"days": {
"2016-05-01": {
"end_time_90k": 131595516000000,
"start_time_90k": 131587740000000,
"total_duration_90k": 52617609
"endTime90k": 131595516000000,
"startTime90k": 131587740000000,
"totalDuration90k": 52617609
},
"2016-05-02": {
"end_time_90k": 131603292000000,
"start_time_90k": 131595516000000,
"total_duration_90k": 20946022
"endTime90k": 131603292000000,
"startTime90k": 131595516000000,
"totalDuration90k": 20946022
}
},
"description":"",
"max_end_time_90k": 131598273666690,
"min_start_time_90k": 131590386129355,
"retain_bytes": 104857600,
"short_name": "driveway",
"total_duration_90k": 73563631,
"total_sample_file_bytes": 98901406,
"maxEndTime90k": 131598273666690,
"minStartTime90k": 131590386129355,
"retainBytes": 104857600,
"shortName": "driveway",
"totalDuration90k": 73563631,
"totalSampleFileBytes": 98901406,
}
```
@ -115,7 +115,7 @@ A GET returns information about recordings, in descending order.
Valid request parameters:
* `start_time_90k` and and `end_time_90k` limit the data returned to only
* `startTime90k` and and `endTime90k` limit the data returned to only
recordings which overlap with the given half-open interval. Either or both
may be absent; they default to the beginning and end of time, respectively.
* TODO(slamb): `continue` to support paging. (If data is too large, the
@ -128,32 +128,32 @@ URI or as a separate `/annotations`?
In the property `recordings`, returns a list of recordings in arbitrary order.
Each recording object has the following properties:
* `start_id`. The id of this recording, which can be used with `/view.mp4`
* `startId`. The id of this recording, which can be used with `/view.mp4`
to retrieve its content.
* `end_id` (optional). If absent, this object describes a single recording.
If present, this indicates that recordings `start_id-end_id` (inclusive)
* `endId` (optional). If absent, this object describes a single recording.
If present, this indicates that recordings `startId-endId` (inclusive)
together are as described. Adjacent recordings from the same RTSP session
may be coalesced in this fashion to reduce the amount of redundant data
transferred.
* `start_time_90k`: the start time of the given recording. Note this may be
less than the requested `start_time_90k` if this recording was ongoing
* `startTime90k`: the start time of the given recording. Note this may be
less than the requested `startTime90k` if this recording was ongoing
at the requested time.
* `end_time_90k`: the end time of the given recording. Note this may be
greater than the requested `end_time_90k` if this recording was ongoing at
* `endTime90k`: the end time of the given recording. Note this may be
greater than the requested `endTime90k` if this recording was ongoing at
the requested time.
* `sample_file_bytes`
* `video_sample_entry_sha1`
* `video_sample_entry_width`
* `video_sample_entry_height`
* `video_samples`: the number of samples (aka frames) of video in this
* `sampleFileBytes`
* `videoSampleEntrySha1`
* `videoSampleEntryWidth`
* `videoSampleEntryHeight`
* `videoSamples`: the number of samples (aka frames) of video in this
recording.
Example request URI (with added whitespace between parameters):
```
/camera/fd20f7a2-9d69-4cb3-94ed-d51a20c3edfe/recordings
?start_time_90k=130888729442361
&end_time_90k=130985466591817
?startTime90k=130888729442361
&endTime90k=130985466591817
```
Example response:
@ -162,16 +162,16 @@ Example response:
{
"recordings": [
{
"start_id": 1,
"start_time_90k": 130985461191810,
"end_time_90k": 130985466591817,
"sample_file_bytes": 8405564,
"video_sample_entry_sha1": "81710c9c51a02cc95439caa8dd3bc12b77ffe767",
"video_sample_entry_width": 1280,
"video_sample_entry_height": 720,
"startId": 1,
"startTime90k": 130985461191810,
"endTime90k": 130985466591817,
"sampleFileBytes": 8405564,
"videoSampleEntrySha1": "81710c9c51a02cc95439caa8dd3bc12b77ffe767",
"videoSampleEntryWidth": 1280,
"videoSampleEntryHeight": 720,
},
{
"end_time_90k": 130985461191810,
"endTime90k": 130985461191810,
...
},
...

View File

@ -43,6 +43,7 @@ pub struct ListCameras<'a> {
/// JSON serialization wrapper for a single camera when processing `/cameras/` and
/// `/cameras/<uuid>/`. See `design/api.md` for details.
#[derive(Debug, Serialize)]
#[serde(rename_all="camelCase")]
pub struct Camera<'a> {
pub uuid: Uuid,
pub short_name: &'a str,
@ -53,6 +54,7 @@ pub struct Camera<'a> {
pub total_duration_90k: i64,
pub total_sample_file_bytes: i64,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(serialize_with = "Camera::serialize_days")]
pub days: Option<&'a BTreeMap<db::CameraDayKey, db::CameraDayValue>>,
}
@ -94,6 +96,7 @@ impl<'a> Camera<'a> {
}
#[derive(Debug, Serialize)]
#[serde(rename_all="camelCase")]
struct CameraDayValue {
pub start_time_90k: i64,
pub end_time_90k: i64,
@ -120,6 +123,7 @@ pub struct ListRecordings {
}
#[derive(Debug, Serialize)]
#[serde(rename_all="camelCase")]
pub struct Recording {
pub start_time_90k: i64,
pub end_time_90k: i64,

View File

@ -326,8 +326,8 @@ impl Service {
for (key, value) in form_urlencoded::parse(q.as_bytes()) {
let (key, value) = (key.borrow(), value.borrow());
match key {
"start_time" => time.start = recording::Time::parse(value)?,
"end_time" => time.end = recording::Time::parse(value)?,
"startTime" => time.start = recording::Time::parse(value)?,
"endTime" => time.end = recording::Time::parse(value)?,
"trim" if value == "true" => trim = true,
_ => {},
}
@ -556,7 +556,7 @@ impl Service {
Ok(http_entity::serve(mp4, req))
}
/// Parses optional `start_time_90k` and `end_time_90k` query parameters, defaulting to the
/// Parses optional `startTime90k` and `endTime90k` query parameters, defaulting to the
/// full range of possible values.
fn get_optional_range(query: Option<&str>) -> Result<Range<recording::Time>, Error> {
let mut start = i64::min_value();
@ -565,8 +565,8 @@ impl Service {
for (key, value) in form_urlencoded::parse(q.as_bytes()) {
let (key, value) = (key.borrow(), value.borrow());
match key {
"start_time_90k" => start = i64::from_str(value)?,
"end_time_90k" => end = i64::from_str(value)?,
"startTime90k" => start = i64::from_str(value)?,
"endTime90k" => end = i64::from_str(value)?,
_ => {},
}
};