changeset 107:1edc60154ba9

geohub: Allow for on-the-fly speed unit transcoding
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 26 Dec 2020 09:04:06 +0100
parents da9fb0032788
children 68107e685890
files README.md src/http.rs src/main.rs src/util.rs
diffstat 4 files changed, 34 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/README.md	Sat Dec 26 08:28:38 2020 +0100
+++ b/README.md	Sat Dec 26 09:04:06 2020 +0100
@@ -44,6 +44,8 @@
   free to do so. **Optional**.
   * `elevation`: Elevation in meters. **Optional**.
   * `accuracy`: Accuracy in meters. **Optional**
+  * `unit`: If given, convert the number given for `&s=` into `km/h` for
+  storage, assuming the given unit. Can be: kn/knots, mph, mps/ms/'m/s', kmh/'km/h'/kph.
   * A body -- if present and encoded in whatever content-type -- is attached as `note` to the
   point and returned as property `note` of GeoJSON points later.
   * Usually returns code **200** except for server errors (500) or malformed inputs (400).
--- a/src/http.rs	Sat Dec 26 08:28:38 2020 +0100
+++ b/src/http.rs	Sat Dec 26 09:04:06 2020 +0100
@@ -24,9 +24,13 @@
 
 fn content_disposition(attachment: bool) -> rocket::http::hyper::header::ContentDisposition {
     rocket::http::hyper::header::ContentDisposition {
-            disposition: if attachment { rocket::http::hyper::header::DispositionType::Attachment } else { rocket::http::hyper::header::DispositionType::Inline },
-            parameters: vec![],
-        }
+        disposition: if attachment {
+            rocket::http::hyper::header::DispositionType::Attachment
+        } else {
+            rocket::http::hyper::header::DispositionType::Inline
+        },
+        parameters: vec![],
+    }
 }
 
 pub fn return_ok(s: String) -> GeoHubResponder {
@@ -83,12 +87,8 @@
     let mut ds = d.open().take(limit);
     let mut dest = Vec::with_capacity(limit as usize);
     if let Err(e) = std::io::copy(&mut ds, &mut dest) {
-        return Err(bad_request(format!(
-            "Error reading request: {}",
-            e
-        )));
+        return Err(bad_request(format!("Error reading request: {}", e)));
     }
 
-    String::from_utf8(dest)
-        .map_err(|e| bad_request(format!("Decoding error: {}", e)))
+    String::from_utf8(dest).map_err(|e| bad_request(format!("Decoding error: {}", e)))
 }
--- a/src/main.rs	Sat Dec 26 08:28:38 2020 +0100
+++ b/src/main.rs	Sat Dec 26 09:04:06 2020 +0100
@@ -178,7 +178,7 @@
 /// time is like 2020-11-30T20:12:36.444Z (ISO 8601). By default, server time is set.
 /// secret can be used to protect points.
 #[rocket::post(
-    "/geo/<name>/log?<lat>&<longitude>&<time>&<s>&<ele>&<secret>&<accuracy>",
+    "/geo/<name>/log?<lat>&<longitude>&<time>&<s>&<ele>&<secret>&<accuracy>&<unit>",
     data = "<note>"
 )]
 fn log(
@@ -192,6 +192,7 @@
     s: Option<f64>,
     ele: Option<f64>,
     accuracy: Option<f64>,
+    unit: Option<String>,
     note: rocket::data::Data,
 ) -> http::GeoHubResponder {
     // Check that secret and client name are legal.
@@ -229,6 +230,15 @@
         Err(e) => return e,
     };
 
+    // Convert speed if needed.
+    let mut s = s;
+    if let (Some(u), Some(speed)) = (unit.as_ref(), s) {
+        match util::to_kph(u.as_str(), speed) {
+            Ok(speed) => s = Some(speed),
+            Err(e) => return e,
+        }
+    }
+
     let point = types::GeoPoint {
         id: None,
         lat: lat,
--- a/src/util.rs	Sat Dec 26 08:28:38 2020 +0100
+++ b/src/util.rs	Sat Dec 26 09:04:06 2020 +0100
@@ -2,6 +2,8 @@
 
 use chrono::TimeZone;
 
+use crate::http;
+
 /// Parse timestamps flexibly. Without any zone information, UTC is assumed.
 pub fn flexible_timestamp_parse(ts: String) -> Option<chrono::DateTime<chrono::Utc>> {
     let fmtstrings = &[
@@ -24,3 +26,13 @@
     }
     None
 }
+
+pub fn to_kph(unit: &str, num: f64) -> Result<f64, http::GeoHubResponder> {
+    match unit {
+        "mps" | "ms" | "m/s" => Ok(3.6*num),
+        "kmh" | "km/h" | "kph" => Ok(num),
+        "mph" => Ok(1.601*num),
+        "kn" | "knots" => Ok(1.852*num),
+        _ => Err(http::bad_request(format!("Unknown unit '{}'", unit)))
+    }
+}