diff --git a/.github/ISSUE_TEMPLATE/add-provider-id.md b/.github/ISSUE_TEMPLATE/add-provider-id.md new file mode 100644 index 00000000..12aadba3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/add-provider-id.md @@ -0,0 +1,24 @@ +--- +name: Add Provider ID +about: Create Provider ID for use in CDS +title: 'Add Provider ID: [Provider Name]' +labels: admin,identifier change +assignees: '' + +--- + +**Note:** See the [Adding a CDS Provider ID](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Adding-a-CDS-Provider-ID) page for more help. + +Opening this issue will allow you as a mobility service provider get an official provider ID for use across CDS globally. + +**Fields needed from you for the [providers.csv file](https://github.com/openmobilityfoundation/curb -data-specification/blob/main/providers.csv).** + +_All fields are required._ + +1. **provider_name** - Short name of your company. + - ... +1. **provider_id** - A random UUID version 4. There are lots of way to generate a unique UUID, like using this [website](https://www.uuidgenerator.net/version4). + - ... +1. **url** - URL to the home page of your company. + +Additionally, please provide your name and role within your agency to help with verification. diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 00000000..30801d77 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,40 @@ +--- +name: Feature request / proposal +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +### Is your feature request related to a problem? Please describe. + +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +### Describe the solution you'd like + +A clear and concise description of what you want to happen. + +### Is this a breaking change + +A breaking change would require consumers or implementors of an API to modify their code for it to continue to function (ex: renaming of a required field or the change in data type of an existing field). A non-breaking change would allow existing code to continue to function (ex: addition of an optional field or the creation of a new optional endpoint). + + * Yes, breaking + * No, not breaking + * I'm not sure + +### Impacted Spec + +For which spec is this feature being requested? + + * `Curbs` + * `Events` + * `Metrics` + +### Describe alternatives you've considered + +A clear and concise description of any alternative solutions or features you've considered. + +### Additional context + +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 00000000..6dfeffe8 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,41 @@ +--- +name: Default +about: Suggest changes to CDS +title: + +--- + +# CDS Pull Request + +Thank you for your contribution! Please review our OMF [contributing page](https://github.com/openmobilityfoundation/governance/blob/main/CONTRIBUTING.md) to understand guidelines and policies for participation, and our [Code of Conduct page](https://github.com/openmobilityfoundation/governance/blob/main/CODE_OF_CONDUCT.md). + +To avoid complications and help make the Review process as smooth as possible, make sure to: + +1. Target [**`dev`**](https://github.com/openmobilityfoundation/curb-data-specification/tree/dev) branch. Please ensure you are targeting **`dev`**, not **`main`**. +1. Keep the *"Allow edits from maintainers"* button checked to help us resolve some issues for you. +1. Be ready to resolve any merge conflicts before we approve your Pull Request. +1. Have an up to date profile, per our Github [community profile](https://github.com/openmobilityfoundation/governance/blob/main/CONTRIBUTING.md#community-profile) guildance. + +## Explain pull request + +Please provide a clear and concise reason for this pull request and the impact of the change + +## Is this a breaking change + +A breaking change would require consumers or implementors of the API to modify their code for it to continue to function (ex: renaming of a required field or the change in data type of an existing field). A non-breaking change would allow existing code to continue to function (ex: addition of an optional field or the creation of a new optional endpoint). + +* Yes, breaking +* No, not breaking +* I'm not sure + +## Impacted Spec + +Which API(s) will this pull request impact? + +* `Curbs` +* `Events` +* `Metrics` + +## Additional context + +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE/release-candidate.md b/.github/PULL_REQUEST_TEMPLATE/release-candidate.md new file mode 100644 index 00000000..5fb3bfba --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/release-candidate.md @@ -0,0 +1,17 @@ +--- +name: Release Candidate +about: Initiate discussion to obtain OMF approval for new release +title: Release Candidate [X.Y.Z] +labels: admin + +--- + +### Summary + +The Release Candidate for CDS `X.Y.Z` has been submitted: + +Please use this pull request to track Technology Council and OMF Board feedback and/or requested changes. + +### Action Item + +This pull request will be merged by an OMF maintainer after OMF Board Approval following the [Release Guidelines](https://github.com/openmobilityfoundation/governance/blob/main/technical/ReleaseGuidelines.md#making-a-release). diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..6dfeffe8 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,41 @@ +--- +name: Default +about: Suggest changes to CDS +title: + +--- + +# CDS Pull Request + +Thank you for your contribution! Please review our OMF [contributing page](https://github.com/openmobilityfoundation/governance/blob/main/CONTRIBUTING.md) to understand guidelines and policies for participation, and our [Code of Conduct page](https://github.com/openmobilityfoundation/governance/blob/main/CODE_OF_CONDUCT.md). + +To avoid complications and help make the Review process as smooth as possible, make sure to: + +1. Target [**`dev`**](https://github.com/openmobilityfoundation/curb-data-specification/tree/dev) branch. Please ensure you are targeting **`dev`**, not **`main`**. +1. Keep the *"Allow edits from maintainers"* button checked to help us resolve some issues for you. +1. Be ready to resolve any merge conflicts before we approve your Pull Request. +1. Have an up to date profile, per our Github [community profile](https://github.com/openmobilityfoundation/governance/blob/main/CONTRIBUTING.md#community-profile) guildance. + +## Explain pull request + +Please provide a clear and concise reason for this pull request and the impact of the change + +## Is this a breaking change + +A breaking change would require consumers or implementors of the API to modify their code for it to continue to function (ex: renaming of a required field or the change in data type of an existing field). A non-breaking change would allow existing code to continue to function (ex: addition of an optional field or the creation of a new optional endpoint). + +* Yes, breaking +* No, not breaking +* I'm not sure + +## Impacted Spec + +Which API(s) will this pull request impact? + +* `Curbs` +* `Events` +* `Metrics` + +## Additional context + +Add any other context or screenshots about the feature request here. diff --git a/CODEOWNERS b/CODEOWNERS index fafbc932..4457a92b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,4 +1,7 @@ -## Below is the MDS CODEOWNERS file, which dictates who is required for review on any given file. +## Below is the CDS CODEOWNERS file, which dictates who is required for review on any given file. -## All MDS approvals +## All CDS approvals * @openmobilityfoundation/omf-admin + +## CDS Working Group +* @openmobilityfoundation/cds-maintainers @openmobilityfoundation/omf-admin diff --git a/README.md b/README.md index dd6d6c5c..89f9c182 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,112 @@ # Curb Data Specification -## Beta -> ⚠ **This repository is current a draft of the initial CDS beta, and not an official release. It will be changed and updated as development and real-world feedback happens and we head for a 1.0 beta release. See our current [timeline](https://github.com/openmobilityfoundation/curb-data-specification/wiki#timeline) and watch the [CDS Releases](https://github.com/openmobilityfoundation/curb-data-specification/releases) page for updates.** +## Release Candidate +> ⚠ **This repository is a [release candidate](https://github.com/openmobilityfoundation/curb-data-specification/releases) for CDS 1.0. It has been approved by the [Working Group Steering Committee](https://github.com/openmobilityfoundation/curb-data-specification/wiki). You may start to use it in your development and production environments for real world use cases. The release is going through the final [OMF approval process](https://github.com/openmobilityfoundation/governance/blob/main/technical/ReleaseGuidelines.md#approval-by-the-open-mobility-foundation), where it may be tweaked or enhanced with more guidance and resources. See the [Release Plan](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Release-1.0.0) page for updates.** ## Table of Contents - [Overview](#overview) -- [Work in Progress](#work-in-progress) -- [Get Involved](#get-involved) - [Curb Data Specification APIs](#curb-data-specification-apis) - - [Modularity](#modularity) - [Structure](#structure) + - [Modularity](#modularity) + - [MDS Overlap](#mds-overlap) +- [Work in Progress](#work-in-progress) +- [Get Involved](#get-involved) - [Versions](#versions) - [Technical Information](#technical-information) - [Membership](#membership) +- [Data Privacy](#data-privacy) +- [Use Cases](#use-cases) # Overview -Urban curb is a valuable, limited, and often under-managed part of the public right of way. Curb demand is growing, including from commercial activity like passenger pickup/drop off, traditional and on-demand delivery services, new mobility programs like scooters, bikeshare, and carshare, and goods and freight delivery. While cities have made some progress in digitizing their curb and using curb data, more tools are needed to proactively manage curbs and sidewalks, and in doing so deliver more public value from this scarce resource. Curb data standards can provide a mechanism for expressing static and dynamic regulations, measuring activity at the curb, and providing access and utilization for curb users. +The Curb Data Specification (**CDS**), a project of the [Open Mobility Foundation](http://www.openmobilityfoundation.org/) (**OMF**), is a data standard and set of Application Programming Interfaces (APIs) that helps cities manage and companies use dynamic curb zones that optimize loading activities of people and goods, and measure the impact of these programs. -The Curb Data Specification (CDS) will help cities and companies pilot and scale dynamic curb zones that optimize commercial loading activities of people and goods, and measure the impact of these programs. +Urban curb is a valuable, limited, and often under-managed part of the public right of way. Curb demand is growing, including from commercial activity like passenger pickup/drop off, traditional and on-demand delivery services, new mobility programs like scooters, bikeshare, and carshare, and goods and freight delivery. While cities have made some progress in digitizing their curb and using curb data, more tools are needed to proactively manage curbs and sidewalks, and to deliver more public value from this scarce resource. CDS can provide a mechanism for expressing static and dynamic regulations, measuring activity at the curb, and developing policies that create more accessible, useful curbs. -In the short term we will produce standards that are necessary to support dynamic curb utilization use cases for commercial loading activities by privately operated companies. In the long term we want to help cities manage their curb zone programs and surrounding areas and measure the utilization and impact for all use cases. +**CDS** is a key piece of digital infrastructure that supports the effective implementation of curb policies in cities and for curb users. For a high level overview and visuals, see the **[About CDS](https://www.openmobilityfoundation.org/about-cds/)** page on the OMF website. -The CDS will be consumed by both cities and transportation providers operating in the public right of way. In many cases, the same mobility providers using curbs with CDS may also be interacting with other OMF [MDS Policy](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/policy), [MDS Provider](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/provider), and [MDS Agency](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/agency) data objects within the same [MDS Jurisdiction](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/jurisdiction) or [MDS Geography](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/geography), and using similar [MDS Metrics](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/metrics). Consistent with the Technology Design Principles codified in the OMF [Architectural Landscape Document](https://github.com/openmobilityfoundation/governance/blob/main/documents/OMF-MDS-Architectural-Landscape.pdf), the members of this working group are making reasonable best efforts to ensure that work is both _modular_ and _interoperable_ with other technology managed by the OMF as to avoid duplication and downstream implementation complexity. +![Curb Data Specification Logo](https://i.imgur.com/iGPCZyQ.png) [Top][toc] -# Work in Progress +# Curb Data Specification APIs -The CDS is a work in progress and is under ongoing development by the community under the guidance of the [Working Group Steering Committee](https://github.com/openmobilityfoundation/curb-data-specification/wiki) on specific [discussion topics](https://github.com/openmobilityfoundation/curb-data-specification/discussions) and bi-weekly [public meetings](https://github.com/openmobilityfoundation/curb-data-specification/wiki#meeting-agendas) around a specific [Scope of Work](https://docs.google.com/document/d/1yY5pRiiei8seVxXOmcYiqCA7wx7DueeatJnjbZoV3hU/). Work and dicussion is also happening in the [Curb Data Specification - Draft and Ideas Doc](https://docs.google.com/document/d/1UgD2fHtVyIMwNG-qXJRv-gcY7nCdYxokbMsLTs32Em4/edit?usp=sharing) before being committed to GitHub. The Steering Committee has created supplemntary resources the [Architectural Decisions](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Curb-Architectural-Decisions), [Curbs Use Cases](https://github.com/openmobilityfoundation/curb-data-specification/wiki/CDS-Curbs-Use-Cases), and [Pilot Project Guide](https://docs.google.com/document/d/1Mb1wpy4AFJ1MLvDpSIJsii4_1j2JC16NxNUVPI5BMNM/edit?usp=sharing) pages. The goal is to release a beta version of the spec by the end of 2021 and incorporate feedback from pilot programs into future versions. +CDS is at its core a set of Application Programming Interfaces (APIs) and endpoints within those APIs, which allow information to flow between organizations managing and using curb places. It includes the following three APIs, with multiple endpoints under each API: -[Top][toc] +--- -# Get Involved +CDS Curbs Icon -The OMF’s [Curb Management Working Group](https://github.com/openmobilityfoundation/curb-data-specification/wiki), led by a steering committee of individuals representing public agencies and private sector companies, is developing this data specification for curb usage. The CDS will encompass digitized curb regulations, real time and historic event information, and utilization metrics. The specification will allow sharing of this data between cities, commercial companies, and the public. Get involoved by siging up to the [Curb Mailing List](https://groups.google.com/a/openmobilityfoundation.org/g/wg-curb). +The [`Curbs`](/curbs/) API is a standard way for cities to digitally publish curb locations and regulations, which can be shared with the public and with companies using curb space. It defines curb policies, curb zones, spaces in zones, and areas around curbs, and is used by Events and Metrics. -The Curb Data Specification is an open source project with all development taking place on GitHub. Read our **[Community Wiki](https://github.com/openmobilityfoundation/curb-data-specification/wiki)** to get started. Comments and ideas can be shared by [starting a discussion](https://github.com/openmobilityfoundation/curb-data-specification/discussions), [creating an issue](https://github.com/openmobilityfoundation/curb-data-specification/issues), and specific changes can be suggested by [opening a pull request](https://github.com/openmobilityfoundation/curb-data-specification/pulls). Before contributing, please review our OMF [CONTRIBUTING page](https://github.com/openmobilityfoundation/governance/blob/main/CONTRIBUTING.md) and our [CODE OF CONDUCT page](https://github.com/openmobilityfoundation/governance/blob/main/CODE_OF_CONDUCT.md) to understand guidelines and policies for participation. +--- -For questions about CDS please contact by email at [info@openmobilityfoundation.org](mailto:info@openmobilityfoundation.org) or [on our website](https://www.openmobilityfoundation.org/get-in-touch/). Media inquiries to [media@openmobilityfoundation.org](mailto:media@openmobilityfoundation.org). +CDS Events Icon -[Top][toc] +The [`Events`](/events/) API is a standard way to transmit real-time and historic commercial events happening at the curb to cities. Event data can be derived from company data feeds, on street sensors, session payments, company check-ins, in-person parking personnel, and/or other city data sources. Connected to Curbs and used by Metrics. -# Curb Data Specification APIs +--- + +CDS Metrics Icon -CDS is at its core a set of Application Programming Interfaces (APIs) and endpoints within those APIs, which allow information to flow between organizations using and managing the curb areas. It includes the following APIs and their associated endpoints: +The [`Metrics`](/metrics/) API is a way to track curb usage session details and define common calculation methodologies to measure historic dwell time, occupancy, usage and other aggregated statistics. It defines sessions and aggregates data derived from raw Events data. -1. [Curbs API](/curbs) -1. [Events API](/events) -1. [Metrics API](/metrics) +--- CDS is a data exchange format and a translation layer between internal systems and external entities using data feeds. It is not expected that CDS will be the format used internally to store curb regulations in a city. The internal storage format is something different, and a subset of that data should be able to be converted to CDS for publishing out to the public and curb users. Many parts of the CDS definitions and APIs align across each other. In these cases, consolidated information can be found on the [General Information](/general-information.md) page. -[Top][toc] +## Structure + +CDS contains a series of connected endpoints and fields beneath each interconnected API. + +

## Modularity CDS is designed to be a modular and flexible specification. Regulatory agencies can use the components of the API that are appropriate for their needs. An agency may choose to use only Curbs, while others may use Curbs, Events, and Metrics. Even within each API many endpoints and fields are optional. This design allows agencies, software and hardware companies, and curb users to use what's appropriate for their use cases, work within their operational capabilities, and text CDS in their pilot projects. -## Structure +## MDS Overlap -CDS contains a series of connected endpoint and fields beneath each interconnected API. +Like the [Mobility Data Specification](https://github.com/openmobilityfoundation/mobility-data-specification/) (MDS), the CDS will be consumed by both cities and transportation providers operating in the public right of way. In many cases, the same mobility providers using curbs with CDS may also be interacting with other OMF [MDS Policy](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/policy), [MDS Provider](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/provider), and [MDS Agency](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/agency) data objects within the same [MDS Jurisdiction](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/jurisdiction) or [MDS Geography](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/geography), and using similar [MDS Metrics](https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/metrics). Consistent with the Technology Design Principles codified in the [Technology Council's](https://github.com/openmobilityfoundation/governance/wiki/Technology-Council) OMF [Architectural Landscape Document](https://github.com/openmobilityfoundation/governance/blob/main/documents/OMF-MDS-Architectural-Landscape.pdf), the members of this working group are making reasonable best efforts to ensure that work is both _modular_ and _inter operable_ with other technology managed by the OMF as to avoid duplication and downstream implementation complexity. The first version of CDS intentionally has no direct connetions to MDS which allowed it to be created based strictly on real-world curb use cases and needs, but may align directly in future versions. -![CDS Structure](https://i.imgur.com/L44996v.gif) +[Top][toc] + +# Work in Progress + +The CDS is a work in progress and is under ongoing development by the community under the guidance of the [Working Group Steering Committee](https://github.com/openmobilityfoundation/curb-data-specification/wiki) on specific [discussion topics](https://github.com/openmobilityfoundation/curb-data-specification/discussions) and bi-weekly [public meetings](https://github.com/openmobilityfoundation/curb-data-specification/wiki#meeting-agendas) around a specific [Scope of Work](https://docs.google.com/document/d/1yY5pRiiei8seVxXOmcYiqCA7wx7DueeatJnjbZoV3hU/). The Steering Committee has created supplementary resources like [Architectural Decisions](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Curb-Architectural-Decisions), [Use Cases](https://github.com/openmobilityfoundation/curb-data-specification/wiki/CDS-Use-Cases), [Privacy Guidance](https://docs.google.com/document/d/117kJhXp6ldv7KHq7k9wHONHVVHw00xweaHpORVu_c10/edit?usp=sharing), [Policy Language Guidance](https://github.com/openmobilityfoundation/governance/blob/main/technical/OMF-CDS-Policy-Language-Guidance.md), and a [Pilot Project Guide](https://docs.google.com/document/d/1Mb1wpy4AFJ1MLvDpSIJsii4_1j2JC16NxNUVPI5BMNM/edit?usp=sharing). After the CDS 1.0 launch, the public working group will incorporate feedback from on-the-ground pilot programs into future versions. + +[Top][toc] + +# Get Involved + +The OMF’s [Curb Management Working Group](https://github.com/openmobilityfoundation/curb-data-specification/wiki), led by a steering committee of individuals representing public agencies and private sector companies, has developed this data specification for curb usage. The CDS encompasses digitized curb regulations, real time and historic event information, and utilization metrics. The specification allows sharing of this data between cities, commercial companies, and the public. Get involved by siging up to the [Curb Mailing List](https://groups.google.com/a/openmobilityfoundation.org/g/wg-curb). + +The Curb Data Specification is an open source project with all development taking place on GitHub. Read our **[Community Wiki](https://github.com/openmobilityfoundation/curb-data-specification/wiki)** to get started. Comments and ideas can be shared by [starting a discussion](https://github.com/openmobilityfoundation/curb-data-specification/discussions), [creating an issue](https://github.com/openmobilityfoundation/curb-data-specification/issues), and specific changes can be suggested by [opening a pull request](https://github.com/openmobilityfoundation/curb-data-specification/pulls). Before contributing, please review our OMF [CONTRIBUTING page](https://github.com/openmobilityfoundation/governance/blob/main/CONTRIBUTING.md) and our [CODE OF CONDUCT page](https://github.com/openmobilityfoundation/governance/blob/main/CODE_OF_CONDUCT.md) to understand guidelines and policies for participation. + +For questions about CDS please contact by email at [info@openmobilityfoundation.org](mailto:info@openmobilityfoundation.org) or [on our website](https://www.openmobilityfoundation.org/get-in-touch/). Media inquiries to [media@openmobilityfoundation.org](mailto:media@openmobilityfoundation.org). [Top][toc] # Versions -CDS has a **current release**, and **upcoming releases** in development. For a full list of releases, their status, recommended versions, and timelines, see the [Official CDS Releases](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Releases) page. +CDS has a **current release** (version 1.0.0), and an **upcoming releases** in development. For a full list of releases, their status, recommended versions, and timelines, see the [Official CDS Releases](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Releases) page. + +The OMF provides guidance on upgrading for cities, providers, and software companies, and sample permit language for cities. See our [CDS Version Guidance](https://github.com/openmobilityfoundation/governance/blob/main/technical/OMF-CDS-Version-Guidance.md) for best practices on how and when to upgrade CDS as new versions become available. Our complimentary [CDS Policy Language Guidance](https://github.com/openmobilityfoundation/governance/blob/main/technical/OMF-CDS-Policy-Language-Guidance.md) document is for cities writing CDS into their operating policy and includes sample policy language. ## Technical Information -The latest CDS release is in the [`main`](https://github.com/openmobilityfoundation/curb-data-specification/tree/main) branch, and development for the next release occurs in the [`dev`](https://github.com/openmobilityfoundation/curb-data-specification/tree/dev) branch. +The latest CDS release is in the [`main`](https://github.com/openmobilityfoundation/curb-data-specification/tree/main) branch, and development for the next release occurs in the [`dev`](https://github.com/openmobilityfoundation/curb-data-specification/tree/dev) and other branches. -The CDS specification is versioned using Git tags and [semantic versioning](https://semver.org/). +The CDS specification is versioned using Git tags and [semantic versioning](https://github.com/openmobilityfoundation/governance/blob/main/technical/ReleaseGuidelines.md#versioning). * [Latest Release Branch](https://github.com/openmobilityfoundation/curb-data-specification/tree/main) (main) * [Development Branch](https://github.com/openmobilityfoundation/curb-data-specification/tree/dev) (dev) * [All GitHub Releases](https://github.com/openmobilityfoundation/curb-data-specification/releases) * [CDS Releases](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Releases) - current/recommended versions, timeline +* [Release Guidelines](https://github.com/openmobilityfoundation/governance/blob/main/technical/ReleaseGuidelines.md) [Top][toc] @@ -103,4 +127,26 @@ Read about [how to become an OMF member](https://www.openmobilityfoundation.org/ [Top][toc] +# Data Privacy + +CDS includes information about commercial vehicles using select curb zones in a city to allow agencies to regulate curb use and policy in the public right of way and to conduct analysis for program improvements. While CDS is not designed to convey any personal information and is focused on commerical curb activity, some uses of some fields can be sensitive. The OMF community has created a number of resources to help cities, fleet operators, and software companies handle vehicle data safely: + +* [CDS Privacy Guidance](https://docs.google.com/document/d/117kJhXp6ldv7KHq7k9wHONHVVHw00xweaHpORVu_c10/edit?usp=sharing) - identifies relevant data in CDS, use cases, and provides suggestions on the safe handling of this data. +* [Privacy Guide for Cities](https://github.com/openmobilityfoundation/governance/raw/main/documents/OMF-MDS-Privacy-Guide-for-Cities.pdf) - guide that covers essential privacy topics and best practices +* [The Privacy Principles for Mobility Data](https://www.mobilitydataprivacyprinciples.org/) - principles endorsed by the OMF and other mobility organizations to guide the mobility ecosystem in the responsible use of data and the protection of individual privacy +* [Mobility Data State of Practice](https://github.com/openmobilityfoundation/privacy-committee/blob/main/products/state-of-the-practice.md) - real-world examples related to the handling and protection of MDS and other types of mobility data +* [CDS Use Cases](https://github.com/openmobilityfoundation/curb-data-specification/wiki/CDS-Use-Cases) - outlines real-world use cases, and how to use CDS to make them happen and why. + +The OMF’s [Privacy, Security, and Transparency Committee](https://github.com/openmobilityfoundation/privacy-committee#welcome-to-the-privacy-security-and-transparency-committee) creates many of these resources, and advises the OMF on principles and practices that ensure the secure handling of mobility data. The committee – which is composed of both private and public sector OMF members – also holds regular public meetings, which provide additional resources and an opportunity to discuss issues related to privacy and mobility data. Learn more [here](https://github.com/openmobilityfoundation/privacy-committee#welcome-to-the-privacy-security-and-transparency-committee). + +[Top][toc] + +# Use Cases + +How cities use CDS depends on a variety of factors: their transportation goals, existing services and infrastructure, and the unique needs of their communities. Cities are using CDS to create policy, manage curbs, and ensure the safe operation of vehicles in the public right of way. + +A list of use cases is useful to show what's possible with CDS, to see many use cases up front for privacy considerations, and to use for policy discussions and policy language. More details and examples can be seen on the [CDS Use Cases](https://github.com/openmobilityfoundation/curb-data-specification/wiki/CDS-Use-Cases). + +[Top][toc] + [toc]: #table-of-contents diff --git a/ReleaseNotes.md b/ReleaseNotes.md new file mode 100644 index 00000000..9a3561e1 --- /dev/null +++ b/ReleaseNotes.md @@ -0,0 +1,32 @@ +## 1.0.0 + +**Release Candidate submitted 2022-01-25** + +[Release Plan](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Release-1.0.0) + +The 1.0.0 major release is the first release of the Curb Data Specification (CDS) after over 15 months of community work across dozens of public meetings, with 70+ organizations and 160+ individuals participating. It includes three major APIs to define Curbs and policies, track Events at the curb and determine sensor status, and derive Metrics for sessions and aggregate curb usage with a well defined methodology. + +### CHANGES + +See work tagged with "Milestone 1.0.0" in [Pull Requests](https://github.com/openmobilityfoundation/curb-data-specification/pulls?q=is%3Apr+is%3Aclosed+milestone%3A1.0.0), [Issues](https://github.com/openmobilityfoundation/curb-data-specification/issues?q=is%3Aissue+milestone%3A1.0.0+is%3Aclosed), and [Discussions](https://github.com/openmobilityfoundation/curb-data-specification/discussions) for a full list of changes and history. + +**_General CDS_** + +- Creation of spec from working group drafts and community code submissions + - See [About CDS](https://www.openmobilityfoundation.org/about-cds/) web page for high level details + +**_Curbs_** + +- The Curbs API is a standard way for cities to digitally publish curb locations and regulations, which can be shared with the public and with companies using curb space. It defines curb policies, curb zones, spaces in zones, and areas around curbs, and is used by Events and Metrics. + +**_Events_** + +- The Events API is a standard way to transmit real-time and historic commercial events happening at the curb to cities. Event data can be derived from company data feeds, on street sensors, session payments, company check-ins, in-person parking personnel, and/or other city data sources. Connected to Curbs and used by Metrics. + +**_Metrics_** + +- The Metrics API is a way to track curb usage session details and define common calculation methodologies to measure historic dwell time, occupancy, usage and other aggregated statistics. It defines sessions and aggregates data derived from raw Events data. + +_Minor Updates_ + +- Formatting of spec, links, TOCs, headers, etc diff --git a/curbs/README.md b/curbs/README.md index 0ec25ba5..9dc47f2f 100644 --- a/curbs/README.md +++ b/curbs/README.md @@ -1,14 +1,15 @@ # Curb Data Specification: Curbs API +CDS Curbs Icon + The Curbs API is a REST API allowing cities to specify areas of interest along the curb along with -the rules for using them: who is allowed to park, load, unload, pick up, drop off, etc. at the curb, -for how long, for what price (if any), at what times, and on what days. Locations defined in the -Curbs API can be connected to event and metric data and shared with companies and the public, for +the rules for using them: who is allowed to park, load, unload, pick up, drop off, etc., +for how long, for what price (if any), at what times, and on which days. Locations defined in the +Curbs API can be connected to event and metrics data, and can be shared with companies and the public, for purposes such as routing, finding legal parking, loading, and pick-up/drop-off spots, or analyzing curb utilization over time. -## ⚠ Beta -> **This feature is current a draft of the initial CDS beta. It will be change as development and real-world feedback happens.** +**See [other CDS APIs](/README.md#curb-data-specification-apis) on the homepage.** # Endpoints @@ -21,58 +22,58 @@ There are four different endpoints that are part of the Curbs API: - A [Curb Area](#curb-area) is a larger area of interest, such as a neighborhood or corridor, that could be used to show proximity, approaches, conflicts, circling, or other activity. Curb areas are *optional*. - - A [Curb Policy](#curb-area) A Policy object is a rule that allows or prohibits a particular set of - users from using a particular curb at a particular time or times. Curb policies are *optional*. + - A [Curb Policy](#policy) A Policy object is a rule that allows or prohibits a particular set of + users from using a particular curb at a particular time or times. Curb policies are *optional* + but recommended with Curb Zones. + +**See [examples](examples.md) for these endpoints.** ![Curb Places](https://i.imgur.com/YQ7P243.jpg) # Table of Contents - [REST Endpoints](#rest-endpoints) - * [Query Curb Zones](#query-curb-zones) - * [Query Curb Areas](#query-curb-areas) - * [Query Curb Spaces](#query-curb-spaces) - * [Query Curb Policies](#query-curb-policies) - * [Fetch a Curb Zone](#fetch-a-curb-zone) - * [Fetch a Curb Area](#fetch-a-curb-area) - * [Fetch a Curb Space](#fetch-a-curb-space) - * [Fetch a Curb Policy](#fetch-a-curb-policy) + - [Authorization](#authorization) + - [Query Curb Zones](#query-curb-zones) + - [Query Curb Areas](#query-curb-areas) + - [Query Curb Spaces](#query-curb-spaces) + - [Query Curb Policies](#query-curb-policies) + - [Fetch a Curb Zone](#fetch-a-curb-zone) + - [Fetch a Curb Area](#fetch-a-curb-area) + - [Fetch a Curb Space](#fetch-a-curb-space) + - [Fetch a Curb Policy](#fetch-a-curb-policy) - [Data Objects](#data-objects) - * [Curb Zone](#curb-zone) - * [Curb Area](#curb-area) - * [Curb Space](#curb-space) - * [Policy](#policy) + - [Curb Zone](#curb-zone) + - [Curb Area](#curb-area) + - [Curb Space](#curb-space) + - [Policy](#policy) + - [Rule](#rule) + - [Activities](#activities) + - [User Classes](#user-classes) + - [Time Span](#time-span) + - [Rate](#rate) + - [Location Reference](#location-reference) +- [Examples](#examples) # REST Endpoints -All endpoints return a JSON object containing the following fields: +All endpoints return a JSON object containing the fields as specified in the [REST Endpoint](/general-information.md#rest-endpoints) details. -| Name | Type | Required/Optional | Description | -| ------ | ------ | ------------------- | ------------- | -| `data` | _Endpoint-dependent_ | Required | The requested data objects. | -| `version` | String | Required | The specification version that the API conforms to (currently, `0.0`) | -| `time_zone` | String | Required | The time zone that applies to parking regulations in this dataset. MUST be a valid [TZ database](https://www.iana.org/time-zones) time zone name (e.g. `"US/Eastern"` or `"Europe/Paris"`). | -| `last_updated` | [Timestamp][ts] | Required | The last time the data in this API was updated. | -| `currency` | String | Required | The ISO 4217 3-letter code for the currency in which rates for curb usage are denominated. | -| `author` | String | Optional | The name of the organization that produces and maintains this data. | -| `license_url` | URL | Optional | The licensing terms under which this data is provided. | - -Servers MUST set the `Content-Type` header to `application/vnd.cds+json;version=0.0` to support -versioning in the future. Clients SHOULD specify an `Accept` header containing -`application/vnd.cds+json;version=0.0`. If the server receives a request that contains an `Accept` -header but does not include this value; it MUST respond with a status of `406 Not Acceptable`. +[Top][toc] + +## Authorization + +[Authorization](/general-information.md#authorization) is not required for any of the Curbs endpoints, as this information should be made public and easily accessible. [Top][toc] ## Query Curb Zones -Endpoint: `/curbs/zone` +Endpoint: `/curbs/zones` Method: `GET` -`data` Payload: a JSON object with the following fields: - - `zones`: an array of [Curb Zone](#curb-zone) objects - - `policies`: an array of [Policy](#policy) objects +`data` Payload: a JSON object with a `zones` field containing an array of [Curb Zone](#curb-zone) objects. -_This endpoint must be implemented by every Curbs API server._ +_This required endpoint must be implemented by every Curbs API server. If attaching policies to curb zones, the [Query Curb Policies](#query-curb-policies) endpoint is also required._ ### Query Parameters @@ -84,18 +85,17 @@ All query parameters are optional. | `min_lat`
`min_lng`
`max_lat`
`max_lng` | Numeric | Specifies a bounding box; if one of these parameters is specified, all four MUST be. If specified only return Curb Zones that intersect the supplied bounding box. | | `lat`
`lng`
`radius` | Numeric | If one of these parameters is specified, all three MUST be. Returns only Curb Zones that are within `radius` centimeters of the point identified by `lat`/`lng`. Curb Zones in the response MUST be ordered ascending by distance from the center point. | | `include_geometry` | `true`/`false` | If the value is `false`, do not include the `geometry` field within the [Curb Zone](#curb-zone) feature object. | -| `include_policies` | `true`/`false` | If the value is `false`, do not include the `policies` field within the response. | | `time` | [Timestamp][ts] | Only Curb Zone objects whose validity period includes this time will be returned; availability data (if supplied) will be returned as of this time. | [Top][toc] ## Query Curb Areas -Endpoint: `/curbs/area` +Endpoint: `/curbs/areas` Method: `GET` `data` Payload: a JSON object with an `areas` field containing an array of [Curb Area](#curb-area) objects. -_Optional endpoint; if not implemented, the server should reply with `501 Not Implemented`._ +_Optional endpoint. If not implemented, the server should reply with `501 Not Implemented`._ ### Query Parameters @@ -110,11 +110,11 @@ All query parameters are optional. ## Query Curb Spaces -Endpoint: `/curbs/space` +Endpoint: `/curbs/spaces` Method: `GET` `data` Payload: a JSON object with a `spaces` field containing an array of [Curb Space](#curb-space) objects. -_Optional endpoint; if not implemented, the server should reply with `501 Not Implemented`._ +_Optional endpoint. If not implemented, the server should reply with `501 Not Implemented`._ ### Query Parameters @@ -131,11 +131,11 @@ All query parameters are optional. ## Query Curb Policies -Endpoint: `/curb/policy` +Endpoint: `/curbs/policies` Method: `GET` -`data` Payload: a JSON object with a `policies` field containing an array of [Curb Policy](#curb-policy) objects. +`data` Payload: a JSON object with a `policies` field containing an array of [Curb Policy](#policy) objects. -_Optional endpoint; if not implemented, the server should reply with `501 Not Implemented`._ +_Optional endpoint, but required if Curb Zones contain policy_id references. If not implemented, the server should reply with `501 Not Implemented`._ ### Query Parameters @@ -149,29 +149,30 @@ All query parameters are optional. ## Fetch a Curb Zone -Endpoint: `/curbs/zone/` +Endpoint: `/curbs/zones/` Method: `GET` `data` Payload: the [Curb Zone](#curb-zone) object with the ID provided in the path. -_Optional endpoint; if not implemented, the server should reply with `501 Not Implemented`._ +_Optional endpoint. If not implemented, the server should reply with `501 Not Implemented`._ ### Query Parameters All query parameters are optional. -| Name | Type | Description | -| ------------ | --------- | ---------------------------------------------- | -| `time` | [Timestamp][ts] | The Curb Zone object will only be returned if its validity period includes this time; otherwise, the server should reply with `404 Not Found`. Availability data (if supplied) will be returned as of this time. | +| Name | Type | Description | +| --------------- | --------------- | ---------------------------------------------- | +| `time` | [Timestamp][ts] | The Curb Zone object will only be returned if its validity period includes this time; otherwise, the server should reply with `404 Not Found`. Availability data (if supplied) will be returned as of this time. | +| `show_historic` | Boolean | Whether to return historic, retired curb zone data. Default is "false" to reduce payload size and complexity. | [Top][toc] ## Fetch a Curb Area -Endpoint: `/curbs/area/` +Endpoint: `/curbs/areas/` Method: `GET` `data` Payload: the [Curb Area](#curb-area) object with the ID provided in the path. -_Optional endpoint; if not implemented, the server should reply with `501 Not Implemented`._ +_Optional endpoint. If not implemented, the server should reply with `501 Not Implemented`._ ### Query Parameters @@ -181,25 +182,27 @@ This endpoint takes no query parameters. ## Fetch a Curb Space -Endpoint: `/curbs/space/` +Endpoint: `/curbs/spaces/` Method: `GET` `data` Payload: the [Curb Space](#curb-space) object with the ID provided in the path. +_Optional endpoint. If not implemented, the server should reply with `501 Not Implemented`._ + ### Query Parameters All query parameters are optional. -| Name | Type | Description | -| ------------ | --------- | ---------------------------------------------- | -| `time` | [Timestamp][ts] | Availability data (if supplied) will be returned as of this time. | +| Name | Type | Description | +| ------------ | --------------- | ---------------------------------------------- | +| `time` | [Timestamp][ts] | Availability data (if supplied) will be returned as of this time. | [Top][toc] ## Fetch a Curb Policy -Endpoint: `/curb/policy/` +Endpoint: `/curbs/policies/` Method: `GET` -`data` Payload: the [Curb Policy](#curb-policy) object with the ID provided in the path. +`data` Payload: the [Curb Policy](#policy) object with the ID provided in the path. ### Query Parameters @@ -224,7 +227,8 @@ criteria: 1. Never overlap other Curb Zones in the same dataset with overlapping validity times. This applies to both the zone's polygon geometries and linear references (if used). 1. Be assigned a unique ID, in the form of a [UUID][uuid]. This ID SHOULD remain consistent as long as - the Curb Zone's extent and policies remain substantially the same. + the Curb Zone's geography remains substantially the same. Policies may be updated without changing + the ID. 1. It SHOULD NOT be possible to legally park a single vehicle in two different Curb Zone at the same time (i.e., a given non-demarcated parking area or loading zone should be represented as a single curb location), unless this conflicts with the requirements above. @@ -234,10 +238,14 @@ A Curb Zone is represented as a JSON object, whose fields are as follows: | Name | Type | Required/Optional | Description | | ------ | ------ | ------------------- | ------------- | | `curb_zone_id` | [UUID][uuid] | Required | The ID of this Curb Zone. | -| `geometry` | [Polygon][polygon] | Required | The spatial extent of this curb zone. | +| `geometry` | [Polygon][polygon] | Required | The spatial extent of this curb zone. A new `curb_zone_id` is required if this geometry changes. | | `curb_policy_ids` | Array of [UUIDs][uuid] | Required | An array of IDs of [Policy objects](#policy). Together, these define the regulations of this Curb Zone. | -| `start_date` | [Timestamp][ts] | Required | The earliest time that the data for this curb location is known to be valid. This could be the date on which the data was collected, for instance. This MUST never change for a given id. | -| `end_date` | [Timestamp][ts] | Optional | The time at which the data for this curb location ceases to be valid. If not present, the data will be presumed to be valid indefinitely. | +| `prev_policies` | Array of [Previous Policy](#previous-policy) objects | Optional | An array of information about previous policies that have applied to this curb zone. They are listed in order with the most recent ones first. | +| `published_date` | [Timestamp][ts] | Required | The date/time that this curb zone was first published in this data feed. | +| `last_updated_date` | [Timestamp][ts] | Required | The date/time that the properties of ths curb zone were last updated. This helps consumers know that some curb objects fields may have changed. | +| `prev_curb_zone_ids` | Array of [UUIDs][uuid] | Optional | An array of IDs of previous curb zone objects. They are listed in order with the most recent ones first. | +| `start_date` | [Timestamp][ts] | Required | The earliest time that the data for this curb location is known to be valid (_inclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). This could be the date on which the data was collected, for instance. This MUST never change for a given id. | +| `end_date` | [Timestamp][ts] | Optional | The time at which the data for this curb location ceases to be valid (_exclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). If not present, the data will be presumed to be valid indefinitely. | | `location_references` | Array of [Location Reference](#location-reference) objects | Optional | One or more linear references for this Curb Zone. | | `name` | String | Optional | A human-readable name for this Curb Zone that identifies it to end users. | | `user_zone_id` | String | Optional | An identifier that can be used to refer to this Curb Zone on physical signage as well as within mobile applications, typically for payment purposes. | @@ -255,19 +263,14 @@ A Curb Zone is represented as a JSON object, whose fields are as follows: | `entire_roadway`| Boolean | Optional | If "true", this curb location takes up the entire width of the roadway (which may be impassible for through traffic when the Curb Zone is being used for parking or loading). This is a common condition for alleyways. If `entire_roadway` is `true`, `street_side` MUST NOT be present. | | `curb_area_id`| [UUID][uuid] | Optional | The ID of the [Curb Area](#curb-area) that this Curb Zone is a part of. If specified, the area identified MUST be retrievable through the Curb API and its geographical area MUST contain that of the Curb Zone. | +[Top][toc] + ### Curb Zone ID Stability -The `curb_zone_id` field uniquely identifies a particular zone with one particular set of policies. +The `curb_zone_id` field uniquely identifies a particular zone with one particular set of policies in a specific geographic area. - - *New ID*: When a Curb Zone ceases to be valid, or it needs substantive changes, its ID - MUST NOT not be reused by a Curb Zone with different data, even if it occupies the same - location. If data updates reflect changes in the physical world or agency regulations, - a new ID MUST be assigned. - - *No new ID*: data updates that reflect changes in how the same physical locations or - regulations are modeled digitally -- e.g., additional metadata, or regulations being modeled - more accurately -- SHOULD NOT be implemented by ending a Curb Zone's validity and creating a - new one with a new ID. The existing Curb Zone can be updated silently with the new data; - callers MAY NOT rely on a Curb Zone with the same ID remaining identical over time. +- *New ID*: When a Curb Zone ceases to be valid, or it needs substantive geometric changes, it will be retired and returned only when the `show_historic` flag is "true" in the [Query Curb Zones](#query-curb-zones) endpoint parameters. Its ID _MUST NOT_ not be reused by a Curb Zone with different data. If geometric data updates reflect changes in the physical world, a new ID MUST be assigned and the previous one stored for historic lookups. +- *No new ID*: data updates that reflect changes in how the same physical locations or regulations are modeled digitally -- e.g., additional metadata, or regulations being modeled more accurately -- SHOULD NOT be implemented by ending a Curb Zone's validity and creating a new one with a new ID. The existing Curb Zone can be updated silently with the new data and its `last_updated_date` changed. Callers MAY NOT rely on a Curb Zone with the same ID remaining identical over time. If policies in a zone change, you may update the policy IDs, track previous policies, and reset the `last_updated_date`, but keep the zone ID the same. [Top][toc] @@ -276,9 +279,10 @@ The `curb_zone_id` field uniquely identifies a particular zone with one particul Defines curb areas in a city and their properties. A Curb Area is a particular neighborhood or area of interest that includes one or more [Curb Zones](#curb-zone). Important notes about Curb Areas: - * Curb Areas MAY overlap with other Curb Areas - * Curb Areas are not meant to be city-wide, and instead should be an area of interest around one + - Curb Areas MAY overlap with other Curb Areas + - Curb Areas are not meant to be city-wide, and instead should be an area of interest around one or more Curb Zones that is no bigger than a neighborhood. + - Unlike Zones, Areas may be updated as needed, with a new `curb_area_id` being optionally assigned by the city A Curb Area is represented as a JSON object, whose fields are as follows: @@ -286,7 +290,9 @@ A Curb Area is represented as a JSON object, whose fields are as follows: | ------ | ------ | ------------------- | ------------- | | `curb_area_id` | [UUID][uuid] | Required | The ID for the curb area. | | `geometry` | [Polygon][polygon] | Required | The spatial extent of this curb location. | -| `name` | String | Required | The name of this curb area. | +| `name` | String | Optional | The name of this curb area for reference. | +| `published_date` | [Timestamp][ts] | Required | The date/time that this curb area was first published in this data feed. | +| `last_updated_date` | [Timestamp][ts] | Required | The date/time that the properties of ths curb area were last updated. This helps consumers know that some fields may have changed. | | `curb_zone_ids` | Array of [UUIDs][uuid] | Required | The IDs of all the Curb Zones included within this Curb Area at the requested time. | [Top][toc] @@ -294,8 +300,10 @@ A Curb Area is represented as a JSON object, whose fields are as follows: ## Curb Space Defines individual demarcated spaces within a Curb Zone. Important notes about Curb Spaces: + - Curb Spaces may NOT overlap with other Curb Spaces - Curb Spaces must be wholly contained within a single Curb Zone + - Unlike Zones, Spaces may be updated as needed, with a new `curb_space_id` being optionally assigned by the city A Curb Space is represented as a JSON object whose fields are as follows: @@ -303,6 +311,9 @@ A Curb Space is represented as a JSON object whose fields are as follows: | ------ | ------ | ------------------- | ------------- | | `curb_space_id` | [UUID][uuid] | Required | The ID of the curb space. | | `geometry` | [Polygon][polygon] | Required |The spatial extent of this curb location. | +| `name` | String | Optional | The name of this curb space for reference. | +| `published_date` | [Timestamp][ts] | Required | The date/time that this curb area was first published in this data feed. | +| `last_updated_date` | [Timestamp][ts] | Required | The date/time that the properties of ths curb area were last updated. This helps consumers know that some fields may have changed. | | `curb_zone_id` | [UUID][uuid] | Required | The ID of the Curb Zone this space is within. The geometry of the specified Curb Zone MUST contain the geometry of this space. | | `space_number` | Integer | Optional | The sequence number of this space within its Zone. If specified, two spaces within the same Curb Zone MUST NOT share a space number, and space numbers SHOULD be consecutive positive integers starting at 1. | | `length` | Integer | Required | Length in centimeters of this Space. If comparing the length of a vehicle to that of a space, note that vehicles may have to account for a buffer for doors, mirrors, bumpers, ramps, etc. | @@ -314,7 +325,7 @@ A Curb Space is represented as a JSON object whose fields are as follows: ## Policy -A Policy object is a rule that allows or prohibits a particular set of users from using a particular curb at a particular time or times. Multiple Policy objects together define the full extent of regulations within a [Curb Zone](#curb-zone). Much of this is similar to curbLR. +A Policy object is a rule that allows or prohibits a particular set of users from using a particular curb at a particular time or times. Multiple Policy objects together define the full extent of regulations within a [Curb Zone](#curb-zone). The design of the Policy object borrows heavily from the work of the [CurbLR](https://github.com/curblr/curblr-spec) project, with additions for the larger scope of CDS. The `policy` field within the FeatureCollection returned by [Query Curb Zones](#query-curb-zones) contains a list of the Policy objects referenced by the returned zones. In addition, the [Query Curb Policies](#query-curb-policies) endpoint return the complete list of policies. @@ -322,23 +333,30 @@ A Policy is represented as a JSON object whose fields are as follows: | Name | Type | Required/Optional | Description | | ------ | ------ | ------------------- | ------------- | -| `curb_policy_id` | UUD | Required | An ID that uniquely identifies this exact regulation across Curb Zones. Two Policy objects containing the same `curb_policy_id` MUST be completely identical. A `curb_policy_id` MUST NOT be reused -- once created, it must continue to refer to the identical policy forever. | -| `priority` | Integer | Required | Specifies which other policies this one takes precedence over. If two Policies on the same Curb Zone have overlapping [Time Spans](#time-span) and apply to the same user class, the one that applies at a given time is the one with the **lowest** priority. Two Policies that apply to the same Curb Zone with overlapping Time Spans and user classes MUST NOT have the same priority. | +| `curb_policy_id` | UUID | Required | An ID that uniquely identifies this exact regulation across Curb Zones. Two Policy objects containing the same `curb_policy_id` MUST be completely identical. A `curb_policy_id` MUST NOT be reused -- once created, it must continue to refer to the identical policy forever. | +| `published_date` | [Timestamp][ts] | Required | The date/time that this policy was first published in this data feed. | +| `priority` | Integer | Required | Specifies which other policies this one takes precedence over. If two Policies on the same Curb Zone have overlapping [Time Spans](#time-span) and apply to the same user class, the one that applies at a given time is the one with the **lowest** priority. E.g., a priority of `1` takes precedence over a priority of `3`. Two Policies that apply to the same Curb Zone with overlapping Time Spans and user classes MUST NOT have the same priority. | | `rules` | Array of [Rules](#rule) | Required | The rule(s) that this policy applies. If a Policy specifies multiple rules, each rule MUST specify disjoint lists of user classes. | | `time_spans` | Array of [Time Spans](#time-span) | Optional | If specified, this regulation only applies at the times defined within. | +| `data_source_operator_id` | Array of [UUIDs][uuid] | Optional | An array of Data Source Operator IDs that this policy only applies to. IDs come from [data_source_operators.csv](/data_source_operators.csv) file here in the CDS repo. Read our [How to Get a Data Source Operator ID](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Adding-a-CDS-Data-Source-Operator-ID) guide. | + +[Top][toc] ### Rule A rule defines who is allowed to do what, and for how long, on a curb, per the policy. + It is a JSON object with the following fields: | Name | Type | Required/Optional | Description | | ------ | ------ | ------------------- | ------------- | -| `activity` | String | Required | The activity that is forbidden or permitted by this regulation. Value MUST be one of the [activities below](#activities). | -| `max_stay` | Integer | Optional | The length of time (in minutes) for which the curb may be used under this regulation. | -| `no_return` | Integer | Optional | The length of time (in minutes) that a user must vacate a Curb Zone before allowed to return for another stay. | -| `user_classes` | Array of Strings | If specified, this regulation only applies to users matching the [user classes](#user-classes) contained within. If not specified, this regulation applies to everyone. | -| `rate` | Array of [Rates](#rate) | Optional | The cost of using this Curb Zone when this regulation applies. Rates are repeated to allow for prices that change over time. For instance, a regulation may have a price of $1 for the first hour but $2 for every subsequent hour. | +| `activity` | [Activity](#activities) String | Required | The activity that is forbidden or permitted by this regulation. Value MUST be one of the [activities](#activities). | +| `max_stay` | Integer | Optional | The length of time (in minutes) for which the curb may be used under this regulation. | +| `no_return` | Integer | Optional | The length of time (in minutes) that a user must vacate a Curb Zone before being allowed to return for another stay. | +| `user_classes` | Array of [user class](#user-classes) Strings | Optional | If specified, this regulation only applies to users matching the [user classes](#user-classes) contained within. If not specified, this regulation applies to everyone. | +| `rate` | Array of [Rates](#rate) | Optional | The cost of using this Curb Zone when this regulation applies. Rates are repeated to allow for prices that change over time. For instance, a regulation may have a price of $1 for the first hour but $2 for every subsequent hour. The complete set of the [Rates](#rate) array must span **from** `start_minutes` = `0` or `null` **to** `end_minutes` = `max_stay` without overlap of effective minutes (i.e. the range created by rate `start_minutes` and `end_minutes`). If a "negative" [activity](#activities) is used, this array should be empty. | + +[Top][toc] #### Activities @@ -346,37 +364,78 @@ The following activities may be specified for rules within a policy. The reason "positive" and "negative" versions of the same activities (like `loading` and `no parking`) is due to priorities: a `loading` rule that is higher priority than a `no loading` rule, for instance, implies that the Curb Zone does allow loading at the time in question, while a -`no parking` rule would not. +`no parking` rule would not. If "negative", `rate` array should be empty. + +- `parking` - implies that loading and stopping are also permitted +- `no parking` - may not stop and leave vehicle unattended +- `loading` - loading of goods; implies that stopping is also permitted +- `no loading` - no loading allowed; implies that parking is also prohibited +- `unloading` - unloading of goods; implies that stopping is also permitted +- `no unloading` - no unloading allowed; implies that parking is also prohibited +- `stopping` - stopping briefly to pick up or drop off passengers +- `no stopping` - stopping, loading, unloading, and parking are all prohibited; not a typical travel lane +- `travel` - represents curbside lanes intended for moving vehicles, like bus lanes, bike lanes, + and rush-hour-only travel lanes; implies that parking, loading, unloading, and stopping are prohibited. -- `parking` (implies that loading and stopping are also permitted) -- `no parking` -- `loading` (of goods; implies that stopping is also permitted) -- `no loading` (implies that parking is also prohibited) -- `stopping` (stopping briefly to pick up or drop off passengers) -- `no stopping` (stopping, loading, and parking are all prohibited) -- `travel`: represents curbside lanes intended for moving vehicles, like bus lanes, bike lanes, - and rush-hour-only travel lanes; implies that parking, loading, and stopping are prohibited). +[Top][toc] #### User Classes A user class represents any class of vehicles that is regulated by a city with respect to curb space. They can be defined by the vehicle's physical characteristics (e.g., trucks, vans, EVs), -the presence/absence of a particular permit (e.g., residential parking permits) or even by the +the presence/absence of a particular permit (e.g., residential parking permits), or even by the intent or destination of the driver, for things like hotel or school unloading zones. -New user classes MAY be generated by data providers to reflect their regulations, but when possible, -the following known values should be used: +These are not meant to be a mirror to similarly named items in the Events API, but instead serve a +unique purpose of describing locally defined regulations at a curb. + +This array of user classes serves as an 'AND' function. A vehicle must have all the properties listed +in the array to use the curb. For example, an accessible EV bus will use `handicap-accessible` AND `electric` +AND `bus`. To create 'OR' values at the same curb, you must create a new rule +with the new array of values. + +New user classes MAY be generated to reflect local regulations, but when possible, +the following well-known recommended values should be used. If multiple similar values apply, then use the more +descriptive/specific value when possible. +**Well-known values:** + +Vehicle types - `bicycle` - `bus` -- `handicap` +- `cargo_bicycle` +- `car` +- `moped` - `motorcycle` -- `resident` +- `scooter` +- `truck` +- `van` + +Vehicle properties +- `handicap-accessible` +- `human` +- `electric_assist` +- `electric` +- `combustion` +- `autonomous` + +Purpose +- `construction` +- `delivery` +- `emergency_use` +- `freight` +- `parking` +- `permit` - `rideshare` +- `school` +- `service_vehicles` +- `special_events` - `taxi` -- `commercial` (applies to "truck"; if "commercial" and "truck" user classes have separate rules, - trucks use the "truck" rule) -- `truck` +- `utilities` +- `vending` +- `waste_management` + +[Top][toc] ### Time Span @@ -394,27 +453,32 @@ A Time Span is represented as a JSON object whose fields are as follows: | Name | Type | Required/Optional | Description | | ------ | ------ | ------------------- | ------------- | -| `from` | [Timestamp][ts] | Optional | The earliest point in time that this Time Span could apply. If unspecified, the Time Span applies to all matching periods arbitrarily far in the past. | -| `to` | [Timestamp][ts] | Optional | The latest point in time that this Time Span could apply. If unspecified, the Time Span applies to all matching periods arbitrarily far in the future. | +| `start_date` | [Timestamp][ts] | Optional | The earliest point in time that this Time Span could apply (_inclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). If unspecified, the Time Span applies to all matching periods arbitrarily far in the past. See note below for more details. | +| `end_date` | [Timestamp][ts] | Optional | The latest point in time that this Time Span could apply (_exclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). If unspecified, the Time Span applies to all matching periods arbitrarily far in the future. See note below for more details. | | `days_of_week` | Array of strings | Optional | An array of days of the week when this Time Span applies, specified as 3-character strings (`"sun"`, `"mon"`, `"tue"`, `"wed"`, `"thu"`, `"fri"`, `"sat"`). | | `days_of_month` | Array of integers | Optional | An array of days of the month when this Time Span applies, specified as integers (1-31). Note that, in order to specify, e.g., the "2nd Monday of the month", you can use `days_of_month` combined with `days_of_week` (in this example, `days_of_week = ["mon"]` and `days_of_month = [8,9,10,11,12,13,14]`). | | `months` | Array of integers | Optional | If specified, this Time Span applies only during these months (1=January, 12=December). | -| `time_of_day_start` | "HH:MM" string | Optional | The 24-hour local time that this Time Span starts to apply. If unspecified, this Time Span starts at midnight. | -| `time_of_day_end` | "HH:MM" string | Optional | The 24-hour local time that this Time Span stops applying. This is not inclusive, so for instance if `time_of_day_end` is `"17:00"`, this Time Span goes up to 5PM but does not include it. If unspecified, this Time Span ends at midnight. | +| `time_of_day_start` | "HH:MM" string | Optional | The 24-hour local time that this Time Span starts to apply (_inclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). If unspecified, this Time Span starts at midnight. | +| `time_of_day_end` | "HH:MM" string | Optional | The 24-hour local time that this Time Span stops applying (_exclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). This is not inclusive, so for instance if `time_of_day_end` is `"17:00"`, this Time Span goes up to 5PM but does not include it. If unspecified, this Time Span ends at midnight. | | `designated_period` | String | Optional | A string representing an arbitrarily-named, externally-defined period of time. Any values MAY be specified but the following known values SHOULD be used when possible:
  • `snow emergency`
  • `holidays`
  • `school days`
  • `game days`
| | `designated_period_except` | `Boolean` | `Optional` | If specified and `true`, this Time Span applies at all times not matching the named designated period. (e.g., if `designated_period` is `snow emergency` and `designated_period_except` is `true`, this Time Span does not apply on snow days). | +**Note about `start_date` and `end_date` in _Time Span_:** these fields are optional but useful for defining policies that will be used once and won't be reused later, like around a specific, temporary event. If used, they are only applicable in any connected Curb Zone during their overlapping time frames. + +[Top][toc] + ### Rate A Rate defines the amount a user of the curb needs to pay when a given rule applies. It is a JSON object with the following fields: | Name | Type | Required/Optional | Description | | ------ | ------ | ------------------- | ------------- | -| `per_hour` | Integer | Required | The rate per hour for this space in cents (or the smallest denomination of local currency). | +| `rate` | Integer | Required | The rate for this space in cents (or the smallest denomination of local currency) per `rate_unit`. | +| `rate_unit` | Enum | Required | The unit of time associated with the rate. One of "second", "minute", "hour", "day", "week", "month", "year". | | `increment_minutes` | Integer | Optional | If specified, this is the smallest amount of time a user can pay for (e.g., if `increment_minutes` is `15`, a user can pay for 15, 30, 45, etc. minutes). | | `increment_amount` | Integer | Optional | If specified, the rate for this space is rounded up to the nearest increment of this amount, specified in the same units as `per_hour`. | -| `start_minutes` | Integer | Optional | The amount of time the vehicle must have already been present in the Curb Zone before this rate starts applying. If not specified, this rate starts when the vehicle arrives. | -| `end_minutes` | Integer | Optional | The amount of time after which the rate stops applying. If not specified, this rate ends when the vehicle departs. | +| `start_minutes` | Integer | Optional | The amount of time the vehicle must have already been present in the Curb Zone before this rate starts applying (_inclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). If not specified, this rate starts when the vehicle arrives. | +| `end_minutes` | Integer | Optional | The amount of time after which the rate stops applying (_exclusive_, see [Time Range](/general-information.md#time-range)). If not specified, this rate ends when the vehicle departs. | [Top][toc] @@ -426,12 +490,32 @@ A Location Reference is a JSON object with the following fields: | Name | Type | Required/Optional | Description | | ------ | ------ | ------------------- | ------------- | -| `source` | URL | Required | An identifier for the source of the linear reference. This MUST be URL pointing to more information about the underlying map or reference system. Values include (but other can be used):
  • `https://sharedstreets.io`: SharedStreets
  • `http://openlr.org`: OpenLR
  • `https://coord.com`: Coord
  • `https://yourcityname.gov`: custom city LR, direct link if possible
  • | +| `source` | URL | Required | An identifier for the source of the linear reference. This MUST be a URL pointing to more information about the underlying map or reference system. Values include (but other can be used):
    • `https://sharedstreets.io`: SharedStreets
    • `http://openlr.org`: OpenLR
    • `https://coord.com`: Coord
    • `https://yourcityname.gov`: custom city LR, direct link if possible
    | | `ref_id` | String | Required | The linear feature being referenced (usually a street or curb segment). For OpenLR, this is the Base64-encoded OpenLR line location for the street segment of which this Curb Zone is part, and the start and end offsets below are relative to this segment. | -| `start` | Integer | Required | The distance (in centimeters) from the start of the referenced linear feature to the start of the Curb Zone. | -| `end` | Integer | Required | The distance (in centimeters) from the start of the referenced linear feature to the end of the Curb Zone. end MAY be smaller than start, implying that the direction of the Curb Zone is opposite to the direction of the referenced linear feature. | +| `start` | Integer | Required | The distance (in centimeters) from the start of the referenced linear feature to the start of the Curb Zone (_inclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). | +| `end` | Integer | Required | The distance (in centimeters) from the start of the referenced linear feature to the end of the Curb Zone (_exclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). 'end' MAY be smaller than start, implying that the direction of the Curb Zone is opposite to the direction of the referenced linear feature - in this case the [Range Boundaries](/general-information.md#range-boundaries)) are reversed. | | `side` | String | Optional | If the referenced linear feature is a roadway, the side of the roadway on which the Curb Zone may be found, when heading from the start to the end of the feature in its native orientation. Values are `left` and `right`. MUST be absent for features where `entire_roadway` is true. | +[Top][toc] + +## Previous Policy + +An array of information about what previous policies applied to a [curb zone](#curb-zone) and when. This allows cities to historically track what policies applied to a curb zone. + +A Previous Policy is a JSON object with the following fields: + +| Name | Type | Required/Optional | Description | +| ------ | ------ | ------------------- | ------------- | +| `curb_policy_ids` | Array of [UUIDs][uuid] | Required | An array of IDs of [Policy objects](#policy). Together, these define the previous regulations of this Curb Zone. | +| `start_date` | [Timestamp][ts] | Required | The date/time that this policy started being active for this curb location (_inclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). | +| `end_date` | [Timestamp][ts] | Required | The date/time that this policy ended being active for this curb location (_exclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). | + +[Top][toc] + +# Examples + +See a series of [CDS Curbs endpoint examples](examples.md) to use as templates. + [Top][toc] [toc]: #table-of-contents diff --git a/curbs/examples.md b/curbs/examples.md new file mode 100644 index 00000000..cd2d1f15 --- /dev/null +++ b/curbs/examples.md @@ -0,0 +1,136 @@ +# Curbs Examples + +This file presents a series of CDS [Curbs](/curbs) endpoint examples to use as templates. + +## Table of Contents + +- [Curb Zones Minimum](#curb-zones-minimum) +- [Curb Policies](#curb-policies) + +## Curb Zones Minimum + +A [Query Curb Zones](/curbs#query-curb-zones) example of `/curbs/zones` with minimum required fields returned, and some [query parameters](/curbs#query-parameters) passed in. + +**Query**: + +`/curbs/zones?include_geometry=true&time=1552678594427` + +**Payload**: + +```json +{ + "version": "1.0", + "time_zone": "US/Eastern", + "last_updated": 1552678594428, + "currency": "USD", + "author": "City of Metropolis", + "license_url": "https://creativecommons.org/licenses/by/4.0/", + "data": [ + { + "zones": [ + { + "curb_zone_id": "7d8a5885-e949-4ac9-afb7-fa4d43b68530", + "geometry": { + "type": "Polygon", + "coordinates": [[ + [-73.982105, 40.767932], + [-73.973694, 40.764551], + [-73.949318, 40.796918], + [-73.958416, 40.800686], + [-73.982105, 40.767932] + ]] + }, + "curb_policy_ids": [ + "cd0996d7-3765-4f0b-a72e-7caf7cf3fe21" + ], + "published_date": 1552678594428, + "last_updated_date": 1552678594428, + "start_date": 1552678594428 + } + ] + } + ] +} +``` + +[Top](#table-of-contents) + +## Curb Policies + +A [Query Curb Policies](https://github.com/openmobilityfoundation/curb-data-specification/tree/feature-release-work-1/curbs#query-curb-policies) example of `/curbs/policies` showing policies giving 3 fleet operators using electric vehicles operating rideshare curb access for max 15 minute drop-offs on weekdays from 10am to 4pm, other commerical activity for up to 60 minutes between 8am and 10pm, but otherwise no stopping (eg overnight). No [query parameters](/curbs#query-parameters-3) passed in. + +**Query**: + +`/curbs/policies` + +**Payload**: + +```json +{ + "version": "1.0", + "time_zone": "US/Eastern", + "last_updated": 1552678594428, + "currency": "USD", + "author": "City of Metropolis", + "license_url": "https://creativecommons.org/licenses/by/4.0/", + "data": [ + { + "policies": [ + { + "curb_policy_id": "cd0996d7-3765-4f0b-a72e-7caf7cf3fe21", + "published_date": 1552678594428, + "priority": 1, + "data_source_operator_id": [ + "b2046faf-2bc2-4f0e-b784-7cc746138555", + "aba63473-351c-4624-93ab-456db34f83a6", + "984cae91-3a11-49eb-b68c-d325a6cc8970" + ], + "time_spans": [ + { + "days_of_week": ["mon", "tue", "wed", "thu", "fri"], + "time_of_day_start": "10:00", + "time_of_day_end": "16:00" + } + ], + "rules": [ + { + "activity": "parking", + "max_stay": 15, + "user_classes": [ + "rideshare", "electric" + ] + } + ] + },{ + "curb_policy_id": "51f58575-1042-4254-b5fc-fed97124a6c7", + "published_date": 1552678857362, + "priority": 2, + "time_spans": [ + { + "time_of_day_start": "08:00", + "time_of_day_end": "22:00" + } + ], + "rules": [ + { + "activity": "parking", + "max_stay": 60 + } + ] + },{ + "curb_policy_id": "8c0abb35-b8d2-469e-bdb1-b6de52c430ac", + "published_date": 1552678857362, + "priority": 3, + "rules": [ + { + "activity": "no stopping" + } + ] + } + ] + } + ] +} +``` + +[Top](#table-of-contents) diff --git a/data_source_operators.csv b/data_source_operators.csv new file mode 100644 index 00000000..bef4b4a5 --- /dev/null +++ b/data_source_operators.csv @@ -0,0 +1,7 @@ +data_source_operator_name,data_source_operator_id,url +Automotus,6ee362db-b059-43ac-83d4-3d634ec7a22c,https://www.automotus.co/ +Bird,2411d395-04f2-47c9-ab66-d09e9e3c3251,https://www.bird.co +Kiwibot,5f19acae-d7e9-4b57-96bd-f6406712d654,https://www.kiwibot.com/ +Passport,55b617b9-730e-485e-83de-5e1a35fdc352,https://www.passportinc.com/ +Spin,70aa475d-1fcd-4504-b69c-2eeb2107f7be,https://www.spin.app +Waymo,288e70d7-fa0b-499d-ab20-a686ec4ee2cb,https://waymo.com/ diff --git a/events/README.md b/events/README.md index 4206a8da..b836545a 100644 --- a/events/README.md +++ b/events/README.md @@ -1,9 +1,10 @@ # Curb Data Specification: Events API -The Events API is a REST API allowing real-time and historic events at the curb to be sent to cities, and the ability to check on the status of any sensors. Events can come from company data feeds, sensors, payments, check-ins, enforcement, and/or other city data sources. Data sent in the Events API can be connected to the Curbs API over time and space, and events are used for calcuations in the Metrics API. +CDS Events Icon -## ⚠ Beta -> **This feature is current a draft of the initial CDS beta release. It will change as development and real-world feedback happens.** +The Events API is a REST API allowing real-time and historic events at the curb to be sent to cities, and the ability to check on the status of any sensors. Events can come from company data feeds, on street sensors, session payments, company check-ins, in-person parking personnel, and/or other city data sources. Data sent in the Events API can be connected to the Curbs API over time and space, and events are used for calculations in the Metrics API. + +**See [other CDS APIs](/README.md#curb-data-specification-apis) on the homepage.** # Endpoints @@ -12,46 +13,44 @@ There are two different endpoints that are part of the Events API: - A [Curb Event](#curb-event) is an activity that occurs near, at, or within a pre-defined curb area. Defining events is *required* as part of the Events API. - A [Status](#status) is the current status of a curb monitoring source. Event status is *optional*. +**See [examples](examples.md) for these endpoints.** + # Table of Contents - [REST Endpoints](#rest-endpoints) + - [Authorization](#authorization) * [Query Event](#query-event) * [Query Status](#query-status) - [Data Objects](#data-objects) * [Curb Event](#curb-event) * [Event Type](#event-type) + * [Source Type](#source-type) * [Vehicle Type](#vehicle-type) * [Propulsion Type](#propulsion-type) + * [Event Purpose](#event-purpose) * [Lane Type](#lane-type) * [Curb Occupant](#curb-occupant) * [Status](#status) +- [Examples](#examples) # REST Endpoints -All endpoints return a JSON object containing the following fields: +All endpoints return a JSON object containing the fields as specified in the [REST Endpoint](/general-information.md#rest-endpoints) details. -| Name | Type | Required/Optional | Description | -| ------ | ------ | ------------------- | ------------- | -| `data` | _Endpoint-dependent_ | Required | The requested data objects. | -| `version` | String | Required | The specification version that the API conforms to (currently, `0.0`) | -| `time_zone` | String | Required | The time zone that applies to parking regulations in this dataset. MUST be a valid [TZ database](https://www.iana.org/time-zones) time zone name (e.g. `"US/Eastern"` or `"Europe/Paris"`). | -| `last_updated` | [Timestamp][ts] | Required | The last time the data in this API was updated. | -| `author` | String | Optional | The name of the organization that produces and maintains this data. | -| `license_url` | URL | Optional | The licensing terms under which this data is provided. | - -Servers MUST set the `Content-Type` header to `application/vnd.cds+json;version=0.0` to support -versioning in the future. Clients SHOULD specify an `Accept` header containing -`application/vnd.cds+json;version=0.0`. If the server receives a request that contains an `Accept` -header but does not include this value; it MUST respond with a status of `406 Not Acceptable`. +[Top][toc] + +## Authorization + +[Authorization](/general-information.md#authorization) is **required** for all of the Events endpoints, since depending on implementation, use cases, and fields required it may contain information only city transporation agencies should have access to. [Top][toc] ## Query Event -Endpoint: `/events/event` +Endpoint: `/events/events` Method: `GET` `data` Payload: a JSON object with the following fields: - - `events`: an array of [Curb Event](#curb-event) objects + - `events`: an array of [Curb Event](#curb-event) objects. See [Event Times](/general-information.md#event-times) guidance about the order of data returned. _This endpoint must be implemented by every Events API server._ @@ -61,9 +60,9 @@ All query parameters are optional. | Name | Type | Description | | ------------ | --------- | ---------------------------------------------- | -| `curb_area_id` | [UUID][uuid] | The ID of a [Curb Area](#curb-area). If specified, only return events occuring within this area. | -| `curb_zone_id` | [UUID][uuid] | The ID of a [Curb Zone](#curb-zone). If specified, only return events occuring within this zone. | -| `curb_space_id` | [UUID][uuid] | The ID of a [Curb Space](#curb-space). If specified, only return events occuring within this space. | +| `curb_area_id` | [UUID][uuid] | The ID of a [Curb Area](#curb-area). If specified, only return events occurring within this area. | +| `curb_zone_id` | [UUID][uuid] | The ID of a [Curb Zone](#curb-zone). If specified, only return events occurring within this zone. | +| `curb_space_id` | [UUID][uuid] | The ID of a [Curb Space](#curb-space). If specified, only return events occurring within this space. | [Top][toc] @@ -99,107 +98,185 @@ A Curb Event is represented as a JSON object, whose fields are as follows: | ------ | ------ | ------------------- | ------------- | | `event_id` | [UUID][uuid] | Required | The globally unique identifier of the event that occurred. | | `event_type` | [Event Type](#event-type) | Required | The event_type that happened for this event. | -| `event_source_category` | Enum [Sensor Category](#sensor-category) | Required | General category of the source creating the event. | -| `source_operator_id` | [UUID][uuid] | Required | Unique identifier of the entity responsible for operating the event source. | -| `source_id` | [UUID][uuid] | Required | Unique identifier of this event source, whether sensor, vehicle, camera, etc. Allows agencies to connect related Events as they are recorded. | +| `event_purpose` | [Event Purpose](#event-purpose) | Conditionally Required | General curb usage purpose that the vehicle performed during the event. Required for sources capable of determining activity type for relevant event_types. | | `event_location` | GeoJSON | Required | The geographic point location where the event occurred. | | `event_time` | [Timestamp][ts] | Required | Time at which the event occurred. | -| `publication_time` | [Timestamp][ts] | Required | Time at which the event became available for consumption by this API. | +| `event_publication_time` | [Timestamp][ts] | Required | Time at which the event became available for consumption by this API. | +| `event_session_id` | [UUID][uuid] | Optional | May be provided to tie known connected `park_start` and `park_end` event types together by a unique session ID. If _not_ confident of being able to determine a `park_end` event at some time after `park_start` is recorded (i.e., you cannot detect when a vehicle departs), then do _not_ use session_id. This field may be most useful to payment companies who provide their source data as sessions (typical for transaction data). _Note also_: the use of the term "session" across CDS means the start and end of curb usage of a vehicle, not necessarily a financial or payment session or transaction. | | `curb_zone_id` | [UUID][uuid] | Conditionally Required | Unique ID of the Curb Zone where the event occurred. Required for events that occurred at a known Curb Zone for ALL _event_types_. | -| `curb_area_ids` | [UUID][uuid] | Conditionally Required | Unique IDs of the Curb Area where the event occurred. Since Curb Areas can overlap, an event may happen in more than one. Required for events that occurred in a known Curb Area for these event_types: _enter_area, exit_area, park_start, park_end_ | -| `curb_space_id` | [UUID][uuid] | Conditionally Required | Unique ID of the Curb Space where the event occurred. Required for events that occurred at a known Curb Space for these event_types: _park_start, park_end, enter_area, exit_area_ | -| `provider_id` | [UUID][uuid] | Optional | Unique ID of the provider responsible for operating the vehicle at the time of the event, if any. IDs are global and come from the [providers.csv](/providers.csv) file here in the CDS repo. | -| `provider_name` | String | Optional | Name of the provider responsible for operating the vehicle, device, or sensor at the time of the event, if any. | -| `sensor_id` | [UUID][uuid] | Optional | If a sensor was used, the globally unique identifier of the sensor that recorded the event. | -| `sensor_status` | Object | Optional | The status of the sensor that reported the event at the time that the event was reported. _is_commissioned_: Boolean, required. Indicates whether the sensor is currently in a state where it should be reporting data. _is_online_: Boolean, required. Indicates whether the sensor is currently online and reporting data. | -| `vehicle_id` | String | Optional | A vehicle identifier visible on the vehicle itself. | +| `curb_area_ids` | [UUID][uuid] | Conditionally Required | Unique IDs of the Curb Area where the event occurred. Since Curb Areas can overlap, an event may happen in more than one. Required for events that occurred in a known Curb Area, if known and used, for these event_types: _enter_area, exit_area, park_start, park_end_ | +| `curb_space_id` | [UUID][uuid] | Conditionally Required | Unique ID of the Curb Space where the event occurred. Required for events that occurred at a known Curb Space, if known and used, for these event_types: _park_start, park_end, enter_area, exit_area_ | +| `data_source_type` | Enum [Source Type](#source-type) | Required | General category of the source creating the event. | +| `data_source_operator_id` | [UUID][uuid] | Conditionally Required | Unique identifier of the entity responsible for operating the event data source. IDs can identify the fleet operator sending a data feed, or the organization (company or city) operating the sensor. IDs for fleet operators are required and global and come from the [data_source_operators.csv](/data_source_operators.csv) file, and optional for others. Read our [How to Get a Data Source Operator ID](https://github.com/openmobilityfoundation/curb-data-specification/wiki/Adding-a-CDS-Data-Source-Operator-ID) guide. An agency at their discretion may allow a small, local company to simply provide a consistent `data_source_operator_name` string instead of this field, otherwise this field is required. | +| `data_source_operator_name` | String | Optional | Name of the provider responsible for operating the vehicle, device, or sensor at the time of the event. May be sent along with `data_source_operator_id` or on its own for small operators at the discretion of the city. | +| `data_source_device_id` | [UUID][uuid] | Required | Unique identifier of this event source, whether sensor, vehicle, camera, etc. Allows agencies to connect related Events as they are recorded by the same source. If coming from a provider, this is a generated UUID they use and not the same as the external `vehicle_id`. If this field is needed for your use cases, review our [Privacy Guidance](/README.md#data-privacy). | +| `data_source_manufacturer` | String | Optional | Manufacturer of the data source hardware or vehicle reporting event data. | +| `data_source_model` | String | Optional | Model of the data source hardware or vehicle reporting event data. | +| `sensor_status_is_commissioned` | Boolean | Optional | If a sensor was used to capture this event, the commissioned status at the time that the event was reported. Indicates whether the sensor is currently in a state where it should be reporting data. | +| `sensor_status_is_online` | Boolean | Optional | If a sensor was used to capture this event, the online status at the time that the event was reported. Indicates whether the sensor is currently online and reporting data. | +| `vehicle_id` | String | Optional | A vehicle identifier visible externally on the vehicle itself. If this field is needed for your use cases, review our [Privacy Guidance](/README.md#data-privacy). | +| `vehicle_license_plate` | String | Optional | The consistently placed vehicle license plate, usable by ALPR systems, when required for curb use. This field is potentially sensitive (depending on local, state, and national laws) and a data privacy framework is recommended for collecting, retention, deletion, obfuscation, and security. If this field is needed for your use cases, review our [Privacy Guidance](/README.md#data-privacy). | +| `vehicle_permit_number` | String | Optional | If applicable, the assigned permit number for this vehicle from the city agency. | | `vehicle_length` | Integer | Conditionally Required | Approximate length of the vehicle that performed the event, in centimeters. Required for sources capable of determining vehicle length. | | `vehicle_type` | [Vehicle Type](#vehicle-type) | Conditionally Required | Type of the vehicle that performed the event. Required for sources capable of determining vehicle type. | -| `propulsion_types` | Array of [Propulsion Type](#propulsion-type) | Conditionally Required | List of propulsion types used by the vehicle that performed the event. Required for sources capable of determining vehicle propulsion type. | -| `blocked_lane_types` | Array of [Lane Type](#lane-type) | Conditionally Required | Type(s) of lane blocked by the vehicle performing the event. If no lanes are blocked by the vehicle performing the event, the array should be empty. Required for the following event_types: _park_start_ | -| `curb_occupants` | Array of [Curb Occupant](#curb-occupants) | Conditionally Required | Current occupants of the Curb Zone. If the sensor is capable of identifying the linear location of the vehicle, then elements are sorted in ascending order according to the start property of the linear reference. Otherwise, elements appear in no particular order. Required for the following event_types: _park_start, park_end, scheduled_report_ | +| `vehicle_propulsion_types` | Array of [Propulsion Type](#propulsion-type) | Conditionally Required | List of propulsion types used by the vehicle that performed the event. Required for sources capable of determining vehicle propulsion type. | +| `vehicle_blocked_lane_types` | Array of [Lane Type](#lane-type) | Conditionally Required | Type(s) of lane blocked by the vehicle performing the event. If no lanes are blocked by the vehicle performing the event, the array should be empty. Required for sources capable of determining it for the following event_types: _park_start_ | +| `curb_occupants` | Array of [Curb Occupant](#curb-occupants) | Conditionally Required | Current occupants of the Curb Zone. If the sensor is capable of identifying the linear location of the vehicle, then elements are sorted in ascending order according to the start property of the linear reference. Otherwise, elements appear in no particular order. Required for sources capable of determining it for the following event_types: _park_start, park_end, scheduled_report_ | +| `actual_cost` | Integer | Optional | If available from the source, the actual cost, in the currency defined in currency, paid by the curb user for this event. The currency type is sent in with the [REST Endpoints](#rest-endpoints) JSON object. All costs should be given as integers in the currency's smallest unit. As an example, to represent $1 USD, specify an amount of 100 (for 100 cents). | [Top][toc] ### Event Type -`event_type`. Curb Event Type enumerates the set of possible types of Curb Event. The values that it can assume are listed below: +Curb Event Type `event_type` enumerates the set of possible types of Curb Event. The values that it can assume are listed below: -- **comms_lost**: communications with the event source were lost -- **comms_restored**: communications with the event source were restored -- **decommissioned**: event source was decommissioned -- **park_start**: a vehicle stopped, parked, or double parked -- **park_end**: a parked vehicle leaving a parked or stopped state and resuming movement -- **scheduled_report**: event source reported status status at a scheduled interval -- **enter_area**: vehicle enters the relevant geographic area -- **exit_area**: vehicle exits the relevant geographic area +| Name | Description | +|--------------------|-------------| +| `comms_lost` | communications with the event source were lost | +| `comms_restored` | communications with the event source were restored | +| `decommissioned` | event source was decommissioned | +| `park_start` | a vehicle stopped, parked, or double parked | +| `park_end` | a parked vehicle leaving a parked or stopped state and resuming movement | +| `scheduled_report` | event source reported status at a scheduled interval | +| `enter_area` | vehicle enters the relevant geographic area | +| `exit_area` | vehicle exits the relevant geographic area | [Top][toc] -### Vehicle Type +### Source Type -Type of vehicle, similar to vehicle_type in MDS. For this CDS release the list will be developed independently here to accommodate CDS and MDS use cases, while still aligning to the MDS design principles. In the next major MDS 2.0 release and next CDS release, alignment between CDS and MDS vehicle types can occur. +Curb Data Source Type `data_source_type` enumerates the set of possible categories of sources that are sending this event. The values that it can assume are listed below: -| `vehicle_type` | Description | +| Name | Description | |----------------| ----------- | -| bicycle | A two-wheeled mobility device intended for personal transportation that can be operated via pedals, with or without a motorized assist (includes e-bikes, recumbents, and tandems) | -| cargo_bicycle | A two- or three-wheeled bicycle intended for transporting larger, heavier cargo than a standard bicycle (such as goods or passengers), with or without motorized assist (includes bakfiets/front-loaders, cargo trikes, and long-tails) | -| car | A passenger car or similar light-duty vehicle | -| scooter | A standing or seated fully-motorized mobility device intended for one rider, capable of travel at low or moderate speeds, and suited for operation in infrastructure shared with motorized bicycles | -| moped | A seated fully-motorized mobility device capable of travel at moderate or high speeds and suited for operation in general urban traffic | -| truck | A light or heavy duty 4 wheeled truck | -| van | A van with significant interior cargo space | -| freight | A large delivery truck with attached cab | -| other | A device that does not fit in the other categories | +| `data_feed` | directly from a provider data feed sent to the agency | +| `camera` | video or static image processing source | +| `above_ground` | sensor deployed above ground | +| `in_ground` | sensor deployed in the ground | +| `meter` | a smart parking meter | +| `payment` | from payment system or app | +| `in_person` | an individual on site recording the event digitally or otherwise | +| `other` | sources not enumerated above | + +[Top][toc] + +### Vehicle Type + +Type of vehicle `vehicle_type` similar to vehicle_type in MDS. For this CDS release the list will be developed independently here to accommodate CDS and MDS use cases, while still aligning to the MDS design principles. In the next major MDS 2.0 release and next CDS release, alignment between CDS and MDS vehicle types can occur. + +| Name | Description | +|----------------- | ----------- | +| `bicycle` | A two-wheeled mobility device intended for personal transportation that can be operated via pedals, with or without a motorized assist (includes e-bikes, recumbents, and tandems) | +| `cargo_bicycle` | A two- or three-wheeled bicycle intended for transporting larger, heavier cargo than a standard bicycle (such as goods or passengers), with or without motorized assist (includes bakfiets/front-loaders, cargo trikes, and long-tails) | +| `car` | A passenger car or similar light-duty vehicle | +| `scooter` | A standing or seated fully-motorized mobility device intended for one rider, capable of travel at low or moderate speeds, and suited for operation in infrastructure shared with motorized bicycles | +| `moped` | A seated fully-motorized mobility device capable of travel at moderate or high speeds and suited for operation in general urban traffic | +| `motorcycle` | A seated mobility device capable of travel at high speeds and suited for operation in general urban traffic or expressways | +| `truck` | A light or heavy duty 4 wheeled truck | +| `van` | A van with significant interior cargo space | +| `freight` | A large delivery truck with attached cab | +| `other` | A device that does not fit in the other categories | +| `unspecified` | Unspecified | [Top][toc] ### Propulsion Type -Propulsion type of the vehicle, similar to propulsion_type in MDS. For this CDS release the list will be developed independently here to accommodate CDS and MDS use cases, while still aligning to the MDS design principles. In the next major MDS 2.0 release and next CDS release, alignment between CDS and MDS propulsion types can occur. +Propulsion type `vehicle_propulsion_types` of the vehicle, similar to propulsion_type in MDS. For this CDS release the list will be developed independently here to accommodate CDS and MDS use cases, while still aligning to the MDS design principles. In the next major MDS 2.0 release and next CDS release, alignment between CDS and MDS propulsion types can occur. -| `propulsion` | Description | +| Name | Description | | ----------------- | ------------------------------------------------------ | | `human` | Pedal or foot propulsion | | `electric_assist` | Provides power only alongside human propulsion | | `electric` | Contains throttle mode with a battery-powered motor | | `combustion` | Contains throttle mode with a gas engine-powered motor | -A vehicle may have one or more values from the `propulsion`, depending on the number of modes of operation. For example, a scooter that can be powered by foot or by electric motor would have the `propulsion` represented by the array `['human', 'electric']`. A bicycle with pedal-assist would have the `propulsion` represented by the array `['human', 'electric_assist']` if it can also be operated as a traditional bicycle. +A vehicle may have one or more values from the `vehicle_propulsion_types`, depending on the number of modes of operation. For example, a scooter that can be powered by foot or by electric motor would have the `vehicle_propulsion_types` represented by the array `["human", "electric"]`. A bicycle with pedal-assist would have the `vehicle_propulsion_types` represented by the array `["human", "electric_assist"]` if it can also be operated as a traditional bicycle. A hybrid vehicle may use `["combustion", "electric"]`. + +[Top][toc] + +### Event Purpose + +General event purpose `event_purpose` that the vehicle performed during its event, discernible by observation, sensors, or self-reported in company data feeds. New event purposes MAY be generated to reflect local curb uses, but when possible, the following well-known recommended values should be used. It may not always be knowable, but where it is possible this information should be conveyed. If multiple purposes apply, then use the more descriptive/specific value. + +| Name | Description | +| --------------------- | ------------------------------------------------------ | +| `construction` | Construction of hard assets including buildings and roadside infrastructure | +| `delivery` | General delivery of parcels, goods, freight | +| `emergency_use` | Includes ambulance, fire truck, police | +| `parking` | Vehicle parking, charging, or stopping | +| `passenger_transport` | Picking up and/or dropping off of human passengers | +| `special_events` | Includes unloading equipment for concerts, theatre, street events | +| `waste_management` | Retrieval/disposal of waste | +| `device_maintenance` | Includes scooter pickup, drop off, battery swapping | +| `autonomous` | Autonomous vehicle use | +| `ems` | Emergency medical vehicle use | +| `fire` | Emergency fire vehicle | +| `food_delivery` | Delivery of food items ready for consumption to an end consumer | +| `parcel_delivery` | Delivery of parcels, including bulk food goods to a restaurant or other business | +| `police` | Use by a police vehicle | +| `public_transit` | Includes large or small buses or paratransit. | +| `ride_hail` | Includes privately run ride hailing services | +| `road_maintenance` | Includes pothole patching, striping, snow plowing, street sweeping | +| `service_vehicles` | Includes private sector activity like some utilities | +| `taxi` | Traditionaly licensed taxi services | +| `utility_work` | Includes public sector activity like sewer, water, telecoms | +| `vehicle_charging` | Parking for electric vehicles to charge | +| `vehicle_parking` | Includes private or commercial vehicle free or paid/metered parking | +| `vending` | Mobile vending or food truck curb uses | +| `unspecified` | Unknown or unspecified activity type | [Top][toc] ### Lane Type -`lane_type`. Type(s) of lane blocked by the vehicle performing the event. +Type(s) of lane used or blocked `vehicle_blocked_lane_types` by the vehicle performing the event, outside of curb zones. E.g., double parking. -- **type1**: TBD +| Name | Description | +| -------------- | ------------------------------------------------------ | +| `travel_lane` | A standard vehicle travel lane. | +| `turn_lane` | A dedicated turn lane. | +| `bike_lane` | A lane dedicated for usage by cyclists. | +| `bus_lane` | A lane dedicated for usage by buses. | +| `parking` | A lane used for parking, not allowed for travel. | +| `shoulder` | A portion of the roadway that is outside (either right or left) of the main travel lanes. A shoulder can have many uses but is not intended for general traffic. | +| `median` | An often unpaved, non-drivable area that separates sections of the roadway. | +| `sidewalk` | A path for pedestrians, usually on the side of the roadway. | +| `unspecified` | Unspecified | [Top][toc] ### Curb Occupants -`curb_occupants`. A Curb Occupant object represents a specific vehicle’s occupancy in a curb region at a specific point in time. Curb Occupant objects contain the following fields: +A Curb Occupant `curb_occupants` object represents a specific vehicle’s occupancy in a curb region at a specific point in time. Curb Occupant objects contain the following fields: -- **type**: _Vehicle Type, required_. The type of the occupant. When the event source is not capable of distinguishing vehicle type, this property must take the value “unspecified.” -- **length**: _Float, conditionally required._ The approximate length in centimeters of the vehicle. Required when the event source is capable of determining vehicle length. -- **linear_location**: _Array of Float, conditionally required._ A two-element array that specifies the start and end of the occupant’s linear location relative to the start of the Curb Zone in that order. Required when the event source is capable of determining the linear location of occupants. +| Name | Type | Required/Optional | Description | +| ----------------- | -------------- | ----------------------- | ----------- | +| `type` | [Vehicle Type](#vehicle-type) | Required | The vehicle type of the occupant. When the event source is not capable of distinguishing vehicle type, this property must take the value "unspecified". +| `length` | Float | Conditionally required | The approximate length in centimeters of the vehicle. Required when the event source is capable of determining vehicle length. +| `linear_location` | Array of Float | Conditionally required | A two-element array that specifies the start and end of the occupant’s linear location relative to the start of the Curb Zone in that order. Required when the event source is capable of determining the linear location of occupants. [Top][toc] ## Status -The Curb Status is the current status of a curb monitoring source. +The Curb Status is the current status of sensors that are monitoring curb places. -A Curb Status is represented as a JSON object array of all deployed sources and/or sensors, whose fields are as follows: +A Curb Status is represented as a JSON object array of all deployed sensors, whose fields are as follows: | Name | Type | Required/Optional | Description | | ------ | ------ | ------------------- | ------------- | -| `sensor_id` | [UUID][uuid] | Required | If a sensor was used, the globally unique identifier of the sensor that records events. | -| `sensor_status` | Object | Required | The status of the sensor that reported the event at the time that the event was reported. _is_commissioned_: Boolean, required. Indicates whether the sensor is currently in a state where it should be reporting data. _is_online_: Boolean, required. Indicates whether the sensor is currently online and reporting data. | -| `event_source_category` | Enum [Sensor Category](#sensor-category) | Optional | General category of the source creating the event. | -| `source_operator_id` | [UUID][uuid] | Optional | Unique identifier of the entity responsible for operating the event source. | -| `source_id` | [UUID][uuid] | Optional | Unique identifier of this event source, whether sensor, vehicle, camera, etc. Allows agencies to connect related Events as they are recorded. | +| `data_source_device_id` | [UUID][uuid] | Required | Unique identifier of this event source, whether sensor, vehicle, camera, etc. | +| `data_source_type` | Enum [Source Type](#source-type) | Required | General category of the source creating the event. | +| `data_source_operator_id` | [UUID][uuid] | Conditionally Required | Unique identifier of the entity responsible for operating the event data source. Can be global from [data_source_operators.csv](/data_source_operators.csv) or defined per city. | +| `sensor_status_is_commissioned` | Boolean | Optional | If a sensor was used to capture this event, the commissioned status at the time that the event was reported. Indicates whether the sensor is currently in a state where it should be reporting data. | +| `sensor_status_is_online` | Boolean | Optional | If a sensor was used to capture this event, the online status at the time that the event was reported. Indicates whether the sensor is currently online and reporting data. | + +[Top][toc] + +# Examples + +See a series of [CDS Events endpoint examples](examples.md) to use as templates. [Top][toc] diff --git a/events/examples.md b/events/examples.md new file mode 100644 index 00000000..691a8fcd --- /dev/null +++ b/events/examples.md @@ -0,0 +1,110 @@ +# Events Examples + +This file presents a series of CDS [Events](/events) endpoint examples to use as templates. + +## Table of Contents + +- [Curb Event Minimum](#curb-event-minimum) +- [Fleet Operator](#fleet-operator) + +## Curb Event Minimum + +A [Query Event](/events#query-event) example of `/events/events` with minimum required fields showing the start of a `park_start` event at a specific curb zone detected by an above ground sensor, and no [query parameters](/events#query-parameters) passed in. + +**Query**: + +`/events/events` + +**Payload**: + +```json +{ + "version": "1.0", + "time_zone": "US/Eastern", + "last_updated": 1552678594428, + "currency": "USD", + "author": "City of Metropolis", + "license_url": "https://creativecommons.org/licenses/by/4.0/", + "data": [ + { + "events": [ + { + "event_id": "7d8a5885-e949-4ac9-afb7-fa4d43b68530", + "event_type": "park_start", + "event_location": { + "type": "Feature", + "properties": { "timestamp": 1552678574581 }, + "geometry": { + "type": "Point", + "coordinates": [ -85.7629808, 38.257341 ] + } + }, + "event_time": "1552678578632", + "event_publication_time": "1552678594428", + "curb_zone_id": "02885f6f-ef93-441b-9e74-487279380656", + "data_source_type": "above_ground", + "data_source_device_id": "0fcb51b0-4529-4d28-a339-81e9a9bbcdb3" + } + ] + } + ] +} +``` + +## Fleet Operator + +A [Query Event](/events#query-event) example of `/events/events` from a fleet operator's data feed with many optional fields showing the start of a `park_start` with event details and vehicle properties, and the curb_zone_id [query parameter](/events#query-parameters) passed in. + +**Query**: + +`/events/events?curb_zone_id=02885f6f-ef93-441b-9e74-487279380656` + +**Payload**: + +```json +{ + "version": "1.0", + "time_zone": "US/Eastern", + "last_updated": 1552678594428, + "currency": "USD", + "author": "City of Metropolis", + "license_url": "https://creativecommons.org/licenses/by/4.0/", + "data": [ + { + "events": [ + { + "event_id": "7d8a5885-e949-4ac9-afb7-fa4d43b68530", + "event_type": "park_start", + "event_purpose": "parcel_delivery", + "event_location": { + "type": "Feature", + "properties": { "timestamp": 1552678574581 }, + "geometry": { + "type": "Point", + "coordinates": [ -85.7629808, 38.257341 ] + } + }, + "event_time": "1552678578632", + "event_publication_time": "1552678594428", + "curb_zone_id": "02885f6f-ef93-441b-9e74-487279380656", + "data_source_type": "data_feed", + "data_source_operator_id": "16a85550-51d3-4f52-8ea9-e8a10306cab2", + "data_source_operator_name": "USPS", + "data_source_device_id": "618e92a4-e557-42a9-8f0a-0273545f7f49", + "data_source_manufacturer": "Grumman", + "data_source_model": "LLV", + "vehicle_id": "USDOT 33213", + "vehicle_permit_number": "KYVID-319380-A", + "vehicle_length": "670", + "vehicle_type": "truck", + "vehicle_propulsion_types": ["electric"], + "vehicle_blocked_lane_types": ["parking"] + } + ] + } + ] +} +``` + + +[Top](#table-of-contents) diff --git a/general-information.md b/general-information.md index 6a5b1a86..4bca66ad 100644 --- a/general-information.md +++ b/general-information.md @@ -5,11 +5,59 @@ This document contains specifications that are shared between the various CDS AP # Table of Contents +- [Authorization](#authorization) - [Beta Features](#beta-features) - [Costs and Currencies](#costs-and-currencies) -- [Polygon](#polygon) +- [Event Times](#event-times) +- [Geographic Data](#geographic-data) + - [Geographic Telemetry Data](geographic-telemetry-data) + - [Polygon](#polygon) + - [Intersection Operation](#intersection-operation) +- [Responses](#responses) +- [REST Endpoints](#rest-endpoints) +- [Pagination](#pagination) +- [Range Boundaries](#range-boundaries) - [UUID](#uuid) - [Timestamp](#timestamp) +- [Versioning](#versioning) + +# Authorization + +CDS implementers **SHALL** provide authorization for API endpoints via a bearer token based auth system, when required. + +For example, the `Authorization` header sent as part of an HTTP request: + +``` +GET /events/event HTTP/1.1 +Host: api.operator.com +Authorization: Bearer +``` + +More info on how to document [Bearer Auth in swagger](https://swagger.io/docs/specification/authentication/bearer-authentication/) + +## JSON Web Tokens + +JSON Web Token ([JWT](https://jwt.io/introduction/)) is **RECOMMENDED** as the token format. + +JWTs provide a safe, secure way to verify the identity of an agency and provide access to MDS resources without providing access to other, potentially sensitive data. + +> JSON Web Token (JWT) is an open standard ([RFC 7519](https://tools.ietf.org/html/rfc7519)) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. + +Implementers **MAY** include any metadata in the JWT they wish that helps to route, log, permission, or debug agency requests, leaving their internal implementation flexible. + +JWT provides a helpful [debugger](https://jwt.io/#debugger) for testing your token and verifying security. + +## OAuth 2.0 + +OAuth 2.0's `client_credentials` grant type (outlined in [RFC6749](https://tools.ietf.org/html/rfc6749#section-4.4)) is **RECOMMENDED** as the authentication and authorization scheme. + +OAuth 2.0 is an industry standard authorization framework with a variety of existing tooling. The `client_credentials` grant type facilitates generation of tokens that can be used for access by agencies and distributed to data partners. + +If implementers use this auth scheme, they **MAY** choose to specify token scopes that define access parameters like allowable time ranges. These guidelines **SHOULD** be encoded into the returned token in a parseable way. + +## Endpoint Authentication Requirements + +All endpoints marked authenticated **SHALL** be authenticated, to protect potentially sensitive information. # Beta Features @@ -21,8 +69,6 @@ Beta features may be suitable for enabling some new tools and analysis, but may Working Groups and their Steering Committees are expected to review beta designated features and feedback with each release cycle and determine whether the feature has reached the level of stability and maturity needed to remove the beta designation. In a case where a beta feature fails to reach substantial adoption after an extended time, Working Group Steering Committees should discuss whether or not the feature should remain in the specification. -> **This CDS repository is currently wholly in the beta state. It will be change as development and real-world feedback happens. See our current [timeline](https://github.com/openmobilityfoundation/curb-data-specification/wiki#timeline) and watch the [CDS Releases](https://github.com/openmobilityfoundation/curb-data-specification/releases) page for updates.** - [Top][toc] # Costs and currencies @@ -44,7 +90,52 @@ Defining terminology and abbreviations used throughout CDS. - Curb Zone - A geographically and policy defined area where transactions may happen at curb space. - Curb Space - A geographically defined area within a Curb Zone for a single vehicle. -# Polygon +# Event Times + +Return data in the order of timestamps of the events on the ground, with most recent items returned first to construct as accurate a timeline as possible. + +Because of unreliability of some device clocks and other factors, sensors and operators are unlikely to know with total confidence what time an event occurred at. However, endpoint producers are responsible for constructing as accurate a timeline as possible. Most importantly, the order of the timestamps for a particular vehicle's events must reflect the producer's best understanding of the order in which those events occurred. + +# Geographic Data + +References to geographic datatypes (Point, MultiPolygon, etc.) imply coordinates encoded in the [WGS 84 (EPSG:4326)][wgs84] standard GPS or GNSS projection expressed as [Decimal Degrees][decimal-degrees]. + +## Geographic Telemetry Data + +Whenever a vehicle or device location coordinate measurement is presented, it must be represented as a GeoJSON [`Feature`][geojson-feature] object with a corresponding `properties` object with the following properties: + + +| Field | Type | Required/Optional | Field Description | +| -------------- | --------------- | --------------------- | ------------------------------------------------------------ | +| `timestamp` | [timestamp][ts] | Required | Date/time that event occurred. Based on GPS or GNSS clock | +| `altitude` | Double | Required if Available | Altitude above mean sea level in meters | +| `heading` | Double | Required if Available | Degrees - clockwise starting at 0 degrees at true North | +| `speed` | Float | Required if Available | Estimated speed in meters / sec as reported by the GPS chipset | +| `accuracy` | Float | Required if Available | Horizontal accuracy, in meters | +| `hdop` | Float | Required if Available | Horizontal GPS or GNSS accuracy value (see [hdop][hdop]) | +| `satellites` | Integer | Required if Available | Number of GPS or GNSS satellites | + +Example of a vehicle location GeoJSON [`Feature`][geojson-feature] object: + +```json +{ + "type": "Feature", + "properties": { + "timestamp": 1529968782421, + "accuracy": 10, + "speed": 1.21 + }, + "geometry": { + "type": "Point", + "coordinates": [ + -118.46710503101347, + 33.9909333514159 + ] + } +} +``` + +## Polygon A polygon is a GeoJSON geometry of type `"Polygon"` as defined in [RFC 7946 3.1.6](https://www.ietf.org/rfc/rfc7946.txt). An example polygon is: @@ -62,6 +153,111 @@ A polygon is a GeoJSON geometry of type `"Polygon"` as defined in } ``` +## Intersection Operation + +For the purposes of this specification, the intersection of two geographic datatypes is defined according to the [`ST_Intersects` PostGIS operation][st-intersects] + +> If a geometry or geography shares any portion of space then they intersect. For geography -- tolerance is 0.00001 meters (so any points that are close are considered to intersect). +> +> Overlaps, Touches, Within all imply spatial intersection. If any of the aforementioned returns true, then the geometries also spatially intersect. Disjoint implies false for spatial intersection. + +[Top][toc] + +# Responses + +List of acceptable endpoint responses. + +* **200:** OK: operation successful. +* **201:** Created: `POST` operations, new object created +* **400:** Bad request. +* **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. +* **406:** Not Acceptable. Invalid response. +* **409:** Conflict: `POST` operations when an object already exists and an update is not possible. +* **500:** Internal server error: In this case, the answer may contain a `text/plain` body with an error message for troubleshooting. +* **501:** Not Implemented. + +## Error Messages + +```json +{ + "error": "...", + "error_description": "...", + "error_details": [ "...", "..." ] +} +``` + +| Field | Type | Field Description | +| ------------------- | -------- | ---------------------- | +| `error` | String | Error message string | +| `error_description` | String | Human readable error description (can be localized) | +| `error_details` | String[] | Array of error details | + +[Top][toc] + +# REST Endpoints + +All dynamic REST endpoints will return a JSON object containing the following fields: + +| Name | Type | Required/Optional | Description | +| ------ | ------ | ------------------- | ------------- | +| `data` | _Endpoint-dependent_ | Required | The requested data objects. | +| `version` | String | Required | The specification version that the API conforms to (currently, `0.0`) | +| `time_zone` | String | Required | The time zone that applies to parking regulations in this dataset. MUST be a valid [TZ database](https://www.iana.org/time-zones) time zone name (e.g. `"US/Eastern"` or `"Europe/Paris"`). | +| `last_updated` | [Timestamp][#timestamp] | Required | The last time the data in this API was updated. | +| `currency` | String | Required | The ISO 4217 3-letter code for the currency in which rates for curb usage are denominated. All costs should be given as integers in the currency's smallest unit. As an example, to represent $1 USD, specify an amount of 100 (for 100 cents). | +| `author` | String | Optional | The name of the organization that produces and maintains this data. | +| `license_url` | URL | Optional | The licensing terms under which this data is provided. | + +Servers MUST set the `Content-Type` header to `application/vnd.cds+json;version=1.0` to support +versioning in the future. Clients SHOULD specify an `Accept` header containing +`application/vnd.cds+json;version=1.0`. If the server receives a request that contains an `Accept` +header but does not include this value; it MUST respond with a status of `406 Not Acceptable`. + +[Top][toc] + +# Pagination + +Endpoints may use pagination, which must comply with the [JSON API][json-api-pagination] specification. See [Event Times](/general-information.md#event-times) guidance about the order of data returned. + +The following keys must be used for pagination links: + +* `first`: url to the first page of data +* `last`: url to the last page of data +* `prev`: url to the previous page of data +* `next`: url to the next page of data + +At a minimum, payloads that use pagination must include a `next` key, which must be set to `null` to indicate the last page of data. + +```json +{ + "version": "x.y.z", + "data": { + "endpoint": [{ + "field_name": "..." + }] + }, + "links": { + "first": "https://...", + "last": "https://...", + "prev": "https://...", + "next": "https://..." + } +} +``` + +[Top][toc] + +# Range Boundaries + +All ranges across the spec of timestamps, times, measurements, dates, etc are 'inclusive' at the start and 'exclusive' at the end, unless otherwise noted. + +For example: + +- `start_datetime`: "2021-08-12 00:00:00" and `end_datetime`: "2021-08-13 00:00:00" + +This covers all of 2021-08-12, which is inclusive of the time "2021-08-12 00:00:00", but exclusive (does not include) the time "2021-08-13 00:00:00". This is easier and more clear than using "2021-08-12 23:59:59" as the `end_datetime`. + [Top][toc] # UUID @@ -75,9 +271,32 @@ in RFC 4122, including time-based (V1), random (V4), or name-based (V5). # Timestamp -A timestamp is an integer representing a number of milliseconds since midnight, January 1st, 1970 UTC -(the UNIX epoch). +A timestamp is an integer representing a number of milliseconds since midnight, January 1st, 1970 UTC (the UNIX epoch). E.g., `1643130000000` is Tuesday, January 25, 2022 5:00:00 PM UTC. + +# Versioning + +CDS APIs must handle requests for specific versions of the specification from clients. + +Versioning must be implemented through the use of a custom media-type, `application/vnd.cds+json`, combined with a required `version` parameter. + +The version parameter specifies the dot-separated combination of major and minor versions from a published version of the specification. For example, the media-type for version `1.0.1` would be specified as `application/vnd.cds+json;version=1.0` + +Clients must specify the version they are targeting through the `Accept` header. For example: + +```http +Accept: application/vnd.cds+json;version=1.2.0 +``` + +If an unsupported or invalid version is requested, the API must respond with a status of `406 Not Acceptable`. [Top][toc] +[decimal-degrees]: https://en.wikipedia.org/wiki/Decimal_degrees +[hdop]: https://en.wikipedia.org/wiki/Dilution_of_precision_(navigation) +[geo]: #geographic-data +[geojson-feature]: https://tools.ietf.org/html/rfc7946#section-3.2 +[geojson-point]: https://tools.ietf.org/html/rfc7946#section-3.1.2 +[st-intersects]: https://postgis.net/docs/ST_Intersects.html [toc]: #table-of-contents +[ts]: /general-information.md#timestamps +[wgs84]: https://en.wikipedia.org/wiki/World_Geodetic_System diff --git a/metrics/README.md b/metrics/README.md index 39bc0376..cfec75c1 100644 --- a/metrics/README.md +++ b/metrics/README.md @@ -1,28 +1,56 @@ # Curb Data Specification: Metrics API -The Metrics API is a REST API allowing historic metrics calculations based on Event activity that happened at defined Curb places. +CDS Metrics Icon -## ⚠ Beta -> **This feature is current a draft of the initial CDS beta release. It will change as development and real-world feedback happens.** +The Metrics API is a REST API allowing historic metrics calculations based on Event activity that happened at defined Curb places. Defines common calculation methodologies to measure historic dwell time, occupancy, usage and other aggregated statistics. + +**See [other CDS APIs](/README.md#curb-data-specification-apis) on the homepage.** # Endpoints There are two different endpoints that are part of the Metrics API: - - A [Activities](#curb-event) is infomration about an activity that occurs near, at, or within a pre-defined curb area. Activities is a subset of items from the Events API. Activities is *optional*. - - A [Aggregates](#status) is aggregated counts and methodology of curb events. Aggregates is *optional*. + - [Session](#session) is information about an activity that occurs near, at, or within a pre-defined curb area. Sessions is a subset of items from the Events API. Sessions is *optional* within Metrics. + - [Aggregate](#aggregate) is aggregated counts and methodology of curb events. Aggregates is *optional* within Metrics. + +**See [examples](examples.md) for these endpoints.** # Table of Contents +- [Representative Sample Data](#representative-sample-data) - [REST Endpoints](#rest-endpoints) + - [Authorization](#authorization) * [Update Frequency](#update-frequency) - * [Query Activities](#query-activities) - * [Query Aggregates](#query-aggregates) + * [Query Session](#query-session) + * [Query Aggregate](#query-aggregate) - [Data Objects](#data-objects) - * [Activities](#activities) - * [Aggregates](#aggregates) + * [Session](#session) + * [Aggregate](#aggregate) * [Methodology](#methodology) - * [Examples](#examples) +- [Examples](#examples) + +# Representative Sample Data + +All data returned by the Metrics API should be viewed as using representative sample data, and not necessarily a 100% accurate picture of what happens at every defined curb space. This is because CDS Events can come from multiple sources (company data feeds, sensors, video analysis, payments, check-ins, enforcement, and/or other city data sources), cities may implement only one or more of these sources, each source returns different types and accuracy of data, and sources may not be easily cross-comparible. It is up to the city consuming Events and producing Metrics to determine accuracy and methodology details within their circumstances, and we welcome feedback, refinement, clarification, and more defined methodology per source type for future CDS releases. + +# REST Endpoints + +All endpoints return a CSV file that can either be pre-computed or created on demand dynamically. + +If returning data from a static CSV file directly (e.g, from a web-based file system, service, or data portal), then adding header information is not required. + +If returning data from a dynamic server, they MUST set the `Content-Type` header to `application/vnd.cds+csv;version=1.0` to support +versioning in the future. Clients SHOULD specify an `Accept` header containing +`application/vnd.cds+csv;version=1.0`. If the server receives a request that contains an `Accept` +header but does not include this value; it MUST respond with a status of `406 Not Acceptable`. + +[Top][toc] + +## Authorization + +[Authorization](/general-information.md#authorization) is **optionally required** for all the Metrics endpoints, since depending on implementation, use cases, fields required, local laws, and audience it may contain information only city transportation agencies should have access to. It is recommended to authenticate when in doubt, though the information in [Query Aggregate](#query-aggregate) is aggregated report level data suitable for data analysis and public release. Review our [Privacy Guidance](/README.md#data-privacy) for more details. + +[Top][toc] # REST Endpoints @@ -33,80 +61,111 @@ versioning in the future. Clients SHOULD specify an `Accept` header containing `application/vnd.cds+csv;version=0.0`. If the server receives a request that contains an `Accept` header but does not include this value; it MUST respond with a status of `406 Not Acceptable`. -You may choose to serve a CSV file directly from a web-based file system, service, or data portal, in which case adding a header is not required. +You may choose to serve a static CSV file directly from a web-based file system, service, or data portal, in which case adding a header is not required. ## Update Frequency -The agency serving the data may choose how frequently they want to update the data. At least monthly is recommended but it may be longer or weekly, daily, hourly, or even more frequently. +The agency serving the data may choose how frequently they want to update the data. At least monthly is recommended but it may be longer, or weekly, daily, hourly, or even more frequently. [Top][toc] -## Query Activities +## Query Session -Endpoint: `/metrics/activities` +Endpoint: `/metrics/sessions` Method: `GET` `data` Payload: a CSV object with the following fields: - - `activities`: an array of [Activities](#activity) objects + - `session`: an array of [Session](#session) objects _Optional endpoint; if not implemented, a server should reply with 501 Not Implemented._ ### Query Parameters -No query parameters for this endpoint. +An agency may choose to make this endpoint static (and return all the available data at once in a single file) or dynamic (and allow the use of any or all of the query parameters below to filter the data). If dynamic, all query parameters are optional. + +| Name | Type | Required/Optional | Description | +| ------------ | --------- | ----------------- | ---------------------------------------------- | +| `curb_place_type` | Enum | Optional | The type of curb place this aggregate applies to from the Curbs API: `area`, `zone`, `space`. Required with `curb_place_id`. | +| `curb_place_id` | [UUID][uuid] | Optional | The ID of this single curb place. If specified, only return data contained within this area. Required with `curb_place_type`. | +| `min_lat`
    `min_lng`
    `max_lat`
    `max_lng` | Numeric | Optional | Specifies a latitude and longitude bounding box. If one of these parameters is specified, all four MUST be. If specified only return Curb Zones that intersect the supplied bounding box. | +| `lat`
    `lng`
    `radius` | Numeric | Optional | Specifies a latitude and longitude bounding point and a radius away from that point. If one of these parameters is specified, all three MUST be. Returns only Curb Zones that are within `radius` centimeters of the point identified by `lat`/`lng`. Curb Zones in the response MUST be ordered ascending by distance from the center point. | +| `start_time` | [Timestamp][ts] | Optional | The start of the time period to return data (_inclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). | +| `end_time` | [Timestamp][ts] | Optional | The end of the time period to return data (_exclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). | [Top][toc] -## Query Aggregates +## Query Aggregate Endpoint: `/metrics/aggregates` Method: `GET` `data` Payload: a CSV object with the following fields: - - `activities`: an array of [Aggregates](#aggregates) objects + - `aggregate`: an array of [Aggregate](#aggregate) objects _Optional endpoint; if not implemented, a server should reply with 501 Not Implemented._ ### Query Parameters -No query parameters for this endpoint. +An agency may choose to make this endpoint static (and return all the available data at once in a single file) or dynamic (and allow the use of any or all of the query parameters below to filter the data). If dynamic, all query parameters are optional. + +| Name | Type | Required/Optional | Description | +| ------------ | --------- | ----------------- | ---------------------------------------------- | +| `curb_place_type` | Enum | Optional | The type of curb place this aggregate applies to from the Curbs API: `area`, `zone`, `space`. Required with `curb_place_id`. | +| `curb_place_id` | [UUID][uuid] | Optional | The ID of this single curb place. If specified, only return data contained within this area. Required with `curb_place_type`. | +| `metric_type` | Enum | Optional | The single metric to return from the [Methodology](#methodology): `total_sessions`, `turnover`, `average_dwell_time`, `occupancy_percent`. | +| `min_lat`
    `min_lng`
    `max_lat`
    `max_lng` | Numeric | Optional | Specifies a latitude and longitude bounding box. If one of these parameters is specified, all four MUST be. If specified only return Curb Zones that intersect the supplied bounding box. | +| `lat`
    `lng`
    `radius` | Numeric | Optional | Specifies a latitude and longitude bounding point and a radius away from that point. If one of these parameters is specified, all three MUST be. Returns only Curb Zones that are within `radius` centimeters of the point identified by `lat`/`lng`. Curb Zones in the response MUST be ordered ascending by distance from the center point. | +| `start_time` | [Timestamp][ts] | Optional | The start of the time period to return data (_inclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). | +| `end_time` | [Timestamp][ts] | Optional | The end of the time period to return data (_exclusive_, see [Range Boundaries](/general-information.md#range-boundaries)). | [Top][toc] # Data Objects -## Activities +## Session -Activities are a historic subset of curb events, with some rows combined, some columns removed for clarity and privacy, and for some curb event types. -Activities are meant to provide a granular view of activity happening around the curb places, so consumers can do their own analysis and aggregation. +Sessions are a historic subset of curb events, with some rows combined, some columns removed for clarity and privacy, and for only some curb event types. +Sessions are meant to provide a granular view of parking and area sessions happening around the curb places, so consumers can do their own analysis. -An Activity is represented as a CSV object, whose fields are as follows, pulled from the Curb Events endpoint in the Events API: +A Session is represented as a CSV object, whose fields are as follows, pulled from the Curb Events endpoint in the Events API: | Name | Type | Required/Optional | Description | | ------ | ------ | ------------------- | ------------- | -| `event_id` | [UUID][uuid] | Required | The globally unique identifier of the event that occurred. | -| `event_type` | [Event Type](#event-type) | Required | The event_type that happened for this event. | -| `event_location` | GeoJSON | Required | The geographic point location where the event occurred. | -| `event_time` | [Timestamp][ts] | Required | Time at which the event occurred. | +| `session_type` | Enum | Required | The type of session that happened for this event: `parking` or `area` | +| `event_session_id` | [UUID][uuid] | Optional | If known and recorded to tie two Events together, then include the `event_session_id` from the [Curb Event](/events#curb-event). | +| `event_id_start` | [UUID][uuid] | Conditionally Required | The globally unique identifier of the **start/enter** event that occurred. | +| `event_id_end` | [UUID][uuid] | Conditionally Required | The globally unique identifier of the **end/exit** event that occurred. | +| `event_location_start_latitude` | Number | Conditionally Required | The geographic latitude point location where the **start/enter** of the event occurred. | +| `event_location_start_longitude` | Number | Conditionally Required | The geographic longitude point location where the **start/enter** of the event occurred. | +| `event_location_end_latitude` | Number | Conditionally Required | The geographic latitude point location where the **end/exit** of the event occurred. | +| `event_location_end_longitude` | Number | Conditionally Required | The geographic longitude point location where the **end/exit** of the event occurred. | +| `event_time_start` | [Timestamp][ts] | Conditionally Required | Timestamp (date/time) at which the event started with the `park_start` or `enter_area` event types. | +| `event_time_end` | [Timestamp][ts] | Conditionally Required | Timestamp (date/time) at which the event occurred. | | `curb_zone_id` | [UUID][uuid] | Conditionally Required | Unique ID of the Curb Zone where the event occurred. Required for events that occurred at a known Curb Zone for ALL _event_types_. | | `curb_area_ids` | [UUID][uuid] | Conditionally Required | Unique IDs of the Curb Area where the event occurred. Since Curb Areas can overlap, an event may happen in more than one. Required for events that occurred in a known Curb Area for these event_types: _enter_area, exit_area, park_start, park_end_ | | `curb_space_id` | [UUID][uuid] | Conditionally Required | Unique ID of the Curb Space where the event occurred. Required for events that occurred at a known Curb Space for these event_types: _park_start, park_end, enter_area, exit_area_ | | `vehicle_length` | Integer | Conditionally Required | Approximate length of the vehicle that performed the event, in centimeters. Required for sources capable of determining vehicle length. | -| `vehicle_type` | [Vehicle Type](#vehicle-type) | Conditionally Required | Type of the vehicle that performed the event. Required for sources capable of determining vehicle type. | -| `propulsion_types` | Array of [Propulsion Type](#propulsion-type) | Conditionally Required | List of propulsion types used by the vehicle that performed the event. Required for sources capable of determining vehicle propulsion type. | +| `vehicle_type` | [Vehicle Type](/events#vehicle-type) | Conditionally Required | Type of the vehicle that performed the event. Required for sources capable of determining vehicle type. | ### Event Types -The following Event Types are included in the Activities data, and the others event types are not returned. +The following Event Types are relevant to the Session data, and the other event types are not utilized. +For `session_type` of `parking`: - **park_start**: a vehicle stopped, parked, or double parked - **park_end**: a parked vehicle leaving a parked or stopped state and resuming movement + +For `session_type` of `area`: - **enter_area**: vehicle enters the relevant geographic area - **exit_area**: vehicle exits the relevant geographic area +**Note:** It is preferable to return both start/end or enter/exit pairs of events. However, even if only one of these is present, the available data should be returned with the corresponding missing values of `event_id_X`, `event_location_X`, `event_time_X` returned as _null_. + +A "session duration" or "dwell time" can be calculated by calculating the difference between the `event_time_start` and `event_time_end`. + [Top][toc] -## Aggregates +## Aggregate -Aggregates are historic pre-computed counts and metrics of Events occuring in curb places, aggregated to the hour. +Aggregates are historic pre-computed counts and metrics of Events occurring in curb places, aggregated to the hour. All Aggregates can be calculated from the data included in [Session](#session). An Aggregate is represented as a CSV object, whose fields are as follows, as calculated from the Metrics [Methodology](#methodology): @@ -114,31 +173,27 @@ An Aggregate is represented as a CSV object, whose fields are as follows, as cal | ------ | ------ | ------------------- | ------------- | | `curb_place_type` | Enum | Required | The type of curb place this aggregate applies to from the Curbs API: `area`, `zone`, `space`. | | `curb_place_id` | [UUID][uuid] | Required | The ID of this curb place. | -| `metric_type` | Enum | Required | The metric this aggregate applies to from the [Methodology](#methodology): `total_events`, `turnover`, `average_dwell_time`, `occupancy_percent`. | +| `metric_type` | Enum | Required | The metric this aggregate applies to from the [Methodology](#methodology): `total_sessions`, `turnover`, `average_dwell_time`, `occupancy_percent`. | | `date` | date | Required | The date the event occured in ISO 8601 format, local timezone, in "YYYY-MM-DD" format. E.g. "2021-10-31" | | `hour` | integer | Required | The hour of the day the event occured in ISO 8601 format, local timezone, in "hh" format. E.g. "23" | -| `value` | number | Required | The results of the calculations for this metric from the [Methodology](#methodology). Note that "-1" means the the sensor/source was offline for the majority of the time. E.g. "6", "2.9", "-1", or "0.05" | +| `value` | number | Required | The results of the calculations for this metric from the [Methodology](#methodology). Note that "-1" means that the sensor/source was offline for the majority of the time. E.g. "6", "2.9", "-1", or "0.05" | ### Methodology -Cities are facilitating access to the curb for different users based on the curb access priorities of that particular area. The following metrics can be useful in understanding how curb usage aligns with priorities. +Cities are facilitating access to the curb for different users based on the curb access priorities of that particular area. The following metrics will be used in understanding how curb usage aligns with priorities. The metrics may be calculated using the [Session](#session) data and returned here, -An event/transaction at the curb is defined as... TBD +#### Total Sessions -Unit of measure, time, length, etc... TBD - -#### Total Events - -`count[events]` for a specific time period -Name: `total_events` +`count[sessions]` for a specific time period +Name: `total_sessions` _Use Case_ -Cities use this to determine ‘demand’ for curb space and understand how much activity is happening at the curb. Seems pretty basic but a lot of cities don’t have this insight or if they do it’s not current or comprehensive. +Cities use this to determine ‘demand’ for curb space and understand how much activity is happening at the curb. A session is a parking event, defined by the `park_start` and `park_end` event types. #### Turnover -`count[events]/hour` for a specific time period +`count[sessions]/hour` for a specific time period Name: `turnover` _Use Case_ @@ -147,7 +202,7 @@ Used together with Average Dwell Time by cities to understand how long vehicles #### Average Dwell Time -`sum[dwell time] / count[events]` for a specific time period +`sum[dwell time] / count[sessions]` for a specific time period Name: `average_dwell_time` _Use Case_ @@ -169,61 +224,9 @@ Occupancy is a metric from parking that cities would like to apply to curbs. Wit [Top][toc] -### Examples - -Example of available for 2 aggregate metrics in 2 places over a 1 day period. - -``` -curb_place_type,curb_place_id,metric_type,date,hour,value -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,0,3 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,1,7 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,2,2 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,3,7 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,4,9 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,5,10 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,6,13 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,7,16 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,8,17 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,9,13 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,10,15 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,11,19 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,12,29 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,13,27 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,14,26 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,15,38 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,16,34 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,17,35 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,18,33 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,19,20 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,20,16 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,21,12 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,22,-1 -Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_events,2021-10-31,23,8 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,0,10.5 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,1,5.0 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,2,3.0 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,3,2.9 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,4,8.3 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,5,14.5 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,6,15.3 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,7,16.2 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,8,18.1 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,9,21.3 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,10,15.2 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,11,12.1 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,12,11.8 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,13,9.3 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,14,5.7 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,15,6.7 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,16,9.2 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,17,6.4 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,18,8.3 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,19,10.3 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,20,13.5 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,21,14.2 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,22,12.1 -Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,23,9.6 -``` +# Examples + +See a series of [CDS Metrics endpoint examples](examples.md) to use as templates. [Top][toc] diff --git a/metrics/examples.md b/metrics/examples.md new file mode 100644 index 00000000..a5784718 --- /dev/null +++ b/metrics/examples.md @@ -0,0 +1,92 @@ +# Metrics Examples + +This file presents a series of CDS [Metrics](/metrics) endpoint examples to use as templates. + +## Table of Contents + +- [Dynamic Sessions](#dynamic-sessions) +- [Static Aggregate Metrics](#static-aggregate-metrics) + +## Dynamic Sessions + +A [Query Session](/metrics#query-session) example of `/metrics/sessions` with all fields returned for parking events in a specific zone over a short time period. Dynamic endpoint with [query parameters](/metrics#query-parameters) passed in. + +**Query**: + +`/metrics/sessions?curb_place_type=zone&curb_place_id=d3c862b1-5404-4635-a90b-056537c50e81&start_time=1641738460&end_time=1642119064` + +**Payload**: + +```csv +session_type,event_id_start,event_id_end,event_location_start_latitude,event_location_start_longitude,event_location_end_latitude,event_location_end_longitude,event_time_start,event_time_end,curb_zone_id,vehicle_length,vehicle_type +parking,f49333b2-d693-4f5b-b187-1a1acd720eae,4cfa75aa-d044-436f-951f-0f3037de0d29,38.257341,-85.7629702,38.256330,-85.7629111,1641738560,1641918255,d3c862b1-5404-4635-a90b-056537c50e81,120,cargo_bicycle +parking,0843d2e7-ce60-44da-a609-fb4317ef15c6,d8599307-27b4-4161-be9a-c0d097cef54d,38.257352,-85.7629804,38.257331,-85.7629810,1641839464,1641919041,d3c862b1-5404-4635-a90b-056537c50e81,670,truck +parking,74e9d1d4-9037-4347-9135-f72010311ef7,f31f1615-adad-4542-83c8-9c858f9ecd0f,38.257349,-85.7629763,38.257836,-85.7630018,1641940456,1642019039,d3c862b1-5404-4635-a90b-056537c50e81,380,van +parking,35c923fd-78f5-471d-a548-efb0dabca3b7,c702915e-9b2e-45a5-ab30-f4413cdb1a1b,38.257359,-85.7629518,38.258139,-85.7629615,1642140839,1642119050,d3c862b1-5404-4635-a90b-056537c50e81,980,freight +``` + +[Top](#table-of-contents) + +## Static Aggregate Metrics + +A [Query Aggregate](/metrics#query-aggregate) example of `/metrics/aggregates` that collects 2 aggregate metrics in 2 places over a 1 day period. Static endpoint, so no [query parameters](/metrics#query-parameters) passed in. + +**Query**: + +`/metrics/aggregates` + +**Payload**: + +```csv +curb_place_type,curb_place_id,metric_type,date,hour,value +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,0,3 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,1,7 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,2,2 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,3,7 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,4,9 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,5,10 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,6,13 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,7,16 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,8,17 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,9,13 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,10,15 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,11,19 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,12,29 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,13,27 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,14,26 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,15,38 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,16,34 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,17,35 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,18,33 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,19,20 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,20,16 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,21,12 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,22,-1 +Zone,0f6a052d-f934-4159-8da4-3135e453b968,total_sessions,2021-10-31,23,8 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,0,10.5 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,1,5.0 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,2,3.0 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,3,2.9 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,4,8.3 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,5,14.5 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,6,15.3 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,7,16.2 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,8,18.1 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,9,21.3 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,10,15.2 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,11,12.1 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,12,11.8 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,13,9.3 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,14,5.7 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,15,6.7 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,16,9.2 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,17,6.4 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,18,8.3 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,19,10.3 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,20,13.5 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,21,14.2 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,22,12.1 +Space,7e6be807-ff61-4f12-85c8-0fb740b24436,average_dwell_time,2021-10-31,23,9.6 +``` + +[Top](#table-of-contents)