From 84d84958afa8cefee77b35e90eab727a78ed495f Mon Sep 17 00:00:00 2001 From: jannasmith <37844599+jannasmith@users.noreply.github.com> Date: Tue, 12 Feb 2019 13:51:53 -0800 Subject: [PATCH 01/40] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b6fa496..26f5332d 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The specification will be versioned using Git tags and [semantic versioning](htt The City of Los Angeles is currently looking for feedback and comments on the draft versions. Comments can be made by making an Github Issue, while suggested changes can be made using a pull request. The rules and guidelines for the Los Angeles Dockless Bikeshare Systems / Pilot Program can be found on [Council Clerk Connect](https://cityclerk.lacity.org/lacityclerkconnect/index.cfm?fa=ccfi.viewrecord&cfnumber=17-1125). -*2/4/2019 Update*: Webinar: City of Los Angeles One Year Permit Application MDS Agency Compliance: LADOT is seeking compliance with MDS Agency as a requirement of the one-year permit, and is hosting a webinar on Thursday, February 7th, from 2 pm to 4 pm (PST) to give an overview of the MDS Agency sandbox, discuss and answer questions about integration and timeline for Agency services. To participate in the webinar, please email: support@ladot.io +*2/12/2019 Update*: City of Los Angeles One Year Permit Application MDS Agency Compliance: LADOT is seeking compliance with MDS Agency as a requirement of the one-year permit, and hosted a webinar on Thursday, February 7th to give an overview of the MDS Agency sandbox, discuss and answer questions about integration and timeline for Agency services. The slides from the webinar presentation can be found [here](https://ladot.lacity.org/sites/g/files/wph266/f/MDS%20Developer%20Webinar%20-%20One%20Year%20Permitting%20Overview.pdf). *12/27/2018 Update*: Applications for the One-Year Dockless On-Demand Personal Mobility Permit are now available on the [LADOT Website](https://ladot.lacity.org/ladot-begins-one-year-dockless-demand-personal-mobility-program) From d12b77468c3d092b947fae46b46c8a935e453628 Mon Sep 17 00:00:00 2001 From: Damien Baty Date: Wed, 13 Feb 2019 08:23:23 +0100 Subject: [PATCH 02/40] Add new `battery_charged` event type reason When the battery of a device is too low, the service yields the `unavailable` event type with the `low_battery` reason. Then the device may charge itself (for example because it has been plugged to a charging dock by the last customer, or because the device has a solar panel). Once the battery is charged enough, the service can yield an `available` event type with the `battery_charged` reason. [closes #210] --- agency/README.md | 1 + generate_schema/provider/status_changes.json | 1 + provider/README.md | 1 + provider/status_changes.json | 3 ++- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/agency/README.md b/agency/README.md index 4428b26c..4115e3af 100644 --- a/agency/README.md +++ b/agency/README.md @@ -191,6 +191,7 @@ List of valid vehicle events and the resulting vehicle status if the event is su | `event_type` | description | valid initial `status` | `status` on success | status_description | | ---------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------- | ----------------------------------------------------------------------- | | `service_start` | Vehicle introduced into service at the beginning of the day (if program does not operate 24/7) | `unavailable`, `removed`, `elsewhere` | `available` | Vehicle is on the street and available for customer use. | +| `battery_charged` | A vehicle becomes available because its battery is charged enough | `unavailable` | `available` | | | `trip_end` | Customer ends trip and reservation | `trip` | `available` | | | `rebalance_drop_off` | Vehicle moved for rebalancing | `removed` | `available` | | | `maintenance_drop_off` | Vehicle introduced into service after being removed for maintenance | `removed` | `available` | | diff --git a/generate_schema/provider/status_changes.json b/generate_schema/provider/status_changes.json index ed66c489..ff839b05 100644 --- a/generate_schema/provider/status_changes.json +++ b/generate_schema/provider/status_changes.json @@ -120,6 +120,7 @@ }, "event_type_reason": { "enum": [ + "battery_charged", "service_start", "user_drop_off", "rebalance_drop_off", diff --git a/provider/README.md b/provider/README.md index be5de24d..285e7fd0 100644 --- a/provider/README.md +++ b/provider/README.md @@ -275,6 +275,7 @@ When multiple query parameters are specified, they should all apply to the retur | `event_type` | Description | `event_type_reason` | Description | | ---------- | ---------------------- | ------- | ------------------ | | `available` | A device becomes available for customer use | `service_start` | Device introduced into service at the beginning of the day (if program does not operate 24/7) | +| | | `battery_charged` | A device becomes available because its battery is charged enough | | | | `user_drop_off` | User ends reservation | | | | `rebalance_drop_off` | Device moved for rebalancing | | | | `maintenance_drop_off` | Device introduced into service after being removed for maintenance | diff --git a/provider/status_changes.json b/provider/status_changes.json index f38c78e0..98464451 100644 --- a/provider/status_changes.json +++ b/provider/status_changes.json @@ -311,6 +311,7 @@ }, "event_type_reason": { "enum": [ + "battery_charged", "service_start", "user_drop_off", "rebalance_drop_off", @@ -400,4 +401,4 @@ } }, "additionalProperties": false -} \ No newline at end of file +} From b5f30bbdfc8e10129fce97197c3605ad168afd9c Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Fri, 22 Feb 2019 10:54:38 -0600 Subject: [PATCH 03/40] drop UUID4 requirement in favor of simply UUID, to make consistent with Provider --- agency/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/agency/README.md b/agency/README.md index bdba3081..7cfa44c2 100644 --- a/agency/README.md +++ b/agency/README.md @@ -39,14 +39,14 @@ Path Params: | Param | Type | Required/Optional | Description | | ------------ | ---- | ----------------- | ------------------------------------------- | -| `device_id` | UUID4 | Optional | If provided, retrieve the specified vehicle | +| `device_id` | UUID | Optional | If provided, retrieve the specified vehicle | 200 Success Response: | Field | Type | Field Description | | ------------- | -------------- | ----------------------------------------------------------------------------- | -| `device_id` | UUID4 | Provided by Operator to uniquely identify a vehicle | -| `provider_id` | UUID4 | Issued by City and [tracked](../providers.csv) | +| `device_id` | UUID | Provided by Operator to uniquely identify a vehicle | +| `provider_id` | UUID | Issued by City and [tracked](../providers.csv) | | `vehicle_id` | String | Vehicle Identification Number (vehicle_id) visible on vehicle | | `type` | Enum | [Vehicle Type](#vehicle-type) | | `propulsion` | Enum[] | Array of [Propulsion Type](#propulsion-type); allows multiple values | @@ -68,7 +68,7 @@ Body Params: | Field | Type | Required/Optional | Field Description | | ------------ | ------- | ----------------- | -------------------------------------------------------------------- | -| `device_id` | UUID4 | Required | Provided by Operator to uniquely identify a vehicle | +| `device_id` | UUID | Required | Provided by Operator to uniquely identify a vehicle | | `vehicle_id` | String | Required | Vehicle Identification Number (vehicle_id) visible on vehicle | | `type` | Enum | Required | [Vehicle Type](#vehicle-type) | | `propulsion` | Enum[] | Required | Array of [Propulsion Type](#propulsion-type); allows multiple values | @@ -104,7 +104,7 @@ Path Params: | Field | Type | Required/Optional | Field Description | | ------------ | ---- | ----------------- | ---------------------------------------- | -| `device_id` | UUID4 | Required | ID used in [Register](#vehicle-register) | +| `device_id` | UUID | Required | ID used in [Register](#vehicle-register) | Body Params: @@ -113,13 +113,13 @@ Body Params: | `event_type` | Enum | Required | [Vehicle Event](#vehicle-events) | | `timestamp` | Timestamp | Required |Date of last event update | | `telemetry` | [Telemetry](#telemetry-data) | Required | Single point of telemetry | -| `trip_id` | UUID4 | Optional | UUID provided by Operator to uniquely identify the trip. Required for `trip_start`, `trip_end`, `trip_enter`, and `trip_leave` event types | +| `trip_id` | UUID | Optional | UUID provided by Operator to uniquely identify the trip. Required for `trip_start`, `trip_end`, `trip_enter`, and `trip_leave` event types | 201 Success Response: | Field | Type | Field Description | | ------------ | ---- | ----------------------------------------------------------------------------- | -| `device_id` | UUID4| UUID provided by Operator to uniquely identify a vehicle | +| `device_id` | UUID | UUID provided by Operator to uniquely identify a vehicle | | `status` | Enum | Vehicle status based on posted `event_type`. See [Vehicle Status](#vehicle-events) | 400 Failure Response: @@ -169,7 +169,7 @@ Path Params: | Field | Type | Required/Optional | Field Description | | ----------------- | ---- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| `service_area_id` | UUID4| Optional | If provided, retrieve a specific service area (e.g. a retired or old service area). If omitted, will return all active service areas. | +| `service_area_id` | UUID | Optional | If provided, retrieve a specific service area (e.g. a retired or old service area). If omitted, will return all active service areas. | Query Params: @@ -181,12 +181,12 @@ Query Params: | Field | Types | Required/Optional | Field Description | | ------------------ | ----------------------------------- | ----------------- | ------------------------------------------------------------------------------------------- | -| `service_area_id` | UUID4 | Required | UUID issued by city | +| `service_area_id` | UUID | Required | UUID issued by city | | `start_date` | Timestamp | Required | Date at which this service area became effective | | `end_date` | Timestamp | Optional | If exists, Date at which this service area was replaced. | | `area` | MultiPolygon | Required | GeoJson [MultiPolygon](https://tools.ietf.org/html/rfc7946#section-3.1.7) in WGS84 degrees. | -| `prev_area` | UUID4 | Optional | If exists, the UUID of the prior service area. | -| `replacement_area` | UUID4 | Optional | If exists, the UUID of the service area that replaced this one | +| `prev_area` | UUID | Optional | If exists, the UUID of the prior service area. | +| `replacement_area` | UUID | Optional | If exists, the UUID of the service area that replaced this one | | `type` | Enum | Required | See [area types](#area-types) | ## Vehicle Events @@ -218,7 +218,7 @@ A standard point of vehicle telemetry. References to latitude and longitude impl | Field | Type | Required/Optional | Field Description | | -------------- | -------------- | --------------------- | ------------------------------------------------------------ | -| `device_id` | UUID4 | Required | ID used in [Register](#vehicle-register) | +| `device_id` | UUID | Required | ID used in [Register](#vehicle-register) | | `timestamp` | Timestamp | Required | Date/time that event occurred. Based on GPS clock | | `gps` | Object | Required | Telemetry position data | | `gps.lat` | Double | Required | Latitude of the location | From 54ea3df6d93dd5d0d93ae8248d65ed9c4a78fc0c Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Fri, 22 Feb 2019 15:05:48 -0600 Subject: [PATCH 04/40] Remove reference to 412 for policy/business-logic; such mechanisms will be developed in different endpoint(s) or API(s) --- agency/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/agency/README.md b/agency/README.md index 7cfa44c2..60119e83 100644 --- a/agency/README.md +++ b/agency/README.md @@ -203,7 +203,7 @@ List of valid vehicle events and the resulting vehicle status if the event is su | `reserve` | Customer reserves vehicle | `available` | `reserved` | Vehicle is reserved or in use. | | `trip_start` | Customer starts a trip | `available`, `reserved` | `trip` | | | `trip_enter` | Customer enters a service area managed by agency during an active trip. | `unavailable`, `removed`, `elsewhere` | `trip` | | -| `trip_leave` | Customer enters a service area managed by agency during an active trip. | `trip` | `elsewhere` | | +| `trip_leave` | Customer leaves a service area managed by agency during an active trip. | `trip` | `elsewhere` | | | `register` | Default state for a newly registered vehicle | `inactive` | `unavailable` | A vehicle is in the active fleet but not yet available for customer use | | `low_battery` | A vehicle is no longer available due to insufficient battery | `available` | `unavailable` | | | `maintenance` | A vehicle is no longer available due to equipment issues | `available`, `reserved` | `unavailable` | | @@ -268,7 +268,6 @@ A vehicle may have one or more values from the `propulsion`, depending on the nu * **401:** Unauthorized: Invalid, expired, or insufficient scope of token. * **404:** Not Found: Object does not exist, returned on `GET` or `POST` operations if the object does not exist. * **409:** Conflict: `POST` operations when an object already exists and an update is not possible. -* **412:** Precondition failed: `POST` operation rejected based on policy or business logic. * **500:** Internal server error: In this case, the answer may contain a `text/plain` body with an error message for troubleshooting. ### Error Message Format From 052958cc51f0ca440762af3f5d55f04fd9d2ff6f Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Fri, 22 Feb 2019 16:43:13 -0600 Subject: [PATCH 05/40] remove error messages related to state-machine validation --- agency/README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/agency/README.md b/agency/README.md index 60119e83..7dcf26c2 100644 --- a/agency/README.md +++ b/agency/README.md @@ -128,11 +128,6 @@ Body Params: | ------------------- | ------------------------------- | ------------------------------- | | `bad_param` | A validation error occurred | Array of parameters with errors | | `missing_param` | A required parameter is missing | Array of missing parameters | -| `unregistered` | Vehicle is not registered | | -| `inactive` | Vehicle is not active | | -| `unavailable` | Vehicle is unavailable | | -| `no_active_trip` | No trip is active for Vehicle | | -| `trip_not_complete` | A trip is active for Vehicle | | ## Vehicles - Update Telemetry From 2f68c46f6488d86239281268568a7d21c305ed24 Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Fri, 22 Feb 2019 21:03:46 -0600 Subject: [PATCH 06/40] add PUT /vehicles/{device_id} also clean up some telemetry wording --- agency/README.md | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/agency/README.md b/agency/README.md index 7cfa44c2..c0b661d5 100644 --- a/agency/README.md +++ b/agency/README.md @@ -93,6 +93,34 @@ _No content returned on success._ | -------------------- | ------------------------------------------------- | ------------------------------- | | `already_registered` | A vehicle with `device_id` is already registered | | +## Vehicle - Update + +The `/vehicles` update endpoint is used to update some mutable aspect of a vehicle. For now, only `vehicle_id`. + +Endpoint: `/vehicles/{device_id}` +Method: `PUT` + +Body Params: + +| Field | Type | Required/Optional | Field Description | +| ------------ | ------- | ----------------- | -------------------------------------------------------------------- | +| `vehicle_id` | String | Required | Vehicle Identification Number (vehicle_id) visible on vehicle | + +201 Success Response: + +_No content returned on success._ + +400 Failure Response: + +| `error` | `error_description` | `error_details`[] | +| -------------------- | ------------------------------------------------- | ------------------------------- | +| `bad_param` | A validation error occurred. | Array of parameters with errors | +| `missing_param` | A required parameter is missing. | Array of missing parameters | + +404 Failure Response: + +_No content returned if no vehicle matching `device_id` is found._ + ## Vehicle - Event The vehicle `/event` endpoint allows the Provider to control the state of the vehicle including deregister a vehicle from the fleet. @@ -134,9 +162,9 @@ Body Params: | `no_active_trip` | No trip is active for Vehicle | | | `trip_not_complete` | A trip is active for Vehicle | | -## Vehicles - Update Telemetry +## Vehicles - Telemetry -The vehicle `/telemetry` endpoint allows a Provider to update vehicle telemetry data in batch for one or many of the vehicles in the fleet. Telemetry data will be reported to the API every 5 seconds while vehicles are in motion. +The vehicle `/telemetry` endpoint allows a Provider to send vehicle telemetry data in a batch for any number of vehicles in the fleet. Telemetry data will be reported to the API every 5 seconds for each vehicle in motion. Endpoint: `/vehicles/telemetry` Method: `POST` From 0e0baeb318b808190aae21bca3333880d0a72cb4 Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Mon, 25 Feb 2019 12:47:43 -0800 Subject: [PATCH 07/40] specify behavior for /vehicles with no device_id --- agency/README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/agency/README.md b/agency/README.md index 7cfa44c2..250d0630 100644 --- a/agency/README.md +++ b/agency/README.md @@ -3,7 +3,7 @@ This specification contains a collection of RESTful APIs used to specify the digital relationship between *mobility as a service* Providers and the Agencies that regulate them. * Authors: LADOT -* Date: 12 Feb 2019 +* Date: 25 Feb 2019 * Version: BETA ## Table of Contents @@ -30,7 +30,7 @@ As with the Provider API, `timestamp` refers to integer milliseconds since Unix ## Vehicles -The `/vehicles` endpoint returns the specified vehicle. Providers can only retrieve data for vehicles in their registered fleet. +The `/vehicles` endpoint returns the specified vehicle (if a device_id is provided) or a list of known vehicles. Providers can only retrieve data for vehicles in their registered fleet. Endpoint: `/vehicles/{device_id}` Method: `GET` @@ -41,8 +41,17 @@ Path Params: | ------------ | ---- | ----------------- | ------------------------------------------- | | `device_id` | UUID | Optional | If provided, retrieve the specified vehicle | +Query Params: + +| Param | Type | Required/Optional | Description | +| ------------ | ---- | ----------------- | ------------------------------------------- | +| `skip` | Integer | Optional | If provided, offset into list | +| `take` | Integer | Optional | If provided, number of vehicles to load | + 200 Success Response: +If `device_id` is specified, `GET` will return a single vehicle record, otherwise it will be a list of vehicle records. A vehicle record is as follows: + | Field | Type | Field Description | | ------------- | -------------- | ----------------------------------------------------------------------------- | | `device_id` | UUID | Provided by Operator to uniquely identify a vehicle | @@ -57,6 +66,10 @@ Path Params: | `prev_event` | Enum | Last [Vehicle Event](#vehicle-events) | | `updated` | Timestamp | Date of last event update | +404 Failure Response: + +_No content returned on vehicle not found._ + ## Vehicle - Register The `/vehicles` registration endpoint is used to register a vehicle for use in the Agency jurisdiction. From 05607e58abbd28b08109637383b8e9a71d910a4f Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Mon, 25 Feb 2019 13:51:32 -0800 Subject: [PATCH 08/40] add pagination stuff --- agency/README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/agency/README.md b/agency/README.md index 250d0630..7d1c2c60 100644 --- a/agency/README.md +++ b/agency/README.md @@ -50,7 +50,21 @@ Query Params: 200 Success Response: -If `device_id` is specified, `GET` will return a single vehicle record, otherwise it will be a list of vehicle records. A vehicle record is as follows: +If `device_id` is specified, `GET` will return a single vehicle record, otherwise it will be a list of vehicle records with pagination details per the [JSON API](https://jsonapi.org/format/#fetching-pagination) spec: + +``` +{ + "vehicles" [ ... ] + "links": { + "first": "https://...", + "last": "https://...", + "prev": "https://...", + "next": "https://..." + } +} +``` + +A vehicle record is as follows: | Field | Type | Field Description | | ------------- | -------------- | ----------------------------------------------------------------------------- | From 5e50570358713209776967184590f5937b92ed94 Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Mon, 25 Feb 2019 13:51:55 -0800 Subject: [PATCH 09/40] missing colon --- agency/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agency/README.md b/agency/README.md index 7d1c2c60..1ff2d2b7 100644 --- a/agency/README.md +++ b/agency/README.md @@ -54,7 +54,7 @@ If `device_id` is specified, `GET` will return a single vehicle record, otherwis ``` { - "vehicles" [ ... ] + "vehicles": [ ... ] "links": { "first": "https://...", "last": "https://...", From f93b05e4d524d5bae2c21501912965b96dcee0cc Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Mon, 25 Feb 2019 14:01:07 -0800 Subject: [PATCH 10/40] drop skip/take from spec, let anyone implement however they want --- agency/README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/agency/README.md b/agency/README.md index 1ff2d2b7..dabbf7e4 100644 --- a/agency/README.md +++ b/agency/README.md @@ -41,13 +41,6 @@ Path Params: | ------------ | ---- | ----------------- | ------------------------------------------- | | `device_id` | UUID | Optional | If provided, retrieve the specified vehicle | -Query Params: - -| Param | Type | Required/Optional | Description | -| ------------ | ---- | ----------------- | ------------------------------------------- | -| `skip` | Integer | Optional | If provided, offset into list | -| `take` | Integer | Optional | If provided, number of vehicles to load | - 200 Success Response: If `device_id` is specified, `GET` will return a single vehicle record, otherwise it will be a list of vehicle records with pagination details per the [JSON API](https://jsonapi.org/format/#fetching-pagination) spec: From 92b1e18ff5504818819cd9106698ccab661d02b4 Mon Sep 17 00:00:00 2001 From: Lionel Panhaleux Date: Fri, 22 Feb 2019 15:49:37 +0100 Subject: [PATCH 11/40] Relax telemetry constraints Depending on the actual device on board of the vehicle, some information can be unavailable. --- agency/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/agency/README.md b/agency/README.md index bdba3081..4bf4b2a9 100644 --- a/agency/README.md +++ b/agency/README.md @@ -223,12 +223,12 @@ A standard point of vehicle telemetry. References to latitude and longitude impl | `gps` | Object | Required | Telemetry position data | | `gps.lat` | Double | Required | Latitude of the location | | `gps.lng` | Double | Required | Longitude of the location | -| `gps.altitude` | Double | Required | Altitude above mean sea level in meters | -| `gps.heading` | Double | Required | Degrees - clockwise starting at 0 degrees at true North | -| `gps.speed` | Float | Required | Speed in meters / sec | -| `gps.hdop` | Float | Required | Horizontal GPS accuracy value (see [hdop](https://support.esri.com/en/other-resources/gis-dictionary/term/358112bd-b61c-4081-9679-4fca9e3eb926)) | -| `gps.satellites` | Integer | Required | Number of GPS satellites -| `charge` | Float | Require if Applicable | Percent battery charge of vehicle, expressed between 0 and 1 | +| `gps.altitude` | Double | Required if Available | Altitude above mean sea level in meters | +| `gps.heading` | Double | Required if Available | Degrees - clockwise starting at 0 degrees at true North | +| `gps.speed` | Float | Required if Available | Speed in meters / sec | +| `gps.hdop` | Float | Required if Available | Horizontal GPS accuracy value (see [hdop](https://support.esri.com/en/other-resources/gis-dictionary/term/358112bd-b61c-4081-9679-4fca9e3eb926)) | +| `gps.satellites` | Integer | Required if Available | Number of GPS satellites +| `charge` | Float | Required if Applicable | Percent battery charge of vehicle, expressed between 0 and 1 | ## Enum Definitions From f45cabca4ab871dc151a998c378cbc8333a8c2d7 Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Tue, 26 Feb 2019 09:44:16 -0800 Subject: [PATCH 12/40] Revert "Add new `battery_charged` event type reason" --- agency/README.md | 1 - generate_schema/provider/status_changes.json | 1 - provider/README.md | 1 - provider/status_changes.json | 3 +-- 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/agency/README.md b/agency/README.md index b3a4b47e..7cfa44c2 100644 --- a/agency/README.md +++ b/agency/README.md @@ -196,7 +196,6 @@ List of valid vehicle events and the resulting vehicle status if the event is su | `event_type` | description | valid initial `status` | `status` on success | status_description | | ---------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------- | ----------------------------------------------------------------------- | | `service_start` | Vehicle introduced into service at the beginning of the day (if program does not operate 24/7) | `unavailable`, `removed`, `elsewhere` | `available` | Vehicle is on the street and available for customer use. | -| `battery_charged` | A vehicle becomes available because its battery is charged enough | `unavailable` | `available` | | | `trip_end` | Customer ends trip and reservation | `trip` | `available` | | | `rebalance_drop_off` | Vehicle moved for rebalancing | `removed` | `available` | | | `maintenance_drop_off` | Vehicle introduced into service after being removed for maintenance | `removed` | `available` | | diff --git a/generate_schema/provider/status_changes.json b/generate_schema/provider/status_changes.json index ff839b05..ed66c489 100644 --- a/generate_schema/provider/status_changes.json +++ b/generate_schema/provider/status_changes.json @@ -120,7 +120,6 @@ }, "event_type_reason": { "enum": [ - "battery_charged", "service_start", "user_drop_off", "rebalance_drop_off", diff --git a/provider/README.md b/provider/README.md index 771684c6..7373c29f 100644 --- a/provider/README.md +++ b/provider/README.md @@ -292,7 +292,6 @@ When multiple query parameters are specified, they should all apply to the retur | `event_type` | Description | `event_type_reason` | Description | | ---------- | ---------------------- | ------- | ------------------ | | `available` | A device becomes available for customer use | `service_start` | Device introduced into service at the beginning of the day (if program does not operate 24/7) | -| | | `battery_charged` | A device becomes available because its battery is charged enough | | | | `user_drop_off` | User ends reservation | | | | `rebalance_drop_off` | Device moved for rebalancing | | | | `maintenance_drop_off` | Device introduced into service after being removed for maintenance | diff --git a/provider/status_changes.json b/provider/status_changes.json index 98464451..f38c78e0 100644 --- a/provider/status_changes.json +++ b/provider/status_changes.json @@ -311,7 +311,6 @@ }, "event_type_reason": { "enum": [ - "battery_charged", "service_start", "user_drop_off", "rebalance_drop_off", @@ -401,4 +400,4 @@ } }, "additionalProperties": false -} +} \ No newline at end of file From 1bde6682232e8c01b0eadfe7b7af69a449fe78a1 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Wed, 27 Feb 2019 17:22:03 -0800 Subject: [PATCH 13/40] updating schema version noting this missing step in ReleaseGuidelines --- ReleaseGuidelines.md | 3 +++ generate_schema/common.json | 4 ++-- provider/status_changes.json | 4 ++-- provider/trips.json | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index dd10214c..7a4887cf 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -70,6 +70,8 @@ The following steps **must** be followed for **every** release of MDS: 1. Ensure the [Milestone][mds-milestones] for this release is at `100%`. +1. Update the [schema version regex][mds-schema-common] + 1. Run the schema generator to ensure the schema files are up to date: ```console @@ -153,5 +155,6 @@ The following steps **must** be followed for **every** release of MDS: [mds-pr-new]: https://github.com/CityOfLosAngeles/mobility-data-specification/compare [mds-releases]: https://github.com/CityOfLosAngeles/mobility-data-specification/releases [mds-releases-new]: https://github.com/CityOfLosAngeles/mobility-data-specification/releases/new +[mds-schema-common]: https://github.com/CityOfLosAngeles/mobility-data-specification/blob/master/generate_schema/common.json [mds-tags]: https://github.com/CityOfLosAngeles/mobility-data-specification/tags [semver]: https://semver.org/ \ No newline at end of file diff --git a/generate_schema/common.json b/generate_schema/common.json index a2640f5a..956a9e45 100644 --- a/generate_schema/common.json +++ b/generate_schema/common.json @@ -9,9 +9,9 @@ "type": "string", "title": "The MDS Provider version this data represents", "examples": [ - "0.2.0" + "0.3.0" ], - "pattern": "^0\\.2\\.[0-9]+$" + "pattern": "^0\\.3\\.[0-9]+$" }, "uuid": { "$id": "#/definitions/uuid", diff --git a/provider/status_changes.json b/provider/status_changes.json index f38c78e0..167c42bf 100644 --- a/provider/status_changes.json +++ b/provider/status_changes.json @@ -169,9 +169,9 @@ "type": "string", "title": "The MDS Provider version this data represents", "examples": [ - "0.2.0" + "0.3.0" ], - "pattern": "^0\\.2\\.[0-9]+$" + "pattern": "^0\\.3\\.[0-9]+$" }, "uuid": { "$id": "#/definitions/uuid", diff --git a/provider/trips.json b/provider/trips.json index 60559901..3f5d9b5d 100644 --- a/provider/trips.json +++ b/provider/trips.json @@ -200,9 +200,9 @@ "type": "string", "title": "The MDS Provider version this data represents", "examples": [ - "0.2.0" + "0.3.0" ], - "pattern": "^0\\.2\\.[0-9]+$" + "pattern": "^0\\.3\\.[0-9]+$" }, "uuid": { "$id": "#/definitions/uuid", From 890c2553a297e91db309946d709ca3f53271e843 Mon Sep 17 00:00:00 2001 From: Morgan Herlocker Date: Thu, 28 Feb 2019 17:29:21 -0800 Subject: [PATCH 14/40] Fix broken link to Feb 7 webinar presentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0abd8051..30026a21 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The specification will be versioned using Git tags and [semantic versioning](htt The City of Los Angeles is currently looking for feedback and comments on the draft versions. Comments can be made by making an Github Issue, while suggested changes can be made using a pull request. The rules and guidelines for the Los Angeles Dockless Bikeshare Systems / Pilot Program can be found on [Council Clerk Connect](https://cityclerk.lacity.org/lacityclerkconnect/index.cfm?fa=ccfi.viewrecord&cfnumber=17-1125). -*2/12/2019 Update*: City of Los Angeles One Year Permit Application MDS Agency Compliance: LADOT is seeking compliance with MDS Agency as a requirement of the one-year permit, and hosted a webinar on Thursday, February 7th to give an overview of the MDS Agency sandbox, discuss and answer questions about integration and timeline for Agency services. The slides from the webinar presentation can be found [here](https://ladot.lacity.org/sites/g/files/wph2 +*2/12/2019 Update*: City of Los Angeles One Year Permit Application MDS Agency Compliance: LADOT is seeking compliance with MDS Agency as a requirement of the one-year permit, and hosted a webinar on Thursday, February 7th to give an overview of the MDS Agency sandbox, discuss and answer questions about integration and timeline for Agency services. The slides from the webinar presentation can be found [here](https://ladot.lacity.org/sites/g/files/wph266/f/MDS%20Developer%20Webinar%20-%20One%20Year%20Permitting%20Overview.pdf) *12/27/2018 Update*: Applications for the One-Year Dockless On-Demand Personal Mobility Permit are now available on the [LADOT Website](https://ladot.lacity.org/ladot-begins-one-year-dockless-demand-personal-mobility-program) From 50c182224dba15eb307feb7db27ccc7d914439c0 Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Fri, 1 Mar 2019 11:13:58 -0800 Subject: [PATCH 15/40] put "unregistered" back as a reason to reject an event --- agency/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/agency/README.md b/agency/README.md index a39a92ea..8a1d52e8 100644 --- a/agency/README.md +++ b/agency/README.md @@ -176,6 +176,7 @@ Body Params: | ------------------- | ------------------------------- | ------------------------------- | | `bad_param` | A validation error occurred | Array of parameters with errors | | `missing_param` | A required parameter is missing | Array of missing parameters | +| `unregistered` | Vehicle is not registered | | ## Vehicles - Telemetry From 862af56159c3b59de5d5142b947f3bd65f1c8f5d Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Fri, 1 Mar 2019 11:30:41 -0800 Subject: [PATCH 16/40] Create temp --- agency/images/temp | 1 + 1 file changed, 1 insertion(+) create mode 100644 agency/images/temp diff --git a/agency/images/temp b/agency/images/temp new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/agency/images/temp @@ -0,0 +1 @@ + From b6b62bd970dc9c48c8d532447ef823f33804f34b Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Fri, 1 Mar 2019 11:32:15 -0800 Subject: [PATCH 17/40] Adding event-state diagram image --- agency/images/MDS_agency_event_state.png | Bin 0 -> 90205 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 agency/images/MDS_agency_event_state.png diff --git a/agency/images/MDS_agency_event_state.png b/agency/images/MDS_agency_event_state.png new file mode 100644 index 0000000000000000000000000000000000000000..d5aeb0194e8a51d4ff051493c7aea6e63edc48fb GIT binary patch literal 90205 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 VZ?BW)FWEZsnhx?xsn(6V{{@*(v-AJ} literal 0 HcmV?d00001 From 7dcee6ad9f6e28ea85d7cecb706aa669f5754250 Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Fri, 1 Mar 2019 11:41:40 -0800 Subject: [PATCH 18/40] Delete temp --- agency/images/temp | 1 - 1 file changed, 1 deletion(-) delete mode 100644 agency/images/temp diff --git a/agency/images/temp b/agency/images/temp deleted file mode 100644 index 8b137891..00000000 --- a/agency/images/temp +++ /dev/null @@ -1 +0,0 @@ - From 0aa06456fd13aaa22158bb46ecc6c36b5b1f2c99 Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Fri, 1 Mar 2019 11:45:22 -0800 Subject: [PATCH 19/40] Updating the event state diagram and event_reason Fixing a number of inconsistencies in the state diagram and adding a graphical representation. Also, adding event_reason to separate the more granual event designators. --- agency/README.md | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/agency/README.md b/agency/README.md index 174212a2..49be1190 100644 --- a/agency/README.md +++ b/agency/README.md @@ -159,7 +159,8 @@ Body Params: | Field | Type | Required/Optional | Field Description | | ----------- | ---------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | `event_type` | Enum | Required | [Vehicle Event](#vehicle-events) | -| `timestamp` | Timestamp | Required |Date of last event update | +| `event_reason` | Enum | Required if Available | [Vehicle Event](#vehicle-events) | +| `timestamp` | Timestamp | Required | Date of last event update | | `telemetry` | [Telemetry](#telemetry-data) | Required | Single point of telemetry | | `trip_id` | UUID | Optional | UUID provided by Operator to uniquely identify the trip. Required for `trip_start`, `trip_end`, `trip_enter`, and `trip_leave` event types | @@ -241,24 +242,24 @@ Query Params: List of valid vehicle events and the resulting vehicle status if the event is sucessful. -| `event_type` | description | valid initial `status` | `status` on success | status_description | -| ---------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------- | ----------------------------------------------------------------------- | -| `service_start` | Vehicle introduced into service at the beginning of the day (if program does not operate 24/7) | `unavailable`, `removed`, `elsewhere` | `available` | Vehicle is on the street and available for customer use. | -| `trip_end` | Customer ends trip and reservation | `trip` | `available` | | -| `rebalance_drop_off` | Vehicle moved for rebalancing | `removed` | `available` | | -| `maintenance_drop_off` | Vehicle introduced into service after being removed for maintenance | `removed` | `available` | | -| `cancel_reservation` | Customer cancels reservation | `reserved` | `available` | | -| `reserve` | Customer reserves vehicle | `available` | `reserved` | Vehicle is reserved or in use. | -| `trip_start` | Customer starts a trip | `available`, `reserved` | `trip` | | -| `trip_enter` | Customer enters a service area managed by agency during an active trip. | `unavailable`, `removed`, `elsewhere` | `trip` | | -| `trip_leave` | Customer enters a service area managed by agency during an active trip. | `trip` | `elsewhere` | | -| `register` | Default state for a newly registered vehicle | `inactive` | `unavailable` | A vehicle is in the active fleet but not yet available for customer use | -| `low_battery` | A vehicle is no longer available due to insufficient battery | `available` | `unavailable` | | -| `maintenance` | A vehicle is no longer available due to equipment issues | `available`, `reserved` | `unavailable` | | -| `service_end` | Vehicle removed from street because service has ended for the day (if program does not operate 24/7) | `available`, `unavailable`, `elsewhere` | `removed` | A vehicle is removed from the street and unavailable for customer use. | -| `rebalance_pick_up` | Vehicle removed from street and will be placed at another location to rebalance service | `available`, `unavailable` | `removed` | | -| `maintenance_pick_up` | Vehicle removed from street so it can be worked on | `available`, `unavailable` | `removed` | | -| `deregister` | A vehicle is deregistered | `available`, `unavailable`, `removed`, `elsewhere` | `inactive` | A vehicle is deactivated from the fleet and unavailable. | +| `event_type` | `event_reason` | description | valid initial `status` | `status` on success | status_description | +| -------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------- | ----------------------------------------------------------------------- | +| `service_start` | | Vehicle introduced into service at the beginning of the day (if program does not operate 24/7) | `unavailable` | `available` | Vehicle is on the street and available for customer use. | +| `trip_end` | | Customer ends trip and reservation | `trip` | `available` | | +| `provider_drop_off` | | Vehicle moved for rebalancing | `removed`, `elsewhere` | `available` | | +| `cancel_reservation` | | Customer cancels reservation | `reserved` | `available` | | +| `reserve` | | Customer reserves vehicle | `available` | `reserved` | Vehicle is reserved or in use. | +| `trip_start` | | Customer starts a trip | `available`, `reserved` | `trip` | | +| `trip_enter` | | Customer enters a service area managed by agency during an active trip. | `removed`, `elsewhere` | `trip` | | +| `trip_leave` | | Customer enters a service area managed by agency during an active trip. | `trip` | `elsewhere` | | +| `register` | | Default state for a newly registered vehicle | `inactive` | `removed` | A vehicle is in the active fleet but not yet available for customer use | +| `service_end` | `low_battery`, `maintenance`, `compliance`, `off_hours` | A vehicle is no longer available due to `event_reason` | `available` | `unavailable` | | +| `provider_pick_up` | `rebalance`, `maintenance`, `charge`, `compliance` | Vehicle removed from street and will be placed at another location to rebalance service | `available`, `unavailable`, `elsewhere` | `removed` | | +| `city_pick_up` | | Vehicle removed by city | `available`, `unavailable` | `removed` | | +| `deregister` | `missing` | A vehicle is deregistered | `available`, `unavailable`, `removed`, `elsewhere` | `inactive` | A vehicle is deactivated from the fleet. | + + +![Event State Diagram](images/MDS_agency_event_state.png?raw=true "MDS Event State Diagram") ## Telemetry Data From 58e7acc0bbf2921eb34ce7046d4093283efa9a37 Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Fri, 1 Mar 2019 11:48:35 -0800 Subject: [PATCH 20/40] Fixed description wording --- agency/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agency/README.md b/agency/README.md index 49be1190..45876c76 100644 --- a/agency/README.md +++ b/agency/README.md @@ -158,8 +158,8 @@ Body Params: | Field | Type | Required/Optional | Field Description | | ----------- | ---------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -| `event_type` | Enum | Required | [Vehicle Event](#vehicle-events) | -| `event_reason` | Enum | Required if Available | [Vehicle Event](#vehicle-events) | +| `event_type` | Enum | Required | see [Vehicle Events](#vehicle-events) | +| `event_reason` | Enum | Required if Available | see [Vehicle Events](#vehicle-events) | | `timestamp` | Timestamp | Required | Date of last event update | | `telemetry` | [Telemetry](#telemetry-data) | Required | Single point of telemetry | | `trip_id` | UUID | Optional | UUID provided by Operator to uniquely identify the trip. Required for `trip_start`, `trip_end`, `trip_enter`, and `trip_leave` event types | From 088a8d053047e6b92e2fe0ce6dc77b2a1604898b Mon Sep 17 00:00:00 2001 From: Mark Maxham Date: Fri, 1 Mar 2019 11:54:36 -0800 Subject: [PATCH 21/40] slight tweak to clarify that the state machine is not currently enforced due to desire to handle out-of-order events --- agency/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agency/README.md b/agency/README.md index 8a1d52e8..f71a2c79 100644 --- a/agency/README.md +++ b/agency/README.md @@ -235,7 +235,7 @@ Query Params: ## Vehicle Events -List of valid vehicle events and the resulting vehicle status if the event is sucessful. +List of valid vehicle events and the resulting vehicle status if the event is sucessful. Note that to handle out-of-order events, the validity of the initial-status is not enforced. Events received out-of-order may result in transient incorrect vehicle states. | `event_type` | description | valid initial `status` | `status` on success | status_description | | ---------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------- | ----------------------------------------------------------------------- | From 0f4ae9315199bd6544701d0e18b886c70172ee2f Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Fri, 1 Mar 2019 16:30:18 -0800 Subject: [PATCH 22/40] Reordering events list --- agency/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/agency/README.md b/agency/README.md index 45876c76..ce9b68de 100644 --- a/agency/README.md +++ b/agency/README.md @@ -244,18 +244,18 @@ List of valid vehicle events and the resulting vehicle status if the event is su | `event_type` | `event_reason` | description | valid initial `status` | `status` on success | status_description | | -------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------- | ----------------------------------------------------------------------- | +| `register` | | Default state for a newly registered vehicle | `inactive` | `removed` | A vehicle is in the active fleet but not yet available for customer use | | `service_start` | | Vehicle introduced into service at the beginning of the day (if program does not operate 24/7) | `unavailable` | `available` | Vehicle is on the street and available for customer use. | -| `trip_end` | | Customer ends trip and reservation | `trip` | `available` | | +| `service_end` | `low_battery`, `maintenance`, `compliance`, `off_hours` | A vehicle is no longer available due to `event_reason` | `available` | `unavailable` | | | `provider_drop_off` | | Vehicle moved for rebalancing | `removed`, `elsewhere` | `available` | | -| `cancel_reservation` | | Customer cancels reservation | `reserved` | `available` | | +| `provider_pick_up` | `rebalance`, `maintenance`, `charge`, `compliance` | Vehicle removed from street and will be placed at another location to rebalance service | `available`, `unavailable`, `elsewhere` | `removed` | | +| `city_pick_up` | | Vehicle removed by city | `available`, `unavailable` | `removed` | | | `reserve` | | Customer reserves vehicle | `available` | `reserved` | Vehicle is reserved or in use. | +| `cancel_reservation` | | Customer cancels reservation | `reserved` | `available` | | | `trip_start` | | Customer starts a trip | `available`, `reserved` | `trip` | | | `trip_enter` | | Customer enters a service area managed by agency during an active trip. | `removed`, `elsewhere` | `trip` | | | `trip_leave` | | Customer enters a service area managed by agency during an active trip. | `trip` | `elsewhere` | | -| `register` | | Default state for a newly registered vehicle | `inactive` | `removed` | A vehicle is in the active fleet but not yet available for customer use | -| `service_end` | `low_battery`, `maintenance`, `compliance`, `off_hours` | A vehicle is no longer available due to `event_reason` | `available` | `unavailable` | | -| `provider_pick_up` | `rebalance`, `maintenance`, `charge`, `compliance` | Vehicle removed from street and will be placed at another location to rebalance service | `available`, `unavailable`, `elsewhere` | `removed` | | -| `city_pick_up` | | Vehicle removed by city | `available`, `unavailable` | `removed` | | +| `trip_end` | | Customer ends trip and reservation | `trip` | `available` | | | `deregister` | `missing` | A vehicle is deregistered | `available`, `unavailable`, `removed`, `elsewhere` | `inactive` | A vehicle is deactivated from the fleet. | From 65bb3eeeac1d2386b03a8a4e8ec2b7fc9a3eb1b3 Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Mon, 4 Mar 2019 10:58:34 -0800 Subject: [PATCH 23/40] Change event_reason to event_type_reason Consistency with Provider API --- agency/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agency/README.md b/agency/README.md index ce9b68de..b23de8dd 100644 --- a/agency/README.md +++ b/agency/README.md @@ -159,7 +159,7 @@ Body Params: | Field | Type | Required/Optional | Field Description | | ----------- | ---------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | `event_type` | Enum | Required | see [Vehicle Events](#vehicle-events) | -| `event_reason` | Enum | Required if Available | see [Vehicle Events](#vehicle-events) | +| `event_type_reason` | Enum | Required if Available | see [Vehicle Events](#vehicle-events) | | `timestamp` | Timestamp | Required | Date of last event update | | `telemetry` | [Telemetry](#telemetry-data) | Required | Single point of telemetry | | `trip_id` | UUID | Optional | UUID provided by Operator to uniquely identify the trip. Required for `trip_start`, `trip_end`, `trip_enter`, and `trip_leave` event types | @@ -242,11 +242,11 @@ Query Params: List of valid vehicle events and the resulting vehicle status if the event is sucessful. -| `event_type` | `event_reason` | description | valid initial `status` | `status` on success | status_description | +| `event_type` | `event_type_reason` | description | valid initial `status` | `status` on success | status_description | | -------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------- | ----------------------------------------------------------------------- | | `register` | | Default state for a newly registered vehicle | `inactive` | `removed` | A vehicle is in the active fleet but not yet available for customer use | | `service_start` | | Vehicle introduced into service at the beginning of the day (if program does not operate 24/7) | `unavailable` | `available` | Vehicle is on the street and available for customer use. | -| `service_end` | `low_battery`, `maintenance`, `compliance`, `off_hours` | A vehicle is no longer available due to `event_reason` | `available` | `unavailable` | | +| `service_end` | `low_battery`, `maintenance`, `compliance`, `off_hours` | A vehicle is no longer available due to `event_type_reason` | `available` | `unavailable` | | | `provider_drop_off` | | Vehicle moved for rebalancing | `removed`, `elsewhere` | `available` | | | `provider_pick_up` | `rebalance`, `maintenance`, `charge`, `compliance` | Vehicle removed from street and will be placed at another location to rebalance service | `available`, `unavailable`, `elsewhere` | `removed` | | | `city_pick_up` | | Vehicle removed by city | `available`, `unavailable` | `removed` | | From f4f45bec804a67d19f9b3204c575361ecf7859e2 Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Mon, 4 Mar 2019 13:48:46 -0800 Subject: [PATCH 24/40] Updating event diagram description --- agency/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agency/README.md b/agency/README.md index b23de8dd..1bf5d8ad 100644 --- a/agency/README.md +++ b/agency/README.md @@ -258,7 +258,7 @@ List of valid vehicle events and the resulting vehicle status if the event is su | `trip_end` | | Customer ends trip and reservation | `trip` | `available` | | | `deregister` | `missing` | A vehicle is deregistered | `available`, `unavailable`, `removed`, `elsewhere` | `inactive` | A vehicle is deactivated from the fleet. | - +The diagram below shows the expected events and related `status` transitions for a vehicle: ![Event State Diagram](images/MDS_agency_event_state.png?raw=true "MDS Event State Diagram") ## Telemetry Data From 0b2262c2d04b1e90c531d08dd8c0aa6833bef992 Mon Sep 17 00:00:00 2001 From: Sean Holman Date: Mon, 4 Mar 2019 13:57:04 -0800 Subject: [PATCH 25/40] Fixing description around enter/leave --- agency/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agency/README.md b/agency/README.md index 1bf5d8ad..2d56efa8 100644 --- a/agency/README.md +++ b/agency/README.md @@ -253,8 +253,8 @@ List of valid vehicle events and the resulting vehicle status if the event is su | `reserve` | | Customer reserves vehicle | `available` | `reserved` | Vehicle is reserved or in use. | | `cancel_reservation` | | Customer cancels reservation | `reserved` | `available` | | | `trip_start` | | Customer starts a trip | `available`, `reserved` | `trip` | | -| `trip_enter` | | Customer enters a service area managed by agency during an active trip. | `removed`, `elsewhere` | `trip` | | -| `trip_leave` | | Customer enters a service area managed by agency during an active trip. | `trip` | `elsewhere` | | +| `trip_enter` | | Customer enters the municipal area managed by agency during an active trip. | `removed`, `elsewhere` | `trip` | | +| `trip_leave` | | Customer leaves the municipal area managed by agency during an active trip. | `trip` | `elsewhere` | | | `trip_end` | | Customer ends trip and reservation | `trip` | `available` | | | `deregister` | `missing` | A vehicle is deregistered | `available`, `unavailable`, `removed`, `elsewhere` | `inactive` | A vehicle is deactivated from the fleet. | From c4ac9518ab40ab21f88017ef185e140f8b930606 Mon Sep 17 00:00:00 2001 From: Damien Baty Date: Mon, 4 Feb 2019 11:20:39 +0100 Subject: [PATCH 26/40] Add provider: BlueLA --- providers.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/providers.csv b/providers.csv index 242f87b0..7753b828 100644 --- a/providers.csv +++ b/providers.csv @@ -11,3 +11,4 @@ Spin,70aa475d-1fcd-4504-b69c-2eeb2107f7be,https://www.spin.app,https://api.spin. WIND,d56d2df6-fa92-43de-ab61-92c3a84acd7d,https://www.wind.co,https://partners.wind.co/v1/mds, Tier,264aad41-b47c-415d-8585-0208d436516e,https://www.tier.app,https://partner.tier-services.io/mds, Cloud,bf95148b-d1d1-464e-a140-6d2563ac43d4,https://www.cloud.tt,https://mds.cloud.tt,https://mds.cloud.tt/gbfs +BlueLA,f3c5a65d-fd85-463e-9564-fc95ea473f7d,https://www.bluela.com,https://api.bluela.com/mds/v0,https://api.bluela.com/gbfs/v1/meta From baece96e2e4078f2635e20abb7e597d3163bfdda Mon Sep 17 00:00:00 2001 From: Chris Raastad Date: Thu, 14 Mar 2019 17:17:47 -0400 Subject: [PATCH 27/40] Added Bolt to list of MDS providers https://www.micromobility.com/ --- providers.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/providers.csv b/providers.csv index 7753b828..c15ba91a 100644 --- a/providers.csv +++ b/providers.csv @@ -12,3 +12,4 @@ WIND,d56d2df6-fa92-43de-ab61-92c3a84acd7d,https://www.wind.co,https://partners.w Tier,264aad41-b47c-415d-8585-0208d436516e,https://www.tier.app,https://partner.tier-services.io/mds, Cloud,bf95148b-d1d1-464e-a140-6d2563ac43d4,https://www.cloud.tt,https://mds.cloud.tt,https://mds.cloud.tt/gbfs BlueLA,f3c5a65d-fd85-463e-9564-fc95ea473f7d,https://www.bluela.com,https://api.bluela.com/mds/v0,https://api.bluela.com/gbfs/v1/meta +Bolt,3291c288-c9c8-42f1-bc3e-8502b077cd7f,https://www.micromobility.com/,https://bolt.miami/bolt2/api/mds From eb7d30b0d209b7fa7d09752543efc88cb5420ac3 Mon Sep 17 00:00:00 2001 From: Hunter Owens Date: Thu, 14 Mar 2019 15:16:00 -0700 Subject: [PATCH 28/40] CSV rendering fix. --- providers.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/providers.csv b/providers.csv index c15ba91a..b970af0f 100644 --- a/providers.csv +++ b/providers.csv @@ -12,4 +12,4 @@ WIND,d56d2df6-fa92-43de-ab61-92c3a84acd7d,https://www.wind.co,https://partners.w Tier,264aad41-b47c-415d-8585-0208d436516e,https://www.tier.app,https://partner.tier-services.io/mds, Cloud,bf95148b-d1d1-464e-a140-6d2563ac43d4,https://www.cloud.tt,https://mds.cloud.tt,https://mds.cloud.tt/gbfs BlueLA,f3c5a65d-fd85-463e-9564-fc95ea473f7d,https://www.bluela.com,https://api.bluela.com/mds/v0,https://api.bluela.com/gbfs/v1/meta -Bolt,3291c288-c9c8-42f1-bc3e-8502b077cd7f,https://www.micromobility.com/,https://bolt.miami/bolt2/api/mds +Bolt,3291c288-c9c8-42f1-bc3e-8502b077cd7f,https://www.micromobility.com/,https://bolt.miami/bolt2/api/mds, From e5077201a5dda24dbd410e0b554837ab6c3c5cb5 Mon Sep 17 00:00:00 2001 From: avigmati Date: Sat, 16 Mar 2019 01:33:33 +0700 Subject: [PATCH 29/40] Update providers.csv --- providers.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/providers.csv b/providers.csv index b970af0f..573d8311 100644 --- a/providers.csv +++ b/providers.csv @@ -13,3 +13,4 @@ Tier,264aad41-b47c-415d-8585-0208d436516e,https://www.tier.app,https://partner.t Cloud,bf95148b-d1d1-464e-a140-6d2563ac43d4,https://www.cloud.tt,https://mds.cloud.tt,https://mds.cloud.tt/gbfs BlueLA,f3c5a65d-fd85-463e-9564-fc95ea473f7d,https://www.bluela.com,https://api.bluela.com/mds/v0,https://api.bluela.com/gbfs/v1/meta Bolt,3291c288-c9c8-42f1-bc3e-8502b077cd7f,https://www.micromobility.com/,https://bolt.miami/bolt2/api/mds, +CLEVR,daecbe87-a9f2-4a5a-b5df-8e3e14180513,https://clevrmobility.com,https://portal.clevrmobility.com/api/la/,https://portal.clevrmobility.com/api/gbfs/en/discovery/ From 8d6f67760fc22ce0c66fb03e891a20fadb45a027 Mon Sep 17 00:00:00 2001 From: Jascha Franklin-Hodge Date: Tue, 12 Mar 2019 12:15:07 -0400 Subject: [PATCH 30/40] Initial edits to reflect new release process --- CONTRIBUTING.md | 32 ++++++++++++++++++++ ReleaseGuidelines.md | 71 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..6dcb4b69 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,32 @@ +# MDS Contributor Guidelines +MDS is an evolving specification with a regular release cycle. Please review the [MDS Release Guidelines](ReleaseGuidelines.md) to understand the release process. + +## Who can contribute +MDS is an open specification and anyone can contribute to its development. Because MDS supports a growing ecosystem of mobility services, policies, and tools, there are some key stakeholders whose participation is particularly encouraged: + +* **Public agencies:** As licensing authority and regulator, public agencies are the ultimate customers for MDS and the data flowing through it. The public agency role is to ensure that MDS effectively supports program management and offers a flexible foundation for policy implementation. Public agencies of all levels of technical capacity are encourage to participate in the evolution of MDS, whether by submitting pull requests and issues, or simply by providing feedback during release cycles. + +* **Mobility Service Providers:** Providers are often required to implement MDS in order to comply with permitting requirements for their services. Providers can inform the development of MDS with real-world operating experience and to offer input on specification design that maximizes data quality, reliability, and utility. + +* **Public agency software partners:** Serve as a key bridge between public agencies and mobility service providers by offering tools that turn MDS data into useful insights. The public agency software partners help ensure that MDS will enable real-world product development, reflects the needs of their public agency customers, and encourages private investment in the MDS ecosystem. + +## How to contribute +Contributions should be offered through GitHub issues and pull requests. Please review the [MDS Release Guidelines](ReleaseGuidelines.md) for details on the release process, schedule, and communications channels. + +In general, you may open an issue or make a pull request at any time. Once the issue or pull request is associated with a particular Milestone, it will be included for review within the process for that release. + +[NEED SOME CONTENT FOR WHAT MAKES A GOOD PULL REQUEST] + +## What belongs in MDS +MDS is a tool to facilitate data exchange between mobility service providers, public agencies, and public agency software partners. Although providers are often required to support MDS as part of mobility permits or policies, MDS is intended as a neutral mechanism for information exchange. It is not intended to force or foreclose any specific policy options that a public agency may choose to pursue. + +## Code of Conduct +To encourage participation by any and all interested people, we aim to create an open and welcoming environment for contributors. We pledge to make participation in this project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +**Examples of behavior that contributes to creating a positive environment include:** + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index 7a4887cf..e02412e8 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -1,12 +1,16 @@ # MDS Release Guidelines -MDS will see periodic updates and new [releases][mds-releases] from time to time. This document describes the general guidelines around how and when a new release is cut. +MDS will see regular updates and new [releases][mds-releases]. This document describes the general guidelines around how and when a new release is cut. ## Table of Contents * [Versioning](#versioning) * [Branch Mechanics](#branch-mechanics) -* [Schedule](#schedule) +* [Release Process](#process) + * [Goals](#goals) + * [Roles](#roles) + * [Schedule](#schedule) + * [Communication and Workflow](#communication-and-workflow) * [Checklist](#release-checklist) ## Versioning @@ -19,7 +23,7 @@ Given that MDS is stabilizing under MAJOR version `0.x` right now, it should be At this early stage, MDS will be moving relatively quickly with an eye toward stabilization rather than backwards-compatibility. -For now, MDS will maintain *two concurrent (MINOR) versions* (e.g. if `0.3.0` were the current verison, the `0.2.x` series would continue to receive maintenace in addition to `0.3.x`). +For now, MDS will maintain *two concurrent (MINOR) versions* (e.g. if `0.3.0` were the current version, the `0.2.x` series would continue to receive maintenance in addition to `0.3.x`). ## Branch Mechanics @@ -47,22 +51,63 @@ When a PATCH release is ready (e.g. `0.2.0` to `0.2.1`), the release branch (e.g As stated earlier, at this time MDS will maintain *two concurrent MINOR versions*. This means that when a MINOR release is made (e.g. `0.4.0`), work on the outgoing series (`0.2.x`, in this case) ceases and its release branch is removed. -## Schedule +## Release Process +The sections below define the release process itself, including timeline, roles, and communication best practices. -MDS does not currently define a set release cadence or schedule. That being said, a MDS -release should not surprise anyone that wishes to be informed. To that end, releases will always: +### Goals -* Categorize issues and PRs under an associated [Milestone][mds-milestones] +* _Fast, regular releases to support rapid evolution of MDS_ -* Assign a due date for said Milestone that is *at least 24 hours ahead of planned release* +* _Consensus-oriented with clear decision making process when consensus can't be reached_ -* Include a summary of the major changes / impacts associated with the release, if any +* _Encourage involvement from all stakeholders, especially public agencies_ -* Be PR-driven, to give the community ample awareness and time for feedback +* _Frequent stakeholder communication on GitHub, web conference, and in-person_ -* Be announced on the [`mds-announce`][mds-announce] Google Group +* _Regular review of release process to ensure it is serving the needs of the community._ -More detail on this can be read in the Release Checklist below. + +### Roles +* **contributors** - Anyone making pull requests, opening issues, or engaging in technical discussion around implementation of features. +* **maintainers** - Project maintainers have commit privileges in the main MDS repository and are responsible for implementing changes such as merging of pull requests and the creation of release branches. +* **release partner** - Review changes when consensus cannot be reached and make final release inclusion recommendations to maintainers for approval. + +As of March 2019, LADOT and the City of Santa Monica are the project maintainers and Remix is the release partner. + +### Schedule + +MDS operates on a six-week release cycle for both major updates (0.x) and patches (0.x.y). In general, major updates (0.x) are expected no more than once per quarter. The release cycle is broken down as follows: + +** week 1 - proposals ** + +Contributors submit proposals for inclusion in the release cycle in the form of pull requests and issues tagged with the Milestone for the upcoming release [Q: DOES THIS MAKE SENSE AS A PROCESS TO CORRAL ALL THE ISSUES TO BE CONSIDERED IN A RELEASE?]. Proposals should come with enough explanation to allow all stakeholders to understand intent and implementation strategy. | + +** weeks 2-4 - discussion, refinement, and implementation ** + +Contributors will provide feedback on proposals. Where possible, discussion will happen via GitHub. Weekly calls will support dialog around more complex or controversial issues. By the end of week 4, all active proposals must be in the form of a pull request. Proposals can be withdrawn or split apart for inclusion in future releases. + +** week 5 - consensus building and decision making ** + +The week will start with an in-person/web conference work session for all contributors to review and discuss current proposals. Goal is to achieve consensus where possible, or to clearly articulate areas of disagreement where not. Minor changes may be accepted at this stage if they bring contributors to consensus. + +At the conclusion of week 5, release partner will review all items for which consensus was not reached and provide a recommended release plan to maintainers for approval. Any remaining approved pull requests to `dev` are merged. + +** week 6 - release ** + +​Changes will be merged into `master`, documentation will be updated, a release branch will be created, and new version will be formally released. + +### Communication and Workflow +The release annoncements and process schedule will be communicated via [`mds-announce`][mds-announce] Google Group. People wishing to stay informed should join the group for updates. Timing of web conference and in person work sessions will be communicated via mds-announce as well. + +The following best practices are intended to create clarity around each release cycle: + +* Categorize issues and PRs under an associated [Milestone][mds-milestones] for the release + +* Assign a due date for said Milestone that aligns with the end of the proposal period for the release cycle (week 1) + +* Include a summary of the major changes / impacts associated with the release + +* Proposed changes should come in the form of PRs to give the community ample awareness and time for feedback ## Release Checklist @@ -157,4 +202,4 @@ The following steps **must** be followed for **every** release of MDS: [mds-releases-new]: https://github.com/CityOfLosAngeles/mobility-data-specification/releases/new [mds-schema-common]: https://github.com/CityOfLosAngeles/mobility-data-specification/blob/master/generate_schema/common.json [mds-tags]: https://github.com/CityOfLosAngeles/mobility-data-specification/tags -[semver]: https://semver.org/ \ No newline at end of file +[semver]: https://semver.org/ From 5215f6d113bf003c991a7531e937fcca1505c00f Mon Sep 17 00:00:00 2001 From: Jascha Franklin-Hodge Date: Tue, 12 Mar 2019 11:53:47 -0700 Subject: [PATCH 31/40] Update ReleaseGuidelines.md Updated to reflect that the process applies only to provider for now. --- ReleaseGuidelines.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index e02412e8..9a6667cd 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -54,6 +54,8 @@ As stated earlier, at this time MDS will maintain *two concurrent MINOR versions ## Release Process The sections below define the release process itself, including timeline, roles, and communication best practices. +> ** The process defined below currently being piloted with the MDS `provider` API only. Proposed changes to the `agency` API will be continue to be reviewed on an ad hoc basis. ** + ### Goals * _Fast, regular releases to support rapid evolution of MDS_ From 60fd312363690f20cfd1c0e04999a2a6e0e0d61e Mon Sep 17 00:00:00 2001 From: Jascha Franklin-Hodge Date: Tue, 12 Mar 2019 11:55:35 -0700 Subject: [PATCH 32/40] Update ReleaseGuidelines.md Clarified language around release notes and change descriptions. --- ReleaseGuidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index 9a6667cd..7689aac4 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -107,7 +107,7 @@ The following best practices are intended to create clarity around each release * Assign a due date for said Milestone that aligns with the end of the proposal period for the release cycle (week 1) -* Include a summary of the major changes / impacts associated with the release +* Pull requests and release notes should include a summary of the major changes / impacts associated with the change or release * Proposed changes should come in the form of PRs to give the community ample awareness and time for feedback From 5c952210b31df6330d78d01be0961ed207ecdc27 Mon Sep 17 00:00:00 2001 From: Jascha Franklin-Hodge Date: Tue, 12 Mar 2019 12:08:55 -0700 Subject: [PATCH 33/40] Formating and minor language tweaks. --- ReleaseGuidelines.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index 7689aac4..6d511125 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -54,7 +54,7 @@ As stated earlier, at this time MDS will maintain *two concurrent MINOR versions ## Release Process The sections below define the release process itself, including timeline, roles, and communication best practices. -> ** The process defined below currently being piloted with the MDS `provider` API only. Proposed changes to the `agency` API will be continue to be reviewed on an ad hoc basis. ** +> **The process defined below currently being piloted with the MDS `provider` API only. Proposed changes to the `agency` API will be continue to be reviewed on an ad hoc basis.** ### Goals @@ -80,21 +80,21 @@ As of March 2019, LADOT and the City of Santa Monica are the project maintainers MDS operates on a six-week release cycle for both major updates (0.x) and patches (0.x.y). In general, major updates (0.x) are expected no more than once per quarter. The release cycle is broken down as follows: -** week 1 - proposals ** +**week 1 - proposals** Contributors submit proposals for inclusion in the release cycle in the form of pull requests and issues tagged with the Milestone for the upcoming release [Q: DOES THIS MAKE SENSE AS A PROCESS TO CORRAL ALL THE ISSUES TO BE CONSIDERED IN A RELEASE?]. Proposals should come with enough explanation to allow all stakeholders to understand intent and implementation strategy. | -** weeks 2-4 - discussion, refinement, and implementation ** +**weeks 2-4 - consensus building, refinement, and implementation** Contributors will provide feedback on proposals. Where possible, discussion will happen via GitHub. Weekly calls will support dialog around more complex or controversial issues. By the end of week 4, all active proposals must be in the form of a pull request. Proposals can be withdrawn or split apart for inclusion in future releases. -** week 5 - consensus building and decision making ** +**week 5 - decision making** The week will start with an in-person/web conference work session for all contributors to review and discuss current proposals. Goal is to achieve consensus where possible, or to clearly articulate areas of disagreement where not. Minor changes may be accepted at this stage if they bring contributors to consensus. At the conclusion of week 5, release partner will review all items for which consensus was not reached and provide a recommended release plan to maintainers for approval. Any remaining approved pull requests to `dev` are merged. -** week 6 - release ** +**week 6 - release** ​Changes will be merged into `master`, documentation will be updated, a release branch will be created, and new version will be formally released. From 41b6718c772bdacfe108350369e65aa61cb802d4 Mon Sep 17 00:00:00 2001 From: Jascha Franklin-Hodge Date: Tue, 12 Mar 2019 13:32:34 -0700 Subject: [PATCH 34/40] Minor language tweaks --- CONTRIBUTING.md | 2 -- ReleaseGuidelines.md | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6dcb4b69..b673198a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,8 +15,6 @@ Contributions should be offered through GitHub issues and pull requests. Please In general, you may open an issue or make a pull request at any time. Once the issue or pull request is associated with a particular Milestone, it will be included for review within the process for that release. -[NEED SOME CONTENT FOR WHAT MAKES A GOOD PULL REQUEST] - ## What belongs in MDS MDS is a tool to facilitate data exchange between mobility service providers, public agencies, and public agency software partners. Although providers are often required to support MDS as part of mobility permits or policies, MDS is intended as a neutral mechanism for information exchange. It is not intended to force or foreclose any specific policy options that a public agency may choose to pursue. diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index 6d511125..1779f6a4 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -82,7 +82,7 @@ MDS operates on a six-week release cycle for both major updates (0.x) and patche **week 1 - proposals** -Contributors submit proposals for inclusion in the release cycle in the form of pull requests and issues tagged with the Milestone for the upcoming release [Q: DOES THIS MAKE SENSE AS A PROCESS TO CORRAL ALL THE ISSUES TO BE CONSIDERED IN A RELEASE?]. Proposals should come with enough explanation to allow all stakeholders to understand intent and implementation strategy. | +Contributors submit proposals for inclusion in the release cycle in the form of pull requests and issues tagged with the Milestone for the upcoming release. Proposals should come with enough explanation to allow all stakeholders to understand intent and implementation strategy. | **weeks 2-4 - consensus building, refinement, and implementation** @@ -92,11 +92,11 @@ Contributors will provide feedback on proposals. Where possible, discussion will The week will start with an in-person/web conference work session for all contributors to review and discuss current proposals. Goal is to achieve consensus where possible, or to clearly articulate areas of disagreement where not. Minor changes may be accepted at this stage if they bring contributors to consensus. -At the conclusion of week 5, release partner will review all items for which consensus was not reached and provide a recommended release plan to maintainers for approval. Any remaining approved pull requests to `dev` are merged. +At the conclusion of week 5, release partner will review all items for which consensus was not reached and provide a recommended release plan to maintainers for approval. Any remaining approved pull requests to `dev` are merged or the release branch as necessary. **week 6 - release** -​Changes will be merged into `master`, documentation will be updated, a release branch will be created, and new version will be formally released. +​Documentation will be updated, a release branch will be created if necessary, changes will be merged into `master`, and new version will be formally released. ### Communication and Workflow The release annoncements and process schedule will be communicated via [`mds-announce`][mds-announce] Google Group. People wishing to stay informed should join the group for updates. Timing of web conference and in person work sessions will be communicated via mds-announce as well. @@ -105,7 +105,7 @@ The following best practices are intended to create clarity around each release * Categorize issues and PRs under an associated [Milestone][mds-milestones] for the release -* Assign a due date for said Milestone that aligns with the end of the proposal period for the release cycle (week 1) +* Assign a due date for said Milestone that aligns with proposed release date * Pull requests and release notes should include a summary of the major changes / impacts associated with the change or release From 9576726af4e8a1c6c05dd00da024509644fb6ca3 Mon Sep 17 00:00:00 2001 From: Jascha Franklin-Hodge Date: Sun, 17 Mar 2019 17:07:44 -0400 Subject: [PATCH 35/40] Changes to reflect comments in PR and additional discussion. --- ReleaseGuidelines.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index 1779f6a4..df403210 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -49,6 +49,8 @@ This *release branch* represents the current state of that release series. All m When a PATCH release is ready (e.g. `0.2.0` to `0.2.1`), the release branch (e.g. `0.2.x`) is merged to `master` (to make the release official) and `dev` is rebased onto `master` (to ensure the patch is incorporated with any new work). +Breaking changes should always be merged to develop. These may be merged at any time and will be incorporated into the next minor release. For non-breaking changes, these should either be merged to develop if the next release is a minor release, or to the appropriate release branch if the next version is a patch release. During each cycle, we merge changes to both dev and 0.n.x branches, so breaking changes can be proposed and worked on at any time + As stated earlier, at this time MDS will maintain *two concurrent MINOR versions*. This means that when a MINOR release is made (e.g. `0.4.0`), work on the outgoing series (`0.2.x`, in this case) ceases and its release branch is removed. ## Release Process @@ -56,6 +58,8 @@ The sections below define the release process itself, including timeline, roles, > **The process defined below currently being piloted with the MDS `provider` API only. Proposed changes to the `agency` API will be continue to be reviewed on an ad hoc basis.** +>**It is our intent to maintain a level of coordination between the technical direction of `agency` and `provider`. As such, proposed changes to either API will be reviewed to ensure they do not create unnecessary duplicative functionality, introduce confusion about which API should be used for a given purpose, or prevent the reconciliation of data between the two APIs (for example: using data from `provider` to cross-validate data received via `agency`).** + ### Goals * _Fast, regular releases to support rapid evolution of MDS_ From fd0a1cc5b55ce25b0f389c2fcf5ea3d7cc472d69 Mon Sep 17 00:00:00 2001 From: Jascha Franklin-Hodge Date: Mon, 18 Mar 2019 15:47:07 -0400 Subject: [PATCH 36/40] Swapped position of Branch Mechanics and Release Process --- ReleaseGuidelines.md | 57 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index df403210..0cc34db9 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -5,12 +5,12 @@ MDS will see regular updates and new [releases][mds-releases]. This document des ## Table of Contents * [Versioning](#versioning) -* [Branch Mechanics](#branch-mechanics) * [Release Process](#process) * [Goals](#goals) * [Roles](#roles) * [Schedule](#schedule) * [Communication and Workflow](#communication-and-workflow) + * [Branch Mechanics](#branch-mechanics) * [Checklist](#release-checklist) ## Versioning @@ -25,33 +25,6 @@ At this early stage, MDS will be moving relatively quickly with an eye toward st For now, MDS will maintain *two concurrent (MINOR) versions* (e.g. if `0.3.0` were the current version, the `0.2.x` series would continue to receive maintenance in addition to `0.3.x`). -## Branch Mechanics - -Aside from using `git tags` as mentioned earlier, here we outline a branching strategy to handle ongoing maintenance changes in parallel with features for new releases. - -### Primary branches - -At a high-level, there are two primary branches: - -* [`master`][mds-master] represents the current stable release (i.e. the most recent tag) of MDS. Development work generally *does not* happen here, but is rather merged from elsewhere. - -* [`dev`][mds-dev] represents work on the next MINOR release, and is the *long-term* development branch. - -### Feature branches - -Work on new features for MDS happens in branches cut from `dev`. When the feature is ready for review, submit a PR against `dev`, ideally with any merge conflicts already resolved. `dev` serves as the collection point for all new feature work. - -### Release branches - -In anticipation of ongoing maintenance, a branch will be created for the current release series. For example, at the time `0.2.0` is released, a branch will be cut from `master` for `0.2.x`. - -This *release branch* represents the current state of that release series. All maintenance/bugfix work for the series is collected in this branch. To work on a patch, cut a branch from the release branch. When ready, submit a PR against the release branch. - -When a PATCH release is ready (e.g. `0.2.0` to `0.2.1`), the release branch (e.g. `0.2.x`) is merged to `master` (to make the release official) and `dev` is rebased onto `master` (to ensure the patch is incorporated with any new work). - -Breaking changes should always be merged to develop. These may be merged at any time and will be incorporated into the next minor release. For non-breaking changes, these should either be merged to develop if the next release is a minor release, or to the appropriate release branch if the next version is a patch release. During each cycle, we merge changes to both dev and 0.n.x branches, so breaking changes can be proposed and worked on at any time - -As stated earlier, at this time MDS will maintain *two concurrent MINOR versions*. This means that when a MINOR release is made (e.g. `0.4.0`), work on the outgoing series (`0.2.x`, in this case) ceases and its release branch is removed. ## Release Process The sections below define the release process itself, including timeline, roles, and communication best practices. @@ -115,6 +88,34 @@ The following best practices are intended to create clarity around each release * Proposed changes should come in the form of PRs to give the community ample awareness and time for feedback +## Branch Mechanics + +Aside from using `git tags` as mentioned earlier, here we outline a branching strategy to handle ongoing maintenance changes in parallel with features for new releases. + +### Primary branches + +At a high-level, there are two primary branches: + +* [`master`][mds-master] represents the current stable release (i.e. the most recent tag) of MDS. Development work generally *does not* happen here, but is rather merged from elsewhere. + +* [`dev`][mds-dev] represents work on the next MINOR release, and is the *long-term* development branch. + +### Feature branches + +Work on new features for MDS happens in branches cut from `dev`. When the feature is ready for review, submit a PR against `dev`, ideally with any merge conflicts already resolved. `dev` serves as the collection point for all new feature work. + +### Release branches + +In anticipation of ongoing maintenance, a branch will be created for the current release series. For example, at the time `0.2.0` is released, a branch will be cut from `master` for `0.2.x`. + +This *release branch* represents the current state of that release series. All maintenance/bugfix work for the series is collected in this branch. To work on a patch, cut a branch from the release branch. When ready, submit a PR against the release branch. + +When a PATCH release is ready (e.g. `0.2.0` to `0.2.1`), the release branch (e.g. `0.2.x`) is merged to `master` (to make the release official) and `dev` is rebased onto `master` (to ensure the patch is incorporated with any new work). + +Breaking changes should always be merged to develop. These may be merged at any time and will be incorporated into the next minor release. For non-breaking changes, these should either be merged to develop if the next release is a minor release, or to the appropriate release branch if the next version is a patch release. During each cycle, we merge changes to both dev and 0.n.x branches, so breaking changes can be proposed and worked on at any time + +As stated earlier, at this time MDS will maintain *two concurrent MINOR versions*. This means that when a MINOR release is made (e.g. `0.4.0`), work on the outgoing series (`0.2.x`, in this case) ceases and its release branch is removed. + ## Release Checklist The following steps **must** be followed for **every** release of MDS: From 128cf67f0380a454a6c4517d38a2a534e1198e40 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Mon, 18 Mar 2019 12:55:38 -0700 Subject: [PATCH 37/40] indentation fix --- ReleaseGuidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseGuidelines.md b/ReleaseGuidelines.md index 0cc34db9..05fb942a 100644 --- a/ReleaseGuidelines.md +++ b/ReleaseGuidelines.md @@ -10,7 +10,7 @@ MDS will see regular updates and new [releases][mds-releases]. This document des * [Roles](#roles) * [Schedule](#schedule) * [Communication and Workflow](#communication-and-workflow) - * [Branch Mechanics](#branch-mechanics) +* [Branch Mechanics](#branch-mechanics) * [Checklist](#release-checklist) ## Versioning From a2326456e932bae413d0a925d4165c34f0712eec Mon Sep 17 00:00:00 2001 From: Todd Petersen Date: Wed, 6 Mar 2019 18:04:04 -0500 Subject: [PATCH 38/40] Removed 5 second requirement from Github Updated based on compliance changed approved by LADOT Compliance will exist in a seperate document. --- agency/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agency/README.md b/agency/README.md index 276b6814..bb5ae161 100644 --- a/agency/README.md +++ b/agency/README.md @@ -181,7 +181,7 @@ Body Params: ## Vehicles - Telemetry -The vehicle `/telemetry` endpoint allows a Provider to send vehicle telemetry data in a batch for any number of vehicles in the fleet. Telemetry data will be reported to the API every 5 seconds for each vehicle in motion. +The vehicle `/telemetry` endpoint allows a Provider to send vehicle telemetry data in a batch for any number of vehicles in the fleet. Endpoint: `/vehicles/telemetry` Method: `POST` From bd69a0f3f9c18f0131987bd44659447440186a00 Mon Sep 17 00:00:00 2001 From: Todd Petersen Date: Wed, 6 Mar 2019 19:05:40 -0500 Subject: [PATCH 39/40] Compliance Update Approved by LADOT. Updated compliance for in-trip telemetry for scooters. --- agency/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/agency/README.md b/agency/README.md index bb5ae161..184739c9 100644 --- a/agency/README.md +++ b/agency/README.md @@ -183,6 +183,9 @@ Body Params: The vehicle `/telemetry` endpoint allows a Provider to send vehicle telemetry data in a batch for any number of vehicles in the fleet. +The Update Telemetry endpoint (/telemetry) shall be called for the specific trip within 24 hrs after the vehicle trip is over. +For any given trip, data reported via the (/telemetry) endpoint shall contain temporal and location data for every 300 ft (91 meters) while vehicle is in motion and 30 seconds while at rest. For Mobility Service Providers who do not calculate distance in real-time, a periodic rate of 14 seconds can be used while vehicle is in motion. + Endpoint: `/vehicles/telemetry` Method: `POST` From 9f93c019e4477a0da48f282db7a5dd26e3a29843 Mon Sep 17 00:00:00 2001 From: Hunter Owens Date: Mon, 11 Mar 2019 16:24:56 -0700 Subject: [PATCH 40/40] add CODEOWNERS file for PR review routing --- CODEOWNERS | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..5e9b665a --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,8 @@ +## Below is the MDS CODEOWNERS file, which dictates who is required for review on any given file. + +## All MDS approvals +* @hunterowens @thekaveman @cityoflosangeles/transportation + + +## Agency Specific +/agency/* @cityoflosangeles/ellis-associates