fleetpull 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fleetpull/__init__.py +36 -0
- fleetpull/api/__init__.py +32 -0
- fleetpull/api/auth_ingress.py +216 -0
- fleetpull/api/catalog.py +139 -0
- fleetpull/api/fetch.py +229 -0
- fleetpull/api/identity.py +90 -0
- fleetpull/api/sync.py +735 -0
- fleetpull/cli.py +146 -0
- fleetpull/config/__init__.py +47 -0
- fleetpull/config/base.py +18 -0
- fleetpull/config/example.py +90 -0
- fleetpull/config/geotab.py +78 -0
- fleetpull/config/http.py +32 -0
- fleetpull/config/loading.py +195 -0
- fleetpull/config/logger.py +139 -0
- fleetpull/config/providers.py +520 -0
- fleetpull/config/rate_limit.py +50 -0
- fleetpull/config/resolution.py +156 -0
- fleetpull/config/retry.py +69 -0
- fleetpull/config/root.py +157 -0
- fleetpull/config/sections.py +146 -0
- fleetpull/endpoints/__init__.py +24 -0
- fleetpull/endpoints/geotab/__init__.py +12 -0
- fleetpull/endpoints/geotab/_requests.py +427 -0
- fleetpull/endpoints/geotab/annotation_logs.py +73 -0
- fleetpull/endpoints/geotab/audits.py +70 -0
- fleetpull/endpoints/geotab/devices.py +79 -0
- fleetpull/endpoints/geotab/driver_changes.py +73 -0
- fleetpull/endpoints/geotab/duty_status_logs.py +75 -0
- fleetpull/endpoints/geotab/dvir_logs.py +76 -0
- fleetpull/endpoints/geotab/exception_events.py +119 -0
- fleetpull/endpoints/geotab/fault_data.py +72 -0
- fleetpull/endpoints/geotab/fill_ups.py +79 -0
- fleetpull/endpoints/geotab/fuel_and_energy_used.py +74 -0
- fleetpull/endpoints/geotab/fuel_tax_details.py +75 -0
- fleetpull/endpoints/geotab/log_records.py +74 -0
- fleetpull/endpoints/geotab/media_files.py +74 -0
- fleetpull/endpoints/geotab/shipment_logs.py +71 -0
- fleetpull/endpoints/geotab/status_data.py +71 -0
- fleetpull/endpoints/geotab/text_messages.py +77 -0
- fleetpull/endpoints/geotab/trips.py +102 -0
- fleetpull/endpoints/geotab/users.py +81 -0
- fleetpull/endpoints/motive/__init__.py +12 -0
- fleetpull/endpoints/motive/_spec_builders.py +94 -0
- fleetpull/endpoints/motive/driver_idle_rollups.py +113 -0
- fleetpull/endpoints/motive/driving_periods.py +85 -0
- fleetpull/endpoints/motive/groups.py +61 -0
- fleetpull/endpoints/motive/idle_events.py +94 -0
- fleetpull/endpoints/motive/users.py +64 -0
- fleetpull/endpoints/motive/vehicle_locations.py +170 -0
- fleetpull/endpoints/motive/vehicle_utilizations.py +122 -0
- fleetpull/endpoints/motive/vehicles.py +106 -0
- fleetpull/endpoints/registry.py +280 -0
- fleetpull/endpoints/samsara/__init__.py +12 -0
- fleetpull/endpoints/samsara/_spec_builders.py +202 -0
- fleetpull/endpoints/samsara/addresses.py +77 -0
- fleetpull/endpoints/samsara/asset_locations.py +217 -0
- fleetpull/endpoints/samsara/driver_fuel_energy_reports.py +124 -0
- fleetpull/endpoints/samsara/driver_vehicle_assignments.py +211 -0
- fleetpull/endpoints/samsara/drivers.py +169 -0
- fleetpull/endpoints/samsara/engine_states.py +114 -0
- fleetpull/endpoints/samsara/gps_readings.py +113 -0
- fleetpull/endpoints/samsara/idling_events.py +195 -0
- fleetpull/endpoints/samsara/odometer_readings.py +116 -0
- fleetpull/endpoints/samsara/trips.py +217 -0
- fleetpull/endpoints/samsara/vehicle_fuel_energy_reports.py +139 -0
- fleetpull/endpoints/samsara/vehicles.py +121 -0
- fleetpull/endpoints/shared/__init__.py +57 -0
- fleetpull/endpoints/shared/base.py +529 -0
- fleetpull/endpoints/shared/request_shape.py +227 -0
- fleetpull/endpoints/shared/resume.py +74 -0
- fleetpull/endpoints/shared/spec_builders.py +59 -0
- fleetpull/endpoints/shared/sync_mode.py +159 -0
- fleetpull/endpoints/shared/url_paths.py +149 -0
- fleetpull/exceptions.py +320 -0
- fleetpull/incremental/__init__.py +27 -0
- fleetpull/incremental/cursor.py +66 -0
- fleetpull/incremental/resolution.py +152 -0
- fleetpull/incremental/seed.py +53 -0
- fleetpull/incremental/window.py +94 -0
- fleetpull/logger/__init__.py +5 -0
- fleetpull/logger/setup.py +145 -0
- fleetpull/model_contract/__init__.py +6 -0
- fleetpull/model_contract/coercions.py +33 -0
- fleetpull/model_contract/response.py +45 -0
- fleetpull/models/__init__.py +7 -0
- fleetpull/models/geotab/__init__.py +166 -0
- fleetpull/models/geotab/annotation_log.py +109 -0
- fleetpull/models/geotab/audit.py +56 -0
- fleetpull/models/geotab/device.py +217 -0
- fleetpull/models/geotab/driver_change.py +102 -0
- fleetpull/models/geotab/duty_status_log.py +200 -0
- fleetpull/models/geotab/dvir_log.py +184 -0
- fleetpull/models/geotab/exception_event.py +135 -0
- fleetpull/models/geotab/fault_data.py +168 -0
- fleetpull/models/geotab/fill_up.py +189 -0
- fleetpull/models/geotab/fuel_and_energy_used.py +81 -0
- fleetpull/models/geotab/fuel_tax_detail.py +150 -0
- fleetpull/models/geotab/log_record.py +68 -0
- fleetpull/models/geotab/media_file.py +133 -0
- fleetpull/models/geotab/shared.py +221 -0
- fleetpull/models/geotab/shipment_log.py +105 -0
- fleetpull/models/geotab/status_data.py +108 -0
- fleetpull/models/geotab/text_message.py +125 -0
- fleetpull/models/geotab/trip.py +162 -0
- fleetpull/models/geotab/user.py +187 -0
- fleetpull/models/motive/__init__.py +43 -0
- fleetpull/models/motive/driver_idle_rollup.py +109 -0
- fleetpull/models/motive/driving_period.py +82 -0
- fleetpull/models/motive/group.py +49 -0
- fleetpull/models/motive/idle_event.py +77 -0
- fleetpull/models/motive/shared.py +192 -0
- fleetpull/models/motive/user.py +217 -0
- fleetpull/models/motive/vehicle.py +162 -0
- fleetpull/models/motive/vehicle_location.py +127 -0
- fleetpull/models/motive/vehicle_utilization.py +128 -0
- fleetpull/models/samsara/__init__.py +108 -0
- fleetpull/models/samsara/address.py +149 -0
- fleetpull/models/samsara/asset_location.py +131 -0
- fleetpull/models/samsara/driver.py +232 -0
- fleetpull/models/samsara/driver_fuel_energy_report.py +153 -0
- fleetpull/models/samsara/driver_vehicle_assignment.py +168 -0
- fleetpull/models/samsara/engine_state.py +92 -0
- fleetpull/models/samsara/gps_reading.py +146 -0
- fleetpull/models/samsara/idling_event.py +174 -0
- fleetpull/models/samsara/odometer_reading.py +90 -0
- fleetpull/models/samsara/trip.py +199 -0
- fleetpull/models/samsara/vehicle.py +167 -0
- fleetpull/models/samsara/vehicle_fuel_energy_report.py +191 -0
- fleetpull/network/__init__.py +9 -0
- fleetpull/network/auth/__init__.py +15 -0
- fleetpull/network/auth/authenticate.py +271 -0
- fleetpull/network/auth/manager.py +223 -0
- fleetpull/network/auth/models.py +57 -0
- fleetpull/network/auth/strategies.py +169 -0
- fleetpull/network/classifiers/__init__.py +11 -0
- fleetpull/network/classifiers/geotab.py +145 -0
- fleetpull/network/classifiers/motive.py +79 -0
- fleetpull/network/classifiers/samsara.py +80 -0
- fleetpull/network/client/__init__.py +25 -0
- fleetpull/network/client/page.py +32 -0
- fleetpull/network/client/profile.py +27 -0
- fleetpull/network/client/registry.py +103 -0
- fleetpull/network/client/registry_base.py +150 -0
- fleetpull/network/client/runtime.py +44 -0
- fleetpull/network/client/transport.py +381 -0
- fleetpull/network/contract/__init__.py +50 -0
- fleetpull/network/contract/auth.py +48 -0
- fleetpull/network/contract/classifier.py +189 -0
- fleetpull/network/contract/envelope_fetcher.py +33 -0
- fleetpull/network/contract/envelopes.py +189 -0
- fleetpull/network/contract/outcome.py +43 -0
- fleetpull/network/contract/page_decoder.py +101 -0
- fleetpull/network/contract/request.py +97 -0
- fleetpull/network/decoders/__init__.py +40 -0
- fleetpull/network/decoders/_window_stamp.py +78 -0
- fleetpull/network/decoders/geotab.py +309 -0
- fleetpull/network/decoders/motive.py +204 -0
- fleetpull/network/decoders/motive_reports.py +114 -0
- fleetpull/network/decoders/samsara.py +343 -0
- fleetpull/network/decoders/samsara_reports.py +119 -0
- fleetpull/network/decoders/single_page.py +55 -0
- fleetpull/network/limits/__init__.py +13 -0
- fleetpull/network/limits/bucket_math.py +58 -0
- fleetpull/network/limits/limiter.py +153 -0
- fleetpull/network/limits/registry.py +96 -0
- fleetpull/network/posture/__init__.py +6 -0
- fleetpull/network/posture/client_options.py +96 -0
- fleetpull/network/retry/__init__.py +13 -0
- fleetpull/network/retry/decision.py +155 -0
- fleetpull/network/tls/__init__.py +5 -0
- fleetpull/network/tls/truststore_context.py +35 -0
- fleetpull/orchestrator/__init__.py +30 -0
- fleetpull/orchestrator/backfill.py +127 -0
- fleetpull/orchestrator/batch.py +155 -0
- fleetpull/orchestrator/bisection.py +271 -0
- fleetpull/orchestrator/drivers.py +350 -0
- fleetpull/orchestrator/entry.py +347 -0
- fleetpull/orchestrator/executors.py +128 -0
- fleetpull/orchestrator/fanout.py +163 -0
- fleetpull/orchestrator/feed_drive.py +266 -0
- fleetpull/orchestrator/metadata_projection.py +195 -0
- fleetpull/orchestrator/outcome.py +53 -0
- fleetpull/orchestrator/recording.py +85 -0
- fleetpull/orchestrator/resume.py +143 -0
- fleetpull/orchestrator/roster_harvest.py +108 -0
- fleetpull/orchestrator/roster_refresh.py +363 -0
- fleetpull/orchestrator/runner.py +262 -0
- fleetpull/orchestrator/shape_resolution.py +221 -0
- fleetpull/orchestrator/spine.py +166 -0
- fleetpull/orchestrator/streaming.py +153 -0
- fleetpull/orchestrator/unit_loop.py +273 -0
- fleetpull/orchestrator/watermark_drive.py +455 -0
- fleetpull/paths/__init__.py +13 -0
- fleetpull/paths/datasets.py +38 -0
- fleetpull/paths/partitions.py +41 -0
- fleetpull/paths/resolution.py +98 -0
- fleetpull/polars_typing/__init__.py +20 -0
- fleetpull/py.typed +0 -0
- fleetpull/records/__init__.py +19 -0
- fleetpull/records/convert.py +53 -0
- fleetpull/records/dataframe.py +63 -0
- fleetpull/records/event_time.py +70 -0
- fleetpull/records/fields.py +190 -0
- fleetpull/records/flatten.py +54 -0
- fleetpull/records/roster_members.py +74 -0
- fleetpull/records/schema.py +73 -0
- fleetpull/records/validation.py +62 -0
- fleetpull/resources/__init__.py +10 -0
- fleetpull/resources/config.example.yaml +222 -0
- fleetpull/roster/__init__.py +16 -0
- fleetpull/roster/definition.py +46 -0
- fleetpull/roster/key.py +40 -0
- fleetpull/roster/registry.py +93 -0
- fleetpull/state/__init__.py +36 -0
- fleetpull/state/cursors.py +417 -0
- fleetpull/state/database.py +463 -0
- fleetpull/state/migrations.py +430 -0
- fleetpull/state/reconcile.py +127 -0
- fleetpull/state/rosters.py +159 -0
- fleetpull/state/run_ledger.py +572 -0
- fleetpull/state/work_units.py +648 -0
- fleetpull/storage/__init__.py +30 -0
- fleetpull/storage/append.py +187 -0
- fleetpull/storage/atomic.py +161 -0
- fleetpull/storage/files.py +176 -0
- fleetpull/storage/frames.py +98 -0
- fleetpull/storage/metadata.py +161 -0
- fleetpull/storage/partitioned.py +205 -0
- fleetpull/storage/pruning.py +169 -0
- fleetpull/storage/read.py +35 -0
- fleetpull/storage/result.py +34 -0
- fleetpull/storage/single_file.py +130 -0
- fleetpull/storage/splitting.py +88 -0
- fleetpull/storage/staging.py +178 -0
- fleetpull/storage/writers.py +145 -0
- fleetpull/timing/__init__.py +21 -0
- fleetpull/timing/canon.py +92 -0
- fleetpull/timing/clock.py +192 -0
- fleetpull/timing/codec.py +122 -0
- fleetpull/timing/sleeper.py +65 -0
- fleetpull/vocabulary/__init__.py +16 -0
- fleetpull/vocabulary/json_types.py +20 -0
- fleetpull/vocabulary/provider.py +29 -0
- fleetpull/vocabulary/quota_scope.py +47 -0
- fleetpull/vocabulary/response_category.py +32 -0
- fleetpull-0.1.0.dist-info/METADATA +248 -0
- fleetpull-0.1.0.dist-info/RECORD +252 -0
- fleetpull-0.1.0.dist-info/WHEEL +5 -0
- fleetpull-0.1.0.dist-info/entry_points.txt +2 -0
- fleetpull-0.1.0.dist-info/licenses/LICENSE +202 -0
- fleetpull-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# src/fleetpull/models/geotab/dvir_log.py
|
|
2
|
+
"""GeoTab DVIRLog response model (``GetFeed`` on ``typeName: DVIRLog``).
|
|
3
|
+
|
|
4
|
+
Written from the 2026-07-21 feed wave two census (30-day seeded pulls at
|
|
5
|
+
the probed tenant), never from docs. A DVIRLog is one driver vehicle
|
|
6
|
+
inspection report. The house class casing is ``DvirLog``; the wire
|
|
7
|
+
``typeName`` stays ``'DVIRLog'`` (the binding's constant). DVIRs are
|
|
8
|
+
certified and edited after creation, so re-emission under newer
|
|
9
|
+
``version`` tokens is expected and the consumer reconciles by
|
|
10
|
+
``(id, max version)`` (DESIGN §4).
|
|
11
|
+
|
|
12
|
+
Requiredness posture (the wave-two conservative stance, DESIGN §8): the
|
|
13
|
+
census is a TENANT-SCOPED observation (500 records), so structural
|
|
14
|
+
requiredness is limited to the record identity — ``id``, ``dateTime``
|
|
15
|
+
(the event time), ``version``, and the primary entity ref (``driver``,
|
|
16
|
+
500/500; ``device`` is only 205/500 and could not be it) — and every
|
|
17
|
+
other field is optional EVEN where the census was total. The observed
|
|
18
|
+
arms and exclusions:
|
|
19
|
+
|
|
20
|
+
- ``device`` is OPTIONAL and commonly absent (205/500 carriers) — a
|
|
21
|
+
plain wire fact of this census, recorded without speculation.
|
|
22
|
+
``engineHours`` and ``odometer`` travel with it (205/500 each);
|
|
23
|
+
``engineHours`` was int-only on its carriers, but its sibling
|
|
24
|
+
surface (``DutyStatusLog``) proved the same physical quantity MIXED
|
|
25
|
+
int-or-float, so it models ``float`` here too (cross-surface dtype
|
|
26
|
+
consistency over a thin single-surface census).
|
|
27
|
+
- ``defectList`` is a WIRE-PLURAL NAME carrying ONE defect node
|
|
28
|
+
``{children, id, name}``. The node models ``id`` + ``name`` ONLY:
|
|
29
|
+
``children`` is EXCLUDED under the documented-exclusion doctrine —
|
|
30
|
+
an EMPTY list on every one of the 200 ``defectList`` nodes the
|
|
31
|
+
census sampled (the nested-block sample depth; ``defectList`` itself
|
|
32
|
+
was present 500/500), so its element shape is unobservable at this
|
|
33
|
+
tenant, and the records layer deliberately supports only observable
|
|
34
|
+
shapes; ``extra='ignore'`` absorbs it wire-side (a record with
|
|
35
|
+
populated children still validates — the pinned absorption test).
|
|
36
|
+
REVISIT when a tenant shows populated ``children``: capture the
|
|
37
|
+
element shape and model it then.
|
|
38
|
+
- ``location`` (496/500) is the shared ``GeotabAddressedLocation``
|
|
39
|
+
wrapper (DutyStatusLog is the co-consumer; DESIGN §8): a
|
|
40
|
+
``{location: {x, y}}`` coordinate arm or an
|
|
41
|
+
``{address: {formattedAddress}}`` arm. This surface showed only the
|
|
42
|
+
coordinate arm on the live-proof walk, but rides the shared wrapper
|
|
43
|
+
whose address arm DutyStatusLog proved.
|
|
44
|
+
- ``duration`` is an opaque duration STRING mirrored verbatim, NOT
|
|
45
|
+
parsed through ``GeotabTimeSpan`` despite that sharing GeoTab's
|
|
46
|
+
provider. The census observed only the wire TYPE (``str``, 500/500),
|
|
47
|
+
never the value FORMAT — unlike ``Trip.duration``, whose TimeSpan
|
|
48
|
+
grammar was probe-confirmed (2026-07-13). Applying the strict
|
|
49
|
+
TimeSpan parser to an unobserved format would crash every record if
|
|
50
|
+
it differs, so the conservative mirror holds until a probe settles
|
|
51
|
+
the format. ``trailer`` (295/500) is an ``{id}`` ref.
|
|
52
|
+
- Every reference field (``device``, ``driver``, ``trailer``) rides
|
|
53
|
+
the shared ``bare_id_to_reference`` lift (the census-scope lesson: a
|
|
54
|
+
tenant census cannot prove the string arm absent).
|
|
55
|
+
|
|
56
|
+
``dateTime`` is recovered tz-aware by validation, the GeoTab sibling
|
|
57
|
+
idiom. ``logType`` is a census-open vocabulary — a plain str, never an
|
|
58
|
+
enum.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
from datetime import datetime
|
|
62
|
+
from typing import Annotated
|
|
63
|
+
|
|
64
|
+
from pydantic import BeforeValidator, ConfigDict
|
|
65
|
+
from pydantic.alias_generators import to_camel
|
|
66
|
+
|
|
67
|
+
from fleetpull.model_contract import ResponseModel
|
|
68
|
+
from fleetpull.models.geotab.shared import GeotabAddressedLocation, bare_id_to_reference
|
|
69
|
+
|
|
70
|
+
__all__: list[str] = [
|
|
71
|
+
'DvirLog',
|
|
72
|
+
'DvirLogDefectList',
|
|
73
|
+
'DvirLogDeviceRef',
|
|
74
|
+
'DvirLogDriverRef',
|
|
75
|
+
'DvirLogTrailerRef',
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class DvirLogDefectList(ResponseModel):
|
|
80
|
+
"""The ``defectList`` block: a WIRE-PLURAL NAME, ONE defect node.
|
|
81
|
+
|
|
82
|
+
Despite the plural wire key, the census shows ONE object —
|
|
83
|
+
``{children, id, name}`` — mirrored as a single nested model, never
|
|
84
|
+
a list. ``children`` is excluded (never populated on the whole
|
|
85
|
+
census; the module docstring's documented-exclusion record); ``id``
|
|
86
|
+
and ``name`` are required within the block — a defect node without
|
|
87
|
+
its identity is a shape change and must fail loudly.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
91
|
+
|
|
92
|
+
id: str
|
|
93
|
+
name: str
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class DvirLogDeviceRef(ResponseModel):
|
|
97
|
+
"""The inspected vehicle unit's reference.
|
|
98
|
+
|
|
99
|
+
Census-observed as an ``{id}`` object on every carrier; the shared
|
|
100
|
+
coercion lifts a bare string defensively (the census-scope lesson).
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
104
|
+
|
|
105
|
+
id: str
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class DvirLogDriverRef(ResponseModel):
|
|
109
|
+
"""The inspecting driver's reference: the id alone, on every record."""
|
|
110
|
+
|
|
111
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
112
|
+
|
|
113
|
+
id: str
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class DvirLogTrailerRef(ResponseModel):
|
|
117
|
+
"""The inspected trailer's reference: the id alone, on every carrier."""
|
|
118
|
+
|
|
119
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
120
|
+
|
|
121
|
+
id: str
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class DvirLog(ResponseModel):
|
|
125
|
+
"""One GeoTab driver vehicle inspection report from the DVIRLog feed.
|
|
126
|
+
|
|
127
|
+
The wave-two conservative mirror (the module docstring's posture):
|
|
128
|
+
``id`` / ``date_time`` / ``version`` / ``driver`` required,
|
|
129
|
+
everything else optional even where census-total.
|
|
130
|
+
|
|
131
|
+
Attributes:
|
|
132
|
+
authority_address: The certifying authority's address.
|
|
133
|
+
authority_name: The certifying authority's name.
|
|
134
|
+
certify_remark: The certification remark.
|
|
135
|
+
date_time: The inspection's UTC instant — the endpoint's event
|
|
136
|
+
time.
|
|
137
|
+
defect_list: The plural-named single defect node (``children``
|
|
138
|
+
excluded — the module docstring's record).
|
|
139
|
+
device: The inspected vehicle unit's reference (205/500 — the
|
|
140
|
+
observed wire fact).
|
|
141
|
+
driver: The inspecting driver's reference.
|
|
142
|
+
driver_remark: The driver's remark.
|
|
143
|
+
duration: The inspection duration — an opaque wire string
|
|
144
|
+
mirrored verbatim (the value format is unobserved, so it is
|
|
145
|
+
not parsed through ``GeotabTimeSpan`` the way ``Trip`` is;
|
|
146
|
+
module docstring).
|
|
147
|
+
engine_hours: The engine-hours reading (205/500; modeled float
|
|
148
|
+
per the cross-surface mixed-numeric proof).
|
|
149
|
+
id: GeoTab's record id.
|
|
150
|
+
is_inspected_by_driver: Whether the driver performed the
|
|
151
|
+
inspection.
|
|
152
|
+
location: The inspection's nested location (496/500; the shared
|
|
153
|
+
wrapper — a ``{x, y}`` coordinate arm, x longitude / y
|
|
154
|
+
latitude, or a ``formattedAddress`` arm).
|
|
155
|
+
log_type: The inspection-type token (census-open plain str).
|
|
156
|
+
odometer: The odometer reading (205/500; modeled float).
|
|
157
|
+
trailer: The inspected trailer's reference (295/500).
|
|
158
|
+
version: The record's version token — the certified/edited-log
|
|
159
|
+
reconcile key beside ``id``.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
163
|
+
|
|
164
|
+
authority_address: str | None = None
|
|
165
|
+
authority_name: str | None = None
|
|
166
|
+
certify_remark: str | None = None
|
|
167
|
+
date_time: datetime
|
|
168
|
+
defect_list: DvirLogDefectList | None = None
|
|
169
|
+
device: Annotated[
|
|
170
|
+
DvirLogDeviceRef | None, BeforeValidator(bare_id_to_reference)
|
|
171
|
+
] = None
|
|
172
|
+
driver: Annotated[DvirLogDriverRef, BeforeValidator(bare_id_to_reference)]
|
|
173
|
+
driver_remark: str | None = None
|
|
174
|
+
duration: str | None = None
|
|
175
|
+
engine_hours: float | None = None
|
|
176
|
+
id: str
|
|
177
|
+
is_inspected_by_driver: bool | None = None
|
|
178
|
+
location: GeotabAddressedLocation | None = None
|
|
179
|
+
log_type: str | None = None
|
|
180
|
+
odometer: float | None = None
|
|
181
|
+
trailer: Annotated[
|
|
182
|
+
DvirLogTrailerRef | None, BeforeValidator(bare_id_to_reference)
|
|
183
|
+
] = None
|
|
184
|
+
version: str
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# src/fleetpull/models/geotab/exception_event.py
|
|
2
|
+
"""The GeoTab ExceptionEvent response model (captured 2026-07-13).
|
|
3
|
+
|
|
4
|
+
One record per continuous rule-violation interval per device per rule:
|
|
5
|
+
the interval opens at ``active_from`` and closes at ``active_to``, and
|
|
6
|
+
``duration = active_to - active_from`` holds exactly on every captured
|
|
7
|
+
record, including a fractional-second span reproducing a fractional
|
|
8
|
+
``active_from`` (DESIGN §8). Records mutate after creation
|
|
9
|
+
(``last_modified_date_time`` observed ~17 minutes past
|
|
10
|
+
``created_date_time``) — the provider-level lookback absorbs it.
|
|
11
|
+
|
|
12
|
+
A pure mirror of the union of captured fields, everything optional.
|
|
13
|
+
``driver`` and ``diagnostic`` arrive as either a reference object or a
|
|
14
|
+
bare sentinel string (``"UnknownDriverId"``, ``"NoDiagnosticId"``) —
|
|
15
|
+
the shared ``bare_id_to_reference`` coercion lifts the bare form to
|
|
16
|
+
``{"id": <string>}`` verbatim, so the sentinel lands as the reference's
|
|
17
|
+
``id`` and its other fields null exactly on sentinel rows. The
|
|
18
|
+
object-form ``driver`` shape is inferred from Trip's captured grammar
|
|
19
|
+
(these captures carry only the sentinel); the first object-form capture
|
|
20
|
+
upgrades it to Captured.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from datetime import datetime
|
|
24
|
+
from typing import Annotated
|
|
25
|
+
|
|
26
|
+
from pydantic import BeforeValidator, ConfigDict
|
|
27
|
+
from pydantic.alias_generators import to_camel
|
|
28
|
+
|
|
29
|
+
from fleetpull.model_contract import ResponseModel
|
|
30
|
+
from fleetpull.models.geotab.shared import GeotabTimeSpan, bare_id_to_reference
|
|
31
|
+
|
|
32
|
+
__all__: list[str] = [
|
|
33
|
+
'ExceptionEvent',
|
|
34
|
+
'ExceptionEventDeviceRef',
|
|
35
|
+
'ExceptionEventDiagnosticRef',
|
|
36
|
+
'ExceptionEventDriverRef',
|
|
37
|
+
'ExceptionEventRuleRef',
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ExceptionEventRuleRef(ResponseModel):
|
|
42
|
+
"""The event's rule reference: state, reason, and the rule id."""
|
|
43
|
+
|
|
44
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
45
|
+
|
|
46
|
+
state: str | None = None
|
|
47
|
+
reason: str | None = None
|
|
48
|
+
id: str | None = None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ExceptionEventDeviceRef(ResponseModel):
|
|
52
|
+
"""The event's device reference: the id alone."""
|
|
53
|
+
|
|
54
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
55
|
+
|
|
56
|
+
id: str | None = None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ExceptionEventDriverRef(ResponseModel):
|
|
60
|
+
"""The event's driver reference.
|
|
61
|
+
|
|
62
|
+
Arrives as an object or the bare ``"UnknownDriverId"`` sentinel
|
|
63
|
+
string; the ``ExceptionEvent.driver`` field's coercion lifts the
|
|
64
|
+
bare form to ``{"id": <string>}``, so ``is_driver`` is null exactly
|
|
65
|
+
on sentinel rows. The object-form shape mirrors Trip's captured
|
|
66
|
+
driver grammar (inferred; no object-form ExceptionEvent capture
|
|
67
|
+
exists yet).
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
71
|
+
|
|
72
|
+
id: str | None = None
|
|
73
|
+
is_driver: bool | None = None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ExceptionEventDiagnosticRef(ResponseModel):
|
|
77
|
+
"""The event's diagnostic reference.
|
|
78
|
+
|
|
79
|
+
Arrives as the bare ``"NoDiagnosticId"`` sentinel string in every
|
|
80
|
+
capture; the coercion lifts it to ``{"id": <string>}``.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
84
|
+
|
|
85
|
+
id: str | None = None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class ExceptionEvent(ResponseModel):
|
|
89
|
+
"""One GeoTab ExceptionEvent: a rule-violation interval.
|
|
90
|
+
|
|
91
|
+
Attributes:
|
|
92
|
+
id: GeoTab's event id (an ``a``-prefixed GUID-like string — a
|
|
93
|
+
different id space from the ``b``-hex entities).
|
|
94
|
+
version: The record's version token.
|
|
95
|
+
rule: The violated rule's reference (state, reason, rule id).
|
|
96
|
+
device: The vehicle reference.
|
|
97
|
+
driver: The driver reference; the bare ``"UnknownDriverId"``
|
|
98
|
+
sentinel lands as ``driver.id`` verbatim.
|
|
99
|
+
diagnostic: The diagnostic reference; the bare
|
|
100
|
+
``"NoDiagnosticId"`` sentinel lands as ``diagnostic.id``.
|
|
101
|
+
active_from: Interval start (UTC) — the endpoint's event time
|
|
102
|
+
and partition anchor.
|
|
103
|
+
active_to: Interval end (UTC).
|
|
104
|
+
duration: The interval length (.NET TimeSpan on the wire);
|
|
105
|
+
reproduces ``active_to - active_from`` exactly in capture.
|
|
106
|
+
distance: Distance traveled during the interval, km.
|
|
107
|
+
state: The event's lifecycle state token, mirrored verbatim.
|
|
108
|
+
created_date_time: When the provider materialized the record.
|
|
109
|
+
last_modified_date_time: The record's last mutation.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
113
|
+
|
|
114
|
+
# Identity.
|
|
115
|
+
id: str | None = None
|
|
116
|
+
version: str | None = None
|
|
117
|
+
rule: ExceptionEventRuleRef | None = None
|
|
118
|
+
device: ExceptionEventDeviceRef | None = None
|
|
119
|
+
driver: Annotated[
|
|
120
|
+
ExceptionEventDriverRef | None, BeforeValidator(bare_id_to_reference)
|
|
121
|
+
] = None
|
|
122
|
+
diagnostic: Annotated[
|
|
123
|
+
ExceptionEventDiagnosticRef | None, BeforeValidator(bare_id_to_reference)
|
|
124
|
+
] = None
|
|
125
|
+
|
|
126
|
+
# The interval.
|
|
127
|
+
active_from: datetime | None = None
|
|
128
|
+
active_to: datetime | None = None
|
|
129
|
+
duration: GeotabTimeSpan = None
|
|
130
|
+
|
|
131
|
+
# Measures and state.
|
|
132
|
+
distance: float | None = None
|
|
133
|
+
state: str | None = None
|
|
134
|
+
created_date_time: datetime | None = None
|
|
135
|
+
last_modified_date_time: datetime | None = None
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# src/fleetpull/models/geotab/fault_data.py
|
|
2
|
+
"""GeoTab FaultData response model (``GetFeed`` on ``typeName: FaultData``).
|
|
3
|
+
|
|
4
|
+
Written from the 2026-07-21 feed wave two census (30-day seeded pulls at
|
|
5
|
+
the probed tenant), never from docs. A FaultData record is one
|
|
6
|
+
engine-fault observation — an ACTIVE feed with NO per-record
|
|
7
|
+
``version`` (the LogRecord asymmetry: append-only storage is trivially
|
|
8
|
+
complete and the consumer reconciles by ``id`` alone, DESIGN §4).
|
|
9
|
+
|
|
10
|
+
Requiredness posture (the wave-two conservative stance, DESIGN §8): the
|
|
11
|
+
census is a TENANT-SCOPED observation, so structural requiredness is
|
|
12
|
+
limited to the record identity — ``id``, ``dateTime`` (the event
|
|
13
|
+
time), and the primary entity ref (``device``, the faulting unit) —
|
|
14
|
+
and every other field is optional EVEN where the census was total
|
|
15
|
+
(2,000/2,000): a tenant census cannot promise another tenant's
|
|
16
|
+
presence. The observed arms:
|
|
17
|
+
|
|
18
|
+
- ``failureMode`` is MIXED object-or-string on this census (the one
|
|
19
|
+
proven mixed ref here); EVERY reference field — ``controller``,
|
|
20
|
+
``device``, ``diagnostic``, ``failureMode`` — rides the shared
|
|
21
|
+
``bare_id_to_reference`` lift regardless, because the census-scope
|
|
22
|
+
lesson (DESIGN §8, StatusData's ``controller``) is that a tenant
|
|
23
|
+
census cannot prove the string arm absent and the lift is structural
|
|
24
|
+
and sentinel-agnostic.
|
|
25
|
+
- The RARE QUARTET — ``diagnosticSeverity`` (str), ``riskOfBreakdown``
|
|
26
|
+
(float), ``severity`` (str), ``sourceAddress`` (int) — appeared on
|
|
27
|
+
2/2,000 records each: optional scalars.
|
|
28
|
+
- ``faultStates`` is a WIRE-PLURAL NAME carrying a SINGULAR object
|
|
29
|
+
shape (``{effectiveStatus}``) — mirrored as one nested model, the
|
|
30
|
+
plural-name/singular-shape wire fact recorded on it.
|
|
31
|
+
|
|
32
|
+
``dateTime`` is recovered tz-aware by validation, the GeoTab sibling
|
|
33
|
+
idiom. ``faultState`` and ``faultStates.effectiveStatus`` are
|
|
34
|
+
census-open vocabularies — plain strs, never enums.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
from datetime import datetime
|
|
38
|
+
from typing import Annotated
|
|
39
|
+
|
|
40
|
+
from pydantic import BeforeValidator, ConfigDict
|
|
41
|
+
from pydantic.alias_generators import to_camel
|
|
42
|
+
|
|
43
|
+
from fleetpull.model_contract import ResponseModel
|
|
44
|
+
from fleetpull.models.geotab.shared import bare_id_to_reference
|
|
45
|
+
|
|
46
|
+
__all__: list[str] = [
|
|
47
|
+
'FaultData',
|
|
48
|
+
'FaultDataControllerRef',
|
|
49
|
+
'FaultDataDeviceRef',
|
|
50
|
+
'FaultDataDiagnosticRef',
|
|
51
|
+
'FaultDataFailureModeRef',
|
|
52
|
+
'FaultDataFaultStates',
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class FaultDataControllerRef(ResponseModel):
|
|
57
|
+
"""The source controller reference.
|
|
58
|
+
|
|
59
|
+
Census-observed as an ``{id}`` object on every carrier; the shared
|
|
60
|
+
coercion lifts a bare string defensively (the StatusData
|
|
61
|
+
census-scope lesson — an unobserved sentinel arm still lands as
|
|
62
|
+
``controller__id``).
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
66
|
+
|
|
67
|
+
id: str
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class FaultDataDeviceRef(ResponseModel):
|
|
71
|
+
"""The faulting vehicle unit's reference: the id alone, on every record."""
|
|
72
|
+
|
|
73
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
74
|
+
|
|
75
|
+
id: str
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class FaultDataDiagnosticRef(ResponseModel):
|
|
79
|
+
"""The fault's diagnostic-definition reference: the id alone."""
|
|
80
|
+
|
|
81
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
82
|
+
|
|
83
|
+
id: str
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class FaultDataFailureModeRef(ResponseModel):
|
|
87
|
+
"""The failure-mode reference.
|
|
88
|
+
|
|
89
|
+
The one PROVEN mixed ref on this census: an ``{id}`` object or a
|
|
90
|
+
bare id string, the bare form lifted by the shared coercion so both
|
|
91
|
+
arms land as ``failure_mode__id``.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
95
|
+
|
|
96
|
+
id: str
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class FaultDataFaultStates(ResponseModel):
|
|
100
|
+
"""The ``faultStates`` block: a WIRE-PLURAL NAME, a SINGULAR shape.
|
|
101
|
+
|
|
102
|
+
Despite the plural wire key, the census shows ONE object carrying
|
|
103
|
+
``effectiveStatus`` (census-open plain str) — mirrored as a single
|
|
104
|
+
nested model, never a list. Required within the block: a
|
|
105
|
+
``faultStates`` block without its one observed key is a shape
|
|
106
|
+
change and must fail loudly.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
110
|
+
|
|
111
|
+
effective_status: str
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class FaultData(ResponseModel):
|
|
115
|
+
"""One GeoTab engine-fault observation from the FaultData feed.
|
|
116
|
+
|
|
117
|
+
The wave-two conservative mirror (the module docstring's posture):
|
|
118
|
+
``id`` / ``date_time`` / ``device`` required, everything else
|
|
119
|
+
optional even where census-total.
|
|
120
|
+
|
|
121
|
+
Attributes:
|
|
122
|
+
amber_warning_lamp: The amber-warning lamp state.
|
|
123
|
+
controller: The source controller reference (object-only on
|
|
124
|
+
this census; defensively lifted).
|
|
125
|
+
count: The fault's occurrence count.
|
|
126
|
+
date_time: The fault's UTC instant — the endpoint's event time.
|
|
127
|
+
device: The faulting vehicle unit's reference.
|
|
128
|
+
diagnostic: The fault's diagnostic-definition reference.
|
|
129
|
+
diagnostic_severity: Rare-quartet severity token (2/2,000;
|
|
130
|
+
census-open plain str).
|
|
131
|
+
failure_mode: The failure-mode reference — proven
|
|
132
|
+
object-or-string, both arms landing as ``failure_mode__id``.
|
|
133
|
+
fault_state: The fault-state token (census-open plain str).
|
|
134
|
+
fault_states: The plural-named singular status block.
|
|
135
|
+
id: GeoTab's record id.
|
|
136
|
+
malfunction_lamp: The malfunction-indicator lamp state.
|
|
137
|
+
protect_warning_lamp: The protect-warning lamp state.
|
|
138
|
+
red_stop_lamp: The red-stop lamp state.
|
|
139
|
+
risk_of_breakdown: Rare-quartet breakdown-risk score (2/2,000).
|
|
140
|
+
severity: Rare-quartet severity token (2/2,000; census-open).
|
|
141
|
+
source_address: Rare-quartet source address (2/2,000).
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
145
|
+
|
|
146
|
+
amber_warning_lamp: bool | None = None
|
|
147
|
+
controller: Annotated[
|
|
148
|
+
FaultDataControllerRef | None, BeforeValidator(bare_id_to_reference)
|
|
149
|
+
] = None
|
|
150
|
+
count: int | None = None
|
|
151
|
+
date_time: datetime
|
|
152
|
+
device: Annotated[FaultDataDeviceRef, BeforeValidator(bare_id_to_reference)]
|
|
153
|
+
diagnostic: Annotated[
|
|
154
|
+
FaultDataDiagnosticRef | None, BeforeValidator(bare_id_to_reference)
|
|
155
|
+
] = None
|
|
156
|
+
diagnostic_severity: str | None = None
|
|
157
|
+
failure_mode: Annotated[
|
|
158
|
+
FaultDataFailureModeRef | None, BeforeValidator(bare_id_to_reference)
|
|
159
|
+
] = None
|
|
160
|
+
fault_state: str | None = None
|
|
161
|
+
fault_states: FaultDataFaultStates | None = None
|
|
162
|
+
id: str
|
|
163
|
+
malfunction_lamp: bool | None = None
|
|
164
|
+
protect_warning_lamp: bool | None = None
|
|
165
|
+
red_stop_lamp: bool | None = None
|
|
166
|
+
risk_of_breakdown: float | None = None
|
|
167
|
+
severity: str | None = None
|
|
168
|
+
source_address: int | None = None
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# src/fleetpull/models/geotab/fill_up.py
|
|
2
|
+
"""GeoTab FillUp response model (``GetFeed`` on ``typeName: FillUp``).
|
|
3
|
+
|
|
4
|
+
Written from the 2026-07-21 live probe session, never from docs. A
|
|
5
|
+
FillUp is one provider-detected fuel-stop event — a CALCULATED feed:
|
|
6
|
+
past records re-emit under a higher ``version`` on reprocessing, stored
|
|
7
|
+
as emitted and reconciled by ``(id, max version)`` (DESIGN §4).
|
|
8
|
+
|
|
9
|
+
THE ESTIMATES-ONLY-TENANT CAVEAT (DESIGN §8): the probed tenant has NO
|
|
10
|
+
fuel-transaction (fuel-card) integration, so every fuel value on this
|
|
11
|
+
surface is provider-derived from telemetry — estimates, not
|
|
12
|
+
transactions. The census cannot speak for integrated tenants: ``cost``
|
|
13
|
+
was 0.0 on ALL records, ``fuelTransactions`` was an EMPTY list on ALL
|
|
14
|
+
records (excluded below as value-unobservable — on tenants with
|
|
15
|
+
fuel-card integration it populates with a shape never captured; it
|
|
16
|
+
joins the model when a capture types it), and ``productType`` was
|
|
17
|
+
``'Unknown'`` throughout.
|
|
18
|
+
|
|
19
|
+
Requiredness posture: the census is a uniform whole-page total —
|
|
20
|
+
100/100 records carried every modeled key — so every field is required,
|
|
21
|
+
with the sentinel arms exactly as observed. The census is a
|
|
22
|
+
TENANT-SCOPED observation. The observed arms:
|
|
23
|
+
|
|
24
|
+
- ``driver`` arrives as either the object reference (``{"id": ...,
|
|
25
|
+
"isDriver": true}``, 87/100) or the bare ``"UnknownDriverId"``
|
|
26
|
+
sentinel string; the shared ``bare_id_to_reference`` coercion (the
|
|
27
|
+
shipped Trip mechanism) lifts the bare form to ``{"id": <string>}``,
|
|
28
|
+
so the sentinel lands as ``driver.id`` and ``is_driver`` is null
|
|
29
|
+
exactly on sentinel rows.
|
|
30
|
+
- ``derivedVolume`` carries an observed ``-1.0`` sentinel (the
|
|
31
|
+
provider's could-not-derive marker) beside real volumes — mirrored
|
|
32
|
+
VERBATIM, never nulled: reshaping a sentinel would be interpretation.
|
|
33
|
+
- ``confidence`` is a comma-joined detection-method token list carried
|
|
34
|
+
as ONE plain string (e.g. ``'FuelLevel, TripStop'``) — splitting it
|
|
35
|
+
would presume a use case; the observed vocabulary is census-open.
|
|
36
|
+
- ``tankCapacity.source`` observed vocabulary: ``EstimateFuelLevel`` /
|
|
37
|
+
``DiagnosticTankCapacity`` / ``Unknown`` — census-open plain str.
|
|
38
|
+
|
|
39
|
+
Mixed int-or-float wire numerics (``derivedVolume``, ``distance``,
|
|
40
|
+
``odometer``, ``tankCapacity.volume``, ``volume``) are modeled
|
|
41
|
+
``float``. ``dateTime`` (the event time) and each extrema point's
|
|
42
|
+
``dateTime`` are recovered tz-aware by validation, the GeoTab sibling
|
|
43
|
+
idiom.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
from datetime import datetime
|
|
47
|
+
from typing import Annotated
|
|
48
|
+
|
|
49
|
+
from pydantic import BeforeValidator, ConfigDict
|
|
50
|
+
from pydantic.alias_generators import to_camel
|
|
51
|
+
|
|
52
|
+
from fleetpull.model_contract import ResponseModel
|
|
53
|
+
from fleetpull.models.geotab.shared import bare_id_to_reference
|
|
54
|
+
|
|
55
|
+
__all__: list[str] = [
|
|
56
|
+
'FillUp',
|
|
57
|
+
'FillUpDeviceRef',
|
|
58
|
+
'FillUpDriverRef',
|
|
59
|
+
'FillUpLocation',
|
|
60
|
+
'FillUpTankCapacity',
|
|
61
|
+
'FillUpTankLevelExtrema',
|
|
62
|
+
'FillUpTankLevelPoint',
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class FillUpDeviceRef(ResponseModel):
|
|
67
|
+
"""The fill-up's device reference: the id alone, on every record."""
|
|
68
|
+
|
|
69
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
70
|
+
|
|
71
|
+
id: str
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class FillUpDriverRef(ResponseModel):
|
|
75
|
+
"""The fill-up's driver reference.
|
|
76
|
+
|
|
77
|
+
Arrives as an object or the bare ``"UnknownDriverId"`` sentinel
|
|
78
|
+
string; the ``FillUp.driver`` field's coercion lifts the bare form
|
|
79
|
+
to ``{"id": <string>}``, so ``is_driver`` is null exactly on
|
|
80
|
+
sentinel rows.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
84
|
+
|
|
85
|
+
id: str
|
|
86
|
+
is_driver: bool | None = None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class FillUpLocation(ResponseModel):
|
|
90
|
+
"""The fill-up's coordinate: ``x`` longitude, ``y`` latitude."""
|
|
91
|
+
|
|
92
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
93
|
+
|
|
94
|
+
x: float
|
|
95
|
+
y: float
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class FillUpTankCapacity(ResponseModel):
|
|
99
|
+
"""The provider's tank-capacity estimate and its derivation source.
|
|
100
|
+
|
|
101
|
+
Attributes:
|
|
102
|
+
source: How the capacity was derived — observed vocabulary
|
|
103
|
+
``EstimateFuelLevel`` / ``DiagnosticTankCapacity`` /
|
|
104
|
+
``Unknown``, census-open plain str.
|
|
105
|
+
volume: The estimated capacity in liters (mixed int-or-float on
|
|
106
|
+
the wire, modeled float).
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
110
|
+
|
|
111
|
+
source: str
|
|
112
|
+
volume: float
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class FillUpTankLevelPoint(ResponseModel):
|
|
116
|
+
"""One tank-level extremum: its source, instant, and level reading."""
|
|
117
|
+
|
|
118
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
119
|
+
|
|
120
|
+
source: str
|
|
121
|
+
date_time: datetime
|
|
122
|
+
data: float
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class FillUpTankLevelExtrema(ResponseModel):
|
|
126
|
+
"""The tank-level extrema pair bracketing the detected fill-up."""
|
|
127
|
+
|
|
128
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
129
|
+
|
|
130
|
+
maxima_point: FillUpTankLevelPoint
|
|
131
|
+
minima_point: FillUpTankLevelPoint
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class FillUp(ResponseModel):
|
|
135
|
+
"""One GeoTab provider-detected fuel-stop event.
|
|
136
|
+
|
|
137
|
+
A pure mirror of the 100/100 whole-page census: every modeled key
|
|
138
|
+
present on every record, so everything is required; the sentinel
|
|
139
|
+
arms (``driver`` string-or-object, the ``-1.0`` ``derived_volume``)
|
|
140
|
+
are exactly as observed. The estimates-only-tenant caveat is the
|
|
141
|
+
module docstring's.
|
|
142
|
+
|
|
143
|
+
Attributes:
|
|
144
|
+
confidence: The comma-joined detection-method token list, one
|
|
145
|
+
plain string (census-open).
|
|
146
|
+
cost: The transaction cost — 0.0 on ALL census records (no fuel
|
|
147
|
+
transaction integration on the probed tenant).
|
|
148
|
+
currency_code: The cost's currency code (census-open plain str).
|
|
149
|
+
date_time: The detected fill-up's UTC instant — the endpoint's
|
|
150
|
+
event time.
|
|
151
|
+
derived_volume: The provider-derived fill volume in liters;
|
|
152
|
+
``-1.0`` is the observed could-not-derive sentinel, mirrored
|
|
153
|
+
verbatim.
|
|
154
|
+
device: The vehicle unit's reference.
|
|
155
|
+
distance: Distance since the prior fill-up, km.
|
|
156
|
+
driver: The driver reference; the bare ``"UnknownDriverId"``
|
|
157
|
+
sentinel lands as ``driver.id`` verbatim.
|
|
158
|
+
id: GeoTab's record id.
|
|
159
|
+
location: The detected stop's coordinate.
|
|
160
|
+
odometer: The odometer reading at the fill-up.
|
|
161
|
+
product_type: The fuel product type — ``'Unknown'`` on all
|
|
162
|
+
census records (census-open plain str).
|
|
163
|
+
tank_capacity: The tank-capacity estimate and its source.
|
|
164
|
+
tank_level_extrema: The level extrema bracketing the fill-up.
|
|
165
|
+
total_fuel_used: Cumulative fuel used at the fill-up, liters.
|
|
166
|
+
version: The record's version token — the calculated-feed
|
|
167
|
+
reconcile key beside ``id``.
|
|
168
|
+
volume: The fill volume in liters (unit reasoning, recorded: the sibling wire key totalIdlingFuelUsedL carries the L suffix, and the probed value range -- median 299, max 848 -- is truck-tank plausible in liters and absurd in gallons).
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
model_config = ConfigDict(alias_generator=to_camel)
|
|
172
|
+
|
|
173
|
+
confidence: str
|
|
174
|
+
cost: float
|
|
175
|
+
currency_code: str
|
|
176
|
+
date_time: datetime
|
|
177
|
+
derived_volume: float
|
|
178
|
+
device: FillUpDeviceRef
|
|
179
|
+
distance: float
|
|
180
|
+
driver: Annotated[FillUpDriverRef, BeforeValidator(bare_id_to_reference)]
|
|
181
|
+
id: str
|
|
182
|
+
location: FillUpLocation
|
|
183
|
+
odometer: float
|
|
184
|
+
product_type: str
|
|
185
|
+
tank_capacity: FillUpTankCapacity
|
|
186
|
+
tank_level_extrema: FillUpTankLevelExtrema
|
|
187
|
+
total_fuel_used: float
|
|
188
|
+
version: str
|
|
189
|
+
volume: float
|