-
Notifications
You must be signed in to change notification settings - Fork 2
Icone field device feed models #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
2bf2627
Updating GIS api to coloradodot.info and LrsServerRounded
jacob6838 cfa14c9
Adding deserializable field device feed objects
jacob6838 65d8ec4
validating field device objects and deserialization
jacob6838 c279b8d
Tweaking model definition defaults
jacob6838 c99bdc6
Merge branch 'poetry' into icone-field-device-feed-models
jacob6838 dff3bf5
Reverting icone raw to standard changes
jacob6838 38169f5
Cleaning up comments and test data
jacob6838 df6b96f
Adding tests for datetime_from_unix
jacob6838 e8dcde5
Re-generating requirements.txt with pydantic
jacob6838 27591b4
Adding descriptions and standardizing docstring comments
jacob6838 9d0502a
Adding defaults for literals and updating date tools
jacob6838 8592f2e
Improving field device feed test
jacob6838 d5863bf
updating poetry lockfile
jacob6838 2052789
Cleaning up data model descriptions
jacob6838 e5b178e
Adding geojson type descriptions
jacob6838 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| { | ||
| "feed_info": { | ||
| "update_date": "2025-12-18T20:34:51.150000Z", | ||
| "publisher": "iCone Products LLC", | ||
| "contact_email": "support@iconeproducts.com", | ||
| "version": "4.2", | ||
| "data_sources": [ | ||
| { | ||
| "data_source_id": "67899A97-0F3E-4683-B169-75C09C3B8F67", | ||
| "update_date": "2025-12-18T20:34:51.150000Z", | ||
| "organization_name": "iCone Products LLC", | ||
| "contact_email": "support@iconeproducts.com" | ||
| } | ||
| ] | ||
| }, | ||
| "type": "FeatureCollection", | ||
| "features": [ | ||
| { | ||
| "id": "E595E296-B1DE-4911-9454-1F2D54AC2EBD", | ||
| "type": "Feature", | ||
| "geometry": { | ||
| "type": "Point", | ||
| "coordinates": [-104.7752009, 39.4983242] | ||
| }, | ||
| "properties": { | ||
| "core_details": { | ||
| "device_type": "arrow-board", | ||
| "data_source_id": "67899A97-0F3E-4683-B169-75C09C3B8F67", | ||
| "device_status": "ok", | ||
| "update_date": "2025-12-18T20:30:27Z", | ||
| "has_automatic_location": true, | ||
| "description": "Roadwork - Caution" | ||
| }, | ||
| "pattern": "four-corners-flashing" | ||
| } | ||
| }, | ||
| { | ||
| "id": "0E1E3B5B-D06E-4390-ABB3-C89091E246F0", | ||
| "type": "Feature", | ||
| "geometry": { | ||
| "type": "Point", | ||
| "coordinates": [-106.0079266, 39.6531149] | ||
| }, | ||
| "properties": { | ||
| "core_details": { | ||
| "device_type": "location-marker", | ||
| "data_source_id": "67899A97-0F3E-4683-B169-75C09C3B8F67", | ||
| "device_status": "ok", | ||
| "update_date": "2025-12-18T20:19:13Z", | ||
| "has_automatic_location": true, | ||
| "description": "Roadwork Active" | ||
| }, | ||
| "marked_locations": [{"type": "work-truck-with-lights-flashing"}] | ||
| } | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| [ | ||
| { | ||
| "feed_info": { | ||
| "update_date": "2025-12-18T20:34:51.1500000Z", | ||
| "publisher": "iCone Products LLC", | ||
| "contact_email": "support@iconeproducts.com", | ||
| "version": "4.2", | ||
| "data_sources": [ | ||
| { | ||
| "data_source_id": "67899A97-0F3E-4683-B169-75C09C3B8F67", | ||
| "update_date": "2025-12-18T20:34:51.1500000Z", | ||
| "organization_name": "iCone Products LLC", | ||
| "contact_email": "support@iconeproducts.com" | ||
| } | ||
| ], | ||
| "custom": { | ||
| "oldest_feature": "2025-12-17T20:34:51.0300000Z", | ||
| "oldest_location": "2025-12-17T20:34:51.0300000Z", | ||
| "username": "cdotfeeds", | ||
| "active_only": false, | ||
| "require_location": false, | ||
| "allow_custom_enums": true, | ||
| "include_custom": true, | ||
| "force_spec_required": false | ||
| } | ||
| }, | ||
| "type": "FeatureCollection", | ||
| "features": [ | ||
| { | ||
| "id": "E595E296-B1DE-4911-9454-1F2D54AC2EBD", | ||
| "type": "Feature", | ||
| "geometry": { | ||
| "type": "Point", | ||
| "coordinates": [ | ||
| -104.7752009, | ||
| 39.4983242 | ||
| ] | ||
| }, | ||
| "properties": { | ||
| "core_details": { | ||
| "device_type": "arrow-board", | ||
| "data_source_id": "67899A97-0F3E-4683-B169-75C09C3B8F67", | ||
| "device_status": "ok", | ||
| "update_date": "2025-12-18T20:30:27Z", | ||
| "has_automatic_location": true, | ||
| "description": "Roadwork - Caution" | ||
| }, | ||
| "pattern": "four-corners-flashing", | ||
| "custom": { | ||
| "start_date": "2025-12-16T16:16:08", | ||
| "waze_incident": { | ||
| "type": "CONSTRUCTION", | ||
| "description": "Roadwork - Caution" | ||
| } | ||
| } | ||
| } | ||
| }, | ||
| { | ||
| "id": "0E1E3B5B-D06E-4390-ABB3-C89091E246F0", | ||
| "type": "Feature", | ||
| "geometry": { | ||
| "type": "Point", | ||
| "coordinates": [ | ||
| -106.0079266, | ||
| 39.6531149 | ||
| ] | ||
| }, | ||
| "properties": { | ||
| "core_details": { | ||
| "device_type": "location-marker", | ||
| "data_source_id": "67899A97-0F3E-4683-B169-75C09C3B8F67", | ||
| "device_status": "ok", | ||
| "update_date": "2025-12-18T20:19:13Z", | ||
| "has_automatic_location": true, | ||
| "description": "Roadwork Active" | ||
| }, | ||
| "marked_locations": [ | ||
| { | ||
| "type": "work-truck-with-lights-flashing" | ||
| } | ||
| ], | ||
| "custom": { | ||
| "isActive": true, | ||
| "start_date": "2025-12-18T20:08:16.1200000", | ||
| "waze_incident": { | ||
| "type": "HAZARD", | ||
| "description": "Roadwork Active" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| from pydantic import TypeAdapter | ||
| from wzdx.models.field_device_feed.device_feed import DeviceFeed | ||
| import json | ||
|
|
||
|
|
||
| def test_deserialization(): | ||
| """Test deserialization and serialization of field device feed""" | ||
| # Load and deserialize JSON | ||
| with open("./tests/data/models/field_device_feed_icone_raw.json") as f: | ||
| json_string = f.read() | ||
|
|
||
| adapter = TypeAdapter(list[DeviceFeed]) | ||
| device_feed_list: list[DeviceFeed] = adapter.validate_json(json_string) | ||
|
|
||
| # Validate structure | ||
| assert len(device_feed_list) == 1, "Expected exactly one device feed" | ||
| device_feed = device_feed_list[0] | ||
| assert len(device_feed.features) > 0, "Expected at least one feature" | ||
|
|
||
| # Validate first feature properties | ||
| first_feature = device_feed.features[0] | ||
| assert first_feature.id is not None, "Feature should have an ID" | ||
| assert first_feature.properties.core_details.device_status is not None | ||
| assert first_feature.properties.core_details.update_date is not None | ||
|
|
||
| # Load expected output | ||
| with open("./tests/data/models/field_device_feed_icone_final.json") as f: | ||
| expected_object = json.load(f) | ||
|
|
||
| # Compare serialized output with expected | ||
| actual_output = device_feed.model_dump( | ||
| by_alias=True, exclude_none=True, mode="json" | ||
| ) | ||
| assert actual_output == expected_object, "Serialized output should match expected" | ||
|
|
||
|
|
||
| def test_roundtrip_serialization(): | ||
| """Test that serialize -> deserialize produces identical results""" | ||
| # Load original data | ||
| with open("./tests/data/models/field_device_feed_icone_raw.json") as f: | ||
| json_string = f.read() | ||
|
|
||
| adapter = TypeAdapter(list[DeviceFeed]) | ||
|
|
||
| # First deserialization | ||
| device_feed_list_1 = adapter.validate_json(json_string) | ||
|
|
||
| # Serialize and deserialize again | ||
| json_output = adapter.dump_json( | ||
| device_feed_list_1, by_alias=True, exclude_none=True | ||
| ) | ||
| device_feed_list_2 = adapter.validate_json(json_output) | ||
|
|
||
| # Should be identical | ||
| assert ( | ||
| device_feed_list_1 == device_feed_list_2 | ||
| ), "Roundtrip serialization should be stable" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| from .feed_info import FeedInfo | ||
| from .feed_data_source import FeedDataSource | ||
|
|
||
| __all__ = [ | ||
| "FeedInfo", | ||
| "FeedDataSource" | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| from typing import Optional | ||
| from datetime import datetime | ||
| from pydantic import BaseModel, EmailStr, Field | ||
|
|
||
|
|
||
| class FeedDataSource(BaseModel): | ||
| """ | ||
| The FeedDataSource object describes information about a specific data source used to build a data feed. A WZDx feed must contain at least one FeedDataSource, included as an entry in the data_sources array of the FeedInfo object. | ||
|
|
||
| Documentation: https://github.com/usdot-jpo-ode/wzdx/blob/develop/spec-content/objects/FeedDataSource.md | ||
| """ | ||
|
|
||
| data_source_id: str = Field( | ||
| alias="data_source_id", | ||
| description="A unique identifier for the data source organization providing work zone data. It is recommended that this identifier is a Universally Unique Identifier (UUID) as defined in RFC 4122 to guarantee uniqueness between feeds and over time.", | ||
| ) | ||
| organization_name: str = Field( | ||
| alias="organization_name", | ||
| description="The name of the organization for the authoritative source of the work zone data.", | ||
| ) | ||
| update_date: Optional[datetime] = Field( | ||
| default=None, | ||
| alias="update_date", | ||
| description="The UTC date and time when the data source was last updated.", | ||
| ) | ||
| update_frequency: Optional[int] = Field( | ||
| default=None, | ||
| alias="update_frequency", | ||
| description="The frequency in seconds at which the data source is updated.", | ||
| ) | ||
| contact_name: Optional[str] = Field( | ||
| default=None, | ||
| alias="contact_name", | ||
| description="The name of the individual or group responsible for the data source.", | ||
| ) | ||
| contact_email: Optional[EmailStr] = Field( | ||
| default=None, | ||
| alias="contact_email", | ||
| description="The email address of the individual or group responsible for the data source.", | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| from typing import Optional | ||
| from pydantic import BaseModel, Field, EmailStr | ||
| from .feed_data_source import FeedDataSource | ||
| from datetime import datetime | ||
|
|
||
|
|
||
| class FeedInfo(BaseModel): | ||
| """ | ||
| The FeedInfo object describes WZDx feed header information such as metadata, contact information, and data sources. There is one FeedInfo per WZDx GeoJSON document. | ||
|
|
||
| Documentation: https://github.com/usdot-jpo-ode/wzdx/blob/develop/spec-content/objects/FeedInfo.md | ||
| """ | ||
|
|
||
| publisher: str = Field( | ||
| alias="publisher", | ||
| description="The organization responsible for publishing the feed.", | ||
| ) | ||
| version: str = Field( | ||
| alias="version", | ||
| description="The WZDx specification version used to create the data feed in major.minor format. Note this mandates that all data in a WZDx feed complies to a single version of WZDx.", | ||
| ) | ||
| license: Optional[str] = Field( | ||
| default=None, | ||
| alias="license", | ||
| description='The URL of the license that applies to the data in the WZDx feed. This must be the string "https://creativecommons.org/publicdomain/zero/1.0/"', | ||
| ) | ||
| data_sources: list[FeedDataSource] = Field( | ||
| alias="data_sources", | ||
| description="A list of specific data sources for the road event data in the feed.", | ||
| ) | ||
| update_date: datetime = Field( | ||
| alias="update_date", | ||
| description="The UTC date and time when the GeoJSON file (representing the instance of the feed) was generated.", | ||
| ) | ||
| update_frequency: Optional[int] = Field( | ||
| default=None, | ||
| alias="update_frequency", | ||
| description="The frequency in seconds at which the data feed is updated.", | ||
| ) | ||
| contact_name: Optional[str] = Field( | ||
| default=None, | ||
| alias="contact_name", | ||
| description="The name of the individual or group responsible for the data feed.", | ||
| ) | ||
| contact_email: Optional[EmailStr] = Field( | ||
| default=None, | ||
| alias="contact_email", | ||
| description="The email address of the individual or group responsible for the data feed.", | ||
| ) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.