From 27cbecb04440b2a741575b9d91638f892a9917d6 Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Thu, 15 Oct 2026 10:30:52 +1000 Subject: [PATCH 1/2] Decode Tesla Fleet Telemetry protobuf for the NATS add-on for Splunk A static Go binary implementing the splunk_nats decoder protocol: one JSON request per line on stdin, one JSON event (or an empty line plus a stderr reason) per line on stdout, flushed per line, exiting when stdin closes. - The record type comes from the subject's last token (data, alerts, errors, connectivity, metrics), verified against live telemetry.> traffic. - Vehicle data is flattened to one top-level field per signal by default ("VehicleSpeed": 28.6, "Location": {"latitude": ...}), with invalid signals listed in "invalid"; -format protojson gives fleet-telemetry's own JSON. Field names follow the protobuf JSON mapping (createdAt); -proto-names switches to created_at. - Messages are generated from Teslemetry/tesla-protocol at a pinned commit by scripts/generate.sh with pinned protoc and protoc-gen-go; CI checks the committed code matches. - Golden tests on anonymized live payloads for every record type, protocol and binary tests, and throughput benchmarks. - CI (gofmt, vet, race tests, benchmarks, generated code, build) and a tag-triggered release with linux/darwin amd64/arm64 binaries and SHA256SUMS. - scripts/e2e-splunk.sh proves it in a disposable Splunk with the add-on against live NATS. --- .github/workflows/ci.yml | 32 + .github/workflows/release.yml | 25 + .gitignore | 1 + README.md | 168 +- go.mod | 9 + go.sum | 4 + internal/decoder/bench_test.go | 105 + internal/decoder/decoder.go | 320 + internal/decoder/decoder_test.go | 238 + internal/decoder/golden_test.go | 103 + internal/decoder/protocol.go | 100 + internal/decoder/protocol_test.go | 152 + .../decoder/testdata/golden/alerts.flat.json | 1 + .../golden/alerts.flat.proto-names.json | 1 + .../testdata/golden/alerts.protojson.json | 1 + .../golden/alerts.protojson.proto-names.json | 1 + .../decoder/testdata/golden/alerts.request | 1 + .../golden/connectivity-connected.flat.json | 1 + ...nnectivity-connected.flat.proto-names.json | 1 + .../connectivity-connected.protojson.json | 1 + ...ivity-connected.protojson.proto-names.json | 1 + .../golden/connectivity-connected.request | 1 + .../connectivity-disconnected.flat.json | 1 + ...ctivity-disconnected.flat.proto-names.json | 1 + .../connectivity-disconnected.protojson.json | 1 + ...ty-disconnected.protojson.proto-names.json | 1 + .../golden/connectivity-disconnected.request | 1 + .../testdata/golden/data-doors.flat.json | 1 + .../golden/data-doors.flat.proto-names.json | 1 + .../testdata/golden/data-doors.protojson.json | 1 + .../data-doors.protojson.proto-names.json | 1 + .../testdata/golden/data-doors.request | 1 + .../testdata/golden/data-full.flat.json | 1 + .../golden/data-full.flat.proto-names.json | 1 + .../testdata/golden/data-full.protojson.json | 1 + .../data-full.protojson.proto-names.json | 1 + .../decoder/testdata/golden/data-full.request | 1 + .../testdata/golden/data-invalid.flat.json | 1 + .../golden/data-invalid.flat.proto-names.json | 1 + .../golden/data-invalid.protojson.json | 1 + .../data-invalid.protojson.proto-names.json | 1 + .../testdata/golden/data-invalid.request | 1 + .../testdata/golden/data-location.flat.json | 1 + .../data-location.flat.proto-names.json | 1 + .../golden/data-location.protojson.json | 1 + .../data-location.protojson.proto-names.json | 1 + .../testdata/golden/data-location.request | 1 + .../testdata/golden/data-resend.flat.json | 1 + .../golden/data-resend.flat.proto-names.json | 1 + .../golden/data-resend.protojson.json | 1 + .../data-resend.protojson.proto-names.json | 1 + .../testdata/golden/data-resend.request | 1 + .../testdata/golden/errors-empty.flat.json | 1 + .../golden/errors-empty.flat.proto-names.json | 1 + .../golden/errors-empty.protojson.json | 1 + .../errors-empty.protojson.proto-names.json | 1 + .../testdata/golden/errors-empty.request | 1 + .../decoder/testdata/golden/errors.flat.json | 1 + .../golden/errors.flat.proto-names.json | 1 + .../testdata/golden/errors.protojson.json | 1 + .../golden/errors.protojson.proto-names.json | 1 + .../decoder/testdata/golden/errors.request | 1 + internal/protos/source.go | 8 + internal/protos/vehicle_alert.pb.go | 292 + internal/protos/vehicle_connectivity.pb.go | 226 + internal/protos/vehicle_data.pb.go | 5840 +++++++++++++++++ internal/protos/vehicle_error.pb.go | 233 + internal/protos/vehicle_metric.pb.go | 222 + main.go | 75 + main_test.go | 105 + scripts/build.sh | 22 + scripts/e2e-splunk.sh | 106 + scripts/generate.sh | 75 + tools/mkfixtures/main.go | 232 + 74 files changed, 8742 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/decoder/bench_test.go create mode 100644 internal/decoder/decoder.go create mode 100644 internal/decoder/decoder_test.go create mode 100644 internal/decoder/golden_test.go create mode 100644 internal/decoder/protocol.go create mode 100644 internal/decoder/protocol_test.go create mode 100644 internal/decoder/testdata/golden/alerts.flat.json create mode 100644 internal/decoder/testdata/golden/alerts.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/alerts.protojson.json create mode 100644 internal/decoder/testdata/golden/alerts.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/alerts.request create mode 100644 internal/decoder/testdata/golden/connectivity-connected.flat.json create mode 100644 internal/decoder/testdata/golden/connectivity-connected.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/connectivity-connected.protojson.json create mode 100644 internal/decoder/testdata/golden/connectivity-connected.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/connectivity-connected.request create mode 100644 internal/decoder/testdata/golden/connectivity-disconnected.flat.json create mode 100644 internal/decoder/testdata/golden/connectivity-disconnected.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/connectivity-disconnected.protojson.json create mode 100644 internal/decoder/testdata/golden/connectivity-disconnected.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/connectivity-disconnected.request create mode 100644 internal/decoder/testdata/golden/data-doors.flat.json create mode 100644 internal/decoder/testdata/golden/data-doors.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-doors.protojson.json create mode 100644 internal/decoder/testdata/golden/data-doors.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-doors.request create mode 100644 internal/decoder/testdata/golden/data-full.flat.json create mode 100644 internal/decoder/testdata/golden/data-full.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-full.protojson.json create mode 100644 internal/decoder/testdata/golden/data-full.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-full.request create mode 100644 internal/decoder/testdata/golden/data-invalid.flat.json create mode 100644 internal/decoder/testdata/golden/data-invalid.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-invalid.protojson.json create mode 100644 internal/decoder/testdata/golden/data-invalid.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-invalid.request create mode 100644 internal/decoder/testdata/golden/data-location.flat.json create mode 100644 internal/decoder/testdata/golden/data-location.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-location.protojson.json create mode 100644 internal/decoder/testdata/golden/data-location.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-location.request create mode 100644 internal/decoder/testdata/golden/data-resend.flat.json create mode 100644 internal/decoder/testdata/golden/data-resend.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-resend.protojson.json create mode 100644 internal/decoder/testdata/golden/data-resend.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/data-resend.request create mode 100644 internal/decoder/testdata/golden/errors-empty.flat.json create mode 100644 internal/decoder/testdata/golden/errors-empty.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/errors-empty.protojson.json create mode 100644 internal/decoder/testdata/golden/errors-empty.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/errors-empty.request create mode 100644 internal/decoder/testdata/golden/errors.flat.json create mode 100644 internal/decoder/testdata/golden/errors.flat.proto-names.json create mode 100644 internal/decoder/testdata/golden/errors.protojson.json create mode 100644 internal/decoder/testdata/golden/errors.protojson.proto-names.json create mode 100644 internal/decoder/testdata/golden/errors.request create mode 100644 internal/protos/source.go create mode 100644 internal/protos/vehicle_alert.pb.go create mode 100644 internal/protos/vehicle_connectivity.pb.go create mode 100644 internal/protos/vehicle_data.pb.go create mode 100644 internal/protos/vehicle_error.pb.go create mode 100644 internal/protos/vehicle_metric.pb.go create mode 100644 main.go create mode 100644 main_test.go create mode 100755 scripts/build.sh create mode 100755 scripts/e2e-splunk.sh create mode 100755 scripts/generate.sh create mode 100644 tools/mkfixtures/main.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..23b78a2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version-file: go.mod + - name: gofmt + run: test -z "$(gofmt -l .)" || { gofmt -l .; exit 1; } + - name: go vet + run: go vet ./... + - name: go test + run: go test -race ./... + - name: Benchmarks run + run: go test -run '^$' -bench . -benchtime 100x ./... + - name: Generated code matches the pinned protos + run: | + scripts/generate.sh + git diff --exit-code -- internal/protos + - name: Build + run: scripts/build.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..f6ab5fb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,25 @@ +name: Release + +on: + push: + tags: ["v*"] + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version-file: go.mod + - name: go test + run: go test ./... + - name: Build + run: scripts/build.sh "$GITHUB_REF_NAME" + - name: Publish the release + env: + GH_TOKEN: ${{ github.token }} + run: gh release create "$GITHUB_REF_NAME" dist/* --title "$GITHUB_REF_NAME" --generate-notes --verify-tag diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..178135c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/dist/ diff --git a/README.md b/README.md index 5f85091..083d49a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,168 @@ # telemetry-decoder -Decodes Tesla Fleet Telemetry protobuf messages to JSON (decoder for the Splunk NATS add-on) + +Decodes Tesla Fleet Telemetry protobuf messages to JSON: a payload decoder for the +[NATS Add-on for Splunk](https://github.com/Bre77/splunk_nats). + +Tesla Fleet Telemetry publishes protobuf on NATS subjects +`telemetry..data`, `.alerts`, `.errors` and `.connectivity` (and `.metrics`). +Without a decoder the add-on indexes those payloads as base64. With this decoder +each message becomes a one-line JSON event whose fields Splunk extracts directly: + +``` +index=nats source="*.data" VehicleSpeed=* | timechart avg(VehicleSpeed) by vin +``` + +It is a single static binary with no runtime dependencies. The messages are +generated from the protos in +[Teslemetry/tesla-protocol](https://github.com/Teslemetry/tesla-protocol/tree/main/proto/telemetry) +(`proto/telemetry`), which track Tesla's +[fleet-telemetry](https://github.com/teslamotors/fleet-telemetry) protos. + +## Install + +1. Download the binary for the Splunk host from the + [latest release](https://github.com/Teslemetry/telemetry-decoder/releases) + (`telemetry-decoder-linux-amd64`, `-linux-arm64`, `-darwin-amd64` or + `-darwin-arm64`) and check it against `SHA256SUMS`, or [build it](#build). +2. Place it in the add-on's decoder directory, owned by the Splunk user and + executable. Its file name there is the decoder's name: + + ``` + sudo install -o splunk -g splunk -m 755 telemetry-decoder-linux-amd64 \ + $SPLUNK_HOME/etc/apps/nats/local/decoders/telemetry-decoder + ``` + +3. On a **NATS Subscribe** input for `telemetry.>`, open **Payload decoder** and + set **Decoder** to `telemetry-decoder`. Leave **Decoded Source Type** at + `nats:json`, which allows the large events alerts produce. +4. To try it from search first: + + ``` + | natssubscribe subject="telemetry.>" account= decoder=telemetry-decoder | spath + ``` + +## Arguments + +Set these as the input's **Decoder Arguments** (or `decoder_args=` on +`natssubscribe`): + +| Argument | Default | Effect | +|---|---|---| +| `-format flat` | yes | Vehicle data has one top-level field per signal (see below). | +| `-format protojson` | | Vehicle data is the protobuf JSON mapping, the same JSON fleet-telemetry writes with `transmit_decoded_records`: `"data":[{"key":"VehicleSpeed","value":{"floatValue":28.6}}]`. | +| `-proto-names` | | Proto field names (`created_at`, `network_interface`, `is_resend`) instead of the JSON names (`createdAt`, `networkInterface`, `isResend`). | +| `-version` | | Prints the version and the tesla-protocol commit, then exits. | + +## Output + +Every event is one line of JSON. Field names follow the protobuf JSON mapping, +as fleet-telemetry's own JSON output does (lowerCamel, enums by name, timestamps +in RFC 3339 UTC), and every field is present even when unset (`null`, `false`, +`0`, `""`), so an alert without `endedAt` is visibly still active. The VIN comes +from the message, or from the subject when the message has none. + +**Vehicle data** (`telemetry..data`), with the default `-format flat`: + +```json +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:16.273960575Z","isResend":false,"MilesToArrival":0.962417613193002,"Location":{"latitude":37.4919,"longitude":-121.9447},"Gear":"ShiftStateD","DoorState":{"DriverFront":true,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false},"invalid":["TpmsPressureFr"]} +``` + +- Each signal is a field named as in Tesla's `Field` enum, holding its value as + plain JSON: numbers, strings and booleans as themselves, enums by name, and + structured values as objects with every field (`Location.latitude`, + `DoorState.DriverFront`, `ScheduledChargingStartTime.hour`). +- Signals the vehicle reports as invalid (unavailable) are listed in `invalid` + rather than given a value. +- A signal newer than the decoder's protos is named by its number (`"312": 4.5`), + and a value type newer than the protos is `null`, so nothing is silently lost. + Updating the protos (see [Development](#development)) names them. + +**Alerts** (`telemetry..alerts`): + +```json +{"alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"startedAt":"2026-10-15T00:14:55.164Z","endedAt":null}],"createdAt":"2026-10-15T00:15:05.180915260Z","vin":"TESTVIN0000000001"} +``` + +**Errors** (`telemetry..errors`): + +```json +{"errors":[{"createdAt":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen"},"body":""}],"createdAt":"2026-10-15T00:10:12.617991348Z","vin":"TESTVIN0000000001"} +``` + +**Connectivity** (`telemetry..connectivity`): + +```json +{"vin":"TESTVIN0000000001","connectionId":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","createdAt":"2026-10-15T00:13:22.426862796Z","networkInterface":"wifi"} +``` + +**Metrics** (`telemetry..metrics`) follow the same mapping: +`{"metrics":[{"name":...,"tags":{...},"value":...}],"createdAt":...,"vin":...}`. + +Example searches (with an input indexing into `index=nats`): + +``` +index=nats source="*.data" | stats latest(BatteryLevel) latest(Odometer) by vin +index=nats source="*.data" Location.latitude=* | table _time vin Location.latitude Location.longitude +index=nats source="*.connectivity" | stats count by status networkInterface +index=nats source="*.alerts" | stats count by alerts{}.name +index=nats source="*.data" invalid{}=* | stats count by invalid{} +``` + +### When a payload cannot be decoded + +The decoder answers with an empty line, so the add-on keeps the payload as +base64 and logs the reason, which the decoder writes to stderr as one line (for +example `telemetry..foo: unknown record type "foo"`). That happens for a +subject whose last token is not a known record type, an empty payload, a payload +that is not valid protobuf for its record type, or a request that is not valid +JSON or base64. The decoder keeps running and answers the next message. + +### Protocol and throughput + +The decoder implements the add-on's +[decoder protocol](https://github.com/Bre77/splunk_nats#decoder-protocol): one +JSON request per line on stdin, one event per line on stdout (flushed after each +line), diagnostics on stderr, and it exits when stdin closes. It answers in a +few microseconds: on live `telemetry.>` traffic it decodes about 200,000 messages +a second on one core, far beyond the stream's rate (about 110 a second). + +## Build + +Needs Go (the version in `go.mod`). + +``` +scripts/build.sh # static binaries for linux/darwin amd64/arm64 in dist/, with SHA256SUMS +go build -o telemetry-decoder . # just for this machine +``` + +Builds are reproducible: the same commit and version give byte-identical +binaries. + +## Development + +``` +go vet ./... && go test ./... # unit, golden, protocol and binary tests +go test -run '^$' -bench . ./internal/decoder # throughput (BenchmarkRun: ns per message) +``` + +- `internal/protos` is generated, and committed. `scripts/generate.sh` + regenerates it from tesla-protocol at the pinned commit with pinned `protoc` + and `protoc-gen-go` (the latter via the `tool` directive in `go.mod`). To move + to a newer tesla-protocol, run `scripts/generate.sh `, update the + pinned commit in the script, refresh the golden files and commit. CI checks that + the committed code matches the pinned protos. +- `internal/decoder/testdata/golden` holds real payloads captured from live + telemetry and anonymized by `tools/mkfixtures` (fake VIN, connection IDs, + locations, names and media), one `.request` per fixture, and the + expected event for each output option. To refresh them from a capture of + decoder requests (one JSON line per message), run + `go run ./tools/mkfixtures < capture.jsonl` and then + `go test ./internal/decoder -run TestGolden -update`, and review the diff. +- `scripts/e2e-splunk.sh` runs the decoder in a disposable Splunk container with + the add-on against live NATS traffic and checks that every message is decoded. + +## Release + +Pushing a `v*` tag runs the release workflow: it tests, builds the binaries with +the tag as their version, and publishes a GitHub release with the binaries and +`SHA256SUMS`. diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ad582e9 --- /dev/null +++ b/go.mod @@ -0,0 +1,9 @@ +module github.com/Teslemetry/telemetry-decoder + +go 1.26.0 + +toolchain go1.27.2 + +tool google.golang.org/protobuf/cmd/protoc-gen-go + +require google.golang.org/protobuf v1.36.12 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a0c9758 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= +google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/internal/decoder/bench_test.go b/internal/decoder/bench_test.go new file mode 100644 index 0000000..8bf6aa1 --- /dev/null +++ b/internal/decoder/bench_test.go @@ -0,0 +1,105 @@ +package decoder + +import ( + "encoding/json" + "io" + "sort" + "testing" +) + +// BenchmarkDecode decodes each fixture payload. +func BenchmarkDecode(b *testing.B) { + requests := goldenRequests(b) + names := make([]string, 0, len(requests)) + for name := range requests { + names = append(names, name) + } + sort.Strings(names) + for _, format := range []Format{FormatFlat, FormatProtoJSON} { + for _, name := range names { + var r Request + if err := json.Unmarshal(requests[name], &r); err != nil { + b.Fatal(err) + } + payload, err := r.DecodePayload() + if err != nil { + b.Fatal(err) + } + b.Run(string(format)+"/"+name, func(b *testing.B) { + d := mustNew(b, Options{Format: format}) + var event []byte + b.SetBytes(int64(len(payload))) + for b.Loop() { + var err error + if event, err = d.Decode(event[:0], r.Subject, payload); err != nil { + b.Fatal(err) + } + } + }) + } + } +} + +// BenchmarkRun serves the decoder protocol over a stream cycling through every +// fixture, as the add-on sends it: one request line in, one event line out, +// flushed. One op is one message, so messages per second is 1e9 / ns/op. +func BenchmarkRun(b *testing.B) { + var lines [][]byte + for _, request := range goldenRequests(b) { + lines = append(lines, request) + } + d := mustNew(b, Options{}) + in := &cyclingReader{lines: lines, remaining: b.N} + var out countingWriter + b.ResetTimer() + if err := d.Run(in, &out, io.Discard); err != nil { + b.Fatal(err) + } + b.StopTimer() + if out.lines != b.N || out.empty != 0 { + b.Fatalf("%d events (%d empty) for %d requests", out.lines, out.empty, b.N) + } +} + +// cyclingReader reads remaining request lines, cycling through lines. +type cyclingReader struct { + lines [][]byte + remaining int + next int + pending []byte +} + +func (r *cyclingReader) Read(p []byte) (int, error) { + if len(r.pending) == 0 { + if r.remaining == 0 { + return 0, io.EOF + } + r.pending = r.lines[r.next%len(r.lines)] + r.next++ + r.remaining-- + } + n := copy(p, r.pending) + r.pending = r.pending[n:] + return n, nil +} + +// countingWriter counts the event lines written, and the empty ones. +type countingWriter struct { + lines, empty int + inLine bool +} + +func (w *countingWriter) Write(p []byte) (int, error) { + for _, c := range p { + if c == '\n' { + w.lines++ + if !w.inLine { + w.empty++ + } + w.inLine = false + } else { + w.inLine = true + } + } + return len(p), nil +} diff --git a/internal/decoder/decoder.go b/internal/decoder/decoder.go new file mode 100644 index 0000000..0d01d4d --- /dev/null +++ b/internal/decoder/decoder.go @@ -0,0 +1,320 @@ +// Package decoder turns Tesla Fleet Telemetry protobuf payloads into JSON events. +package decoder + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "math" + "strconv" + "strings" + "unicode/utf8" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/Teslemetry/telemetry-decoder/internal/protos" +) + +// Format selects the shape of a decoded vehicle data event. +type Format string + +const ( + // FormatFlat puts each vehicle data signal in its own top-level field + // ("VehicleSpeed": 28.6) so Splunk extracts it directly. + FormatFlat Format = "flat" + // FormatProtoJSON is the protobuf JSON mapping, as fleet-telemetry writes it + // with transmit_decoded_records: data is a list of {"key", "value"} pairs. + FormatProtoJSON Format = "protojson" +) + +// Options controls how payloads are decoded. +type Options struct { + Format Format + // ProtoNames uses the proto field names (created_at) instead of the JSON + // names (createdAt). + ProtoNames bool +} + +// Record types, named by the last token of the subject the payload is published +// on (telemetry..data and so on), as fleet-telemetry names them. +var recordTypes = map[string]func() proto.Message{ + "data": func() proto.Message { return &protos.Payload{} }, + "alerts": func() proto.Message { return &protos.VehicleAlerts{} }, + "errors": func() proto.Message { return &protos.VehicleErrors{} }, + "connectivity": func() proto.Message { return &protos.VehicleConnectivity{} }, + "metrics": func() proto.Message { return &protos.VehicleMetrics{} }, +} + +// Decoder decodes payloads into one-line JSON events. +type Decoder struct { + format Format + json protojson.MarshalOptions + inner protojson.MarshalOptions // for the messages inside a flattened data value + names fieldNames + scratch bytes.Buffer +} + +type fieldNames struct { + vin, createdAt, isResend string +} + +// New returns a Decoder for the options. +func New(opts Options) (*Decoder, error) { + switch opts.Format { + case "": + opts.Format = FormatFlat + case FormatFlat, FormatProtoJSON: + default: + return nil, fmt.Errorf("unknown format %q: use %q or %q", opts.Format, FormatFlat, FormatProtoJSON) + } + d := &Decoder{ + format: opts.Format, + // Every field is written, even when unset, as fleet-telemetry does: an + // alert without endedAt is still active, a door that is false is closed. + json: protojson.MarshalOptions{EmitUnpopulated: true, UseProtoNames: opts.ProtoNames}, + inner: protojson.MarshalOptions{EmitUnpopulated: true, UseProtoNames: opts.ProtoNames}, + names: fieldNames{"vin", "createdAt", "isResend"}, + } + if opts.ProtoNames { + d.names = fieldNames{"vin", "created_at", "is_resend"} + } + return d, nil +} + +// RecordType returns the record type a subject carries: its last token. +func RecordType(subject string) string { + return subject[strings.LastIndexByte(subject, '.')+1:] +} + +// Decode decodes a payload published on subject and appends the JSON event, +// without a newline, to dst. +func (d *Decoder) Decode(dst []byte, subject string, payload []byte) ([]byte, error) { + recordType := RecordType(subject) + newMessage, ok := recordTypes[recordType] + if !ok { + return dst, fmt.Errorf("unknown record type %q (subject %q): expected one of data, alerts, errors, connectivity, metrics", recordType, subject) + } + if len(payload) == 0 { + return dst, errors.New("empty payload") + } + message := newMessage() + if err := proto.Unmarshal(payload, message); err != nil { + return dst, fmt.Errorf("cannot decode %s payload: %w", recordType, err) + } + fillVIN(message, subject) + if payload, ok := message.(*protos.Payload); ok && d.format == FormatFlat { + return d.appendFlatPayload(dst, payload) + } + return d.appendProtoJSON(dst, message) +} + +// fillVIN sets the VIN from the subject (telemetry..) when the +// message has none. +func fillVIN(message proto.Message, subject string) { + m := message.ProtoReflect() + field := m.Descriptor().Fields().ByName("vin") + if field == nil || m.Get(field).String() != "" { + return + } + tokens := strings.Split(subject, ".") + if len(tokens) == 3 && tokens[1] != "" { + m.Set(field, protoreflect.ValueOfString(tokens[1])) + } +} + +// appendProtoJSON appends the message in the protobuf JSON mapping, compacted: +// protojson varies its whitespace on purpose, and an event must be one stable line. +func (d *Decoder) appendProtoJSON(dst []byte, message proto.Message) ([]byte, error) { + b, err := d.json.Marshal(message) + if err != nil { + return dst, err + } + return appendCompact(dst, &d.scratch, b) +} + +func appendCompact(dst []byte, scratch *bytes.Buffer, b []byte) ([]byte, error) { + scratch.Reset() + if err := json.Compact(scratch, b); err != nil { + return dst, err + } + return append(dst, scratch.Bytes()...), nil +} + +// appendFlatPayload appends a vehicle data payload with one field per signal: +// +// {"vin":"...","createdAt":"...","isResend":false,"VehicleSpeed":28.6,"Location":{"latitude":..,"longitude":..}} +// +// Signals the vehicle reports as invalid are listed in "invalid" instead. A signal +// repeated in one payload keeps its last value. +func (d *Decoder) appendFlatPayload(dst []byte, p *protos.Payload) ([]byte, error) { + start := len(dst) + dst = append(dst, '{') + dst = appendKey(dst, d.names.vin) + dst = appendString(dst, p.GetVin()) + dst = append(dst, ',') + dst = appendKey(dst, d.names.createdAt) + if p.GetCreatedAt() == nil { + dst = append(dst, "null"...) + } else { + var err error + if dst, err = d.appendInner(dst, p.GetCreatedAt()); err != nil { + return dst[:start], err + } + } + dst = append(dst, ',') + dst = appendKey(dst, d.names.isResend) + dst = strconv.AppendBool(dst, p.GetIsResend()) + + data := p.GetData() + last := make(map[protos.Field]int, len(data)) + for i, datum := range data { + last[datum.GetKey()] = i + } + var invalid []string + for i, datum := range data { + if last[datum.GetKey()] != i { + continue + } + name := fieldName(datum.GetKey()) + if datum.GetValue().GetInvalid() { + invalid = append(invalid, name) + continue + } + dst = append(dst, ',') + dst = appendKey(dst, name) + var err error + if dst, err = d.appendValue(dst, datum.GetValue()); err != nil { + return dst[:start], fmt.Errorf("%s: %w", name, err) + } + } + if len(invalid) > 0 { + dst = append(dst, `,"invalid":[`...) + for i, name := range invalid { + if i > 0 { + dst = append(dst, ',') + } + dst = appendString(dst, name) + } + dst = append(dst, ']') + } + return append(dst, '}'), nil +} + +// fieldName is the signal's name in the Field enum, or its number when this +// decoder's protos do not know it yet. +func fieldName(f protos.Field) string { + if v := f.Descriptor().Values().ByNumber(protoreflect.EnumNumber(f)); v != nil { + return string(v.Name()) + } + return strconv.Itoa(int(f)) +} + +var valueOneof = (&protos.Value{}).ProtoReflect().Descriptor().Oneofs().ByName("value") + +// appendValue appends a signal's value as plain JSON: numbers, strings and +// booleans as themselves, enums by name, and messages (Location, Doors, ...) as +// objects with every field. +func (d *Decoder) appendValue(dst []byte, v *protos.Value) ([]byte, error) { + m := v.ProtoReflect() + field := m.WhichOneof(valueOneof) + if field == nil { + // No value, or a value type newer than this decoder's protos + return append(dst, "null"...), nil + } + value := m.Get(field) + switch field.Kind() { + case protoreflect.StringKind: + return appendString(dst, value.String()), nil + case protoreflect.BoolKind: + return strconv.AppendBool(dst, value.Bool()), nil + case protoreflect.Int32Kind, protoreflect.Int64Kind, protoreflect.Sint32Kind, protoreflect.Sint64Kind, + protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: + return strconv.AppendInt(dst, value.Int(), 10), nil + case protoreflect.Uint32Kind, protoreflect.Uint64Kind, protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: + return strconv.AppendUint(dst, value.Uint(), 10), nil + case protoreflect.FloatKind: + return appendFloat(dst, value.Float(), 32), nil + case protoreflect.DoubleKind: + return appendFloat(dst, value.Float(), 64), nil + case protoreflect.EnumKind: + if name := field.Enum().Values().ByNumber(value.Enum()); name != nil { + return appendString(dst, string(name.Name())), nil + } + return strconv.AppendInt(dst, int64(value.Enum()), 10), nil + case protoreflect.MessageKind: + return d.appendInner(dst, value.Message().Interface()) + default: + return dst, fmt.Errorf("unsupported value type %s", field.Kind()) + } +} + +func (d *Decoder) appendInner(dst []byte, message proto.Message) ([]byte, error) { + b, err := d.inner.Marshal(message) + if err != nil { + return dst, err + } + return appendCompact(dst, &d.scratch, b) +} + +func appendKey(dst []byte, key string) []byte { + return append(appendString(dst, key), ':') +} + +// appendFloat formats a float as encoding/json does, with the shortest +// representation for its size (a float32 28.6 is 28.6, not 28.600000381469727). +// JSON has no NaN or infinity, so those are written as protojson writes them. +func appendFloat(dst []byte, f float64, bits int) []byte { + switch { + case math.IsNaN(f): + return append(dst, `"NaN"`...) + case math.IsInf(f, 1): + return append(dst, `"Infinity"`...) + case math.IsInf(f, -1): + return append(dst, `"-Infinity"`...) + } + abs := math.Abs(f) + format := byte('f') + if abs != 0 { + if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) { + format = 'e' + } + } + dst = strconv.AppendFloat(dst, f, format, -1, bits) + if format == 'e' { + // clean up e-09 to e-9 + n := len(dst) + if n >= 4 && dst[n-4] == 'e' && dst[n-3] == '-' && dst[n-2] == '0' { + dst[n-2] = dst[n-1] + dst = dst[:n-1] + } + } + return dst +} + +const hex = "0123456789abcdef" + +// appendString appends s as a JSON string. Invalid UTF-8 becomes U+FFFD, so the +// event is always valid UTF-8 (the add-on rejects anything else). +func appendString(dst []byte, s string) []byte { + dst = append(dst, '"') + for _, r := range s { + switch { + case r == '"' || r == '\\': + dst = append(dst, '\\', byte(r)) + case r == '\n': + dst = append(dst, '\\', 'n') + case r == '\r': + dst = append(dst, '\\', 'r') + case r == '\t': + dst = append(dst, '\\', 't') + case r < 0x20 || r == '
' || r == '
': + dst = append(dst, '\\', 'u', hex[r>>12&0xf], hex[r>>8&0xf], hex[r>>4&0xf], hex[r&0xf]) + default: + dst = utf8.AppendRune(dst, r) + } + } + return append(dst, '"') +} diff --git a/internal/decoder/decoder_test.go b/internal/decoder/decoder_test.go new file mode 100644 index 0000000..2a5a965 --- /dev/null +++ b/internal/decoder/decoder_test.go @@ -0,0 +1,238 @@ +package decoder + +import ( + "encoding/json" + "math" + "strings" + "testing" + + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/Teslemetry/telemetry-decoder/internal/protos" +) + +func mustNew(t testing.TB, opts Options) *Decoder { + t.Helper() + d, err := New(opts) + if err != nil { + t.Fatal(err) + } + return d +} + +func decode(t *testing.T, d *Decoder, subject string, message proto.Message) string { + t.Helper() + payload, err := proto.Marshal(message) + if err != nil { + t.Fatal(err) + } + event, err := d.Decode(nil, subject, payload) + if err != nil { + t.Fatal(err) + } + checkEvent(t, event) + return string(event) +} + +func datum(key protos.Field, value *protos.Value) *protos.Datum { + return &protos.Datum{Key: key, Value: value} +} + +func TestFlatValues(t *testing.T) { + p := &protos.Payload{ + Vin: "TESTVIN0000000001", + CreatedAt: ×tamppb.Timestamp{Seconds: 1792000000, Nanos: 500000000}, + Data: []*protos.Datum{ + datum(protos.Field_VehicleSpeed, &protos.Value{Value: &protos.Value_FloatValue{FloatValue: 28.6}}), + datum(protos.Field_Odometer, &protos.Value{Value: &protos.Value_DoubleValue{DoubleValue: 12345.678}}), + datum(protos.Field_ChargeAmps, &protos.Value{Value: &protos.Value_IntValue{IntValue: -16}}), + datum(protos.Field_LifetimeEnergyUsed, &protos.Value{Value: &protos.Value_LongValue{LongValue: 1 << 40}}), + datum(protos.Field_Locked, &protos.Value{Value: &protos.Value_BooleanValue{BooleanValue: true}}), + datum(protos.Field_VehicleName, &protos.Value{Value: &protos.Value_StringValue{StringValue: "Say \"hi\"\n\u2028"}}), + datum(protos.Field_Gear, &protos.Value{Value: &protos.Value_ShiftStateValue{ShiftStateValue: protos.ShiftState_ShiftStateD}}), + datum(protos.Field_Location, &protos.Value{Value: &protos.Value_LocationValue{LocationValue: &protos.LocationValue{Latitude: 37.4919, Longitude: -121.9447}}}), + datum(protos.Field_DoorState, &protos.Value{Value: &protos.Value_DoorValue{DoorValue: &protos.Doors{DriverFront: true}}}), + datum(protos.Field_ScheduledChargingStartTime, &protos.Value{Value: &protos.Value_TimeValue{TimeValue: &protos.Time{Hour: 7}}}), + datum(protos.Field_TpmsPressureFl, &protos.Value{Value: &protos.Value_Invalid{Invalid: true}}), + datum(protos.Field_TpmsPressureFr, &protos.Value{Value: &protos.Value_Invalid{Invalid: true}}), + }, + } + got := decode(t, mustNew(t, Options{}), "telemetry.TESTVIN0000000001.data", p) + want := `{"vin":"TESTVIN0000000001","createdAt":"2026-10-14T17:46:40.500Z","isResend":false,` + + `"VehicleSpeed":28.6,"Odometer":12345.678,"ChargeAmps":-16,"LifetimeEnergyUsed":1099511627776,` + + `"Locked":true,"VehicleName":"Say \"hi\"\n\u2028","Gear":"ShiftStateD",` + + `"Location":{"latitude":37.4919,"longitude":-121.9447},` + + `"DoorState":{"DriverFront":true,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false},` + + `"ScheduledChargingStartTime":{"hour":7,"minute":0,"second":0},` + + `"invalid":["TpmsPressureFl","TpmsPressureFr"]}` + if got != want { + t.Errorf("got %s\nwant %s", got, want) + } +} + +func TestFlatProtoNames(t *testing.T) { + p := &protos.Payload{ + IsResend: true, + Data: []*protos.Datum{ + datum(protos.Field_TpmsHardWarnings, &protos.Value{Value: &protos.Value_TireLocationValue{TireLocationValue: &protos.TireLocation{FrontLeft: true}}}), + }, + } + got := decode(t, mustNew(t, Options{ProtoNames: true}), "telemetry.TESTVIN0000000001.data", p) + if !strings.HasPrefix(got, `{"vin":"TESTVIN0000000001","created_at":null,"is_resend":true,"TpmsHardWarnings":{"front_left":true,"front_right":false,`) { + t.Errorf("got %s", got) + } +} + +func TestFlatDuplicateSignalKeepsLast(t *testing.T) { + p := &protos.Payload{Data: []*protos.Datum{ + datum(protos.Field_VehicleSpeed, &protos.Value{Value: &protos.Value_FloatValue{FloatValue: 1}}), + datum(protos.Field_Soc, &protos.Value{Value: &protos.Value_FloatValue{FloatValue: 50}}), + datum(protos.Field_VehicleSpeed, &protos.Value{Value: &protos.Value_FloatValue{FloatValue: 2}}), + }} + got := decode(t, mustNew(t, Options{}), "telemetry.V.data", p) + if want := `{"vin":"V","createdAt":null,"isResend":false,"Soc":50,"VehicleSpeed":2}`; got != want { + t.Errorf("got %s\nwant %s", got, want) + } +} + +// Vehicles can send signals and value types newer than the decoder's protos. +func TestFlatNewerThanProtos(t *testing.T) { + var value []byte + value = protowire.AppendTag(value, 999, protowire.VarintType) // an unknown value type + value = protowire.AppendVarint(value, 1) + var unknownValue []byte + unknownValue = protowire.AppendTag(unknownValue, 1, protowire.VarintType) + unknownValue = protowire.AppendVarint(unknownValue, uint64(protos.Field_VehicleSpeed)) + unknownValue = protowire.AppendTag(unknownValue, 2, protowire.BytesType) + unknownValue = protowire.AppendBytes(unknownValue, value) + + var enumValue []byte + enumValue = protowire.AppendTag(enumValue, 9, protowire.VarintType) // shift_state_value + enumValue = protowire.AppendVarint(enumValue, 77) + var unknownField []byte + unknownField = protowire.AppendTag(unknownField, 1, protowire.VarintType) + unknownField = protowire.AppendVarint(unknownField, 4321) + unknownField = protowire.AppendTag(unknownField, 2, protowire.BytesType) + unknownField = protowire.AppendBytes(unknownField, enumValue) + + var payload []byte + payload = protowire.AppendTag(payload, 1, protowire.BytesType) + payload = protowire.AppendBytes(payload, unknownValue) + payload = protowire.AppendTag(payload, 1, protowire.BytesType) + payload = protowire.AppendBytes(payload, unknownField) + + event, err := mustNew(t, Options{}).Decode(nil, "telemetry.V.data", payload) + if err != nil { + t.Fatal(err) + } + if got, want := string(event), `{"vin":"V","createdAt":null,"isResend":false,"VehicleSpeed":null,"4321":77}`; got != want { + t.Errorf("got %s\nwant %s", got, want) + } +} + +func TestProtoJSONPayload(t *testing.T) { + p := &protos.Payload{ + Vin: "TESTVIN0000000001", + Data: []*protos.Datum{ + datum(protos.Field_VehicleSpeed, &protos.Value{Value: &protos.Value_FloatValue{FloatValue: 28.6}}), + }, + } + got := decode(t, mustNew(t, Options{Format: FormatProtoJSON}), "telemetry.TESTVIN0000000001.data", p) + want := `{"data":[{"key":"VehicleSpeed","value":{"floatValue":28.6}}],"createdAt":null,"vin":"TESTVIN0000000001","isResend":false}` + if got != want { + t.Errorf("got %s\nwant %s", got, want) + } +} + +func TestRecordTypes(t *testing.T) { + d := mustNew(t, Options{}) + for _, tc := range []struct { + subject string + message proto.Message + want string + }{ + {"telemetry.V.alerts", &protos.VehicleAlerts{Alerts: []*protos.VehicleAlert{{Name: "A", Audiences: []protos.Audience{protos.Audience_Customer}}}}, + `{"alerts":[{"name":"A","audiences":["Customer"],"startedAt":null,"endedAt":null}],"createdAt":null,"vin":"V"}`}, + {"telemetry.V.errors", &protos.VehicleErrors{Errors: []*protos.VehicleError{{Name: "E", Tags: map[string]string{"k": "v"}}}}, + `{"errors":[{"createdAt":null,"name":"E","tags":{"k":"v"},"body":""}],"createdAt":null,"vin":"V"}`}, + {"telemetry.V.connectivity", &protos.VehicleConnectivity{Status: protos.ConnectivityEvent_CONNECTED, NetworkInterface: "wifi"}, + `{"vin":"V","connectionId":"","status":"CONNECTED","createdAt":null,"networkInterface":"wifi"}`}, + {"telemetry.V.metrics", &protos.VehicleMetrics{Metrics: []*protos.Metric{{Name: "m", Value: 1.5}}}, + `{"metrics":[{"name":"m","tags":{},"value":1.5}],"createdAt":null,"vin":"V"}`}, + // The VIN in the message wins over the subject + {"telemetry.OTHER.connectivity", &protos.VehicleConnectivity{Vin: "V", Status: protos.ConnectivityEvent_DISCONNECTED}, + `{"vin":"V","connectionId":"","status":"DISCONNECTED","createdAt":null,"networkInterface":""}`}, + // No VIN anywhere + {"connectivity", &protos.VehicleConnectivity{Status: protos.ConnectivityEvent_DISCONNECTED}, + `{"vin":"","connectionId":"","status":"DISCONNECTED","createdAt":null,"networkInterface":""}`}, + } { + if got := decode(t, d, tc.subject, tc.message); got != tc.want { + t.Errorf("%s:\ngot %s\nwant %s", tc.subject, got, tc.want) + } + } +} + +func TestDecodeErrors(t *testing.T) { + d := mustNew(t, Options{}) + for _, tc := range []struct { + subject string + payload []byte + want string + }{ + {"telemetry.V.unknown", []byte{0x08, 0x01}, `unknown record type "unknown"`}, + {"", []byte{0x08, 0x01}, `unknown record type ""`}, + {"telemetry.V.data", nil, "empty payload"}, + {"telemetry.V.data", []byte("not a protobuf"), "cannot decode data payload"}, + } { + dst := []byte("prefix") + got, err := d.Decode(dst, tc.subject, tc.payload) + if err == nil || !strings.Contains(err.Error(), tc.want) { + t.Errorf("%s %q: error %v, want %q", tc.subject, tc.payload, err, tc.want) + } + if string(got) != "prefix" { + t.Errorf("%s %q: dst changed to %q", tc.subject, tc.payload, got) + } + } + if _, err := New(Options{Format: "xml"}); err == nil { + t.Error("New accepted an unknown format") + } +} + +func TestAppendFloat(t *testing.T) { + for _, tc := range []struct { + f float64 + bits int + want string + }{ + {float64(float32(28.6)), 32, "28.6"}, + {28.6, 64, "28.6"}, + {0, 64, "0"}, + {-0.5, 32, "-0.5"}, + {1e-7, 64, "1e-7"}, + {1e21, 64, "1e+21"}, + {123456789, 64, "123456789"}, + {math.NaN(), 64, `"NaN"`}, + {math.Inf(1), 32, `"Infinity"`}, + {math.Inf(-1), 64, `"-Infinity"`}, + } { + if got := string(appendFloat(nil, tc.f, tc.bits)); got != tc.want { + t.Errorf("appendFloat(%v, %d) = %s, want %s", tc.f, tc.bits, got, tc.want) + } + } +} + +func TestAppendString(t *testing.T) { + for _, s := range []string{"", "plain", "quote\" backslash\\ tab\t nl\n cr\r", "\x00\x1f\u2028\u2029", "héllo 🚗", "bad \xff utf8"} { + var got string + if err := json.Unmarshal(appendString(nil, s), &got); err != nil { + t.Errorf("appendString(%q) is not a JSON string: %v", s, err) + continue + } + want := strings.ToValidUTF8(s, "\uFFFD") + if got != want { + t.Errorf("appendString(%q) decodes to %q, want %q", s, got, want) + } + } +} diff --git a/internal/decoder/golden_test.go b/internal/decoder/golden_test.go new file mode 100644 index 0000000..6163909 --- /dev/null +++ b/internal/decoder/golden_test.go @@ -0,0 +1,103 @@ +package decoder + +import ( + "bytes" + "encoding/json" + "flag" + "os" + "path/filepath" + "strings" + "testing" + "unicode/utf8" +) + +var update = flag.Bool("update", false, "rewrite the golden files from the decoder's output") + +// The fixtures are real payloads from live telemetry, anonymized by +// tools/mkfixtures. Each .request is a decoder protocol request; the +// golden files hold the event for each output option. +var goldenOptions = map[string]Options{ + "flat": {Format: FormatFlat}, + "flat.proto-names": {Format: FormatFlat, ProtoNames: true}, + "protojson": {Format: FormatProtoJSON}, + "protojson.proto-names": {Format: FormatProtoJSON, ProtoNames: true}, +} + +func goldenRequests(t testing.TB) map[string][]byte { + t.Helper() + paths, err := filepath.Glob("testdata/golden/*.request") + if err != nil { + t.Fatal(err) + } + if len(paths) == 0 { + t.Fatal("no fixtures in testdata/golden") + } + requests := map[string][]byte{} + for _, path := range paths { + b, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + requests[strings.TrimSuffix(filepath.Base(path), ".request")] = b + } + return requests +} + +func TestGolden(t *testing.T) { + requests := goldenRequests(t) + types := map[string]bool{} + for name, request := range requests { + var r Request + if err := json.Unmarshal(request, &r); err != nil { + t.Fatalf("%s: %v", name, err) + } + types[RecordType(r.Subject)] = true + for suffix, opts := range goldenOptions { + t.Run(name+"."+suffix, func(t *testing.T) { + d, err := New(opts) + if err != nil { + t.Fatal(err) + } + event, err := d.handle(nil, request) + if err != nil { + t.Fatal(err) + } + checkEvent(t, event) + path := filepath.Join("testdata", "golden", name+"."+suffix+".json") + if *update { + if err := os.WriteFile(path, append(event, '\n'), 0o644); err != nil { + t.Fatal(err) + } + return + } + want, err := os.ReadFile(path) + if err != nil { + t.Fatalf("%v (run go test ./internal/decoder -update to create it)", err) + } + if got := string(event) + "\n"; got != string(want) { + t.Errorf("event differs from %s\ngot: %s\nwant: %s", path, got, want) + } + }) + } + } + for _, recordType := range []string{"data", "alerts", "errors", "connectivity"} { + if !types[recordType] { + t.Errorf("no fixture for %s", recordType) + } + } +} + +// checkEvent fails unless event is one line of valid UTF-8 holding a JSON object. +func checkEvent(t *testing.T, event []byte) { + t.Helper() + if bytes.ContainsAny(event, "\r\n") { + t.Errorf("event is not one line: %q", event) + } + if !utf8.Valid(event) { + t.Errorf("event is not valid UTF-8: %q", event) + } + var object map[string]any + if err := json.Unmarshal(event, &object); err != nil { + t.Errorf("event is not a JSON object: %v: %s", err, event) + } +} diff --git a/internal/decoder/protocol.go b/internal/decoder/protocol.go new file mode 100644 index 0000000..fd53067 --- /dev/null +++ b/internal/decoder/protocol.go @@ -0,0 +1,100 @@ +package decoder + +import ( + "bufio" + "bytes" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" +) + +// Request is one message from the NATS add-on: a JSON object on one line. +type Request struct { + Subject string `json:"subject"` + // Payload is the message payload in base64. + Payload string `json:"payload"` + // Headers are the NATS message headers; the decoder does not use them. +} + +// DecodePayload returns the message payload. +func (r *Request) DecodePayload() ([]byte, error) { + payload, err := base64.StdEncoding.DecodeString(r.Payload) + if err != nil { + return nil, fmt.Errorf("invalid payload: %w", err) + } + return payload, nil +} + +// Run serves the NATS add-on's decoder protocol until in closes: for each +// request line read from in, it writes one line to out, the decoded event or an +// empty line when the payload cannot be decoded, and flushes it. Why a payload +// could not be decoded is written to diag, one line each. +// +// Run returns nil when in closes, or the error that stopped it reading in or +// writing out. +func (d *Decoder) Run(in io.Reader, out io.Writer, diag io.Writer) error { + r := bufio.NewReaderSize(in, 64*1024) + w := bufio.NewWriterSize(out, 64*1024) + var event []byte + for { + line, readErr := r.ReadSlice('\n') + if errors.Is(readErr, bufio.ErrBufferFull) { + // A request longer than the buffer: collect the rest of it + long := append([]byte(nil), line...) + for errors.Is(readErr, bufio.ErrBufferFull) { + line, readErr = r.ReadSlice('\n') + long = append(long, line...) + } + line = long + } + if readErr != nil && readErr != io.EOF { + return readErr + } + if len(line) > 0 { + var err error + event, err = d.handle(event[:0], line) + if err != nil { + // A diagnostic that cannot be written must not stop decoding + _, _ = fmt.Fprintf(diag, "telemetry-decoder: %v\n", err) + } + event = append(event, '\n') + if _, err := w.Write(event); err != nil { + return err + } + if err := w.Flush(); err != nil { + return err + } + } + if readErr == io.EOF { + return nil + } + } +} + +// handle decodes one request line into an event appended to dst, or returns dst +// unchanged and the reason it could not. +func (d *Decoder) handle(dst []byte, line []byte) (event []byte, err error) { + defer func() { + if r := recover(); r != nil { + event, err = dst, fmt.Errorf("decoder panic: %v", r) + } + }() + line = bytes.TrimRight(line, "\r\n") + if len(bytes.TrimSpace(line)) == 0 { + return dst, errors.New("empty request line") + } + var request Request + if err := json.Unmarshal(line, &request); err != nil { + return dst, fmt.Errorf("invalid request: %w", err) + } + payload, err := request.DecodePayload() + if err == nil { + event, err = d.Decode(dst, request.Subject, payload) + } + if err != nil { + return dst, fmt.Errorf("%s: %w", request.Subject, err) + } + return event, nil +} diff --git a/internal/decoder/protocol_test.go b/internal/decoder/protocol_test.go new file mode 100644 index 0000000..f063dcb --- /dev/null +++ b/internal/decoder/protocol_test.go @@ -0,0 +1,152 @@ +package decoder + +import ( + "bufio" + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "strings" + "testing" + + "google.golang.org/protobuf/proto" + + "github.com/Teslemetry/telemetry-decoder/internal/protos" +) + +func request(subject string, payload []byte) string { + b, _ := json.Marshal(map[string]any{"subject": subject, "headers": map[string]string{}, "payload": payload}) + return string(b) + "\n" +} + +func connectivityPayload(t testing.TB) []byte { + payload, err := proto.Marshal(&protos.VehicleConnectivity{Vin: "V", Status: protos.ConnectivityEvent_CONNECTED}) + if err != nil { + t.Fatal(err) + } + return payload +} + +func run(t *testing.T, input string) (out []string, diag string) { + t.Helper() + var stdout, stderr bytes.Buffer + if err := mustNew(t, Options{}).Run(strings.NewReader(input), &stdout, &stderr); err != nil { + t.Fatalf("Run: %v", err) + } + if stdout.Len() > 0 && !bytes.HasSuffix(stdout.Bytes(), []byte("\n")) { + t.Errorf("output does not end with a newline: %q", stdout.String()) + } + return strings.Split(strings.TrimSuffix(stdout.String(), "\n"), "\n"), stderr.String() +} + +func TestProtocol(t *testing.T) { + good := request("telemetry.V.connectivity", connectivityPayload(t)) + wantGood := `{"vin":"V","connectionId":"","status":"CONNECTED","createdAt":null,"networkInterface":""}` + for _, tc := range []struct { + name string + request string + wantDiag string + }{ + {"bad base64", `{"subject":"telemetry.V.data","headers":{},"payload":"not base64!"}` + "\n", "invalid payload: illegal base64 data"}, + {"unknown subject", request("telemetry.V.other", connectivityPayload(t)), `telemetry.V.other: unknown record type "other"`}, + {"empty payload", request("telemetry.V.data", nil), "telemetry.V.data: empty payload"}, + {"missing payload", `{"subject":"telemetry.V.data","headers":{}}` + "\n", "telemetry.V.data: empty payload"}, + {"not a protobuf", request("telemetry.V.data", []byte("\xff\xff\xff")), "telemetry.V.data: cannot decode data payload"}, + {"not JSON", "hello\n", "invalid request"}, + {"empty line", "\n", "empty request line"}, + {"CRLF", strings.TrimSuffix(good, "\n") + "\r\n", ""}, + } { + t.Run(tc.name, func(t *testing.T) { + // A bad request gets an empty line and leaves the decoder serving the next + out, diag := run(t, tc.request+good) + want := []string{"", wantGood} + if tc.wantDiag == "" { + want = []string{wantGood, wantGood} + } + if fmt.Sprint(out) != fmt.Sprint(want) { + t.Errorf("output %q, want %q", out, want) + } + if tc.wantDiag == "" && diag != "" || !strings.Contains(diag, tc.wantDiag) { + t.Errorf("stderr %q, want %q", diag, tc.wantDiag) + } + if strings.Count(diag, "\n") > 1 { + t.Errorf("more than one diagnostic line: %q", diag) + } + }) + } +} + +func TestProtocolEOF(t *testing.T) { + good := request("telemetry.V.connectivity", connectivityPayload(t)) + // No input: no output + if out, _ := run(t, ""); fmt.Sprint(out) != "[]" { + t.Errorf("output %q for no input", out) + } + // A last request without a newline is still answered + out, _ := run(t, good+strings.TrimSuffix(good, "\n")) + if len(out) != 2 || out[1] == "" { + t.Errorf("output %q, want two events", out) + } +} + +func TestProtocolLongRequest(t *testing.T) { + // A request far beyond the read buffer + p := &protos.Payload{Vin: "V"} + for range 5000 { + p.Data = append(p.Data, &protos.Datum{Key: protos.Field_VehicleName, + Value: &protos.Value{Value: &protos.Value_StringValue{StringValue: strings.Repeat("x", 100)}}}) + } + payload, err := proto.Marshal(p) + if err != nil { + t.Fatal(err) + } + input := request("telemetry.V.data", payload) + if len(input) < 512*1024 { + t.Fatalf("request is only %d bytes", len(input)) + } + out, diag := run(t, input+input) + if len(out) != 2 || !strings.Contains(out[0], `"VehicleName":"xxx`) || out[0] != out[1] { + t.Errorf("unexpected output for long requests (%d lines), stderr %q", len(out), diag) + } +} + +// Each event is flushed as soon as it is written: the add-on waits for it before +// sending the next request. +func TestProtocolFlushesEachLine(t *testing.T) { + inR, inW := io.Pipe() + outR, outW := io.Pipe() + done := make(chan error, 1) + go func() { + done <- mustNew(t, Options{}).Run(inR, outW, io.Discard) + _ = outW.Close() + }() + reader := bufio.NewReader(outR) + good := request("telemetry.V.connectivity", connectivityPayload(t)) + for i := range 3 { + if _, err := io.WriteString(inW, good); err != nil { + t.Fatal(err) + } + line, err := reader.ReadString('\n') + if err != nil { + t.Fatalf("request %d: %v", i, err) + } + if !strings.Contains(line, `"status":"CONNECTED"`) { + t.Fatalf("request %d: got %q", i, line) + } + } + _ = inW.Close() + if err := <-done; err != nil { + t.Fatalf("Run after stdin closed: %v", err) + } +} + +func TestRequestPayloadIsStandardBase64(t *testing.T) { + payload := connectivityPayload(t) + line := fmt.Sprintf(`{"subject":"telemetry.V.connectivity","headers":{"traceparent":"00-1-2-00"},"payload":%q}`, + base64.StdEncoding.EncodeToString(payload)) + event, err := mustNew(t, Options{}).handle(nil, []byte(line)) + if err != nil || !strings.Contains(string(event), "CONNECTED") { + t.Errorf("event %q, error %v", event, err) + } +} diff --git a/internal/decoder/testdata/golden/alerts.flat.json b/internal/decoder/testdata/golden/alerts.flat.json new file mode 100644 index 0000000..7df3848 --- /dev/null +++ b/internal/decoder/testdata/golden/alerts.flat.json @@ -0,0 +1 @@ +{"alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"startedAt":"2026-10-15T00:14:55.164Z","endedAt":null}],"createdAt":"2026-10-15T00:15:05.180915260Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/alerts.flat.proto-names.json b/internal/decoder/testdata/golden/alerts.flat.proto-names.json new file mode 100644 index 0000000..e5ad497 --- /dev/null +++ b/internal/decoder/testdata/golden/alerts.flat.proto-names.json @@ -0,0 +1 @@ +{"alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"started_at":"2026-10-15T00:14:55.164Z","ended_at":null}],"created_at":"2026-10-15T00:15:05.180915260Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/alerts.protojson.json b/internal/decoder/testdata/golden/alerts.protojson.json new file mode 100644 index 0000000..7df3848 --- /dev/null +++ b/internal/decoder/testdata/golden/alerts.protojson.json @@ -0,0 +1 @@ +{"alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"startedAt":"2026-10-15T00:14:55.164Z","endedAt":null}],"createdAt":"2026-10-15T00:15:05.180915260Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/alerts.protojson.proto-names.json b/internal/decoder/testdata/golden/alerts.protojson.proto-names.json new file mode 100644 index 0000000..e5ad497 --- /dev/null +++ b/internal/decoder/testdata/golden/alerts.protojson.proto-names.json @@ -0,0 +1 @@ +{"alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"started_at":"2026-10-15T00:14:55.164Z","ended_at":null}],"created_at":"2026-10-15T00:15:05.180915260Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/alerts.request b/internal/decoder/testdata/golden/alerts.request new file mode 100644 index 0000000..4c9d70d --- /dev/null +++ b/internal/decoder/testdata/golden/alerts.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"CisKGENQX2ExMDFfd2NGb2xkYmFja0FjdGl2ZRICAQIaCwj/tcDWBhCA4plOEgsIibbA1gYQvJiiVhoRVEVTVFZJTjAwMDAwMDAwMDE=","subject":"telemetry.TESTVIN0000000001.alerts"} diff --git a/internal/decoder/testdata/golden/connectivity-connected.flat.json b/internal/decoder/testdata/golden/connectivity-connected.flat.json new file mode 100644 index 0000000..420bf59 --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-connected.flat.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","connectionId":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","createdAt":"2026-10-15T00:13:22.426862796Z","networkInterface":"wifi"} diff --git a/internal/decoder/testdata/golden/connectivity-connected.flat.proto-names.json b/internal/decoder/testdata/golden/connectivity-connected.flat.proto-names.json new file mode 100644 index 0000000..cc33ec5 --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-connected.flat.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","connection_id":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","created_at":"2026-10-15T00:13:22.426862796Z","network_interface":"wifi"} diff --git a/internal/decoder/testdata/golden/connectivity-connected.protojson.json b/internal/decoder/testdata/golden/connectivity-connected.protojson.json new file mode 100644 index 0000000..420bf59 --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-connected.protojson.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","connectionId":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","createdAt":"2026-10-15T00:13:22.426862796Z","networkInterface":"wifi"} diff --git a/internal/decoder/testdata/golden/connectivity-connected.protojson.proto-names.json b/internal/decoder/testdata/golden/connectivity-connected.protojson.proto-names.json new file mode 100644 index 0000000..cc33ec5 --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-connected.protojson.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","connection_id":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","created_at":"2026-10-15T00:13:22.426862796Z","network_interface":"wifi"} diff --git a/internal/decoder/testdata/golden/connectivity-connected.request b/internal/decoder/testdata/golden/connectivity-connected.request new file mode 100644 index 0000000..4c11341 --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-connected.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"ChFURVNUVklOMDAwMDAwMDAwMRIkMDAwMDAwMDAtMDAwMC00MDAwLTgwMDAtMDAwMDAwMDAwMDAxGAEiDAiitcDWBhDM0cXLASoEd2lmaQ==","subject":"telemetry.TESTVIN0000000001.connectivity"} diff --git a/internal/decoder/testdata/golden/connectivity-disconnected.flat.json b/internal/decoder/testdata/golden/connectivity-disconnected.flat.json new file mode 100644 index 0000000..f63e59e --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-disconnected.flat.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","connectionId":"00000000-0000-4000-8000-000000000001","status":"DISCONNECTED","createdAt":"2026-10-15T00:13:19.375925589Z","networkInterface":"cellular"} diff --git a/internal/decoder/testdata/golden/connectivity-disconnected.flat.proto-names.json b/internal/decoder/testdata/golden/connectivity-disconnected.flat.proto-names.json new file mode 100644 index 0000000..a3f00ff --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-disconnected.flat.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","connection_id":"00000000-0000-4000-8000-000000000001","status":"DISCONNECTED","created_at":"2026-10-15T00:13:19.375925589Z","network_interface":"cellular"} diff --git a/internal/decoder/testdata/golden/connectivity-disconnected.protojson.json b/internal/decoder/testdata/golden/connectivity-disconnected.protojson.json new file mode 100644 index 0000000..f63e59e --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-disconnected.protojson.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","connectionId":"00000000-0000-4000-8000-000000000001","status":"DISCONNECTED","createdAt":"2026-10-15T00:13:19.375925589Z","networkInterface":"cellular"} diff --git a/internal/decoder/testdata/golden/connectivity-disconnected.protojson.proto-names.json b/internal/decoder/testdata/golden/connectivity-disconnected.protojson.proto-names.json new file mode 100644 index 0000000..a3f00ff --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-disconnected.protojson.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","connection_id":"00000000-0000-4000-8000-000000000001","status":"DISCONNECTED","created_at":"2026-10-15T00:13:19.375925589Z","network_interface":"cellular"} diff --git a/internal/decoder/testdata/golden/connectivity-disconnected.request b/internal/decoder/testdata/golden/connectivity-disconnected.request new file mode 100644 index 0000000..2f9ed65 --- /dev/null +++ b/internal/decoder/testdata/golden/connectivity-disconnected.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"ChFURVNUVklOMDAwMDAwMDAwMRIkMDAwMDAwMDAtMDAwMC00MDAwLTgwMDAtMDAwMDAwMDAwMDAxGAIiDAiftcDWBhDV1qCzASoIY2VsbHVsYXI=","subject":"telemetry.TESTVIN0000000001.connectivity"} diff --git a/internal/decoder/testdata/golden/data-doors.flat.json b/internal/decoder/testdata/golden/data-doors.flat.json new file mode 100644 index 0000000..9748bc7 --- /dev/null +++ b/internal/decoder/testdata/golden/data-doors.flat.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:17.788055947Z","isResend":false,"Locked":false,"DoorState":{"DriverFront":true,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false}} diff --git a/internal/decoder/testdata/golden/data-doors.flat.proto-names.json b/internal/decoder/testdata/golden/data-doors.flat.proto-names.json new file mode 100644 index 0000000..3b2126c --- /dev/null +++ b/internal/decoder/testdata/golden/data-doors.flat.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:13:17.788055947Z","is_resend":false,"Locked":false,"DoorState":{"DriverFront":true,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false}} diff --git a/internal/decoder/testdata/golden/data-doors.protojson.json b/internal/decoder/testdata/golden/data-doors.protojson.json new file mode 100644 index 0000000..8173c4c --- /dev/null +++ b/internal/decoder/testdata/golden/data-doors.protojson.json @@ -0,0 +1 @@ +{"data":[{"key":"Locked","value":{"booleanValue":false}},{"key":"DoorState","value":{"doorValue":{"DriverFront":true,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false}}}],"createdAt":"2026-10-15T00:13:17.788055947Z","vin":"TESTVIN0000000001","isResend":false} diff --git a/internal/decoder/testdata/golden/data-doors.protojson.proto-names.json b/internal/decoder/testdata/golden/data-doors.protojson.proto-names.json new file mode 100644 index 0000000..41ca38e --- /dev/null +++ b/internal/decoder/testdata/golden/data-doors.protojson.proto-names.json @@ -0,0 +1 @@ +{"data":[{"key":"Locked","value":{"boolean_value":false}},{"key":"DoorState","value":{"door_value":{"DriverFront":true,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false}}}],"created_at":"2026-10-15T00:13:17.788055947Z","vin":"TESTVIN0000000001","is_resend":false} diff --git a/internal/decoder/testdata/golden/data-doors.request b/internal/decoder/testdata/golden/data-doors.request new file mode 100644 index 0000000..8ba651f --- /dev/null +++ b/internal/decoder/testdata/golden/data-doors.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"CgYIOxICMAAKCQg6EgWqAQIIARIMCJ21wNYGEIuP4/cCGhFURVNUVklOMDAwMDAwMDAwMQ==","subject":"telemetry.TESTVIN0000000001.data"} diff --git a/internal/decoder/testdata/golden/data-full.flat.json b/internal/decoder/testdata/golden/data-full.flat.json new file mode 100644 index 0000000..88a1fbd --- /dev/null +++ b/internal/decoder/testdata/golden/data-full.flat.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:14:38.872811608Z","isResend":false,"HvacACEnabled":false,"ClimateSeatCoolingFrontLeft":0,"MediaNowPlayingTitle":"Test Title","InsideTemp":11.00000075995922,"ChargeCurrentRequestMax":16,"RouteTrafficMinutesDelay":0,"TpmsPressureFl":2.8750000428408384,"ChargeLimitSoc":80,"DefrostMode":"DefrostModeStateOff","SoftwareUpdateDownloadPercentComplete":0,"MediaAudioVolume":0.3333333333333333,"TpmsLastSeenPressureTimeRl":1792046866,"RightHandDrive":false,"ExteriorColor":"SolidBlack","SoftwareUpdateExpectedDurationMinutes":45,"SoftwareUpdateVersion":" ","ChargePortDoorOpen":true,"LifetimeEnergyUsed":16607.024788791314,"SeatHeaterLeft":0,"SeatHeaterRearLeft":0,"DCChargingPower":0,"ChargingCableType":"CableTypeIEC","IdealBatteryRange":42.4489786430281,"ExpectedEnergyPercentAtTripArrival":8,"ScheduledChargingMode":"ScheduledChargingModeOff","HvacSteeringWheelHeatAuto":true,"SeatHeaterRight":0,"HvacPower":"HvacPowerStateOff","TpmsPressureRl":3.0750000458210707,"RdWindow":"WindowStateClosed","RpWindow":"WindowStateClosed","ScheduledChargingPending":false,"SoftwareUpdateInstallationPercentComplete":1,"DestinationLocation":{"latitude":37.4919,"longitude":-121.9447},"TpmsPressureFr":3.0750000458210707,"FastChargerType":"FastChargerACSingleWireCAN","Locked":true,"CenterDisplay":"DisplayStateOff","SeatHeaterRearCenter":0,"MediaNowPlayingAlbum":"","TpmsLastSeenPressureTimeFl":1792046866,"TpmsLastSeenPressureTimeFr":1792046866,"Version":"2026.38.3.1","RoofColor":"RoofColorGlass","CabinOverheatProtectionMode":"CabinOverheatProtectionModeStateOff","CabinOverheatProtectionTemperatureLimit":"ClimateOverheatProtectionTempLimitHigh","GuestModeEnabled":false,"ChargeCurrentRequest":3,"Location":{"latitude":37.4919,"longitude":-121.9447},"BatteryHeaterOn":false,"ChargeAmps":0,"DCChargingEnergyIn":4.379999902099371,"MediaPlaybackStatus":"MediaStatusStopped","LocatedAtWork":false,"PreconditioningEnabled":false,"ACChargingEnergyIn":5.2072222998159114,"TpmsLastSeenPressureTimeRr":1792046866,"ChargerVoltage":1.8149999901652336,"MediaNowPlayingDuration":0,"OutsideTemp":8.5,"FpWindow":"WindowStateClosed","ClimateKeeperMode":"ClimateKeeperModeStateOff","ChargeEnableRequest":false,"RemoteStartEnabled":true,"ValetModeEnabled":false,"HvacLeftTemperatureRequest":21.5,"MediaPlaybackSource":"13","FdWindow":"WindowStateClosed","Soc":14.981273408239701,"DetailedChargeState":"DetailedChargeStateStopped","SentryMode":"SentryModeStateOff","LocatedAtHome":false,"AutoSeatClimateLeft":true,"AutoSeatClimateRight":false,"MediaNowPlayingElapsed":0,"ChargePortLatch":"ChargePortLatchEngaged","ClimateSeatCoolingFrontRight":0,"HvacSteeringWheelHeatLevel":0,"MediaNowPlayingArtist":"","TpmsPressureRr":3.0000000447034836,"BatteryLevel":14.981273408239701,"ACChargingPower":0,"Odometer":32678.241257255184,"SeatHeaterRearRight":0,"MediaNowPlayingStation":"Test Station","DoorState":{"DriverFront":false,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false},"invalid":["TimeToFullCharge","ChargerPhases","SoftwareUpdateScheduledStartTime","Gear","VehicleSpeed","ScheduledChargingStartTime","MinutesToArrival","MilesToArrival","DestinationName"]} diff --git a/internal/decoder/testdata/golden/data-full.flat.proto-names.json b/internal/decoder/testdata/golden/data-full.flat.proto-names.json new file mode 100644 index 0000000..6fd9ca7 --- /dev/null +++ b/internal/decoder/testdata/golden/data-full.flat.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:14:38.872811608Z","is_resend":false,"HvacACEnabled":false,"ClimateSeatCoolingFrontLeft":0,"MediaNowPlayingTitle":"Test Title","InsideTemp":11.00000075995922,"ChargeCurrentRequestMax":16,"RouteTrafficMinutesDelay":0,"TpmsPressureFl":2.8750000428408384,"ChargeLimitSoc":80,"DefrostMode":"DefrostModeStateOff","SoftwareUpdateDownloadPercentComplete":0,"MediaAudioVolume":0.3333333333333333,"TpmsLastSeenPressureTimeRl":1792046866,"RightHandDrive":false,"ExteriorColor":"SolidBlack","SoftwareUpdateExpectedDurationMinutes":45,"SoftwareUpdateVersion":" ","ChargePortDoorOpen":true,"LifetimeEnergyUsed":16607.024788791314,"SeatHeaterLeft":0,"SeatHeaterRearLeft":0,"DCChargingPower":0,"ChargingCableType":"CableTypeIEC","IdealBatteryRange":42.4489786430281,"ExpectedEnergyPercentAtTripArrival":8,"ScheduledChargingMode":"ScheduledChargingModeOff","HvacSteeringWheelHeatAuto":true,"SeatHeaterRight":0,"HvacPower":"HvacPowerStateOff","TpmsPressureRl":3.0750000458210707,"RdWindow":"WindowStateClosed","RpWindow":"WindowStateClosed","ScheduledChargingPending":false,"SoftwareUpdateInstallationPercentComplete":1,"DestinationLocation":{"latitude":37.4919,"longitude":-121.9447},"TpmsPressureFr":3.0750000458210707,"FastChargerType":"FastChargerACSingleWireCAN","Locked":true,"CenterDisplay":"DisplayStateOff","SeatHeaterRearCenter":0,"MediaNowPlayingAlbum":"","TpmsLastSeenPressureTimeFl":1792046866,"TpmsLastSeenPressureTimeFr":1792046866,"Version":"2026.38.3.1","RoofColor":"RoofColorGlass","CabinOverheatProtectionMode":"CabinOverheatProtectionModeStateOff","CabinOverheatProtectionTemperatureLimit":"ClimateOverheatProtectionTempLimitHigh","GuestModeEnabled":false,"ChargeCurrentRequest":3,"Location":{"latitude":37.4919,"longitude":-121.9447},"BatteryHeaterOn":false,"ChargeAmps":0,"DCChargingEnergyIn":4.379999902099371,"MediaPlaybackStatus":"MediaStatusStopped","LocatedAtWork":false,"PreconditioningEnabled":false,"ACChargingEnergyIn":5.2072222998159114,"TpmsLastSeenPressureTimeRr":1792046866,"ChargerVoltage":1.8149999901652336,"MediaNowPlayingDuration":0,"OutsideTemp":8.5,"FpWindow":"WindowStateClosed","ClimateKeeperMode":"ClimateKeeperModeStateOff","ChargeEnableRequest":false,"RemoteStartEnabled":true,"ValetModeEnabled":false,"HvacLeftTemperatureRequest":21.5,"MediaPlaybackSource":"13","FdWindow":"WindowStateClosed","Soc":14.981273408239701,"DetailedChargeState":"DetailedChargeStateStopped","SentryMode":"SentryModeStateOff","LocatedAtHome":false,"AutoSeatClimateLeft":true,"AutoSeatClimateRight":false,"MediaNowPlayingElapsed":0,"ChargePortLatch":"ChargePortLatchEngaged","ClimateSeatCoolingFrontRight":0,"HvacSteeringWheelHeatLevel":0,"MediaNowPlayingArtist":"","TpmsPressureRr":3.0000000447034836,"BatteryLevel":14.981273408239701,"ACChargingPower":0,"Odometer":32678.241257255184,"SeatHeaterRearRight":0,"MediaNowPlayingStation":"Test Station","DoorState":{"DriverFront":false,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false},"invalid":["TimeToFullCharge","ChargerPhases","SoftwareUpdateScheduledStartTime","Gear","VehicleSpeed","ScheduledChargingStartTime","MinutesToArrival","MilesToArrival","DestinationName"]} diff --git a/internal/decoder/testdata/golden/data-full.protojson.json b/internal/decoder/testdata/golden/data-full.protojson.json new file mode 100644 index 0000000..2495341 --- /dev/null +++ b/internal/decoder/testdata/golden/data-full.protojson.json @@ -0,0 +1 @@ +{"data":[{"key":"HvacACEnabled","value":{"booleanValue":false}},{"key":"ClimateSeatCoolingFrontLeft","value":{"intValue":0}},{"key":"MediaNowPlayingTitle","value":{"stringValue":"Test Title"}},{"key":"InsideTemp","value":{"doubleValue":11.00000075995922}},{"key":"TimeToFullCharge","value":{"invalid":true}},{"key":"ChargeCurrentRequestMax","value":{"intValue":16}},{"key":"RouteTrafficMinutesDelay","value":{"doubleValue":0}},{"key":"TpmsPressureFl","value":{"doubleValue":2.8750000428408384}},{"key":"ChargerPhases","value":{"invalid":true}},{"key":"ChargeLimitSoc","value":{"intValue":80}},{"key":"DefrostMode","value":{"defrostModeValue":"DefrostModeStateOff"}},{"key":"SoftwareUpdateDownloadPercentComplete","value":{"intValue":0}},{"key":"MediaAudioVolume","value":{"doubleValue":0.3333333333333333}},{"key":"TpmsLastSeenPressureTimeRl","value":{"longValue":"1792046866"}},{"key":"RightHandDrive","value":{"booleanValue":false}},{"key":"ExteriorColor","value":{"stringValue":"SolidBlack"}},{"key":"SoftwareUpdateExpectedDurationMinutes","value":{"intValue":45}},{"key":"SoftwareUpdateVersion","value":{"stringValue":" "}},{"key":"ChargePortDoorOpen","value":{"booleanValue":true}},{"key":"LifetimeEnergyUsed","value":{"doubleValue":16607.024788791314}},{"key":"SoftwareUpdateScheduledStartTime","value":{"invalid":true}},{"key":"SeatHeaterLeft","value":{"intValue":0}},{"key":"SeatHeaterRearLeft","value":{"intValue":0}},{"key":"DCChargingPower","value":{"doubleValue":0}},{"key":"ChargingCableType","value":{"cableTypeValue":"CableTypeIEC"}},{"key":"Gear","value":{"invalid":true}},{"key":"IdealBatteryRange","value":{"doubleValue":42.4489786430281}},{"key":"VehicleSpeed","value":{"invalid":true}},{"key":"ExpectedEnergyPercentAtTripArrival","value":{"intValue":8}},{"key":"ScheduledChargingMode","value":{"scheduledChargingModeValue":"ScheduledChargingModeOff"}},{"key":"HvacSteeringWheelHeatAuto","value":{"booleanValue":true}},{"key":"SeatHeaterRight","value":{"intValue":0}},{"key":"HvacPower","value":{"hvacPowerValue":"HvacPowerStateOff"}},{"key":"TpmsPressureRl","value":{"doubleValue":3.0750000458210707}},{"key":"RdWindow","value":{"windowStateValue":"WindowStateClosed"}},{"key":"RpWindow","value":{"windowStateValue":"WindowStateClosed"}},{"key":"ScheduledChargingPending","value":{"booleanValue":false}},{"key":"SoftwareUpdateInstallationPercentComplete","value":{"intValue":1}},{"key":"DestinationLocation","value":{"locationValue":{"latitude":37.4919,"longitude":-121.9447}}},{"key":"TpmsPressureFr","value":{"doubleValue":3.0750000458210707}},{"key":"FastChargerType","value":{"fastChargerValue":"FastChargerACSingleWireCAN"}},{"key":"Locked","value":{"booleanValue":true}},{"key":"CenterDisplay","value":{"displayStateValue":"DisplayStateOff"}},{"key":"SeatHeaterRearCenter","value":{"intValue":0}},{"key":"MediaNowPlayingAlbum","value":{"stringValue":""}},{"key":"TpmsLastSeenPressureTimeFl","value":{"longValue":"1792046866"}},{"key":"TpmsLastSeenPressureTimeFr","value":{"longValue":"1792046866"}},{"key":"ScheduledChargingStartTime","value":{"invalid":true}},{"key":"Version","value":{"stringValue":"2026.38.3.1"}},{"key":"RoofColor","value":{"stringValue":"RoofColorGlass"}},{"key":"CabinOverheatProtectionMode","value":{"cabinOverheatProtectionModeValue":"CabinOverheatProtectionModeStateOff"}},{"key":"CabinOverheatProtectionTemperatureLimit","value":{"cabinOverheatProtectionTemperatureLimitValue":"ClimateOverheatProtectionTempLimitHigh"}},{"key":"GuestModeEnabled","value":{"booleanValue":false}},{"key":"ChargeCurrentRequest","value":{"intValue":3}},{"key":"Location","value":{"locationValue":{"latitude":37.4919,"longitude":-121.9447}}},{"key":"MinutesToArrival","value":{"invalid":true}},{"key":"BatteryHeaterOn","value":{"booleanValue":false}},{"key":"ChargeAmps","value":{"doubleValue":0}},{"key":"DCChargingEnergyIn","value":{"doubleValue":4.379999902099371}},{"key":"MediaPlaybackStatus","value":{"mediaStatusValue":"MediaStatusStopped"}},{"key":"LocatedAtWork","value":{"booleanValue":false}},{"key":"PreconditioningEnabled","value":{"booleanValue":false}},{"key":"ACChargingEnergyIn","value":{"doubleValue":5.2072222998159114}},{"key":"TpmsLastSeenPressureTimeRr","value":{"longValue":"1792046866"}},{"key":"ChargerVoltage","value":{"doubleValue":1.8149999901652336}},{"key":"MediaNowPlayingDuration","value":{"intValue":0}},{"key":"OutsideTemp","value":{"doubleValue":8.5}},{"key":"FpWindow","value":{"windowStateValue":"WindowStateClosed"}},{"key":"ClimateKeeperMode","value":{"climateKeeperModeValue":"ClimateKeeperModeStateOff"}},{"key":"ChargeEnableRequest","value":{"booleanValue":false}},{"key":"RemoteStartEnabled","value":{"booleanValue":true}},{"key":"ValetModeEnabled","value":{"booleanValue":false}},{"key":"HvacLeftTemperatureRequest","value":{"doubleValue":21.5}},{"key":"MediaPlaybackSource","value":{"stringValue":"13"}},{"key":"FdWindow","value":{"windowStateValue":"WindowStateClosed"}},{"key":"Soc","value":{"doubleValue":14.981273408239701}},{"key":"DetailedChargeState","value":{"detailedChargeStateValue":"DetailedChargeStateStopped"}},{"key":"SentryMode","value":{"sentryModeStateValue":"SentryModeStateOff"}},{"key":"LocatedAtHome","value":{"booleanValue":false}},{"key":"AutoSeatClimateLeft","value":{"booleanValue":true}},{"key":"AutoSeatClimateRight","value":{"booleanValue":false}},{"key":"MediaNowPlayingElapsed","value":{"intValue":0}},{"key":"MilesToArrival","value":{"invalid":true}},{"key":"ChargePortLatch","value":{"chargePortLatchValue":"ChargePortLatchEngaged"}},{"key":"ClimateSeatCoolingFrontRight","value":{"intValue":0}},{"key":"HvacSteeringWheelHeatLevel","value":{"intValue":0}},{"key":"DestinationName","value":{"invalid":true}},{"key":"MediaNowPlayingArtist","value":{"stringValue":""}},{"key":"TpmsPressureRr","value":{"doubleValue":3.0000000447034836}},{"key":"BatteryLevel","value":{"doubleValue":14.981273408239701}},{"key":"ACChargingPower","value":{"doubleValue":0}},{"key":"Odometer","value":{"doubleValue":32678.241257255184}},{"key":"SeatHeaterRearRight","value":{"intValue":0}},{"key":"MediaNowPlayingStation","value":{"stringValue":"Test Station"}},{"key":"DoorState","value":{"doorValue":{"DriverFront":false,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false}}}],"createdAt":"2026-10-15T00:14:38.872811608Z","vin":"TESTVIN0000000001","isResend":false} diff --git a/internal/decoder/testdata/golden/data-full.protojson.proto-names.json b/internal/decoder/testdata/golden/data-full.protojson.proto-names.json new file mode 100644 index 0000000..c8c5d46 --- /dev/null +++ b/internal/decoder/testdata/golden/data-full.protojson.proto-names.json @@ -0,0 +1 @@ +{"data":[{"key":"HvacACEnabled","value":{"boolean_value":false}},{"key":"ClimateSeatCoolingFrontLeft","value":{"int_value":0}},{"key":"MediaNowPlayingTitle","value":{"string_value":"Test Title"}},{"key":"InsideTemp","value":{"double_value":11.00000075995922}},{"key":"TimeToFullCharge","value":{"invalid":true}},{"key":"ChargeCurrentRequestMax","value":{"int_value":16}},{"key":"RouteTrafficMinutesDelay","value":{"double_value":0}},{"key":"TpmsPressureFl","value":{"double_value":2.8750000428408384}},{"key":"ChargerPhases","value":{"invalid":true}},{"key":"ChargeLimitSoc","value":{"int_value":80}},{"key":"DefrostMode","value":{"defrost_mode_value":"DefrostModeStateOff"}},{"key":"SoftwareUpdateDownloadPercentComplete","value":{"int_value":0}},{"key":"MediaAudioVolume","value":{"double_value":0.3333333333333333}},{"key":"TpmsLastSeenPressureTimeRl","value":{"long_value":"1792046866"}},{"key":"RightHandDrive","value":{"boolean_value":false}},{"key":"ExteriorColor","value":{"string_value":"SolidBlack"}},{"key":"SoftwareUpdateExpectedDurationMinutes","value":{"int_value":45}},{"key":"SoftwareUpdateVersion","value":{"string_value":" "}},{"key":"ChargePortDoorOpen","value":{"boolean_value":true}},{"key":"LifetimeEnergyUsed","value":{"double_value":16607.024788791314}},{"key":"SoftwareUpdateScheduledStartTime","value":{"invalid":true}},{"key":"SeatHeaterLeft","value":{"int_value":0}},{"key":"SeatHeaterRearLeft","value":{"int_value":0}},{"key":"DCChargingPower","value":{"double_value":0}},{"key":"ChargingCableType","value":{"cable_type_value":"CableTypeIEC"}},{"key":"Gear","value":{"invalid":true}},{"key":"IdealBatteryRange","value":{"double_value":42.4489786430281}},{"key":"VehicleSpeed","value":{"invalid":true}},{"key":"ExpectedEnergyPercentAtTripArrival","value":{"int_value":8}},{"key":"ScheduledChargingMode","value":{"scheduled_charging_mode_value":"ScheduledChargingModeOff"}},{"key":"HvacSteeringWheelHeatAuto","value":{"boolean_value":true}},{"key":"SeatHeaterRight","value":{"int_value":0}},{"key":"HvacPower","value":{"hvac_power_value":"HvacPowerStateOff"}},{"key":"TpmsPressureRl","value":{"double_value":3.0750000458210707}},{"key":"RdWindow","value":{"window_state_value":"WindowStateClosed"}},{"key":"RpWindow","value":{"window_state_value":"WindowStateClosed"}},{"key":"ScheduledChargingPending","value":{"boolean_value":false}},{"key":"SoftwareUpdateInstallationPercentComplete","value":{"int_value":1}},{"key":"DestinationLocation","value":{"location_value":{"latitude":37.4919,"longitude":-121.9447}}},{"key":"TpmsPressureFr","value":{"double_value":3.0750000458210707}},{"key":"FastChargerType","value":{"fast_charger_value":"FastChargerACSingleWireCAN"}},{"key":"Locked","value":{"boolean_value":true}},{"key":"CenterDisplay","value":{"display_state_value":"DisplayStateOff"}},{"key":"SeatHeaterRearCenter","value":{"int_value":0}},{"key":"MediaNowPlayingAlbum","value":{"string_value":""}},{"key":"TpmsLastSeenPressureTimeFl","value":{"long_value":"1792046866"}},{"key":"TpmsLastSeenPressureTimeFr","value":{"long_value":"1792046866"}},{"key":"ScheduledChargingStartTime","value":{"invalid":true}},{"key":"Version","value":{"string_value":"2026.38.3.1"}},{"key":"RoofColor","value":{"string_value":"RoofColorGlass"}},{"key":"CabinOverheatProtectionMode","value":{"cabin_overheat_protection_mode_value":"CabinOverheatProtectionModeStateOff"}},{"key":"CabinOverheatProtectionTemperatureLimit","value":{"cabin_overheat_protection_temperature_limit_value":"ClimateOverheatProtectionTempLimitHigh"}},{"key":"GuestModeEnabled","value":{"boolean_value":false}},{"key":"ChargeCurrentRequest","value":{"int_value":3}},{"key":"Location","value":{"location_value":{"latitude":37.4919,"longitude":-121.9447}}},{"key":"MinutesToArrival","value":{"invalid":true}},{"key":"BatteryHeaterOn","value":{"boolean_value":false}},{"key":"ChargeAmps","value":{"double_value":0}},{"key":"DCChargingEnergyIn","value":{"double_value":4.379999902099371}},{"key":"MediaPlaybackStatus","value":{"media_status_value":"MediaStatusStopped"}},{"key":"LocatedAtWork","value":{"boolean_value":false}},{"key":"PreconditioningEnabled","value":{"boolean_value":false}},{"key":"ACChargingEnergyIn","value":{"double_value":5.2072222998159114}},{"key":"TpmsLastSeenPressureTimeRr","value":{"long_value":"1792046866"}},{"key":"ChargerVoltage","value":{"double_value":1.8149999901652336}},{"key":"MediaNowPlayingDuration","value":{"int_value":0}},{"key":"OutsideTemp","value":{"double_value":8.5}},{"key":"FpWindow","value":{"window_state_value":"WindowStateClosed"}},{"key":"ClimateKeeperMode","value":{"climate_keeper_mode_value":"ClimateKeeperModeStateOff"}},{"key":"ChargeEnableRequest","value":{"boolean_value":false}},{"key":"RemoteStartEnabled","value":{"boolean_value":true}},{"key":"ValetModeEnabled","value":{"boolean_value":false}},{"key":"HvacLeftTemperatureRequest","value":{"double_value":21.5}},{"key":"MediaPlaybackSource","value":{"string_value":"13"}},{"key":"FdWindow","value":{"window_state_value":"WindowStateClosed"}},{"key":"Soc","value":{"double_value":14.981273408239701}},{"key":"DetailedChargeState","value":{"detailed_charge_state_value":"DetailedChargeStateStopped"}},{"key":"SentryMode","value":{"sentry_mode_state_value":"SentryModeStateOff"}},{"key":"LocatedAtHome","value":{"boolean_value":false}},{"key":"AutoSeatClimateLeft","value":{"boolean_value":true}},{"key":"AutoSeatClimateRight","value":{"boolean_value":false}},{"key":"MediaNowPlayingElapsed","value":{"int_value":0}},{"key":"MilesToArrival","value":{"invalid":true}},{"key":"ChargePortLatch","value":{"charge_port_latch_value":"ChargePortLatchEngaged"}},{"key":"ClimateSeatCoolingFrontRight","value":{"int_value":0}},{"key":"HvacSteeringWheelHeatLevel","value":{"int_value":0}},{"key":"DestinationName","value":{"invalid":true}},{"key":"MediaNowPlayingArtist","value":{"string_value":""}},{"key":"TpmsPressureRr","value":{"double_value":3.0000000447034836}},{"key":"BatteryLevel","value":{"double_value":14.981273408239701}},{"key":"ACChargingPower","value":{"double_value":0}},{"key":"Odometer","value":{"double_value":32678.241257255184}},{"key":"SeatHeaterRearRight","value":{"int_value":0}},{"key":"MediaNowPlayingStation","value":{"string_value":"Test Station"}},{"key":"DoorState","value":{"door_value":{"DriverFront":false,"DriverRear":false,"PassengerFront":false,"PassengerRear":false,"TrunkFront":false,"TrunkRear":false}}}],"created_at":"2026-10-15T00:14:38.872811608Z","vin":"TESTVIN0000000001","is_resend":false} diff --git a/internal/decoder/testdata/golden/data-full.request b/internal/decoder/testdata/golden/data-full.request new file mode 100644 index 0000000..e95f010 --- /dev/null +++ b/internal/decoder/testdata/golden/data-full.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"CgcIxAESAjAACgcI7QESAhAAChEI+AESDAoKVGVzdCBUaXRsZQoNCFUSCSkAAIAZAAAmQAoGCCsSAlABCgYINhICEBAKDgjXARIJKQAAAAAAAAAACg0IRRIJKQAAwAUAAAdACgYIMxICUAEKBggmEgIQUAoICLwBEgOgAgEKBwjYARICEAAKDgj0ARIJKVVVVVVVVdU/CgoIUxIGGJLuwdYGCgcI1gESAjAAChAIcxIMCgpTb2xpZEJsYWNrCgcI2QESAhAtCggI3AESAwoBIAoHCLcBEgIwAQoNCGYSCSkAuiOWwTfQQAoHCNsBEgJQAQoGCFcSAhAACgYIWRICEAAKDQgjEgkpAAAAAAAAAAAKCAi5ARIDyAIBCgYIChICUAEKDQgpEgkpPjTWIXg5RUAKBggEEgJQAQoHCMABEgIQCAoGCDASAmABCgcIywESAjABCgYIWBICEAAKCAjJARIDsAIBCg0IRxIJKQAAwJ+ZmQhACgcIPhIDwAEBCgcIPxIDwAEBCgYILRICMAAKBwjaARICEAEKGAhwEhQ6EgmCc0aU9r5CQBH/If32dXxewAoNCEYSCSkAAMCfmZkIQAoICMEBEgPAAgQKBgg7EgIwAQoICLYBEgP4AgEKBghbEgIQAAoHCPkBEgIKAAoKCFESBhiS7sHWBgoKCFISBhiS7sHWBgoGCCwSAlABChEIRBINCgsyMDI2LjM4LjMuMQoUCHQSEAoOUm9vZkNvbG9yR2xhc3MKCAi0ARIDkAIBCggItQESA5gCAQoGCHsSAjAACgYINRICEAMKGAgVEhQ6EgmCc0aU9r5CQBH/If32dXxewAoGCG4SAlABCgYINxICMAAKDQgxEgkpAAAAAAAAAAAKDQgiEgkpAADAsR6FEUAKCAjyARIDqAMBCgcI5gESAjAACgYILxICMAAKDQgkEgkpUdgiFTLUFEAKCghUEgYYku7B1gYKDgi4ARIJKQAAAG49Cv0/CgcI9QESAhAACg0IVhIJKQAAAAAAACFACgcIPRIDwAEBCggIugESA6gCAQoGCDISAjAACgcI1QESAjABCgcI4gESAjAACg4IyAESCSkAAAAAAIA1QAoJCPMBEgQKAjEzCgcIPBIDwAEBCg0ICBIJKeCl2Xdp9i1ACggIswESA4ACBgoGCEESAmgBCgcI5QESAjAACgYIXBICMAEKBghdEgIwAAoHCPYBEgIQAAoGCG0SAlABCgcIdhIDmAEDCgcI7gESAhAACgcIzAESAhAACgcIowESAlABCgcI9wESAgoACg0ISBIJKQAAAAYAAAhACg0IKhIJKeCl2Xdp9i1ACg0IJRIJKQAAAAAAAAAACg0IBRIJKTxFwnCP6d9ACgYIWhICEAAKEwj6ARIOCgxUZXN0IFN0YXRpb24KBwg6EgOqAQASDAjutcDWBhDYmJigAxoRVEVTVFZJTjAwMDAwMDAwMDE=","subject":"telemetry.TESTVIN0000000001.data"} diff --git a/internal/decoder/testdata/golden/data-invalid.flat.json b/internal/decoder/testdata/golden/data-invalid.flat.json new file mode 100644 index 0000000..473de6a --- /dev/null +++ b/internal/decoder/testdata/golden/data-invalid.flat.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:14.415584955Z","isResend":false,"invalid":["TpmsPressureFr"]} diff --git a/internal/decoder/testdata/golden/data-invalid.flat.proto-names.json b/internal/decoder/testdata/golden/data-invalid.flat.proto-names.json new file mode 100644 index 0000000..94c1d6d --- /dev/null +++ b/internal/decoder/testdata/golden/data-invalid.flat.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:13:14.415584955Z","is_resend":false,"invalid":["TpmsPressureFr"]} diff --git a/internal/decoder/testdata/golden/data-invalid.protojson.json b/internal/decoder/testdata/golden/data-invalid.protojson.json new file mode 100644 index 0000000..8412d6e --- /dev/null +++ b/internal/decoder/testdata/golden/data-invalid.protojson.json @@ -0,0 +1 @@ +{"data":[{"key":"TpmsPressureFr","value":{"invalid":true}}],"createdAt":"2026-10-15T00:13:14.415584955Z","vin":"TESTVIN0000000001","isResend":false} diff --git a/internal/decoder/testdata/golden/data-invalid.protojson.proto-names.json b/internal/decoder/testdata/golden/data-invalid.protojson.proto-names.json new file mode 100644 index 0000000..abd0c5f --- /dev/null +++ b/internal/decoder/testdata/golden/data-invalid.protojson.proto-names.json @@ -0,0 +1 @@ +{"data":[{"key":"TpmsPressureFr","value":{"invalid":true}}],"created_at":"2026-10-15T00:13:14.415584955Z","vin":"TESTVIN0000000001","is_resend":false} diff --git a/internal/decoder/testdata/golden/data-invalid.request b/internal/decoder/testdata/golden/data-invalid.request new file mode 100644 index 0000000..86efce9 --- /dev/null +++ b/internal/decoder/testdata/golden/data-invalid.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"CgYIRhICUAESDAiatcDWBhC7pZXGARoRVEVTVFZJTjAwMDAwMDAwMDE=","subject":"telemetry.TESTVIN0000000001.data"} diff --git a/internal/decoder/testdata/golden/data-location.flat.json b/internal/decoder/testdata/golden/data-location.flat.json new file mode 100644 index 0000000..35ddd26 --- /dev/null +++ b/internal/decoder/testdata/golden/data-location.flat.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:16.273960575Z","isResend":false,"MilesToArrival":0.962417613193002,"MinutesToArrival":3.163118386298044,"Location":{"latitude":37.4919,"longitude":-121.9447}} diff --git a/internal/decoder/testdata/golden/data-location.flat.proto-names.json b/internal/decoder/testdata/golden/data-location.flat.proto-names.json new file mode 100644 index 0000000..db8f08f --- /dev/null +++ b/internal/decoder/testdata/golden/data-location.flat.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:13:16.273960575Z","is_resend":false,"MilesToArrival":0.962417613193002,"MinutesToArrival":3.163118386298044,"Location":{"latitude":37.4919,"longitude":-121.9447}} diff --git a/internal/decoder/testdata/golden/data-location.protojson.json b/internal/decoder/testdata/golden/data-location.protojson.json new file mode 100644 index 0000000..f004fa5 --- /dev/null +++ b/internal/decoder/testdata/golden/data-location.protojson.json @@ -0,0 +1 @@ +{"data":[{"key":"MilesToArrival","value":{"doubleValue":0.962417613193002}},{"key":"MinutesToArrival","value":{"doubleValue":3.163118386298044}},{"key":"Location","value":{"locationValue":{"latitude":37.4919,"longitude":-121.9447}}}],"createdAt":"2026-10-15T00:13:16.273960575Z","vin":"TESTVIN0000000001","isResend":false} diff --git a/internal/decoder/testdata/golden/data-location.protojson.proto-names.json b/internal/decoder/testdata/golden/data-location.protojson.proto-names.json new file mode 100644 index 0000000..c064033 --- /dev/null +++ b/internal/decoder/testdata/golden/data-location.protojson.proto-names.json @@ -0,0 +1 @@ +{"data":[{"key":"MilesToArrival","value":{"double_value":0.962417613193002}},{"key":"MinutesToArrival","value":{"double_value":3.163118386298044}},{"key":"Location","value":{"location_value":{"latitude":37.4919,"longitude":-121.9447}}}],"created_at":"2026-10-15T00:13:16.273960575Z","vin":"TESTVIN0000000001","is_resend":false} diff --git a/internal/decoder/testdata/golden/data-location.request b/internal/decoder/testdata/golden/data-location.request new file mode 100644 index 0000000..7b85bad --- /dev/null +++ b/internal/decoder/testdata/golden/data-location.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"Cg0IbRIJKSxEuAUgzO4/Cg0IbhIJKQ42NAMRTglAChgIFRIUOhIJgnNGlPa+QkAR/yH99nV8XsASDAictcDWBhD/nNGCARoRVEVTVFZJTjAwMDAwMDAwMDE=","subject":"telemetry.TESTVIN0000000001.data"} diff --git a/internal/decoder/testdata/golden/data-resend.flat.json b/internal/decoder/testdata/golden/data-resend.flat.json new file mode 100644 index 0000000..095974a --- /dev/null +++ b/internal/decoder/testdata/golden/data-resend.flat.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:23.271593814Z","isResend":true,"ChargerVoltage":225.9179987758398,"ACChargingEnergyIn":22.03738921727249,"Soc":49.98139188686267,"IdealBatteryRange":121.20938357234755,"BatteryLevel":50.130256791961294} diff --git a/internal/decoder/testdata/golden/data-resend.flat.proto-names.json b/internal/decoder/testdata/golden/data-resend.flat.proto-names.json new file mode 100644 index 0000000..1c3e6ab --- /dev/null +++ b/internal/decoder/testdata/golden/data-resend.flat.proto-names.json @@ -0,0 +1 @@ +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:13:23.271593814Z","is_resend":true,"ChargerVoltage":225.9179987758398,"ACChargingEnergyIn":22.03738921727249,"Soc":49.98139188686267,"IdealBatteryRange":121.20938357234755,"BatteryLevel":50.130256791961294} diff --git a/internal/decoder/testdata/golden/data-resend.protojson.json b/internal/decoder/testdata/golden/data-resend.protojson.json new file mode 100644 index 0000000..5ae1d97 --- /dev/null +++ b/internal/decoder/testdata/golden/data-resend.protojson.json @@ -0,0 +1 @@ +{"data":[{"key":"ChargerVoltage","value":{"doubleValue":225.9179987758398}},{"key":"ACChargingEnergyIn","value":{"doubleValue":22.03738921727249}},{"key":"Soc","value":{"doubleValue":49.98139188686267}},{"key":"IdealBatteryRange","value":{"doubleValue":121.20938357234755}},{"key":"BatteryLevel","value":{"doubleValue":50.130256791961294}}],"createdAt":"2026-10-15T00:13:23.271593814Z","vin":"TESTVIN0000000001","isResend":true} diff --git a/internal/decoder/testdata/golden/data-resend.protojson.proto-names.json b/internal/decoder/testdata/golden/data-resend.protojson.proto-names.json new file mode 100644 index 0000000..e1fddae --- /dev/null +++ b/internal/decoder/testdata/golden/data-resend.protojson.proto-names.json @@ -0,0 +1 @@ +{"data":[{"key":"ChargerVoltage","value":{"double_value":225.9179987758398}},{"key":"ACChargingEnergyIn","value":{"double_value":22.03738921727249}},{"key":"Soc","value":{"double_value":49.98139188686267}},{"key":"IdealBatteryRange","value":{"double_value":121.20938357234755}},{"key":"BatteryLevel","value":{"double_value":50.130256791961294}}],"created_at":"2026-10-15T00:13:23.271593814Z","vin":"TESTVIN0000000001","is_resend":true} diff --git a/internal/decoder/testdata/golden/data-resend.request b/internal/decoder/testdata/golden/data-resend.request new file mode 100644 index 0000000..83b8e98 --- /dev/null +++ b/internal/decoder/testdata/golden/data-resend.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"Cg4IuAESCSkAAPg+YD1sQAoNCCQSCSmMaPlWkgk2QAoNCAgSCSlEUdU/nv1IQAoNCCkSCSla41qKZk1eQAoNCCoSCSkfxypBrBBJQBIMCKO1wNYGENbiwIEBGhFURVNUVklOMDAwMDAwMDAwMSAB","subject":"telemetry.TESTVIN0000000001.data"} diff --git a/internal/decoder/testdata/golden/errors-empty.flat.json b/internal/decoder/testdata/golden/errors-empty.flat.json new file mode 100644 index 0000000..5059a30 --- /dev/null +++ b/internal/decoder/testdata/golden/errors-empty.flat.json @@ -0,0 +1 @@ +{"errors":[],"createdAt":"2026-10-15T00:13:21.673998462Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/errors-empty.flat.proto-names.json b/internal/decoder/testdata/golden/errors-empty.flat.proto-names.json new file mode 100644 index 0000000..c61e608 --- /dev/null +++ b/internal/decoder/testdata/golden/errors-empty.flat.proto-names.json @@ -0,0 +1 @@ +{"errors":[],"created_at":"2026-10-15T00:13:21.673998462Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/errors-empty.protojson.json b/internal/decoder/testdata/golden/errors-empty.protojson.json new file mode 100644 index 0000000..5059a30 --- /dev/null +++ b/internal/decoder/testdata/golden/errors-empty.protojson.json @@ -0,0 +1 @@ +{"errors":[],"createdAt":"2026-10-15T00:13:21.673998462Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/errors-empty.protojson.proto-names.json b/internal/decoder/testdata/golden/errors-empty.protojson.proto-names.json new file mode 100644 index 0000000..c61e608 --- /dev/null +++ b/internal/decoder/testdata/golden/errors-empty.protojson.proto-names.json @@ -0,0 +1 @@ +{"errors":[],"created_at":"2026-10-15T00:13:21.673998462Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/errors-empty.request b/internal/decoder/testdata/golden/errors-empty.request new file mode 100644 index 0000000..4f9e430 --- /dev/null +++ b/internal/decoder/testdata/golden/errors-empty.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"EgwIobXA1gYQ/syxwQIaEVRFU1RWSU4wMDAwMDAwMDAx","subject":"telemetry.TESTVIN0000000001.errors"} diff --git a/internal/decoder/testdata/golden/errors.flat.json b/internal/decoder/testdata/golden/errors.flat.json new file mode 100644 index 0000000..97c820e --- /dev/null +++ b/internal/decoder/testdata/golden/errors.flat.json @@ -0,0 +1 @@ +{"errors":[{"createdAt":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen","name":"00000000-0000-4000-8000-000000000001"},"body":""}],"createdAt":"2026-10-15T00:10:12.617991348Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/errors.flat.proto-names.json b/internal/decoder/testdata/golden/errors.flat.proto-names.json new file mode 100644 index 0000000..5d108b3 --- /dev/null +++ b/internal/decoder/testdata/golden/errors.flat.proto-names.json @@ -0,0 +1 @@ +{"errors":[{"created_at":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen","name":"00000000-0000-4000-8000-000000000001"},"body":""}],"created_at":"2026-10-15T00:10:12.617991348Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/errors.protojson.json b/internal/decoder/testdata/golden/errors.protojson.json new file mode 100644 index 0000000..97c820e --- /dev/null +++ b/internal/decoder/testdata/golden/errors.protojson.json @@ -0,0 +1 @@ +{"errors":[{"createdAt":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen","name":"00000000-0000-4000-8000-000000000001"},"body":""}],"createdAt":"2026-10-15T00:10:12.617991348Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/errors.protojson.proto-names.json b/internal/decoder/testdata/golden/errors.protojson.proto-names.json new file mode 100644 index 0000000..5d108b3 --- /dev/null +++ b/internal/decoder/testdata/golden/errors.protojson.proto-names.json @@ -0,0 +1 @@ +{"errors":[{"created_at":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen","name":"00000000-0000-4000-8000-000000000001"},"body":""}],"created_at":"2026-10-15T00:10:12.617991348Z","vin":"TESTVIN0000000001"} diff --git a/internal/decoder/testdata/golden/errors.request b/internal/decoder/testdata/golden/errors.request new file mode 100644 index 0000000..ee3a3aa --- /dev/null +++ b/internal/decoder/testdata/golden/errors.request @@ -0,0 +1 @@ +{"headers":{"traceparent":"00-00000000000000000000000000000001-0000000000000001-00"},"payload":"CngKDAiAqMDWBhDP3ffAARIRdW5zdXBwb3J0ZWRfZmllbGQaJwoKZmllbGRfbmFtZRIZTGlmZXRpbWVFbmVyZ3lHYWluZWRSZWdlbhosCgRuYW1lEiQwMDAwMDAwMC0wMDAwLTQwMDAtODAwMC0wMDAwMDAwMDAwMDESDAjks8DWBhC0mdemAhoRVEVTVFZJTjAwMDAwMDAwMDE=","subject":"telemetry.TESTVIN0000000001.errors"} diff --git a/internal/protos/source.go b/internal/protos/source.go new file mode 100644 index 0000000..7137a9e --- /dev/null +++ b/internal/protos/source.go @@ -0,0 +1,8 @@ +// Code generated by scripts/generate.sh. DO NOT EDIT. + +// Package protos holds the Tesla Fleet Telemetry messages, generated from +// https://github.com/Teslemetry/tesla-protocol/tree/e6f7afb1b633d7215e34d0cdac66dab983c6ae78/proto/telemetry +package protos + +// TeslaProtocolCommit is the tesla-protocol commit the messages are generated from. +const TeslaProtocolCommit = "e6f7afb1b633d7215e34d0cdac66dab983c6ae78" diff --git a/internal/protos/vehicle_alert.pb.go b/internal/protos/vehicle_alert.pb.go new file mode 100644 index 0000000..9f2abfc --- /dev/null +++ b/internal/protos/vehicle_alert.pb.go @@ -0,0 +1,292 @@ +// UPSTREAM-SOURCE: teslamotors/fleet-telemetry +// UPSTREAM-PATH: protos/vehicle_alert.proto +// UPSTREAM-COMMIT: see upstream.json +// This file tracks upstream verbatim; no Teslemetry extensions. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc v7.36.2 +// source: vehicle_alert.proto + +package protos + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Audience the target audience for the alert. +type Audience int32 + +const ( + Audience_Unknown Audience = 0 + Audience_Customer Audience = 1 + Audience_Service Audience = 2 + Audience_ServiceFix Audience = 3 +) + +// Enum value maps for Audience. +var ( + Audience_name = map[int32]string{ + 0: "Unknown", + 1: "Customer", + 2: "Service", + 3: "ServiceFix", + } + Audience_value = map[string]int32{ + "Unknown": 0, + "Customer": 1, + "Service": 2, + "ServiceFix": 3, + } +) + +func (x Audience) Enum() *Audience { + p := new(Audience) + *p = x + return p +} + +func (x Audience) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Audience) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_alert_proto_enumTypes[0].Descriptor() +} + +func (Audience) Type() protoreflect.EnumType { + return &file_vehicle_alert_proto_enumTypes[0] +} + +func (x Audience) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Audience.Descriptor instead. +func (Audience) EnumDescriptor() ([]byte, []int) { + return file_vehicle_alert_proto_rawDescGZIP(), []int{0} +} + +// VehicleAlerts is a collection of recent alerts. +type VehicleAlerts struct { + state protoimpl.MessageState `protogen:"open.v1"` + Alerts []*VehicleAlert `protobuf:"bytes,1,rep,name=alerts,proto3" json:"alerts,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + Vin string `protobuf:"bytes,3,opt,name=vin,proto3" json:"vin,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VehicleAlerts) Reset() { + *x = VehicleAlerts{} + mi := &file_vehicle_alert_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VehicleAlerts) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VehicleAlerts) ProtoMessage() {} + +func (x *VehicleAlerts) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_alert_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VehicleAlerts.ProtoReflect.Descriptor instead. +func (*VehicleAlerts) Descriptor() ([]byte, []int) { + return file_vehicle_alert_proto_rawDescGZIP(), []int{0} +} + +func (x *VehicleAlerts) GetAlerts() []*VehicleAlert { + if x != nil { + return x.Alerts + } + return nil +} + +func (x *VehicleAlerts) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *VehicleAlerts) GetVin() string { + if x != nil { + return x.Vin + } + return "" +} + +// VehicleAlert is a single alert and is active if ended_at is nil. +type VehicleAlert struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Audiences []Audience `protobuf:"varint,2,rep,packed,name=audiences,proto3,enum=telemetry.vehicle_alerts.Audience" json:"audiences,omitempty"` + StartedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"` + EndedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=ended_at,json=endedAt,proto3" json:"ended_at,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VehicleAlert) Reset() { + *x = VehicleAlert{} + mi := &file_vehicle_alert_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VehicleAlert) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VehicleAlert) ProtoMessage() {} + +func (x *VehicleAlert) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_alert_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VehicleAlert.ProtoReflect.Descriptor instead. +func (*VehicleAlert) Descriptor() ([]byte, []int) { + return file_vehicle_alert_proto_rawDescGZIP(), []int{1} +} + +func (x *VehicleAlert) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *VehicleAlert) GetAudiences() []Audience { + if x != nil { + return x.Audiences + } + return nil +} + +func (x *VehicleAlert) GetStartedAt() *timestamppb.Timestamp { + if x != nil { + return x.StartedAt + } + return nil +} + +func (x *VehicleAlert) GetEndedAt() *timestamppb.Timestamp { + if x != nil { + return x.EndedAt + } + return nil +} + +var File_vehicle_alert_proto protoreflect.FileDescriptor + +const file_vehicle_alert_proto_rawDesc = "" + + "\n" + + "\x13vehicle_alert.proto\x12\x18telemetry.vehicle_alerts\x1a\x1fgoogle/protobuf/timestamp.proto\"\x9c\x01\n" + + "\rVehicleAlerts\x12>\n" + + "\x06alerts\x18\x01 \x03(\v2&.telemetry.vehicle_alerts.VehicleAlertR\x06alerts\x129\n" + + "\n" + + "created_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x10\n" + + "\x03vin\x18\x03 \x01(\tR\x03vin\"\xd6\x01\n" + + "\fVehicleAlert\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12@\n" + + "\taudiences\x18\x02 \x03(\x0e2\".telemetry.vehicle_alerts.AudienceR\taudiences\x129\n" + + "\n" + + "started_at\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x125\n" + + "\bended_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\aendedAt*B\n" + + "\bAudience\x12\v\n" + + "\aUnknown\x10\x00\x12\f\n" + + "\bCustomer\x10\x01\x12\v\n" + + "\aService\x10\x02\x12\x0e\n" + + "\n" + + "ServiceFix\x10\x03B/Z-github.com/teslamotors/fleet-telemetry/protosb\x06proto3" + +var ( + file_vehicle_alert_proto_rawDescOnce sync.Once + file_vehicle_alert_proto_rawDescData []byte +) + +func file_vehicle_alert_proto_rawDescGZIP() []byte { + file_vehicle_alert_proto_rawDescOnce.Do(func() { + file_vehicle_alert_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_vehicle_alert_proto_rawDesc), len(file_vehicle_alert_proto_rawDesc))) + }) + return file_vehicle_alert_proto_rawDescData +} + +var file_vehicle_alert_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_vehicle_alert_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_vehicle_alert_proto_goTypes = []any{ + (Audience)(0), // 0: telemetry.vehicle_alerts.Audience + (*VehicleAlerts)(nil), // 1: telemetry.vehicle_alerts.VehicleAlerts + (*VehicleAlert)(nil), // 2: telemetry.vehicle_alerts.VehicleAlert + (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp +} +var file_vehicle_alert_proto_depIdxs = []int32{ + 2, // 0: telemetry.vehicle_alerts.VehicleAlerts.alerts:type_name -> telemetry.vehicle_alerts.VehicleAlert + 3, // 1: telemetry.vehicle_alerts.VehicleAlerts.created_at:type_name -> google.protobuf.Timestamp + 0, // 2: telemetry.vehicle_alerts.VehicleAlert.audiences:type_name -> telemetry.vehicle_alerts.Audience + 3, // 3: telemetry.vehicle_alerts.VehicleAlert.started_at:type_name -> google.protobuf.Timestamp + 3, // 4: telemetry.vehicle_alerts.VehicleAlert.ended_at:type_name -> google.protobuf.Timestamp + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_vehicle_alert_proto_init() } +func file_vehicle_alert_proto_init() { + if File_vehicle_alert_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_vehicle_alert_proto_rawDesc), len(file_vehicle_alert_proto_rawDesc)), + NumEnums: 1, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_vehicle_alert_proto_goTypes, + DependencyIndexes: file_vehicle_alert_proto_depIdxs, + EnumInfos: file_vehicle_alert_proto_enumTypes, + MessageInfos: file_vehicle_alert_proto_msgTypes, + }.Build() + File_vehicle_alert_proto = out.File + file_vehicle_alert_proto_goTypes = nil + file_vehicle_alert_proto_depIdxs = nil +} diff --git a/internal/protos/vehicle_connectivity.pb.go b/internal/protos/vehicle_connectivity.pb.go new file mode 100644 index 0000000..2b42500 --- /dev/null +++ b/internal/protos/vehicle_connectivity.pb.go @@ -0,0 +1,226 @@ +// UPSTREAM-SOURCE: teslamotors/fleet-telemetry +// UPSTREAM-PATH: protos/vehicle_connectivity.proto +// UPSTREAM-COMMIT: see upstream.json +// This file tracks upstream verbatim; no Teslemetry extensions. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc v7.36.2 +// source: vehicle_connectivity.proto + +package protos + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// ConnectivityEvent represents connection state of the vehicle +type ConnectivityEvent int32 + +const ( + ConnectivityEvent_UNKNOWN ConnectivityEvent = 0 + ConnectivityEvent_CONNECTED ConnectivityEvent = 1 + ConnectivityEvent_DISCONNECTED ConnectivityEvent = 2 +) + +// Enum value maps for ConnectivityEvent. +var ( + ConnectivityEvent_name = map[int32]string{ + 0: "UNKNOWN", + 1: "CONNECTED", + 2: "DISCONNECTED", + } + ConnectivityEvent_value = map[string]int32{ + "UNKNOWN": 0, + "CONNECTED": 1, + "DISCONNECTED": 2, + } +) + +func (x ConnectivityEvent) Enum() *ConnectivityEvent { + p := new(ConnectivityEvent) + *p = x + return p +} + +func (x ConnectivityEvent) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ConnectivityEvent) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_connectivity_proto_enumTypes[0].Descriptor() +} + +func (ConnectivityEvent) Type() protoreflect.EnumType { + return &file_vehicle_connectivity_proto_enumTypes[0] +} + +func (x ConnectivityEvent) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ConnectivityEvent.Descriptor instead. +func (ConnectivityEvent) EnumDescriptor() ([]byte, []int) { + return file_vehicle_connectivity_proto_rawDescGZIP(), []int{0} +} + +// VehicleConnectivity represents connection status change for the vehicle +type VehicleConnectivity struct { + state protoimpl.MessageState `protogen:"open.v1"` + Vin string `protobuf:"bytes,1,opt,name=vin,proto3" json:"vin,omitempty"` + ConnectionId string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` + Status ConnectivityEvent `protobuf:"varint,3,opt,name=status,proto3,enum=telemetry.vehicle_connectivity.ConnectivityEvent" json:"status,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + NetworkInterface string `protobuf:"bytes,5,opt,name=network_interface,json=networkInterface,proto3" json:"network_interface,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VehicleConnectivity) Reset() { + *x = VehicleConnectivity{} + mi := &file_vehicle_connectivity_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VehicleConnectivity) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VehicleConnectivity) ProtoMessage() {} + +func (x *VehicleConnectivity) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_connectivity_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VehicleConnectivity.ProtoReflect.Descriptor instead. +func (*VehicleConnectivity) Descriptor() ([]byte, []int) { + return file_vehicle_connectivity_proto_rawDescGZIP(), []int{0} +} + +func (x *VehicleConnectivity) GetVin() string { + if x != nil { + return x.Vin + } + return "" +} + +func (x *VehicleConnectivity) GetConnectionId() string { + if x != nil { + return x.ConnectionId + } + return "" +} + +func (x *VehicleConnectivity) GetStatus() ConnectivityEvent { + if x != nil { + return x.Status + } + return ConnectivityEvent_UNKNOWN +} + +func (x *VehicleConnectivity) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *VehicleConnectivity) GetNetworkInterface() string { + if x != nil { + return x.NetworkInterface + } + return "" +} + +var File_vehicle_connectivity_proto protoreflect.FileDescriptor + +const file_vehicle_connectivity_proto_rawDesc = "" + + "\n" + + "\x1avehicle_connectivity.proto\x12\x1etelemetry.vehicle_connectivity\x1a\x1fgoogle/protobuf/timestamp.proto\"\xff\x01\n" + + "\x13VehicleConnectivity\x12\x10\n" + + "\x03vin\x18\x01 \x01(\tR\x03vin\x12#\n" + + "\rconnection_id\x18\x02 \x01(\tR\fconnectionId\x12I\n" + + "\x06status\x18\x03 \x01(\x0e21.telemetry.vehicle_connectivity.ConnectivityEventR\x06status\x129\n" + + "\n" + + "created_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12+\n" + + "\x11network_interface\x18\x05 \x01(\tR\x10networkInterface*A\n" + + "\x11ConnectivityEvent\x12\v\n" + + "\aUNKNOWN\x10\x00\x12\r\n" + + "\tCONNECTED\x10\x01\x12\x10\n" + + "\fDISCONNECTED\x10\x02B/Z-github.com/teslamotors/fleet-telemetry/protosb\x06proto3" + +var ( + file_vehicle_connectivity_proto_rawDescOnce sync.Once + file_vehicle_connectivity_proto_rawDescData []byte +) + +func file_vehicle_connectivity_proto_rawDescGZIP() []byte { + file_vehicle_connectivity_proto_rawDescOnce.Do(func() { + file_vehicle_connectivity_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_vehicle_connectivity_proto_rawDesc), len(file_vehicle_connectivity_proto_rawDesc))) + }) + return file_vehicle_connectivity_proto_rawDescData +} + +var file_vehicle_connectivity_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_vehicle_connectivity_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_vehicle_connectivity_proto_goTypes = []any{ + (ConnectivityEvent)(0), // 0: telemetry.vehicle_connectivity.ConnectivityEvent + (*VehicleConnectivity)(nil), // 1: telemetry.vehicle_connectivity.VehicleConnectivity + (*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp +} +var file_vehicle_connectivity_proto_depIdxs = []int32{ + 0, // 0: telemetry.vehicle_connectivity.VehicleConnectivity.status:type_name -> telemetry.vehicle_connectivity.ConnectivityEvent + 2, // 1: telemetry.vehicle_connectivity.VehicleConnectivity.created_at:type_name -> google.protobuf.Timestamp + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_vehicle_connectivity_proto_init() } +func file_vehicle_connectivity_proto_init() { + if File_vehicle_connectivity_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_vehicle_connectivity_proto_rawDesc), len(file_vehicle_connectivity_proto_rawDesc)), + NumEnums: 1, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_vehicle_connectivity_proto_goTypes, + DependencyIndexes: file_vehicle_connectivity_proto_depIdxs, + EnumInfos: file_vehicle_connectivity_proto_enumTypes, + MessageInfos: file_vehicle_connectivity_proto_msgTypes, + }.Build() + File_vehicle_connectivity_proto = out.File + file_vehicle_connectivity_proto_goTypes = nil + file_vehicle_connectivity_proto_depIdxs = nil +} diff --git a/internal/protos/vehicle_data.pb.go b/internal/protos/vehicle_data.pb.go new file mode 100644 index 0000000..9d27bc3 --- /dev/null +++ b/internal/protos/vehicle_data.pb.go @@ -0,0 +1,5840 @@ +// UPSTREAM-SOURCE: teslamotors/fleet-telemetry +// UPSTREAM-PATH: protos/vehicle_data.proto +// UPSTREAM-COMMIT: see upstream.json +// This file tracks upstream verbatim, plus marked Teslemetry extensions +// (TESLEMETRY-EXT); reserved numbers annotated "expected" are not-yet- +// confirmed candidates and are not active members. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc v7.36.2 +// source: vehicle_data.proto + +package protos + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Field int32 + +const ( + Field_Unknown Field = 0 + Field_DriveRail Field = 1 + Field_ChargeState Field = 2 + Field_BmsFullchargecomplete Field = 3 + Field_VehicleSpeed Field = 4 + Field_Odometer Field = 5 + Field_PackVoltage Field = 6 + Field_PackCurrent Field = 7 + Field_Soc Field = 8 + Field_DCDCEnable Field = 9 + Field_Gear Field = 10 + Field_IsolationResistance Field = 11 + Field_PedalPosition Field = 12 + Field_BrakePedal Field = 13 + Field_DiStateR Field = 14 + Field_DiHeatsinkTR Field = 15 + Field_DiAxleSpeedR Field = 16 + Field_DiTorquemotor Field = 17 + Field_DiStatorTempR Field = 18 + Field_DiVBatR Field = 19 + Field_DiMotorCurrentR Field = 20 + Field_Location Field = 21 + Field_GpsState Field = 22 + Field_GpsHeading Field = 23 + Field_NumBrickVoltageMax Field = 24 + Field_BrickVoltageMax Field = 25 + Field_NumBrickVoltageMin Field = 26 + Field_BrickVoltageMin Field = 27 + Field_NumModuleTempMax Field = 28 + Field_ModuleTempMax Field = 29 + Field_NumModuleTempMin Field = 30 + Field_ModuleTempMin Field = 31 + Field_RatedRange Field = 32 + Field_Hvil Field = 33 + Field_DCChargingEnergyIn Field = 34 + Field_DCChargingPower Field = 35 + Field_ACChargingEnergyIn Field = 36 + Field_ACChargingPower Field = 37 + Field_ChargeLimitSoc Field = 38 + Field_FastChargerPresent Field = 39 + Field_EstBatteryRange Field = 40 + Field_IdealBatteryRange Field = 41 + Field_BatteryLevel Field = 42 + Field_TimeToFullCharge Field = 43 + Field_ScheduledChargingStartTime Field = 44 + Field_ScheduledChargingPending Field = 45 + Field_ScheduledDepartureTime Field = 46 + Field_PreconditioningEnabled Field = 47 + Field_ScheduledChargingMode Field = 48 + Field_ChargeAmps Field = 49 + Field_ChargeEnableRequest Field = 50 + Field_ChargerPhases Field = 51 + Field_ChargePortColdWeatherMode Field = 52 + Field_ChargeCurrentRequest Field = 53 + Field_ChargeCurrentRequestMax Field = 54 + Field_BatteryHeaterOn Field = 55 + Field_NotEnoughPowerToHeat Field = 56 + Field_SuperchargerSessionTripPlanner Field = 57 + Field_DoorState Field = 58 + Field_Locked Field = 59 + Field_FdWindow Field = 60 + Field_FpWindow Field = 61 + Field_RdWindow Field = 62 + Field_RpWindow Field = 63 + Field_VehicleName Field = 64 + Field_SentryMode Field = 65 + Field_SpeedLimitMode Field = 66 + Field_CurrentLimitMph Field = 67 + Field_Version Field = 68 + Field_TpmsPressureFl Field = 69 + Field_TpmsPressureFr Field = 70 + Field_TpmsPressureRl Field = 71 + Field_TpmsPressureRr Field = 72 + Field_SemitruckTpmsPressureRe1L0 Field = 73 // Semi-truck only + Field_SemitruckTpmsPressureRe1L1 Field = 74 // Semi-truck only + Field_SemitruckTpmsPressureRe1R0 Field = 75 // Semi-truck only + Field_SemitruckTpmsPressureRe1R1 Field = 76 // Semi-truck only + Field_SemitruckTpmsPressureRe2L0 Field = 77 // Semi-truck only + Field_SemitruckTpmsPressureRe2L1 Field = 78 // Semi-truck only + Field_SemitruckTpmsPressureRe2R0 Field = 79 // Semi-truck only + Field_SemitruckTpmsPressureRe2R1 Field = 80 // Semi-truck only + Field_TpmsLastSeenPressureTimeFl Field = 81 + Field_TpmsLastSeenPressureTimeFr Field = 82 + Field_TpmsLastSeenPressureTimeRl Field = 83 + Field_TpmsLastSeenPressureTimeRr Field = 84 + Field_InsideTemp Field = 85 + Field_OutsideTemp Field = 86 + Field_SeatHeaterLeft Field = 87 + Field_SeatHeaterRight Field = 88 + Field_SeatHeaterRearLeft Field = 89 + Field_SeatHeaterRearRight Field = 90 + Field_SeatHeaterRearCenter Field = 91 + Field_AutoSeatClimateLeft Field = 92 + Field_AutoSeatClimateRight Field = 93 + Field_DriverSeatBelt Field = 94 + Field_PassengerSeatBelt Field = 95 + Field_DriverSeatOccupied Field = 96 + Field_SemitruckPassengerSeatFoldPosition Field = 97 // Semi-truck only + Field_LateralAcceleration Field = 98 + Field_LongitudinalAcceleration Field = 99 + Field_Deprecated_2 Field = 100 + Field_CruiseSetSpeed Field = 101 + Field_LifetimeEnergyUsed Field = 102 + Field_LifetimeEnergyUsedDrive Field = 103 // Semi-truck only + Field_SemitruckTractorParkBrakeStatus Field = 104 // Semi-truck only + Field_SemitruckTrailerParkBrakeStatus Field = 105 // Semi-truck only + Field_BrakePedalPos Field = 106 + Field_RouteLastUpdated Field = 107 // Requires firmware version 2024.26 or later + Field_RouteLine Field = 108 // Requires firmware version 2024.26 or later + Field_MilesToArrival Field = 109 // Requires firmware version 2024.26 or later + Field_MinutesToArrival Field = 110 // Requires firmware version 2024.26 or later + Field_OriginLocation Field = 111 // Requires firmware version 2024.26 or later + Field_DestinationLocation Field = 112 // Requires firmware version 2024.26 or later + Field_CarType Field = 113 + Field_Trim Field = 114 + Field_ExteriorColor Field = 115 + Field_RoofColor Field = 116 + Field_ChargePort Field = 117 + Field_ChargePortLatch Field = 118 + Field_Experimental_1 Field = 119 + Field_Experimental_2 Field = 120 + Field_Experimental_3 Field = 121 + Field_Experimental_4 Field = 122 + Field_GuestModeEnabled Field = 123 + Field_PinToDriveEnabled Field = 124 + Field_PairedPhoneKeyAndKeyFobQty Field = 125 + Field_CruiseFollowDistance Field = 126 + Field_AutomaticBlindSpotCamera Field = 127 + Field_BlindSpotCollisionWarningChime Field = 128 + Field_SpeedLimitWarning Field = 129 + Field_ForwardCollisionWarning Field = 130 + Field_LaneDepartureAvoidance Field = 131 + Field_EmergencyLaneDepartureAvoidance Field = 132 + Field_AutomaticEmergencyBrakingOff Field = 133 + Field_LifetimeEnergyGainedRegen Field = 134 + Field_DiStateF Field = 135 + Field_DiStateREL Field = 136 + Field_DiStateRER Field = 137 + Field_DiHeatsinkTF Field = 138 + Field_DiHeatsinkTREL Field = 139 + Field_DiHeatsinkTRER Field = 140 + Field_DiAxleSpeedF Field = 141 + Field_DiAxleSpeedREL Field = 142 + Field_DiAxleSpeedRER Field = 143 + Field_DiSlaveTorqueCmd Field = 144 + Field_DiTorqueActualR Field = 145 + Field_DiTorqueActualF Field = 146 + Field_DiTorqueActualREL Field = 147 + Field_DiTorqueActualRER Field = 148 + Field_DiStatorTempF Field = 149 + Field_DiStatorTempREL Field = 150 + Field_DiStatorTempRER Field = 151 + Field_DiVBatF Field = 152 + Field_DiVBatREL Field = 153 + Field_DiVBatRER Field = 154 + Field_DiMotorCurrentF Field = 155 + Field_DiMotorCurrentREL Field = 156 + Field_DiMotorCurrentRER Field = 157 + Field_EnergyRemaining Field = 158 + Field_ServiceMode Field = 159 + Field_BMSState Field = 160 + Field_GuestModeMobileAccessState Field = 161 + Field_Deprecated_1 Field = 162 + Field_DestinationName Field = 163 // Requires firmware version 2024.26 or later + Field_DiInverterTR Field = 164 + Field_DiInverterTF Field = 165 + Field_DiInverterTREL Field = 166 + Field_DiInverterTRER Field = 167 + Field_Experimental_5 Field = 168 + Field_Experimental_6 Field = 169 + Field_Experimental_7 Field = 170 + Field_Experimental_8 Field = 171 + Field_Experimental_9 Field = 172 + Field_Experimental_10 Field = 173 + Field_Experimental_11 Field = 174 + Field_Experimental_12 Field = 175 + Field_Experimental_13 Field = 176 + Field_Experimental_14 Field = 177 + Field_Experimental_15 Field = 178 + Field_DetailedChargeState Field = 179 + Field_CabinOverheatProtectionMode Field = 180 + Field_CabinOverheatProtectionTemperatureLimit Field = 181 + Field_CenterDisplay Field = 182 + Field_ChargePortDoorOpen Field = 183 + Field_ChargerVoltage Field = 184 + Field_ChargingCableType Field = 185 + Field_ClimateKeeperMode Field = 186 + Field_DefrostForPreconditioning Field = 187 + Field_DefrostMode Field = 188 + Field_EfficiencyPackage Field = 189 + Field_EstimatedHoursToChargeTermination Field = 190 + Field_EuropeVehicle Field = 191 + Field_ExpectedEnergyPercentAtTripArrival Field = 192 + Field_FastChargerType Field = 193 + Field_HomelinkDeviceCount Field = 194 + Field_HomelinkNearby Field = 195 + Field_HvacACEnabled Field = 196 + Field_HvacAutoMode Field = 197 + Field_HvacFanSpeed Field = 198 + Field_HvacFanStatus Field = 199 + Field_HvacLeftTemperatureRequest Field = 200 + Field_HvacPower Field = 201 + Field_HvacRightTemperatureRequest Field = 202 + Field_HvacSteeringWheelHeatAuto Field = 203 + Field_HvacSteeringWheelHeatLevel Field = 204 + Field_OffroadLightbarPresent Field = 205 + Field_PowershareHoursLeft Field = 206 + Field_PowershareInstantaneousPowerKW Field = 207 + Field_PowershareStatus Field = 208 + Field_PowershareStopReason Field = 209 + Field_PowershareType Field = 210 + Field_RearDisplayHvacEnabled Field = 211 + Field_RearSeatHeaters Field = 212 + Field_RemoteStartEnabled Field = 213 + Field_RightHandDrive Field = 214 + Field_RouteTrafficMinutesDelay Field = 215 + Field_SoftwareUpdateDownloadPercentComplete Field = 216 + Field_SoftwareUpdateExpectedDurationMinutes Field = 217 + Field_SoftwareUpdateInstallationPercentComplete Field = 218 + Field_SoftwareUpdateScheduledStartTime Field = 219 + Field_SoftwareUpdateVersion Field = 220 + Field_TonneauOpenPercent Field = 221 + Field_TonneauPosition Field = 222 + Field_TonneauTentMode Field = 223 + Field_TpmsHardWarnings Field = 224 + Field_TpmsSoftWarnings Field = 225 + Field_ValetModeEnabled Field = 226 + Field_WheelType Field = 227 + Field_WiperHeatEnabled Field = 228 + Field_LocatedAtHome Field = 229 + Field_LocatedAtWork Field = 230 + Field_LocatedAtFavorite Field = 231 + Field_SettingDistanceUnit Field = 232 + Field_SettingTemperatureUnit Field = 233 + Field_Setting24HourTime Field = 234 + Field_SettingTirePressureUnit Field = 235 + Field_SettingChargeUnit Field = 236 + Field_ClimateSeatCoolingFrontLeft Field = 237 + Field_ClimateSeatCoolingFrontRight Field = 238 + Field_LightsHazardsActive Field = 239 + Field_LightsTurnSignal Field = 240 + Field_LightsHighBeams Field = 241 + Field_MediaPlaybackStatus Field = 242 + Field_MediaPlaybackSource Field = 243 + Field_MediaAudioVolume Field = 244 + Field_MediaNowPlayingDuration Field = 245 + Field_MediaNowPlayingElapsed Field = 246 + Field_MediaNowPlayingArtist Field = 247 + Field_MediaNowPlayingTitle Field = 248 + Field_MediaNowPlayingAlbum Field = 249 + Field_MediaNowPlayingStation Field = 250 + Field_MediaAudioVolumeIncrement Field = 251 + Field_MediaAudioVolumeMax Field = 252 + Field_SunroofInstalled Field = 253 + Field_SeatVentEnabled Field = 254 + Field_RearDefrostEnabled Field = 255 + Field_ChargeRateMilePerHour Field = 256 + Field_Deprecated_3 Field = 257 + Field_MilesSinceReset Field = 258 + Field_SelfDrivingMilesSinceReset Field = 259 + Field_GpsAccuracyMeters Field = 260 + Field_LifetimeEnergyChargedKwh Field = 261 + Field_BrickSocMinPercent Field = 262 + Field_NominalFullPackEnergyKwh Field = 263 + Field_GradeEstimatePercent Field = 264 + Field_MaxSpeedToReachDestinationMph Field = 265 + Field_SoftwareUpdateAvailable Field = 266 + Field_SoftwareUpdateInProgress Field = 267 + Field_RemoteStartActive Field = 268 + Field_SemiCruiseSpeedLimitMph Field = 269 // Semi-truck only + Field_Cabin12vPortKeepOn Field = 270 // Semi-truck only + Field_Cabin48vPortKeepOn Field = 271 // Semi-truck only + Field_AccRail Field = 272 + Field_PowerTransferStatus Field = 273 + Field_AutomaticEmergencyBrakingState Field = 274 + Field_RollingResistanceCoefficient Field = 275 + Field_CruiseState Field = 276 + Field_LifetimeDcChargeEnergyKwh Field = 277 + Field_VehicleMassKg Field = 278 // Semi-truck only +) + +// Enum value maps for Field. +var ( + Field_name = map[int32]string{ + 0: "Unknown", + 1: "DriveRail", + 2: "ChargeState", + 3: "BmsFullchargecomplete", + 4: "VehicleSpeed", + 5: "Odometer", + 6: "PackVoltage", + 7: "PackCurrent", + 8: "Soc", + 9: "DCDCEnable", + 10: "Gear", + 11: "IsolationResistance", + 12: "PedalPosition", + 13: "BrakePedal", + 14: "DiStateR", + 15: "DiHeatsinkTR", + 16: "DiAxleSpeedR", + 17: "DiTorquemotor", + 18: "DiStatorTempR", + 19: "DiVBatR", + 20: "DiMotorCurrentR", + 21: "Location", + 22: "GpsState", + 23: "GpsHeading", + 24: "NumBrickVoltageMax", + 25: "BrickVoltageMax", + 26: "NumBrickVoltageMin", + 27: "BrickVoltageMin", + 28: "NumModuleTempMax", + 29: "ModuleTempMax", + 30: "NumModuleTempMin", + 31: "ModuleTempMin", + 32: "RatedRange", + 33: "Hvil", + 34: "DCChargingEnergyIn", + 35: "DCChargingPower", + 36: "ACChargingEnergyIn", + 37: "ACChargingPower", + 38: "ChargeLimitSoc", + 39: "FastChargerPresent", + 40: "EstBatteryRange", + 41: "IdealBatteryRange", + 42: "BatteryLevel", + 43: "TimeToFullCharge", + 44: "ScheduledChargingStartTime", + 45: "ScheduledChargingPending", + 46: "ScheduledDepartureTime", + 47: "PreconditioningEnabled", + 48: "ScheduledChargingMode", + 49: "ChargeAmps", + 50: "ChargeEnableRequest", + 51: "ChargerPhases", + 52: "ChargePortColdWeatherMode", + 53: "ChargeCurrentRequest", + 54: "ChargeCurrentRequestMax", + 55: "BatteryHeaterOn", + 56: "NotEnoughPowerToHeat", + 57: "SuperchargerSessionTripPlanner", + 58: "DoorState", + 59: "Locked", + 60: "FdWindow", + 61: "FpWindow", + 62: "RdWindow", + 63: "RpWindow", + 64: "VehicleName", + 65: "SentryMode", + 66: "SpeedLimitMode", + 67: "CurrentLimitMph", + 68: "Version", + 69: "TpmsPressureFl", + 70: "TpmsPressureFr", + 71: "TpmsPressureRl", + 72: "TpmsPressureRr", + 73: "SemitruckTpmsPressureRe1L0", + 74: "SemitruckTpmsPressureRe1L1", + 75: "SemitruckTpmsPressureRe1R0", + 76: "SemitruckTpmsPressureRe1R1", + 77: "SemitruckTpmsPressureRe2L0", + 78: "SemitruckTpmsPressureRe2L1", + 79: "SemitruckTpmsPressureRe2R0", + 80: "SemitruckTpmsPressureRe2R1", + 81: "TpmsLastSeenPressureTimeFl", + 82: "TpmsLastSeenPressureTimeFr", + 83: "TpmsLastSeenPressureTimeRl", + 84: "TpmsLastSeenPressureTimeRr", + 85: "InsideTemp", + 86: "OutsideTemp", + 87: "SeatHeaterLeft", + 88: "SeatHeaterRight", + 89: "SeatHeaterRearLeft", + 90: "SeatHeaterRearRight", + 91: "SeatHeaterRearCenter", + 92: "AutoSeatClimateLeft", + 93: "AutoSeatClimateRight", + 94: "DriverSeatBelt", + 95: "PassengerSeatBelt", + 96: "DriverSeatOccupied", + 97: "SemitruckPassengerSeatFoldPosition", + 98: "LateralAcceleration", + 99: "LongitudinalAcceleration", + 100: "Deprecated_2", + 101: "CruiseSetSpeed", + 102: "LifetimeEnergyUsed", + 103: "LifetimeEnergyUsedDrive", + 104: "SemitruckTractorParkBrakeStatus", + 105: "SemitruckTrailerParkBrakeStatus", + 106: "BrakePedalPos", + 107: "RouteLastUpdated", + 108: "RouteLine", + 109: "MilesToArrival", + 110: "MinutesToArrival", + 111: "OriginLocation", + 112: "DestinationLocation", + 113: "CarType", + 114: "Trim", + 115: "ExteriorColor", + 116: "RoofColor", + 117: "ChargePort", + 118: "ChargePortLatch", + 119: "Experimental_1", + 120: "Experimental_2", + 121: "Experimental_3", + 122: "Experimental_4", + 123: "GuestModeEnabled", + 124: "PinToDriveEnabled", + 125: "PairedPhoneKeyAndKeyFobQty", + 126: "CruiseFollowDistance", + 127: "AutomaticBlindSpotCamera", + 128: "BlindSpotCollisionWarningChime", + 129: "SpeedLimitWarning", + 130: "ForwardCollisionWarning", + 131: "LaneDepartureAvoidance", + 132: "EmergencyLaneDepartureAvoidance", + 133: "AutomaticEmergencyBrakingOff", + 134: "LifetimeEnergyGainedRegen", + 135: "DiStateF", + 136: "DiStateREL", + 137: "DiStateRER", + 138: "DiHeatsinkTF", + 139: "DiHeatsinkTREL", + 140: "DiHeatsinkTRER", + 141: "DiAxleSpeedF", + 142: "DiAxleSpeedREL", + 143: "DiAxleSpeedRER", + 144: "DiSlaveTorqueCmd", + 145: "DiTorqueActualR", + 146: "DiTorqueActualF", + 147: "DiTorqueActualREL", + 148: "DiTorqueActualRER", + 149: "DiStatorTempF", + 150: "DiStatorTempREL", + 151: "DiStatorTempRER", + 152: "DiVBatF", + 153: "DiVBatREL", + 154: "DiVBatRER", + 155: "DiMotorCurrentF", + 156: "DiMotorCurrentREL", + 157: "DiMotorCurrentRER", + 158: "EnergyRemaining", + 159: "ServiceMode", + 160: "BMSState", + 161: "GuestModeMobileAccessState", + 162: "Deprecated_1", + 163: "DestinationName", + 164: "DiInverterTR", + 165: "DiInverterTF", + 166: "DiInverterTREL", + 167: "DiInverterTRER", + 168: "Experimental_5", + 169: "Experimental_6", + 170: "Experimental_7", + 171: "Experimental_8", + 172: "Experimental_9", + 173: "Experimental_10", + 174: "Experimental_11", + 175: "Experimental_12", + 176: "Experimental_13", + 177: "Experimental_14", + 178: "Experimental_15", + 179: "DetailedChargeState", + 180: "CabinOverheatProtectionMode", + 181: "CabinOverheatProtectionTemperatureLimit", + 182: "CenterDisplay", + 183: "ChargePortDoorOpen", + 184: "ChargerVoltage", + 185: "ChargingCableType", + 186: "ClimateKeeperMode", + 187: "DefrostForPreconditioning", + 188: "DefrostMode", + 189: "EfficiencyPackage", + 190: "EstimatedHoursToChargeTermination", + 191: "EuropeVehicle", + 192: "ExpectedEnergyPercentAtTripArrival", + 193: "FastChargerType", + 194: "HomelinkDeviceCount", + 195: "HomelinkNearby", + 196: "HvacACEnabled", + 197: "HvacAutoMode", + 198: "HvacFanSpeed", + 199: "HvacFanStatus", + 200: "HvacLeftTemperatureRequest", + 201: "HvacPower", + 202: "HvacRightTemperatureRequest", + 203: "HvacSteeringWheelHeatAuto", + 204: "HvacSteeringWheelHeatLevel", + 205: "OffroadLightbarPresent", + 206: "PowershareHoursLeft", + 207: "PowershareInstantaneousPowerKW", + 208: "PowershareStatus", + 209: "PowershareStopReason", + 210: "PowershareType", + 211: "RearDisplayHvacEnabled", + 212: "RearSeatHeaters", + 213: "RemoteStartEnabled", + 214: "RightHandDrive", + 215: "RouteTrafficMinutesDelay", + 216: "SoftwareUpdateDownloadPercentComplete", + 217: "SoftwareUpdateExpectedDurationMinutes", + 218: "SoftwareUpdateInstallationPercentComplete", + 219: "SoftwareUpdateScheduledStartTime", + 220: "SoftwareUpdateVersion", + 221: "TonneauOpenPercent", + 222: "TonneauPosition", + 223: "TonneauTentMode", + 224: "TpmsHardWarnings", + 225: "TpmsSoftWarnings", + 226: "ValetModeEnabled", + 227: "WheelType", + 228: "WiperHeatEnabled", + 229: "LocatedAtHome", + 230: "LocatedAtWork", + 231: "LocatedAtFavorite", + 232: "SettingDistanceUnit", + 233: "SettingTemperatureUnit", + 234: "Setting24HourTime", + 235: "SettingTirePressureUnit", + 236: "SettingChargeUnit", + 237: "ClimateSeatCoolingFrontLeft", + 238: "ClimateSeatCoolingFrontRight", + 239: "LightsHazardsActive", + 240: "LightsTurnSignal", + 241: "LightsHighBeams", + 242: "MediaPlaybackStatus", + 243: "MediaPlaybackSource", + 244: "MediaAudioVolume", + 245: "MediaNowPlayingDuration", + 246: "MediaNowPlayingElapsed", + 247: "MediaNowPlayingArtist", + 248: "MediaNowPlayingTitle", + 249: "MediaNowPlayingAlbum", + 250: "MediaNowPlayingStation", + 251: "MediaAudioVolumeIncrement", + 252: "MediaAudioVolumeMax", + 253: "SunroofInstalled", + 254: "SeatVentEnabled", + 255: "RearDefrostEnabled", + 256: "ChargeRateMilePerHour", + 257: "Deprecated_3", + 258: "MilesSinceReset", + 259: "SelfDrivingMilesSinceReset", + 260: "GpsAccuracyMeters", + 261: "LifetimeEnergyChargedKwh", + 262: "BrickSocMinPercent", + 263: "NominalFullPackEnergyKwh", + 264: "GradeEstimatePercent", + 265: "MaxSpeedToReachDestinationMph", + 266: "SoftwareUpdateAvailable", + 267: "SoftwareUpdateInProgress", + 268: "RemoteStartActive", + 269: "SemiCruiseSpeedLimitMph", + 270: "Cabin12vPortKeepOn", + 271: "Cabin48vPortKeepOn", + 272: "AccRail", + 273: "PowerTransferStatus", + 274: "AutomaticEmergencyBrakingState", + 275: "RollingResistanceCoefficient", + 276: "CruiseState", + 277: "LifetimeDcChargeEnergyKwh", + 278: "VehicleMassKg", + } + Field_value = map[string]int32{ + "Unknown": 0, + "DriveRail": 1, + "ChargeState": 2, + "BmsFullchargecomplete": 3, + "VehicleSpeed": 4, + "Odometer": 5, + "PackVoltage": 6, + "PackCurrent": 7, + "Soc": 8, + "DCDCEnable": 9, + "Gear": 10, + "IsolationResistance": 11, + "PedalPosition": 12, + "BrakePedal": 13, + "DiStateR": 14, + "DiHeatsinkTR": 15, + "DiAxleSpeedR": 16, + "DiTorquemotor": 17, + "DiStatorTempR": 18, + "DiVBatR": 19, + "DiMotorCurrentR": 20, + "Location": 21, + "GpsState": 22, + "GpsHeading": 23, + "NumBrickVoltageMax": 24, + "BrickVoltageMax": 25, + "NumBrickVoltageMin": 26, + "BrickVoltageMin": 27, + "NumModuleTempMax": 28, + "ModuleTempMax": 29, + "NumModuleTempMin": 30, + "ModuleTempMin": 31, + "RatedRange": 32, + "Hvil": 33, + "DCChargingEnergyIn": 34, + "DCChargingPower": 35, + "ACChargingEnergyIn": 36, + "ACChargingPower": 37, + "ChargeLimitSoc": 38, + "FastChargerPresent": 39, + "EstBatteryRange": 40, + "IdealBatteryRange": 41, + "BatteryLevel": 42, + "TimeToFullCharge": 43, + "ScheduledChargingStartTime": 44, + "ScheduledChargingPending": 45, + "ScheduledDepartureTime": 46, + "PreconditioningEnabled": 47, + "ScheduledChargingMode": 48, + "ChargeAmps": 49, + "ChargeEnableRequest": 50, + "ChargerPhases": 51, + "ChargePortColdWeatherMode": 52, + "ChargeCurrentRequest": 53, + "ChargeCurrentRequestMax": 54, + "BatteryHeaterOn": 55, + "NotEnoughPowerToHeat": 56, + "SuperchargerSessionTripPlanner": 57, + "DoorState": 58, + "Locked": 59, + "FdWindow": 60, + "FpWindow": 61, + "RdWindow": 62, + "RpWindow": 63, + "VehicleName": 64, + "SentryMode": 65, + "SpeedLimitMode": 66, + "CurrentLimitMph": 67, + "Version": 68, + "TpmsPressureFl": 69, + "TpmsPressureFr": 70, + "TpmsPressureRl": 71, + "TpmsPressureRr": 72, + "SemitruckTpmsPressureRe1L0": 73, + "SemitruckTpmsPressureRe1L1": 74, + "SemitruckTpmsPressureRe1R0": 75, + "SemitruckTpmsPressureRe1R1": 76, + "SemitruckTpmsPressureRe2L0": 77, + "SemitruckTpmsPressureRe2L1": 78, + "SemitruckTpmsPressureRe2R0": 79, + "SemitruckTpmsPressureRe2R1": 80, + "TpmsLastSeenPressureTimeFl": 81, + "TpmsLastSeenPressureTimeFr": 82, + "TpmsLastSeenPressureTimeRl": 83, + "TpmsLastSeenPressureTimeRr": 84, + "InsideTemp": 85, + "OutsideTemp": 86, + "SeatHeaterLeft": 87, + "SeatHeaterRight": 88, + "SeatHeaterRearLeft": 89, + "SeatHeaterRearRight": 90, + "SeatHeaterRearCenter": 91, + "AutoSeatClimateLeft": 92, + "AutoSeatClimateRight": 93, + "DriverSeatBelt": 94, + "PassengerSeatBelt": 95, + "DriverSeatOccupied": 96, + "SemitruckPassengerSeatFoldPosition": 97, + "LateralAcceleration": 98, + "LongitudinalAcceleration": 99, + "Deprecated_2": 100, + "CruiseSetSpeed": 101, + "LifetimeEnergyUsed": 102, + "LifetimeEnergyUsedDrive": 103, + "SemitruckTractorParkBrakeStatus": 104, + "SemitruckTrailerParkBrakeStatus": 105, + "BrakePedalPos": 106, + "RouteLastUpdated": 107, + "RouteLine": 108, + "MilesToArrival": 109, + "MinutesToArrival": 110, + "OriginLocation": 111, + "DestinationLocation": 112, + "CarType": 113, + "Trim": 114, + "ExteriorColor": 115, + "RoofColor": 116, + "ChargePort": 117, + "ChargePortLatch": 118, + "Experimental_1": 119, + "Experimental_2": 120, + "Experimental_3": 121, + "Experimental_4": 122, + "GuestModeEnabled": 123, + "PinToDriveEnabled": 124, + "PairedPhoneKeyAndKeyFobQty": 125, + "CruiseFollowDistance": 126, + "AutomaticBlindSpotCamera": 127, + "BlindSpotCollisionWarningChime": 128, + "SpeedLimitWarning": 129, + "ForwardCollisionWarning": 130, + "LaneDepartureAvoidance": 131, + "EmergencyLaneDepartureAvoidance": 132, + "AutomaticEmergencyBrakingOff": 133, + "LifetimeEnergyGainedRegen": 134, + "DiStateF": 135, + "DiStateREL": 136, + "DiStateRER": 137, + "DiHeatsinkTF": 138, + "DiHeatsinkTREL": 139, + "DiHeatsinkTRER": 140, + "DiAxleSpeedF": 141, + "DiAxleSpeedREL": 142, + "DiAxleSpeedRER": 143, + "DiSlaveTorqueCmd": 144, + "DiTorqueActualR": 145, + "DiTorqueActualF": 146, + "DiTorqueActualREL": 147, + "DiTorqueActualRER": 148, + "DiStatorTempF": 149, + "DiStatorTempREL": 150, + "DiStatorTempRER": 151, + "DiVBatF": 152, + "DiVBatREL": 153, + "DiVBatRER": 154, + "DiMotorCurrentF": 155, + "DiMotorCurrentREL": 156, + "DiMotorCurrentRER": 157, + "EnergyRemaining": 158, + "ServiceMode": 159, + "BMSState": 160, + "GuestModeMobileAccessState": 161, + "Deprecated_1": 162, + "DestinationName": 163, + "DiInverterTR": 164, + "DiInverterTF": 165, + "DiInverterTREL": 166, + "DiInverterTRER": 167, + "Experimental_5": 168, + "Experimental_6": 169, + "Experimental_7": 170, + "Experimental_8": 171, + "Experimental_9": 172, + "Experimental_10": 173, + "Experimental_11": 174, + "Experimental_12": 175, + "Experimental_13": 176, + "Experimental_14": 177, + "Experimental_15": 178, + "DetailedChargeState": 179, + "CabinOverheatProtectionMode": 180, + "CabinOverheatProtectionTemperatureLimit": 181, + "CenterDisplay": 182, + "ChargePortDoorOpen": 183, + "ChargerVoltage": 184, + "ChargingCableType": 185, + "ClimateKeeperMode": 186, + "DefrostForPreconditioning": 187, + "DefrostMode": 188, + "EfficiencyPackage": 189, + "EstimatedHoursToChargeTermination": 190, + "EuropeVehicle": 191, + "ExpectedEnergyPercentAtTripArrival": 192, + "FastChargerType": 193, + "HomelinkDeviceCount": 194, + "HomelinkNearby": 195, + "HvacACEnabled": 196, + "HvacAutoMode": 197, + "HvacFanSpeed": 198, + "HvacFanStatus": 199, + "HvacLeftTemperatureRequest": 200, + "HvacPower": 201, + "HvacRightTemperatureRequest": 202, + "HvacSteeringWheelHeatAuto": 203, + "HvacSteeringWheelHeatLevel": 204, + "OffroadLightbarPresent": 205, + "PowershareHoursLeft": 206, + "PowershareInstantaneousPowerKW": 207, + "PowershareStatus": 208, + "PowershareStopReason": 209, + "PowershareType": 210, + "RearDisplayHvacEnabled": 211, + "RearSeatHeaters": 212, + "RemoteStartEnabled": 213, + "RightHandDrive": 214, + "RouteTrafficMinutesDelay": 215, + "SoftwareUpdateDownloadPercentComplete": 216, + "SoftwareUpdateExpectedDurationMinutes": 217, + "SoftwareUpdateInstallationPercentComplete": 218, + "SoftwareUpdateScheduledStartTime": 219, + "SoftwareUpdateVersion": 220, + "TonneauOpenPercent": 221, + "TonneauPosition": 222, + "TonneauTentMode": 223, + "TpmsHardWarnings": 224, + "TpmsSoftWarnings": 225, + "ValetModeEnabled": 226, + "WheelType": 227, + "WiperHeatEnabled": 228, + "LocatedAtHome": 229, + "LocatedAtWork": 230, + "LocatedAtFavorite": 231, + "SettingDistanceUnit": 232, + "SettingTemperatureUnit": 233, + "Setting24HourTime": 234, + "SettingTirePressureUnit": 235, + "SettingChargeUnit": 236, + "ClimateSeatCoolingFrontLeft": 237, + "ClimateSeatCoolingFrontRight": 238, + "LightsHazardsActive": 239, + "LightsTurnSignal": 240, + "LightsHighBeams": 241, + "MediaPlaybackStatus": 242, + "MediaPlaybackSource": 243, + "MediaAudioVolume": 244, + "MediaNowPlayingDuration": 245, + "MediaNowPlayingElapsed": 246, + "MediaNowPlayingArtist": 247, + "MediaNowPlayingTitle": 248, + "MediaNowPlayingAlbum": 249, + "MediaNowPlayingStation": 250, + "MediaAudioVolumeIncrement": 251, + "MediaAudioVolumeMax": 252, + "SunroofInstalled": 253, + "SeatVentEnabled": 254, + "RearDefrostEnabled": 255, + "ChargeRateMilePerHour": 256, + "Deprecated_3": 257, + "MilesSinceReset": 258, + "SelfDrivingMilesSinceReset": 259, + "GpsAccuracyMeters": 260, + "LifetimeEnergyChargedKwh": 261, + "BrickSocMinPercent": 262, + "NominalFullPackEnergyKwh": 263, + "GradeEstimatePercent": 264, + "MaxSpeedToReachDestinationMph": 265, + "SoftwareUpdateAvailable": 266, + "SoftwareUpdateInProgress": 267, + "RemoteStartActive": 268, + "SemiCruiseSpeedLimitMph": 269, + "Cabin12vPortKeepOn": 270, + "Cabin48vPortKeepOn": 271, + "AccRail": 272, + "PowerTransferStatus": 273, + "AutomaticEmergencyBrakingState": 274, + "RollingResistanceCoefficient": 275, + "CruiseState": 276, + "LifetimeDcChargeEnergyKwh": 277, + "VehicleMassKg": 278, + } +) + +func (x Field) Enum() *Field { + p := new(Field) + *p = x + return p +} + +func (x Field) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Field) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[0].Descriptor() +} + +func (Field) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[0] +} + +func (x Field) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Field.Descriptor instead. +func (Field) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{0} +} + +// ChargingState is deprecated and not used +type ChargingState int32 + +const ( + ChargingState_ChargeStateUnknown ChargingState = 0 + ChargingState_ChargeStateDisconnected ChargingState = 1 + ChargingState_ChargeStateNoPower ChargingState = 2 + ChargingState_ChargeStateStarting ChargingState = 3 + ChargingState_ChargeStateCharging ChargingState = 4 + ChargingState_ChargeStateComplete ChargingState = 5 + ChargingState_ChargeStateStopped ChargingState = 6 +) + +// Enum value maps for ChargingState. +var ( + ChargingState_name = map[int32]string{ + 0: "ChargeStateUnknown", + 1: "ChargeStateDisconnected", + 2: "ChargeStateNoPower", + 3: "ChargeStateStarting", + 4: "ChargeStateCharging", + 5: "ChargeStateComplete", + 6: "ChargeStateStopped", + } + ChargingState_value = map[string]int32{ + "ChargeStateUnknown": 0, + "ChargeStateDisconnected": 1, + "ChargeStateNoPower": 2, + "ChargeStateStarting": 3, + "ChargeStateCharging": 4, + "ChargeStateComplete": 5, + "ChargeStateStopped": 6, + } +) + +func (x ChargingState) Enum() *ChargingState { + p := new(ChargingState) + *p = x + return p +} + +func (x ChargingState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ChargingState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[1].Descriptor() +} + +func (ChargingState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[1] +} + +func (x ChargingState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ChargingState.Descriptor instead. +func (ChargingState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{1} +} + +type DetailedChargeStateValue int32 + +const ( + DetailedChargeStateValue_DetailedChargeStateUnknown DetailedChargeStateValue = 0 + DetailedChargeStateValue_DetailedChargeStateDisconnected DetailedChargeStateValue = 1 + DetailedChargeStateValue_DetailedChargeStateNoPower DetailedChargeStateValue = 2 + DetailedChargeStateValue_DetailedChargeStateStarting DetailedChargeStateValue = 3 + DetailedChargeStateValue_DetailedChargeStateCharging DetailedChargeStateValue = 4 + DetailedChargeStateValue_DetailedChargeStateComplete DetailedChargeStateValue = 5 + DetailedChargeStateValue_DetailedChargeStateStopped DetailedChargeStateValue = 6 + DetailedChargeStateValue_DetailedChargeStateCalibrating DetailedChargeStateValue = 7 // TESLEMETRY-EXT (teslamotors/vehicle-command ChargeState.ChargingState.Calibrating=8, offset -1 to match this enum's established numbering) +) + +// Enum value maps for DetailedChargeStateValue. +var ( + DetailedChargeStateValue_name = map[int32]string{ + 0: "DetailedChargeStateUnknown", + 1: "DetailedChargeStateDisconnected", + 2: "DetailedChargeStateNoPower", + 3: "DetailedChargeStateStarting", + 4: "DetailedChargeStateCharging", + 5: "DetailedChargeStateComplete", + 6: "DetailedChargeStateStopped", + 7: "DetailedChargeStateCalibrating", + } + DetailedChargeStateValue_value = map[string]int32{ + "DetailedChargeStateUnknown": 0, + "DetailedChargeStateDisconnected": 1, + "DetailedChargeStateNoPower": 2, + "DetailedChargeStateStarting": 3, + "DetailedChargeStateCharging": 4, + "DetailedChargeStateComplete": 5, + "DetailedChargeStateStopped": 6, + "DetailedChargeStateCalibrating": 7, + } +) + +func (x DetailedChargeStateValue) Enum() *DetailedChargeStateValue { + p := new(DetailedChargeStateValue) + *p = x + return p +} + +func (x DetailedChargeStateValue) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DetailedChargeStateValue) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[2].Descriptor() +} + +func (DetailedChargeStateValue) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[2] +} + +func (x DetailedChargeStateValue) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DetailedChargeStateValue.Descriptor instead. +func (DetailedChargeStateValue) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{2} +} + +// ShiftState are the gear options +type ShiftState int32 + +const ( + ShiftState_ShiftStateUnknown ShiftState = 0 + ShiftState_ShiftStateInvalid ShiftState = 1 + ShiftState_ShiftStateP ShiftState = 2 + ShiftState_ShiftStateR ShiftState = 3 + ShiftState_ShiftStateN ShiftState = 4 + ShiftState_ShiftStateD ShiftState = 5 + ShiftState_ShiftStateSNA ShiftState = 6 +) + +// Enum value maps for ShiftState. +var ( + ShiftState_name = map[int32]string{ + 0: "ShiftStateUnknown", + 1: "ShiftStateInvalid", + 2: "ShiftStateP", + 3: "ShiftStateR", + 4: "ShiftStateN", + 5: "ShiftStateD", + 6: "ShiftStateSNA", + } + ShiftState_value = map[string]int32{ + "ShiftStateUnknown": 0, + "ShiftStateInvalid": 1, + "ShiftStateP": 2, + "ShiftStateR": 3, + "ShiftStateN": 4, + "ShiftStateD": 5, + "ShiftStateSNA": 6, + } +) + +func (x ShiftState) Enum() *ShiftState { + p := new(ShiftState) + *p = x + return p +} + +func (x ShiftState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ShiftState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[3].Descriptor() +} + +func (ShiftState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[3] +} + +func (x ShiftState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ShiftState.Descriptor instead. +func (ShiftState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{3} +} + +type FollowDistance int32 + +const ( + FollowDistance_FollowDistanceUnknown FollowDistance = 0 + FollowDistance_FollowDistance1 FollowDistance = 1 + FollowDistance_FollowDistance2 FollowDistance = 2 + FollowDistance_FollowDistance3 FollowDistance = 3 + FollowDistance_FollowDistance4 FollowDistance = 4 + FollowDistance_FollowDistance5 FollowDistance = 5 + FollowDistance_FollowDistance6 FollowDistance = 6 + FollowDistance_FollowDistance7 FollowDistance = 7 +) + +// Enum value maps for FollowDistance. +var ( + FollowDistance_name = map[int32]string{ + 0: "FollowDistanceUnknown", + 1: "FollowDistance1", + 2: "FollowDistance2", + 3: "FollowDistance3", + 4: "FollowDistance4", + 5: "FollowDistance5", + 6: "FollowDistance6", + 7: "FollowDistance7", + } + FollowDistance_value = map[string]int32{ + "FollowDistanceUnknown": 0, + "FollowDistance1": 1, + "FollowDistance2": 2, + "FollowDistance3": 3, + "FollowDistance4": 4, + "FollowDistance5": 5, + "FollowDistance6": 6, + "FollowDistance7": 7, + } +) + +func (x FollowDistance) Enum() *FollowDistance { + p := new(FollowDistance) + *p = x + return p +} + +func (x FollowDistance) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FollowDistance) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[4].Descriptor() +} + +func (FollowDistance) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[4] +} + +func (x FollowDistance) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use FollowDistance.Descriptor instead. +func (FollowDistance) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{4} +} + +type ForwardCollisionSensitivity int32 + +const ( + ForwardCollisionSensitivity_ForwardCollisionSensitivityUnknown ForwardCollisionSensitivity = 0 + ForwardCollisionSensitivity_ForwardCollisionSensitivityOff ForwardCollisionSensitivity = 1 + ForwardCollisionSensitivity_ForwardCollisionSensitivityLate ForwardCollisionSensitivity = 2 + ForwardCollisionSensitivity_ForwardCollisionSensitivityAverage ForwardCollisionSensitivity = 3 + ForwardCollisionSensitivity_ForwardCollisionSensitivityEarly ForwardCollisionSensitivity = 4 +) + +// Enum value maps for ForwardCollisionSensitivity. +var ( + ForwardCollisionSensitivity_name = map[int32]string{ + 0: "ForwardCollisionSensitivityUnknown", + 1: "ForwardCollisionSensitivityOff", + 2: "ForwardCollisionSensitivityLate", + 3: "ForwardCollisionSensitivityAverage", + 4: "ForwardCollisionSensitivityEarly", + } + ForwardCollisionSensitivity_value = map[string]int32{ + "ForwardCollisionSensitivityUnknown": 0, + "ForwardCollisionSensitivityOff": 1, + "ForwardCollisionSensitivityLate": 2, + "ForwardCollisionSensitivityAverage": 3, + "ForwardCollisionSensitivityEarly": 4, + } +) + +func (x ForwardCollisionSensitivity) Enum() *ForwardCollisionSensitivity { + p := new(ForwardCollisionSensitivity) + *p = x + return p +} + +func (x ForwardCollisionSensitivity) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ForwardCollisionSensitivity) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[5].Descriptor() +} + +func (ForwardCollisionSensitivity) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[5] +} + +func (x ForwardCollisionSensitivity) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ForwardCollisionSensitivity.Descriptor instead. +func (ForwardCollisionSensitivity) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{5} +} + +type GuestModeMobileAccess int32 + +const ( + GuestModeMobileAccess_GuestModeMobileAccessUnknown GuestModeMobileAccess = 0 + GuestModeMobileAccess_GuestModeMobileAccessInit GuestModeMobileAccess = 1 + GuestModeMobileAccess_GuestModeMobileAccessNotAuthenticated GuestModeMobileAccess = 2 + GuestModeMobileAccess_GuestModeMobileAccessAuthenticated GuestModeMobileAccess = 3 + GuestModeMobileAccess_GuestModeMobileAccessAbortedDriving GuestModeMobileAccess = 4 + GuestModeMobileAccess_GuestModeMobileAccessAbortedUsingRemoteStart GuestModeMobileAccess = 5 + GuestModeMobileAccess_GuestModeMobileAccessAbortedUsingBLEKeys GuestModeMobileAccess = 6 + GuestModeMobileAccess_GuestModeMobileAccessAbortedValetMode GuestModeMobileAccess = 7 + GuestModeMobileAccess_GuestModeMobileAccessAbortedGuestModeOff GuestModeMobileAccess = 8 + GuestModeMobileAccess_GuestModeMobileAccessAbortedDriveAuthTimeExceeded GuestModeMobileAccess = 9 + GuestModeMobileAccess_GuestModeMobileAccessAbortedNoDataReceived GuestModeMobileAccess = 10 + GuestModeMobileAccess_GuestModeMobileAccessRequestingFromMothership GuestModeMobileAccess = 11 + GuestModeMobileAccess_GuestModeMobileAccessRequestingFromAuthD GuestModeMobileAccess = 12 + GuestModeMobileAccess_GuestModeMobileAccessAbortedFetchFailed GuestModeMobileAccess = 13 + GuestModeMobileAccess_GuestModeMobileAccessAbortedBadDataReceived GuestModeMobileAccess = 14 + GuestModeMobileAccess_GuestModeMobileAccessShowingQRCode GuestModeMobileAccess = 15 + GuestModeMobileAccess_GuestModeMobileAccessSwipedAway GuestModeMobileAccess = 16 + GuestModeMobileAccess_GuestModeMobileAccessDismissedQRCodeExpired GuestModeMobileAccess = 17 + GuestModeMobileAccess_GuestModeMobileAccessSucceededPairedNewBLEKey GuestModeMobileAccess = 18 +) + +// Enum value maps for GuestModeMobileAccess. +var ( + GuestModeMobileAccess_name = map[int32]string{ + 0: "GuestModeMobileAccessUnknown", + 1: "GuestModeMobileAccessInit", + 2: "GuestModeMobileAccessNotAuthenticated", + 3: "GuestModeMobileAccessAuthenticated", + 4: "GuestModeMobileAccessAbortedDriving", + 5: "GuestModeMobileAccessAbortedUsingRemoteStart", + 6: "GuestModeMobileAccessAbortedUsingBLEKeys", + 7: "GuestModeMobileAccessAbortedValetMode", + 8: "GuestModeMobileAccessAbortedGuestModeOff", + 9: "GuestModeMobileAccessAbortedDriveAuthTimeExceeded", + 10: "GuestModeMobileAccessAbortedNoDataReceived", + 11: "GuestModeMobileAccessRequestingFromMothership", + 12: "GuestModeMobileAccessRequestingFromAuthD", + 13: "GuestModeMobileAccessAbortedFetchFailed", + 14: "GuestModeMobileAccessAbortedBadDataReceived", + 15: "GuestModeMobileAccessShowingQRCode", + 16: "GuestModeMobileAccessSwipedAway", + 17: "GuestModeMobileAccessDismissedQRCodeExpired", + 18: "GuestModeMobileAccessSucceededPairedNewBLEKey", + } + GuestModeMobileAccess_value = map[string]int32{ + "GuestModeMobileAccessUnknown": 0, + "GuestModeMobileAccessInit": 1, + "GuestModeMobileAccessNotAuthenticated": 2, + "GuestModeMobileAccessAuthenticated": 3, + "GuestModeMobileAccessAbortedDriving": 4, + "GuestModeMobileAccessAbortedUsingRemoteStart": 5, + "GuestModeMobileAccessAbortedUsingBLEKeys": 6, + "GuestModeMobileAccessAbortedValetMode": 7, + "GuestModeMobileAccessAbortedGuestModeOff": 8, + "GuestModeMobileAccessAbortedDriveAuthTimeExceeded": 9, + "GuestModeMobileAccessAbortedNoDataReceived": 10, + "GuestModeMobileAccessRequestingFromMothership": 11, + "GuestModeMobileAccessRequestingFromAuthD": 12, + "GuestModeMobileAccessAbortedFetchFailed": 13, + "GuestModeMobileAccessAbortedBadDataReceived": 14, + "GuestModeMobileAccessShowingQRCode": 15, + "GuestModeMobileAccessSwipedAway": 16, + "GuestModeMobileAccessDismissedQRCodeExpired": 17, + "GuestModeMobileAccessSucceededPairedNewBLEKey": 18, + } +) + +func (x GuestModeMobileAccess) Enum() *GuestModeMobileAccess { + p := new(GuestModeMobileAccess) + *p = x + return p +} + +func (x GuestModeMobileAccess) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (GuestModeMobileAccess) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[6].Descriptor() +} + +func (GuestModeMobileAccess) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[6] +} + +func (x GuestModeMobileAccess) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use GuestModeMobileAccess.Descriptor instead. +func (GuestModeMobileAccess) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{6} +} + +type LaneAssistLevel int32 + +const ( + LaneAssistLevel_LaneAssistLevelUnknown LaneAssistLevel = 0 + LaneAssistLevel_LaneAssistLevelNone LaneAssistLevel = 1 + LaneAssistLevel_LaneAssistLevelWarning LaneAssistLevel = 2 + LaneAssistLevel_LaneAssistLevelAssist LaneAssistLevel = 3 +) + +// Enum value maps for LaneAssistLevel. +var ( + LaneAssistLevel_name = map[int32]string{ + 0: "LaneAssistLevelUnknown", + 1: "LaneAssistLevelNone", + 2: "LaneAssistLevelWarning", + 3: "LaneAssistLevelAssist", + } + LaneAssistLevel_value = map[string]int32{ + "LaneAssistLevelUnknown": 0, + "LaneAssistLevelNone": 1, + "LaneAssistLevelWarning": 2, + "LaneAssistLevelAssist": 3, + } +) + +func (x LaneAssistLevel) Enum() *LaneAssistLevel { + p := new(LaneAssistLevel) + *p = x + return p +} + +func (x LaneAssistLevel) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (LaneAssistLevel) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[7].Descriptor() +} + +func (LaneAssistLevel) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[7] +} + +func (x LaneAssistLevel) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use LaneAssistLevel.Descriptor instead. +func (LaneAssistLevel) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{7} +} + +type ScheduledChargingModeValue int32 + +const ( + ScheduledChargingModeValue_ScheduledChargingModeUnknown ScheduledChargingModeValue = 0 + ScheduledChargingModeValue_ScheduledChargingModeOff ScheduledChargingModeValue = 1 + ScheduledChargingModeValue_ScheduledChargingModeStartAt ScheduledChargingModeValue = 2 + ScheduledChargingModeValue_ScheduledChargingModeDepartBy ScheduledChargingModeValue = 3 +) + +// Enum value maps for ScheduledChargingModeValue. +var ( + ScheduledChargingModeValue_name = map[int32]string{ + 0: "ScheduledChargingModeUnknown", + 1: "ScheduledChargingModeOff", + 2: "ScheduledChargingModeStartAt", + 3: "ScheduledChargingModeDepartBy", + } + ScheduledChargingModeValue_value = map[string]int32{ + "ScheduledChargingModeUnknown": 0, + "ScheduledChargingModeOff": 1, + "ScheduledChargingModeStartAt": 2, + "ScheduledChargingModeDepartBy": 3, + } +) + +func (x ScheduledChargingModeValue) Enum() *ScheduledChargingModeValue { + p := new(ScheduledChargingModeValue) + *p = x + return p +} + +func (x ScheduledChargingModeValue) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ScheduledChargingModeValue) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[8].Descriptor() +} + +func (ScheduledChargingModeValue) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[8] +} + +func (x ScheduledChargingModeValue) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ScheduledChargingModeValue.Descriptor instead. +func (ScheduledChargingModeValue) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{8} +} + +type SentryModeState int32 + +const ( + SentryModeState_SentryModeStateUnknown SentryModeState = 0 + SentryModeState_SentryModeStateOff SentryModeState = 1 + SentryModeState_SentryModeStateIdle SentryModeState = 2 + SentryModeState_SentryModeStateArmed SentryModeState = 3 + SentryModeState_SentryModeStateAware SentryModeState = 4 + SentryModeState_SentryModeStatePanic SentryModeState = 5 + SentryModeState_SentryModeStateQuiet SentryModeState = 6 +) + +// Enum value maps for SentryModeState. +var ( + SentryModeState_name = map[int32]string{ + 0: "SentryModeStateUnknown", + 1: "SentryModeStateOff", + 2: "SentryModeStateIdle", + 3: "SentryModeStateArmed", + 4: "SentryModeStateAware", + 5: "SentryModeStatePanic", + 6: "SentryModeStateQuiet", + } + SentryModeState_value = map[string]int32{ + "SentryModeStateUnknown": 0, + "SentryModeStateOff": 1, + "SentryModeStateIdle": 2, + "SentryModeStateArmed": 3, + "SentryModeStateAware": 4, + "SentryModeStatePanic": 5, + "SentryModeStateQuiet": 6, + } +) + +func (x SentryModeState) Enum() *SentryModeState { + p := new(SentryModeState) + *p = x + return p +} + +func (x SentryModeState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SentryModeState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[9].Descriptor() +} + +func (SentryModeState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[9] +} + +func (x SentryModeState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SentryModeState.Descriptor instead. +func (SentryModeState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{9} +} + +type SpeedAssistLevel int32 + +const ( + SpeedAssistLevel_SpeedAssistLevelUnknown SpeedAssistLevel = 0 + SpeedAssistLevel_SpeedAssistLevelNone SpeedAssistLevel = 1 + SpeedAssistLevel_SpeedAssistLevelDisplay SpeedAssistLevel = 2 + SpeedAssistLevel_SpeedAssistLevelChime SpeedAssistLevel = 3 +) + +// Enum value maps for SpeedAssistLevel. +var ( + SpeedAssistLevel_name = map[int32]string{ + 0: "SpeedAssistLevelUnknown", + 1: "SpeedAssistLevelNone", + 2: "SpeedAssistLevelDisplay", + 3: "SpeedAssistLevelChime", + } + SpeedAssistLevel_value = map[string]int32{ + "SpeedAssistLevelUnknown": 0, + "SpeedAssistLevelNone": 1, + "SpeedAssistLevelDisplay": 2, + "SpeedAssistLevelChime": 3, + } +) + +func (x SpeedAssistLevel) Enum() *SpeedAssistLevel { + p := new(SpeedAssistLevel) + *p = x + return p +} + +func (x SpeedAssistLevel) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SpeedAssistLevel) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[10].Descriptor() +} + +func (SpeedAssistLevel) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[10] +} + +func (x SpeedAssistLevel) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SpeedAssistLevel.Descriptor instead. +func (SpeedAssistLevel) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{10} +} + +type BMSStateValue int32 + +const ( + BMSStateValue_BMSStateUnknown BMSStateValue = 0 + BMSStateValue_BMSStateStandby BMSStateValue = 1 + BMSStateValue_BMSStateDrive BMSStateValue = 2 + BMSStateValue_BMSStateSupport BMSStateValue = 3 + BMSStateValue_BMSStateCharge BMSStateValue = 4 + BMSStateValue_BMSStateFEIM BMSStateValue = 5 + BMSStateValue_BMSStateClearFault BMSStateValue = 6 + BMSStateValue_BMSStateFault BMSStateValue = 7 + BMSStateValue_BMSStateWeld BMSStateValue = 8 + BMSStateValue_BMSStateTest BMSStateValue = 9 + BMSStateValue_BMSStateSNA BMSStateValue = 10 +) + +// Enum value maps for BMSStateValue. +var ( + BMSStateValue_name = map[int32]string{ + 0: "BMSStateUnknown", + 1: "BMSStateStandby", + 2: "BMSStateDrive", + 3: "BMSStateSupport", + 4: "BMSStateCharge", + 5: "BMSStateFEIM", + 6: "BMSStateClearFault", + 7: "BMSStateFault", + 8: "BMSStateWeld", + 9: "BMSStateTest", + 10: "BMSStateSNA", + } + BMSStateValue_value = map[string]int32{ + "BMSStateUnknown": 0, + "BMSStateStandby": 1, + "BMSStateDrive": 2, + "BMSStateSupport": 3, + "BMSStateCharge": 4, + "BMSStateFEIM": 5, + "BMSStateClearFault": 6, + "BMSStateFault": 7, + "BMSStateWeld": 8, + "BMSStateTest": 9, + "BMSStateSNA": 10, + } +) + +func (x BMSStateValue) Enum() *BMSStateValue { + p := new(BMSStateValue) + *p = x + return p +} + +func (x BMSStateValue) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (BMSStateValue) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[11].Descriptor() +} + +func (BMSStateValue) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[11] +} + +func (x BMSStateValue) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use BMSStateValue.Descriptor instead. +func (BMSStateValue) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{11} +} + +type BuckleStatus int32 + +const ( + BuckleStatus_BuckleStatusUnknown BuckleStatus = 0 + BuckleStatus_BuckleStatusUnlatched BuckleStatus = 1 + BuckleStatus_BuckleStatusLatched BuckleStatus = 2 + BuckleStatus_BuckleStatusFaulted BuckleStatus = 3 + BuckleStatus_BuckleStatusSNA BuckleStatus = 4 // TESLEMETRY-EXT +) + +// Enum value maps for BuckleStatus. +var ( + BuckleStatus_name = map[int32]string{ + 0: "BuckleStatusUnknown", + 1: "BuckleStatusUnlatched", + 2: "BuckleStatusLatched", + 3: "BuckleStatusFaulted", + 4: "BuckleStatusSNA", + } + BuckleStatus_value = map[string]int32{ + "BuckleStatusUnknown": 0, + "BuckleStatusUnlatched": 1, + "BuckleStatusLatched": 2, + "BuckleStatusFaulted": 3, + "BuckleStatusSNA": 4, + } +) + +func (x BuckleStatus) Enum() *BuckleStatus { + p := new(BuckleStatus) + *p = x + return p +} + +func (x BuckleStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (BuckleStatus) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[12].Descriptor() +} + +func (BuckleStatus) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[12] +} + +func (x BuckleStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use BuckleStatus.Descriptor instead. +func (BuckleStatus) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{12} +} + +type CarTypeValue int32 + +const ( + CarTypeValue_CarTypeUnknown CarTypeValue = 0 + CarTypeValue_CarTypeModelS CarTypeValue = 1 + CarTypeValue_CarTypeModelX CarTypeValue = 2 + CarTypeValue_CarTypeModel3 CarTypeValue = 3 + CarTypeValue_CarTypeModelY CarTypeValue = 4 + CarTypeValue_CarTypeSemiTruck CarTypeValue = 5 + CarTypeValue_CarTypeCybertruck CarTypeValue = 6 + CarTypeValue_CarTypeSemiTruckV2 CarTypeValue = 7 + CarTypeValue_CarTypeCybercab CarTypeValue = 8 +) + +// Enum value maps for CarTypeValue. +var ( + CarTypeValue_name = map[int32]string{ + 0: "CarTypeUnknown", + 1: "CarTypeModelS", + 2: "CarTypeModelX", + 3: "CarTypeModel3", + 4: "CarTypeModelY", + 5: "CarTypeSemiTruck", + 6: "CarTypeCybertruck", + 7: "CarTypeSemiTruckV2", + 8: "CarTypeCybercab", + } + CarTypeValue_value = map[string]int32{ + "CarTypeUnknown": 0, + "CarTypeModelS": 1, + "CarTypeModelX": 2, + "CarTypeModel3": 3, + "CarTypeModelY": 4, + "CarTypeSemiTruck": 5, + "CarTypeCybertruck": 6, + "CarTypeSemiTruckV2": 7, + "CarTypeCybercab": 8, + } +) + +func (x CarTypeValue) Enum() *CarTypeValue { + p := new(CarTypeValue) + *p = x + return p +} + +func (x CarTypeValue) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CarTypeValue) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[13].Descriptor() +} + +func (CarTypeValue) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[13] +} + +func (x CarTypeValue) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CarTypeValue.Descriptor instead. +func (CarTypeValue) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{13} +} + +type ChargePortValue int32 + +const ( + ChargePortValue_ChargePortUnknown ChargePortValue = 0 + ChargePortValue_ChargePortUS ChargePortValue = 1 + ChargePortValue_ChargePortEU ChargePortValue = 2 + ChargePortValue_ChargePortGB ChargePortValue = 3 + ChargePortValue_ChargePortCCS ChargePortValue = 4 +) + +// Enum value maps for ChargePortValue. +var ( + ChargePortValue_name = map[int32]string{ + 0: "ChargePortUnknown", + 1: "ChargePortUS", + 2: "ChargePortEU", + 3: "ChargePortGB", + 4: "ChargePortCCS", + } + ChargePortValue_value = map[string]int32{ + "ChargePortUnknown": 0, + "ChargePortUS": 1, + "ChargePortEU": 2, + "ChargePortGB": 3, + "ChargePortCCS": 4, + } +) + +func (x ChargePortValue) Enum() *ChargePortValue { + p := new(ChargePortValue) + *p = x + return p +} + +func (x ChargePortValue) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ChargePortValue) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[14].Descriptor() +} + +func (ChargePortValue) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[14] +} + +func (x ChargePortValue) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ChargePortValue.Descriptor instead. +func (ChargePortValue) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{14} +} + +type ChargePortLatchValue int32 + +const ( + ChargePortLatchValue_ChargePortLatchUnknown ChargePortLatchValue = 0 + ChargePortLatchValue_ChargePortLatchSNA ChargePortLatchValue = 1 + ChargePortLatchValue_ChargePortLatchDisengaged ChargePortLatchValue = 2 + ChargePortLatchValue_ChargePortLatchEngaged ChargePortLatchValue = 3 + ChargePortLatchValue_ChargePortLatchBlocking ChargePortLatchValue = 4 +) + +// Enum value maps for ChargePortLatchValue. +var ( + ChargePortLatchValue_name = map[int32]string{ + 0: "ChargePortLatchUnknown", + 1: "ChargePortLatchSNA", + 2: "ChargePortLatchDisengaged", + 3: "ChargePortLatchEngaged", + 4: "ChargePortLatchBlocking", + } + ChargePortLatchValue_value = map[string]int32{ + "ChargePortLatchUnknown": 0, + "ChargePortLatchSNA": 1, + "ChargePortLatchDisengaged": 2, + "ChargePortLatchEngaged": 3, + "ChargePortLatchBlocking": 4, + } +) + +func (x ChargePortLatchValue) Enum() *ChargePortLatchValue { + p := new(ChargePortLatchValue) + *p = x + return p +} + +func (x ChargePortLatchValue) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ChargePortLatchValue) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[15].Descriptor() +} + +func (ChargePortLatchValue) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[15] +} + +func (x ChargePortLatchValue) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ChargePortLatchValue.Descriptor instead. +func (ChargePortLatchValue) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{15} +} + +type DriveInverterState int32 + +const ( + DriveInverterState_DriveInverterStateUnknown DriveInverterState = 0 + DriveInverterState_DriveInverterStateUnavailable DriveInverterState = 1 + DriveInverterState_DriveInverterStateStandby DriveInverterState = 2 + DriveInverterState_DriveInverterStateFault DriveInverterState = 3 + DriveInverterState_DriveInverterStateAbort DriveInverterState = 4 + DriveInverterState_DriveInverterStateEnable DriveInverterState = 5 +) + +// Enum value maps for DriveInverterState. +var ( + DriveInverterState_name = map[int32]string{ + 0: "DriveInverterStateUnknown", + 1: "DriveInverterStateUnavailable", + 2: "DriveInverterStateStandby", + 3: "DriveInverterStateFault", + 4: "DriveInverterStateAbort", + 5: "DriveInverterStateEnable", + } + DriveInverterState_value = map[string]int32{ + "DriveInverterStateUnknown": 0, + "DriveInverterStateUnavailable": 1, + "DriveInverterStateStandby": 2, + "DriveInverterStateFault": 3, + "DriveInverterStateAbort": 4, + "DriveInverterStateEnable": 5, + } +) + +func (x DriveInverterState) Enum() *DriveInverterState { + p := new(DriveInverterState) + *p = x + return p +} + +func (x DriveInverterState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DriveInverterState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[16].Descriptor() +} + +func (DriveInverterState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[16] +} + +func (x DriveInverterState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DriveInverterState.Descriptor instead. +func (DriveInverterState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{16} +} + +type HvilStatus int32 + +const ( + HvilStatus_HvilStatusUnknown HvilStatus = 0 + HvilStatus_HvilStatusFault HvilStatus = 1 + HvilStatus_HvilStatusOK HvilStatus = 2 +) + +// Enum value maps for HvilStatus. +var ( + HvilStatus_name = map[int32]string{ + 0: "HvilStatusUnknown", + 1: "HvilStatusFault", + 2: "HvilStatusOK", + } + HvilStatus_value = map[string]int32{ + "HvilStatusUnknown": 0, + "HvilStatusFault": 1, + "HvilStatusOK": 2, + } +) + +func (x HvilStatus) Enum() *HvilStatus { + p := new(HvilStatus) + *p = x + return p +} + +func (x HvilStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HvilStatus) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[17].Descriptor() +} + +func (HvilStatus) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[17] +} + +func (x HvilStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HvilStatus.Descriptor instead. +func (HvilStatus) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{17} +} + +type WindowState int32 + +const ( + WindowState_WindowStateUnknown WindowState = 0 + WindowState_WindowStateClosed WindowState = 1 + WindowState_WindowStatePartiallyOpen WindowState = 2 + WindowState_WindowStateOpened WindowState = 3 +) + +// Enum value maps for WindowState. +var ( + WindowState_name = map[int32]string{ + 0: "WindowStateUnknown", + 1: "WindowStateClosed", + 2: "WindowStatePartiallyOpen", + 3: "WindowStateOpened", + } + WindowState_value = map[string]int32{ + "WindowStateUnknown": 0, + "WindowStateClosed": 1, + "WindowStatePartiallyOpen": 2, + "WindowStateOpened": 3, + } +) + +func (x WindowState) Enum() *WindowState { + p := new(WindowState) + *p = x + return p +} + +func (x WindowState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (WindowState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[18].Descriptor() +} + +func (WindowState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[18] +} + +func (x WindowState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use WindowState.Descriptor instead. +func (WindowState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{18} +} + +type SeatFoldPosition int32 + +const ( + SeatFoldPosition_SeatFoldPositionUnknown SeatFoldPosition = 0 + SeatFoldPosition_SeatFoldPositionSNA SeatFoldPosition = 1 + SeatFoldPosition_SeatFoldPositionFaulted SeatFoldPosition = 2 + SeatFoldPosition_SeatFoldPositionNotConfigured SeatFoldPosition = 3 + SeatFoldPosition_SeatFoldPositionFolded SeatFoldPosition = 4 + SeatFoldPosition_SeatFoldPositionUnfolded SeatFoldPosition = 5 +) + +// Enum value maps for SeatFoldPosition. +var ( + SeatFoldPosition_name = map[int32]string{ + 0: "SeatFoldPositionUnknown", + 1: "SeatFoldPositionSNA", + 2: "SeatFoldPositionFaulted", + 3: "SeatFoldPositionNotConfigured", + 4: "SeatFoldPositionFolded", + 5: "SeatFoldPositionUnfolded", + } + SeatFoldPosition_value = map[string]int32{ + "SeatFoldPositionUnknown": 0, + "SeatFoldPositionSNA": 1, + "SeatFoldPositionFaulted": 2, + "SeatFoldPositionNotConfigured": 3, + "SeatFoldPositionFolded": 4, + "SeatFoldPositionUnfolded": 5, + } +) + +func (x SeatFoldPosition) Enum() *SeatFoldPosition { + p := new(SeatFoldPosition) + *p = x + return p +} + +func (x SeatFoldPosition) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SeatFoldPosition) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[19].Descriptor() +} + +func (SeatFoldPosition) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[19] +} + +func (x SeatFoldPosition) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SeatFoldPosition.Descriptor instead. +func (SeatFoldPosition) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{19} +} + +type TractorAirStatus int32 + +const ( + TractorAirStatus_TractorAirStatusUnknown TractorAirStatus = 0 + TractorAirStatus_TractorAirStatusNotAvailable TractorAirStatus = 1 + TractorAirStatus_TractorAirStatusError TractorAirStatus = 2 + TractorAirStatus_TractorAirStatusCharged TractorAirStatus = 3 + TractorAirStatus_TractorAirStatusBuildingPressureIntermediate TractorAirStatus = 4 + TractorAirStatus_TractorAirStatusExhaustingPressureIntermediate TractorAirStatus = 5 + TractorAirStatus_TractorAirStatusExhausted TractorAirStatus = 6 +) + +// Enum value maps for TractorAirStatus. +var ( + TractorAirStatus_name = map[int32]string{ + 0: "TractorAirStatusUnknown", + 1: "TractorAirStatusNotAvailable", + 2: "TractorAirStatusError", + 3: "TractorAirStatusCharged", + 4: "TractorAirStatusBuildingPressureIntermediate", + 5: "TractorAirStatusExhaustingPressureIntermediate", + 6: "TractorAirStatusExhausted", + } + TractorAirStatus_value = map[string]int32{ + "TractorAirStatusUnknown": 0, + "TractorAirStatusNotAvailable": 1, + "TractorAirStatusError": 2, + "TractorAirStatusCharged": 3, + "TractorAirStatusBuildingPressureIntermediate": 4, + "TractorAirStatusExhaustingPressureIntermediate": 5, + "TractorAirStatusExhausted": 6, + } +) + +func (x TractorAirStatus) Enum() *TractorAirStatus { + p := new(TractorAirStatus) + *p = x + return p +} + +func (x TractorAirStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TractorAirStatus) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[20].Descriptor() +} + +func (TractorAirStatus) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[20] +} + +func (x TractorAirStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TractorAirStatus.Descriptor instead. +func (TractorAirStatus) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{20} +} + +type TrailerAirStatus int32 + +const ( + TrailerAirStatus_TrailerAirStatusUnknown TrailerAirStatus = 0 + TrailerAirStatus_TrailerAirStatusSNA TrailerAirStatus = 1 + TrailerAirStatus_TrailerAirStatusInvalid TrailerAirStatus = 2 + TrailerAirStatus_TrailerAirStatusBobtailMode TrailerAirStatus = 3 + TrailerAirStatus_TrailerAirStatusCharged TrailerAirStatus = 4 + TrailerAirStatus_TrailerAirStatusBuildingPressureIntermediate TrailerAirStatus = 5 + TrailerAirStatus_TrailerAirStatusExhaustingPressureIntermediate TrailerAirStatus = 6 + TrailerAirStatus_TrailerAirStatusExhausted TrailerAirStatus = 7 +) + +// Enum value maps for TrailerAirStatus. +var ( + TrailerAirStatus_name = map[int32]string{ + 0: "TrailerAirStatusUnknown", + 1: "TrailerAirStatusSNA", + 2: "TrailerAirStatusInvalid", + 3: "TrailerAirStatusBobtailMode", + 4: "TrailerAirStatusCharged", + 5: "TrailerAirStatusBuildingPressureIntermediate", + 6: "TrailerAirStatusExhaustingPressureIntermediate", + 7: "TrailerAirStatusExhausted", + } + TrailerAirStatus_value = map[string]int32{ + "TrailerAirStatusUnknown": 0, + "TrailerAirStatusSNA": 1, + "TrailerAirStatusInvalid": 2, + "TrailerAirStatusBobtailMode": 3, + "TrailerAirStatusCharged": 4, + "TrailerAirStatusBuildingPressureIntermediate": 5, + "TrailerAirStatusExhaustingPressureIntermediate": 6, + "TrailerAirStatusExhausted": 7, + } +) + +func (x TrailerAirStatus) Enum() *TrailerAirStatus { + p := new(TrailerAirStatus) + *p = x + return p +} + +func (x TrailerAirStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TrailerAirStatus) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[21].Descriptor() +} + +func (TrailerAirStatus) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[21] +} + +func (x TrailerAirStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TrailerAirStatus.Descriptor instead. +func (TrailerAirStatus) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{21} +} + +type HvacAutoModeState int32 + +const ( + HvacAutoModeState_HvacAutoModeStateUnknown HvacAutoModeState = 0 + HvacAutoModeState_HvacAutoModeStateOn HvacAutoModeState = 1 + HvacAutoModeState_HvacAutoModeStateOverride HvacAutoModeState = 2 +) + +// Enum value maps for HvacAutoModeState. +var ( + HvacAutoModeState_name = map[int32]string{ + 0: "HvacAutoModeStateUnknown", + 1: "HvacAutoModeStateOn", + 2: "HvacAutoModeStateOverride", + } + HvacAutoModeState_value = map[string]int32{ + "HvacAutoModeStateUnknown": 0, + "HvacAutoModeStateOn": 1, + "HvacAutoModeStateOverride": 2, + } +) + +func (x HvacAutoModeState) Enum() *HvacAutoModeState { + p := new(HvacAutoModeState) + *p = x + return p +} + +func (x HvacAutoModeState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HvacAutoModeState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[22].Descriptor() +} + +func (HvacAutoModeState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[22] +} + +func (x HvacAutoModeState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HvacAutoModeState.Descriptor instead. +func (HvacAutoModeState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{22} +} + +type CabinOverheatProtectionModeState int32 + +const ( + CabinOverheatProtectionModeState_CabinOverheatProtectionModeStateUnknown CabinOverheatProtectionModeState = 0 + CabinOverheatProtectionModeState_CabinOverheatProtectionModeStateOff CabinOverheatProtectionModeState = 1 + CabinOverheatProtectionModeState_CabinOverheatProtectionModeStateOn CabinOverheatProtectionModeState = 2 + CabinOverheatProtectionModeState_CabinOverheatProtectionModeStateFanOnly CabinOverheatProtectionModeState = 3 +) + +// Enum value maps for CabinOverheatProtectionModeState. +var ( + CabinOverheatProtectionModeState_name = map[int32]string{ + 0: "CabinOverheatProtectionModeStateUnknown", + 1: "CabinOverheatProtectionModeStateOff", + 2: "CabinOverheatProtectionModeStateOn", + 3: "CabinOverheatProtectionModeStateFanOnly", + } + CabinOverheatProtectionModeState_value = map[string]int32{ + "CabinOverheatProtectionModeStateUnknown": 0, + "CabinOverheatProtectionModeStateOff": 1, + "CabinOverheatProtectionModeStateOn": 2, + "CabinOverheatProtectionModeStateFanOnly": 3, + } +) + +func (x CabinOverheatProtectionModeState) Enum() *CabinOverheatProtectionModeState { + p := new(CabinOverheatProtectionModeState) + *p = x + return p +} + +func (x CabinOverheatProtectionModeState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CabinOverheatProtectionModeState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[23].Descriptor() +} + +func (CabinOverheatProtectionModeState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[23] +} + +func (x CabinOverheatProtectionModeState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CabinOverheatProtectionModeState.Descriptor instead. +func (CabinOverheatProtectionModeState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{23} +} + +type ClimateOverheatProtectionTempLimit int32 + +const ( + ClimateOverheatProtectionTempLimit_ClimateOverheatProtectionTempLimitUnknown ClimateOverheatProtectionTempLimit = 0 + ClimateOverheatProtectionTempLimit_ClimateOverheatProtectionTempLimitHigh ClimateOverheatProtectionTempLimit = 1 + ClimateOverheatProtectionTempLimit_ClimateOverheatProtectionTempLimitMedium ClimateOverheatProtectionTempLimit = 2 + ClimateOverheatProtectionTempLimit_ClimateOverheatProtectionTempLimitLow ClimateOverheatProtectionTempLimit = 3 +) + +// Enum value maps for ClimateOverheatProtectionTempLimit. +var ( + ClimateOverheatProtectionTempLimit_name = map[int32]string{ + 0: "ClimateOverheatProtectionTempLimitUnknown", + 1: "ClimateOverheatProtectionTempLimitHigh", + 2: "ClimateOverheatProtectionTempLimitMedium", + 3: "ClimateOverheatProtectionTempLimitLow", + } + ClimateOverheatProtectionTempLimit_value = map[string]int32{ + "ClimateOverheatProtectionTempLimitUnknown": 0, + "ClimateOverheatProtectionTempLimitHigh": 1, + "ClimateOverheatProtectionTempLimitMedium": 2, + "ClimateOverheatProtectionTempLimitLow": 3, + } +) + +func (x ClimateOverheatProtectionTempLimit) Enum() *ClimateOverheatProtectionTempLimit { + p := new(ClimateOverheatProtectionTempLimit) + *p = x + return p +} + +func (x ClimateOverheatProtectionTempLimit) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ClimateOverheatProtectionTempLimit) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[24].Descriptor() +} + +func (ClimateOverheatProtectionTempLimit) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[24] +} + +func (x ClimateOverheatProtectionTempLimit) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ClimateOverheatProtectionTempLimit.Descriptor instead. +func (ClimateOverheatProtectionTempLimit) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{24} +} + +type DefrostModeState int32 + +const ( + DefrostModeState_DefrostModeStateUnknown DefrostModeState = 0 + DefrostModeState_DefrostModeStateOff DefrostModeState = 1 + DefrostModeState_DefrostModeStateNormal DefrostModeState = 2 + DefrostModeState_DefrostModeStateMax DefrostModeState = 3 + DefrostModeState_DefrostModeStateAutoDefog DefrostModeState = 4 +) + +// Enum value maps for DefrostModeState. +var ( + DefrostModeState_name = map[int32]string{ + 0: "DefrostModeStateUnknown", + 1: "DefrostModeStateOff", + 2: "DefrostModeStateNormal", + 3: "DefrostModeStateMax", + 4: "DefrostModeStateAutoDefog", + } + DefrostModeState_value = map[string]int32{ + "DefrostModeStateUnknown": 0, + "DefrostModeStateOff": 1, + "DefrostModeStateNormal": 2, + "DefrostModeStateMax": 3, + "DefrostModeStateAutoDefog": 4, + } +) + +func (x DefrostModeState) Enum() *DefrostModeState { + p := new(DefrostModeState) + *p = x + return p +} + +func (x DefrostModeState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DefrostModeState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[25].Descriptor() +} + +func (DefrostModeState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[25] +} + +func (x DefrostModeState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DefrostModeState.Descriptor instead. +func (DefrostModeState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{25} +} + +type ClimateKeeperModeState int32 + +const ( + ClimateKeeperModeState_ClimateKeeperModeStateUnknown ClimateKeeperModeState = 0 + ClimateKeeperModeState_ClimateKeeperModeStateOff ClimateKeeperModeState = 1 + ClimateKeeperModeState_ClimateKeeperModeStateOn ClimateKeeperModeState = 2 + ClimateKeeperModeState_ClimateKeeperModeStateDog ClimateKeeperModeState = 3 + ClimateKeeperModeState_ClimateKeeperModeStateParty ClimateKeeperModeState = 4 +) + +// Enum value maps for ClimateKeeperModeState. +var ( + ClimateKeeperModeState_name = map[int32]string{ + 0: "ClimateKeeperModeStateUnknown", + 1: "ClimateKeeperModeStateOff", + 2: "ClimateKeeperModeStateOn", + 3: "ClimateKeeperModeStateDog", + 4: "ClimateKeeperModeStateParty", + } + ClimateKeeperModeState_value = map[string]int32{ + "ClimateKeeperModeStateUnknown": 0, + "ClimateKeeperModeStateOff": 1, + "ClimateKeeperModeStateOn": 2, + "ClimateKeeperModeStateDog": 3, + "ClimateKeeperModeStateParty": 4, + } +) + +func (x ClimateKeeperModeState) Enum() *ClimateKeeperModeState { + p := new(ClimateKeeperModeState) + *p = x + return p +} + +func (x ClimateKeeperModeState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ClimateKeeperModeState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[26].Descriptor() +} + +func (ClimateKeeperModeState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[26] +} + +func (x ClimateKeeperModeState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ClimateKeeperModeState.Descriptor instead. +func (ClimateKeeperModeState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{26} +} + +type HvacPowerState int32 + +const ( + HvacPowerState_HvacPowerStateUnknown HvacPowerState = 0 + HvacPowerState_HvacPowerStateOff HvacPowerState = 1 + HvacPowerState_HvacPowerStateOn HvacPowerState = 2 + HvacPowerState_HvacPowerStatePrecondition HvacPowerState = 3 + HvacPowerState_HvacPowerStateOverheatProtect HvacPowerState = 4 +) + +// Enum value maps for HvacPowerState. +var ( + HvacPowerState_name = map[int32]string{ + 0: "HvacPowerStateUnknown", + 1: "HvacPowerStateOff", + 2: "HvacPowerStateOn", + 3: "HvacPowerStatePrecondition", + 4: "HvacPowerStateOverheatProtect", + } + HvacPowerState_value = map[string]int32{ + "HvacPowerStateUnknown": 0, + "HvacPowerStateOff": 1, + "HvacPowerStateOn": 2, + "HvacPowerStatePrecondition": 3, + "HvacPowerStateOverheatProtect": 4, + } +) + +func (x HvacPowerState) Enum() *HvacPowerState { + p := new(HvacPowerState) + *p = x + return p +} + +func (x HvacPowerState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HvacPowerState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[27].Descriptor() +} + +func (HvacPowerState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[27] +} + +func (x HvacPowerState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HvacPowerState.Descriptor instead. +func (HvacPowerState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{27} +} + +type FastCharger int32 + +const ( + FastCharger_FastChargerUnknown FastCharger = 0 + FastCharger_FastChargerSupercharger FastCharger = 1 + FastCharger_FastChargerCHAdeMO FastCharger = 2 + FastCharger_FastChargerGB FastCharger = 3 + FastCharger_FastChargerACSingleWireCAN FastCharger = 4 + FastCharger_FastChargerCombo FastCharger = 5 + FastCharger_FastChargerMCSingleWireCAN FastCharger = 6 + FastCharger_FastChargerOther FastCharger = 7 + FastCharger_FastChargerSNA FastCharger = 8 +) + +// Enum value maps for FastCharger. +var ( + FastCharger_name = map[int32]string{ + 0: "FastChargerUnknown", + 1: "FastChargerSupercharger", + 2: "FastChargerCHAdeMO", + 3: "FastChargerGB", + 4: "FastChargerACSingleWireCAN", + 5: "FastChargerCombo", + 6: "FastChargerMCSingleWireCAN", + 7: "FastChargerOther", + 8: "FastChargerSNA", + } + FastCharger_value = map[string]int32{ + "FastChargerUnknown": 0, + "FastChargerSupercharger": 1, + "FastChargerCHAdeMO": 2, + "FastChargerGB": 3, + "FastChargerACSingleWireCAN": 4, + "FastChargerCombo": 5, + "FastChargerMCSingleWireCAN": 6, + "FastChargerOther": 7, + "FastChargerSNA": 8, + } +) + +func (x FastCharger) Enum() *FastCharger { + p := new(FastCharger) + *p = x + return p +} + +func (x FastCharger) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FastCharger) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[28].Descriptor() +} + +func (FastCharger) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[28] +} + +func (x FastCharger) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use FastCharger.Descriptor instead. +func (FastCharger) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{28} +} + +type CableType int32 + +const ( + CableType_CableTypeUnknown CableType = 0 + CableType_CableTypeIEC CableType = 1 + CableType_CableTypeSAE CableType = 2 + CableType_CableTypeGB_AC CableType = 3 + CableType_CableTypeGB_DC CableType = 4 + CableType_CableTypeSNA CableType = 5 +) + +// Enum value maps for CableType. +var ( + CableType_name = map[int32]string{ + 0: "CableTypeUnknown", + 1: "CableTypeIEC", + 2: "CableTypeSAE", + 3: "CableTypeGB_AC", + 4: "CableTypeGB_DC", + 5: "CableTypeSNA", + } + CableType_value = map[string]int32{ + "CableTypeUnknown": 0, + "CableTypeIEC": 1, + "CableTypeSAE": 2, + "CableTypeGB_AC": 3, + "CableTypeGB_DC": 4, + "CableTypeSNA": 5, + } +) + +func (x CableType) Enum() *CableType { + p := new(CableType) + *p = x + return p +} + +func (x CableType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CableType) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[29].Descriptor() +} + +func (CableType) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[29] +} + +func (x CableType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CableType.Descriptor instead. +func (CableType) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{29} +} + +type TonneauTentModeState int32 + +const ( + TonneauTentModeState_TonneauTentModeStateUnknown TonneauTentModeState = 0 + TonneauTentModeState_TonneauTentModeStateInactive TonneauTentModeState = 1 + TonneauTentModeState_TonneauTentModeStateMoving TonneauTentModeState = 2 + TonneauTentModeState_TonneauTentModeStateFailed TonneauTentModeState = 3 + TonneauTentModeState_TonneauTentModeStateActive TonneauTentModeState = 4 +) + +// Enum value maps for TonneauTentModeState. +var ( + TonneauTentModeState_name = map[int32]string{ + 0: "TonneauTentModeStateUnknown", + 1: "TonneauTentModeStateInactive", + 2: "TonneauTentModeStateMoving", + 3: "TonneauTentModeStateFailed", + 4: "TonneauTentModeStateActive", + } + TonneauTentModeState_value = map[string]int32{ + "TonneauTentModeStateUnknown": 0, + "TonneauTentModeStateInactive": 1, + "TonneauTentModeStateMoving": 2, + "TonneauTentModeStateFailed": 3, + "TonneauTentModeStateActive": 4, + } +) + +func (x TonneauTentModeState) Enum() *TonneauTentModeState { + p := new(TonneauTentModeState) + *p = x + return p +} + +func (x TonneauTentModeState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TonneauTentModeState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[30].Descriptor() +} + +func (TonneauTentModeState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[30] +} + +func (x TonneauTentModeState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TonneauTentModeState.Descriptor instead. +func (TonneauTentModeState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{30} +} + +type TonneauPositionState int32 + +const ( + TonneauPositionState_TonneauPositionStateUnknown TonneauPositionState = 0 + TonneauPositionState_TonneauPositionStateInvalid TonneauPositionState = 1 + TonneauPositionState_TonneauPositionStateClosed TonneauPositionState = 2 + TonneauPositionState_TonneauPositionStatePartiallyOpen TonneauPositionState = 3 + TonneauPositionState_TonneauPositionStateFullyOpen TonneauPositionState = 4 +) + +// Enum value maps for TonneauPositionState. +var ( + TonneauPositionState_name = map[int32]string{ + 0: "TonneauPositionStateUnknown", + 1: "TonneauPositionStateInvalid", + 2: "TonneauPositionStateClosed", + 3: "TonneauPositionStatePartiallyOpen", + 4: "TonneauPositionStateFullyOpen", + } + TonneauPositionState_value = map[string]int32{ + "TonneauPositionStateUnknown": 0, + "TonneauPositionStateInvalid": 1, + "TonneauPositionStateClosed": 2, + "TonneauPositionStatePartiallyOpen": 3, + "TonneauPositionStateFullyOpen": 4, + } +) + +func (x TonneauPositionState) Enum() *TonneauPositionState { + p := new(TonneauPositionState) + *p = x + return p +} + +func (x TonneauPositionState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TonneauPositionState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[31].Descriptor() +} + +func (TonneauPositionState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[31] +} + +func (x TonneauPositionState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TonneauPositionState.Descriptor instead. +func (TonneauPositionState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{31} +} + +type PowershareState int32 + +const ( + PowershareState_PowershareStateUnknown PowershareState = 0 + PowershareState_PowershareStateInactive PowershareState = 1 + PowershareState_PowershareStateHandshaking PowershareState = 2 + PowershareState_PowershareStateInit PowershareState = 3 + PowershareState_PowershareStateEnabled PowershareState = 4 + PowershareState_PowershareStateEnabledReconnectingSoon PowershareState = 5 + PowershareState_PowershareStateStopped PowershareState = 6 +) + +// Enum value maps for PowershareState. +var ( + PowershareState_name = map[int32]string{ + 0: "PowershareStateUnknown", + 1: "PowershareStateInactive", + 2: "PowershareStateHandshaking", + 3: "PowershareStateInit", + 4: "PowershareStateEnabled", + 5: "PowershareStateEnabledReconnectingSoon", + 6: "PowershareStateStopped", + } + PowershareState_value = map[string]int32{ + "PowershareStateUnknown": 0, + "PowershareStateInactive": 1, + "PowershareStateHandshaking": 2, + "PowershareStateInit": 3, + "PowershareStateEnabled": 4, + "PowershareStateEnabledReconnectingSoon": 5, + "PowershareStateStopped": 6, + } +) + +func (x PowershareState) Enum() *PowershareState { + p := new(PowershareState) + *p = x + return p +} + +func (x PowershareState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PowershareState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[32].Descriptor() +} + +func (PowershareState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[32] +} + +func (x PowershareState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PowershareState.Descriptor instead. +func (PowershareState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{32} +} + +type PowershareStopReasonStatus int32 + +const ( + PowershareStopReasonStatus_PowershareStopReasonStatusUnknown PowershareStopReasonStatus = 0 + PowershareStopReasonStatus_PowershareStopReasonStatusNone PowershareStopReasonStatus = 1 + PowershareStopReasonStatus_PowershareStopReasonStatusSOCTooLow PowershareStopReasonStatus = 2 + PowershareStopReasonStatus_PowershareStopReasonStatusRetry PowershareStopReasonStatus = 3 + PowershareStopReasonStatus_PowershareStopReasonStatusFault PowershareStopReasonStatus = 4 + PowershareStopReasonStatus_PowershareStopReasonStatusUser PowershareStopReasonStatus = 5 + PowershareStopReasonStatus_PowershareStopReasonStatusReconnecting PowershareStopReasonStatus = 6 + PowershareStopReasonStatus_PowershareStopReasonStatusAuthentication PowershareStopReasonStatus = 7 +) + +// Enum value maps for PowershareStopReasonStatus. +var ( + PowershareStopReasonStatus_name = map[int32]string{ + 0: "PowershareStopReasonStatusUnknown", + 1: "PowershareStopReasonStatusNone", + 2: "PowershareStopReasonStatusSOCTooLow", + 3: "PowershareStopReasonStatusRetry", + 4: "PowershareStopReasonStatusFault", + 5: "PowershareStopReasonStatusUser", + 6: "PowershareStopReasonStatusReconnecting", + 7: "PowershareStopReasonStatusAuthentication", + } + PowershareStopReasonStatus_value = map[string]int32{ + "PowershareStopReasonStatusUnknown": 0, + "PowershareStopReasonStatusNone": 1, + "PowershareStopReasonStatusSOCTooLow": 2, + "PowershareStopReasonStatusRetry": 3, + "PowershareStopReasonStatusFault": 4, + "PowershareStopReasonStatusUser": 5, + "PowershareStopReasonStatusReconnecting": 6, + "PowershareStopReasonStatusAuthentication": 7, + } +) + +func (x PowershareStopReasonStatus) Enum() *PowershareStopReasonStatus { + p := new(PowershareStopReasonStatus) + *p = x + return p +} + +func (x PowershareStopReasonStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PowershareStopReasonStatus) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[33].Descriptor() +} + +func (PowershareStopReasonStatus) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[33] +} + +func (x PowershareStopReasonStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PowershareStopReasonStatus.Descriptor instead. +func (PowershareStopReasonStatus) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{33} +} + +type PowershareTypeStatus int32 + +const ( + PowershareTypeStatus_PowershareTypeStatusUnknown PowershareTypeStatus = 0 + PowershareTypeStatus_PowershareTypeStatusNone PowershareTypeStatus = 1 + PowershareTypeStatus_PowershareTypeStatusLoad PowershareTypeStatus = 2 + PowershareTypeStatus_PowershareTypeStatusHome PowershareTypeStatus = 3 +) + +// Enum value maps for PowershareTypeStatus. +var ( + PowershareTypeStatus_name = map[int32]string{ + 0: "PowershareTypeStatusUnknown", + 1: "PowershareTypeStatusNone", + 2: "PowershareTypeStatusLoad", + 3: "PowershareTypeStatusHome", + } + PowershareTypeStatus_value = map[string]int32{ + "PowershareTypeStatusUnknown": 0, + "PowershareTypeStatusNone": 1, + "PowershareTypeStatusLoad": 2, + "PowershareTypeStatusHome": 3, + } +) + +func (x PowershareTypeStatus) Enum() *PowershareTypeStatus { + p := new(PowershareTypeStatus) + *p = x + return p +} + +func (x PowershareTypeStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PowershareTypeStatus) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[34].Descriptor() +} + +func (PowershareTypeStatus) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[34] +} + +func (x PowershareTypeStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PowershareTypeStatus.Descriptor instead. +func (PowershareTypeStatus) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{34} +} + +type DisplayState int32 + +const ( + DisplayState_DisplayStateUnknown DisplayState = 0 + DisplayState_DisplayStateOff DisplayState = 1 + DisplayState_DisplayStateDim DisplayState = 2 + DisplayState_DisplayStateAccessory DisplayState = 3 + DisplayState_DisplayStateOn DisplayState = 4 + DisplayState_DisplayStateDriving DisplayState = 5 + DisplayState_DisplayStateCharging DisplayState = 6 + DisplayState_DisplayStateLock DisplayState = 7 + DisplayState_DisplayStateSentry DisplayState = 8 + DisplayState_DisplayStateDog DisplayState = 9 + DisplayState_DisplayStateEntertainment DisplayState = 10 +) + +// Enum value maps for DisplayState. +var ( + DisplayState_name = map[int32]string{ + 0: "DisplayStateUnknown", + 1: "DisplayStateOff", + 2: "DisplayStateDim", + 3: "DisplayStateAccessory", + 4: "DisplayStateOn", + 5: "DisplayStateDriving", + 6: "DisplayStateCharging", + 7: "DisplayStateLock", + 8: "DisplayStateSentry", + 9: "DisplayStateDog", + 10: "DisplayStateEntertainment", + } + DisplayState_value = map[string]int32{ + "DisplayStateUnknown": 0, + "DisplayStateOff": 1, + "DisplayStateDim": 2, + "DisplayStateAccessory": 3, + "DisplayStateOn": 4, + "DisplayStateDriving": 5, + "DisplayStateCharging": 6, + "DisplayStateLock": 7, + "DisplayStateSentry": 8, + "DisplayStateDog": 9, + "DisplayStateEntertainment": 10, + } +) + +func (x DisplayState) Enum() *DisplayState { + p := new(DisplayState) + *p = x + return p +} + +func (x DisplayState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DisplayState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[35].Descriptor() +} + +func (DisplayState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[35] +} + +func (x DisplayState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DisplayState.Descriptor instead. +func (DisplayState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{35} +} + +type DistanceUnit int32 + +const ( + DistanceUnit_DistanceUnitUnknown DistanceUnit = 0 + DistanceUnit_DistanceUnitMiles DistanceUnit = 1 + DistanceUnit_DistanceUnitKilometers DistanceUnit = 2 +) + +// Enum value maps for DistanceUnit. +var ( + DistanceUnit_name = map[int32]string{ + 0: "DistanceUnitUnknown", + 1: "DistanceUnitMiles", + 2: "DistanceUnitKilometers", + } + DistanceUnit_value = map[string]int32{ + "DistanceUnitUnknown": 0, + "DistanceUnitMiles": 1, + "DistanceUnitKilometers": 2, + } +) + +func (x DistanceUnit) Enum() *DistanceUnit { + p := new(DistanceUnit) + *p = x + return p +} + +func (x DistanceUnit) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DistanceUnit) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[36].Descriptor() +} + +func (DistanceUnit) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[36] +} + +func (x DistanceUnit) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DistanceUnit.Descriptor instead. +func (DistanceUnit) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{36} +} + +type TemperatureUnit int32 + +const ( + TemperatureUnit_TemperatureUnitUnknown TemperatureUnit = 0 + TemperatureUnit_TemperatureUnitFahrenheit TemperatureUnit = 1 + TemperatureUnit_TemperatureUnitCelsius TemperatureUnit = 2 +) + +// Enum value maps for TemperatureUnit. +var ( + TemperatureUnit_name = map[int32]string{ + 0: "TemperatureUnitUnknown", + 1: "TemperatureUnitFahrenheit", + 2: "TemperatureUnitCelsius", + } + TemperatureUnit_value = map[string]int32{ + "TemperatureUnitUnknown": 0, + "TemperatureUnitFahrenheit": 1, + "TemperatureUnitCelsius": 2, + } +) + +func (x TemperatureUnit) Enum() *TemperatureUnit { + p := new(TemperatureUnit) + *p = x + return p +} + +func (x TemperatureUnit) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TemperatureUnit) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[37].Descriptor() +} + +func (TemperatureUnit) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[37] +} + +func (x TemperatureUnit) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TemperatureUnit.Descriptor instead. +func (TemperatureUnit) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{37} +} + +type PressureUnit int32 + +const ( + PressureUnit_PressureUnitUnknown PressureUnit = 0 + PressureUnit_PressureUnitPsi PressureUnit = 1 + PressureUnit_PressureUnitBar PressureUnit = 2 +) + +// Enum value maps for PressureUnit. +var ( + PressureUnit_name = map[int32]string{ + 0: "PressureUnitUnknown", + 1: "PressureUnitPsi", + 2: "PressureUnitBar", + } + PressureUnit_value = map[string]int32{ + "PressureUnitUnknown": 0, + "PressureUnitPsi": 1, + "PressureUnitBar": 2, + } +) + +func (x PressureUnit) Enum() *PressureUnit { + p := new(PressureUnit) + *p = x + return p +} + +func (x PressureUnit) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PressureUnit) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[38].Descriptor() +} + +func (PressureUnit) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[38] +} + +func (x PressureUnit) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PressureUnit.Descriptor instead. +func (PressureUnit) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{38} +} + +type ChargeUnitPreference int32 + +const ( + ChargeUnitPreference_ChargeUnitUnknown ChargeUnitPreference = 0 + ChargeUnitPreference_ChargeUnitDistance ChargeUnitPreference = 1 + ChargeUnitPreference_ChargeUnitPercent ChargeUnitPreference = 2 +) + +// Enum value maps for ChargeUnitPreference. +var ( + ChargeUnitPreference_name = map[int32]string{ + 0: "ChargeUnitUnknown", + 1: "ChargeUnitDistance", + 2: "ChargeUnitPercent", + } + ChargeUnitPreference_value = map[string]int32{ + "ChargeUnitUnknown": 0, + "ChargeUnitDistance": 1, + "ChargeUnitPercent": 2, + } +) + +func (x ChargeUnitPreference) Enum() *ChargeUnitPreference { + p := new(ChargeUnitPreference) + *p = x + return p +} + +func (x ChargeUnitPreference) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ChargeUnitPreference) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[39].Descriptor() +} + +func (ChargeUnitPreference) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[39] +} + +func (x ChargeUnitPreference) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ChargeUnitPreference.Descriptor instead. +func (ChargeUnitPreference) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{39} +} + +type SunroofInstalledState int32 + +const ( + SunroofInstalledState_SunroofInstalledStateUnknown SunroofInstalledState = 0 + SunroofInstalledState_SunroofInstalledStateNotInstalled SunroofInstalledState = 1 + SunroofInstalledState_SunroofInstalledStateGen1Installed SunroofInstalledState = 2 + SunroofInstalledState_SunroofInstalledStateGen2Installed SunroofInstalledState = 3 +) + +// Enum value maps for SunroofInstalledState. +var ( + SunroofInstalledState_name = map[int32]string{ + 0: "SunroofInstalledStateUnknown", + 1: "SunroofInstalledStateNotInstalled", + 2: "SunroofInstalledStateGen1Installed", + 3: "SunroofInstalledStateGen2Installed", + } + SunroofInstalledState_value = map[string]int32{ + "SunroofInstalledStateUnknown": 0, + "SunroofInstalledStateNotInstalled": 1, + "SunroofInstalledStateGen1Installed": 2, + "SunroofInstalledStateGen2Installed": 3, + } +) + +func (x SunroofInstalledState) Enum() *SunroofInstalledState { + p := new(SunroofInstalledState) + *p = x + return p +} + +func (x SunroofInstalledState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SunroofInstalledState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[40].Descriptor() +} + +func (SunroofInstalledState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[40] +} + +func (x SunroofInstalledState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SunroofInstalledState.Descriptor instead. +func (SunroofInstalledState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{40} +} + +type CabinPortKeepOnState int32 + +const ( + CabinPortKeepOnState_CabinPortKeepOnStateUnknown CabinPortKeepOnState = 0 + CabinPortKeepOnState_CabinPortKeepOnStateOff CabinPortKeepOnState = 1 + CabinPortKeepOnState_CabinPortKeepOnStateOn CabinPortKeepOnState = 2 +) + +// Enum value maps for CabinPortKeepOnState. +var ( + CabinPortKeepOnState_name = map[int32]string{ + 0: "CabinPortKeepOnStateUnknown", + 1: "CabinPortKeepOnStateOff", + 2: "CabinPortKeepOnStateOn", + } + CabinPortKeepOnState_value = map[string]int32{ + "CabinPortKeepOnStateUnknown": 0, + "CabinPortKeepOnStateOff": 1, + "CabinPortKeepOnStateOn": 2, + } +) + +func (x CabinPortKeepOnState) Enum() *CabinPortKeepOnState { + p := new(CabinPortKeepOnState) + *p = x + return p +} + +func (x CabinPortKeepOnState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CabinPortKeepOnState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[41].Descriptor() +} + +func (CabinPortKeepOnState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[41] +} + +func (x CabinPortKeepOnState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CabinPortKeepOnState.Descriptor instead. +func (CabinPortKeepOnState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{41} +} + +type CruiseStateValue int32 + +const ( + CruiseStateValue_CruiseStateUnknown CruiseStateValue = 0 + CruiseStateValue_CruiseStateOff CruiseStateValue = 1 + CruiseStateValue_CruiseStateStandby CruiseStateValue = 2 + CruiseStateValue_CruiseStateOn CruiseStateValue = 3 + CruiseStateValue_CruiseStateStandstill CruiseStateValue = 4 + CruiseStateValue_CruiseStateOverride CruiseStateValue = 5 + CruiseStateValue_CruiseStateFault CruiseStateValue = 6 + CruiseStateValue_CruiseStatePreFault CruiseStateValue = 7 + CruiseStateValue_CruiseStatePreCancel CruiseStateValue = 8 +) + +// Enum value maps for CruiseStateValue. +var ( + CruiseStateValue_name = map[int32]string{ + 0: "CruiseStateUnknown", + 1: "CruiseStateOff", + 2: "CruiseStateStandby", + 3: "CruiseStateOn", + 4: "CruiseStateStandstill", + 5: "CruiseStateOverride", + 6: "CruiseStateFault", + 7: "CruiseStatePreFault", + 8: "CruiseStatePreCancel", + } + CruiseStateValue_value = map[string]int32{ + "CruiseStateUnknown": 0, + "CruiseStateOff": 1, + "CruiseStateStandby": 2, + "CruiseStateOn": 3, + "CruiseStateStandstill": 4, + "CruiseStateOverride": 5, + "CruiseStateFault": 6, + "CruiseStatePreFault": 7, + "CruiseStatePreCancel": 8, + } +) + +func (x CruiseStateValue) Enum() *CruiseStateValue { + p := new(CruiseStateValue) + *p = x + return p +} + +func (x CruiseStateValue) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CruiseStateValue) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[42].Descriptor() +} + +func (CruiseStateValue) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[42] +} + +func (x CruiseStateValue) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CruiseStateValue.Descriptor instead. +func (CruiseStateValue) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{42} +} + +type PowerTransferStatusValue int32 + +const ( + PowerTransferStatusValue_PowerTransferStatusUnknown PowerTransferStatusValue = 0 + PowerTransferStatusValue_PowerTransferStatusStandby PowerTransferStatusValue = 1 + PowerTransferStatusValue_PowerTransferStatusFaulted PowerTransferStatusValue = 2 + PowerTransferStatusValue_PowerTransferStatusEmergencyShutdown PowerTransferStatusValue = 3 + PowerTransferStatusValue_PowerTransferStatusExtEvseTestAllowed PowerTransferStatusValue = 4 + PowerTransferStatusValue_PowerTransferStatusExtPrechargeAllowed PowerTransferStatusValue = 5 + PowerTransferStatusValue_PowerTransferStatusChargeEnabling PowerTransferStatusValue = 6 + PowerTransferStatusValue_PowerTransferStatusChargeEnabled PowerTransferStatusValue = 7 + PowerTransferStatusValue_PowerTransferStatusGracefulShutdown PowerTransferStatusValue = 8 + PowerTransferStatusValue_PowerTransferStatusBlocked PowerTransferStatusValue = 9 +) + +// Enum value maps for PowerTransferStatusValue. +var ( + PowerTransferStatusValue_name = map[int32]string{ + 0: "PowerTransferStatusUnknown", + 1: "PowerTransferStatusStandby", + 2: "PowerTransferStatusFaulted", + 3: "PowerTransferStatusEmergencyShutdown", + 4: "PowerTransferStatusExtEvseTestAllowed", + 5: "PowerTransferStatusExtPrechargeAllowed", + 6: "PowerTransferStatusChargeEnabling", + 7: "PowerTransferStatusChargeEnabled", + 8: "PowerTransferStatusGracefulShutdown", + 9: "PowerTransferStatusBlocked", + } + PowerTransferStatusValue_value = map[string]int32{ + "PowerTransferStatusUnknown": 0, + "PowerTransferStatusStandby": 1, + "PowerTransferStatusFaulted": 2, + "PowerTransferStatusEmergencyShutdown": 3, + "PowerTransferStatusExtEvseTestAllowed": 4, + "PowerTransferStatusExtPrechargeAllowed": 5, + "PowerTransferStatusChargeEnabling": 6, + "PowerTransferStatusChargeEnabled": 7, + "PowerTransferStatusGracefulShutdown": 8, + "PowerTransferStatusBlocked": 9, + } +) + +func (x PowerTransferStatusValue) Enum() *PowerTransferStatusValue { + p := new(PowerTransferStatusValue) + *p = x + return p +} + +func (x PowerTransferStatusValue) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PowerTransferStatusValue) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[43].Descriptor() +} + +func (PowerTransferStatusValue) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[43] +} + +func (x PowerTransferStatusValue) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PowerTransferStatusValue.Descriptor instead. +func (PowerTransferStatusValue) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{43} +} + +type TurnSignalState int32 + +const ( + TurnSignalState_TurnSignalStateUnknown TurnSignalState = 0 + TurnSignalState_TurnSignalStateOff TurnSignalState = 1 + TurnSignalState_TurnSignalStateLeft TurnSignalState = 2 + TurnSignalState_TurnSignalStateRight TurnSignalState = 3 + TurnSignalState_TurnSignalStateBoth TurnSignalState = 4 +) + +// Enum value maps for TurnSignalState. +var ( + TurnSignalState_name = map[int32]string{ + 0: "TurnSignalStateUnknown", + 1: "TurnSignalStateOff", + 2: "TurnSignalStateLeft", + 3: "TurnSignalStateRight", + 4: "TurnSignalStateBoth", + } + TurnSignalState_value = map[string]int32{ + "TurnSignalStateUnknown": 0, + "TurnSignalStateOff": 1, + "TurnSignalStateLeft": 2, + "TurnSignalStateRight": 3, + "TurnSignalStateBoth": 4, + } +) + +func (x TurnSignalState) Enum() *TurnSignalState { + p := new(TurnSignalState) + *p = x + return p +} + +func (x TurnSignalState) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TurnSignalState) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[44].Descriptor() +} + +func (TurnSignalState) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[44] +} + +func (x TurnSignalState) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TurnSignalState.Descriptor instead. +func (TurnSignalState) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{44} +} + +type MediaStatus int32 + +const ( + MediaStatus_MediaStatusUnknown MediaStatus = 0 + MediaStatus_MediaStatusStopped MediaStatus = 1 + MediaStatus_MediaStatusPlaying MediaStatus = 2 + MediaStatus_MediaStatusPaused MediaStatus = 3 +) + +// Enum value maps for MediaStatus. +var ( + MediaStatus_name = map[int32]string{ + 0: "MediaStatusUnknown", + 1: "MediaStatusStopped", + 2: "MediaStatusPlaying", + 3: "MediaStatusPaused", + } + MediaStatus_value = map[string]int32{ + "MediaStatusUnknown": 0, + "MediaStatusStopped": 1, + "MediaStatusPlaying": 2, + "MediaStatusPaused": 3, + } +) + +func (x MediaStatus) Enum() *MediaStatus { + p := new(MediaStatus) + *p = x + return p +} + +func (x MediaStatus) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MediaStatus) Descriptor() protoreflect.EnumDescriptor { + return file_vehicle_data_proto_enumTypes[45].Descriptor() +} + +func (MediaStatus) Type() protoreflect.EnumType { + return &file_vehicle_data_proto_enumTypes[45] +} + +func (x MediaStatus) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MediaStatus.Descriptor instead. +func (MediaStatus) EnumDescriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{45} +} + +// LocationValue is a Datum value type +type LocationValue struct { + state protoimpl.MessageState `protogen:"open.v1"` + Latitude float64 `protobuf:"fixed64,1,opt,name=latitude,proto3" json:"latitude,omitempty"` + Longitude float64 `protobuf:"fixed64,2,opt,name=longitude,proto3" json:"longitude,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *LocationValue) Reset() { + *x = LocationValue{} + mi := &file_vehicle_data_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *LocationValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LocationValue) ProtoMessage() {} + +func (x *LocationValue) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_data_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LocationValue.ProtoReflect.Descriptor instead. +func (*LocationValue) Descriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{0} +} + +func (x *LocationValue) GetLatitude() float64 { + if x != nil { + return x.Latitude + } + return 0 +} + +func (x *LocationValue) GetLongitude() float64 { + if x != nil { + return x.Longitude + } + return 0 +} + +type Doors struct { + state protoimpl.MessageState `protogen:"open.v1"` + DriverFront bool `protobuf:"varint,1,opt,name=DriverFront,proto3" json:"DriverFront,omitempty"` + DriverRear bool `protobuf:"varint,2,opt,name=DriverRear,proto3" json:"DriverRear,omitempty"` + PassengerFront bool `protobuf:"varint,3,opt,name=PassengerFront,proto3" json:"PassengerFront,omitempty"` + PassengerRear bool `protobuf:"varint,4,opt,name=PassengerRear,proto3" json:"PassengerRear,omitempty"` + TrunkFront bool `protobuf:"varint,5,opt,name=TrunkFront,proto3" json:"TrunkFront,omitempty"` + TrunkRear bool `protobuf:"varint,6,opt,name=TrunkRear,proto3" json:"TrunkRear,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Doors) Reset() { + *x = Doors{} + mi := &file_vehicle_data_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Doors) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Doors) ProtoMessage() {} + +func (x *Doors) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_data_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Doors.ProtoReflect.Descriptor instead. +func (*Doors) Descriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{1} +} + +func (x *Doors) GetDriverFront() bool { + if x != nil { + return x.DriverFront + } + return false +} + +func (x *Doors) GetDriverRear() bool { + if x != nil { + return x.DriverRear + } + return false +} + +func (x *Doors) GetPassengerFront() bool { + if x != nil { + return x.PassengerFront + } + return false +} + +func (x *Doors) GetPassengerRear() bool { + if x != nil { + return x.PassengerRear + } + return false +} + +func (x *Doors) GetTrunkFront() bool { + if x != nil { + return x.TrunkFront + } + return false +} + +func (x *Doors) GetTrunkRear() bool { + if x != nil { + return x.TrunkRear + } + return false +} + +type TireLocation struct { + state protoimpl.MessageState `protogen:"open.v1"` + FrontLeft bool `protobuf:"varint,1,opt,name=front_left,json=frontLeft,proto3" json:"front_left,omitempty"` + FrontRight bool `protobuf:"varint,2,opt,name=front_right,json=frontRight,proto3" json:"front_right,omitempty"` + RearLeft bool `protobuf:"varint,3,opt,name=rear_left,json=rearLeft,proto3" json:"rear_left,omitempty"` + RearRight bool `protobuf:"varint,4,opt,name=rear_right,json=rearRight,proto3" json:"rear_right,omitempty"` + SemiMiddleAxleLeft_2 bool `protobuf:"varint,5,opt,name=semi_middle_axle_left_2,json=semiMiddleAxleLeft2,proto3" json:"semi_middle_axle_left_2,omitempty"` + SemiMiddleAxleRight_2 bool `protobuf:"varint,6,opt,name=semi_middle_axle_right_2,json=semiMiddleAxleRight2,proto3" json:"semi_middle_axle_right_2,omitempty"` + SemiRearAxleLeft bool `protobuf:"varint,7,opt,name=semi_rear_axle_left,json=semiRearAxleLeft,proto3" json:"semi_rear_axle_left,omitempty"` + SemiRearAxleRight bool `protobuf:"varint,8,opt,name=semi_rear_axle_right,json=semiRearAxleRight,proto3" json:"semi_rear_axle_right,omitempty"` + SemiRearAxleLeft_2 bool `protobuf:"varint,9,opt,name=semi_rear_axle_left_2,json=semiRearAxleLeft2,proto3" json:"semi_rear_axle_left_2,omitempty"` + SemiRearAxleRight_2 bool `protobuf:"varint,10,opt,name=semi_rear_axle_right_2,json=semiRearAxleRight2,proto3" json:"semi_rear_axle_right_2,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TireLocation) Reset() { + *x = TireLocation{} + mi := &file_vehicle_data_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TireLocation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TireLocation) ProtoMessage() {} + +func (x *TireLocation) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_data_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TireLocation.ProtoReflect.Descriptor instead. +func (*TireLocation) Descriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{2} +} + +func (x *TireLocation) GetFrontLeft() bool { + if x != nil { + return x.FrontLeft + } + return false +} + +func (x *TireLocation) GetFrontRight() bool { + if x != nil { + return x.FrontRight + } + return false +} + +func (x *TireLocation) GetRearLeft() bool { + if x != nil { + return x.RearLeft + } + return false +} + +func (x *TireLocation) GetRearRight() bool { + if x != nil { + return x.RearRight + } + return false +} + +func (x *TireLocation) GetSemiMiddleAxleLeft_2() bool { + if x != nil { + return x.SemiMiddleAxleLeft_2 + } + return false +} + +func (x *TireLocation) GetSemiMiddleAxleRight_2() bool { + if x != nil { + return x.SemiMiddleAxleRight_2 + } + return false +} + +func (x *TireLocation) GetSemiRearAxleLeft() bool { + if x != nil { + return x.SemiRearAxleLeft + } + return false +} + +func (x *TireLocation) GetSemiRearAxleRight() bool { + if x != nil { + return x.SemiRearAxleRight + } + return false +} + +func (x *TireLocation) GetSemiRearAxleLeft_2() bool { + if x != nil { + return x.SemiRearAxleLeft_2 + } + return false +} + +func (x *TireLocation) GetSemiRearAxleRight_2() bool { + if x != nil { + return x.SemiRearAxleRight_2 + } + return false +} + +type Time struct { + state protoimpl.MessageState `protogen:"open.v1"` + Hour int32 `protobuf:"varint,1,opt,name=hour,proto3" json:"hour,omitempty"` + Minute int32 `protobuf:"varint,2,opt,name=minute,proto3" json:"minute,omitempty"` + Second int32 `protobuf:"varint,3,opt,name=second,proto3" json:"second,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Time) Reset() { + *x = Time{} + mi := &file_vehicle_data_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Time) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Time) ProtoMessage() {} + +func (x *Time) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_data_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Time.ProtoReflect.Descriptor instead. +func (*Time) Descriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{3} +} + +func (x *Time) GetHour() int32 { + if x != nil { + return x.Hour + } + return 0 +} + +func (x *Time) GetMinute() int32 { + if x != nil { + return x.Minute + } + return 0 +} + +func (x *Time) GetSecond() int32 { + if x != nil { + return x.Second + } + return 0 +} + +// Value is a dynamic Datum type. Most Datums are strings and is the default format +// Note: Fields may have their types updated with different software and vehicle +// versions to optimize for precision or space +type Value struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Value: + // + // *Value_StringValue + // *Value_IntValue + // *Value_LongValue + // *Value_FloatValue + // *Value_DoubleValue + // *Value_BooleanValue + // *Value_LocationValue + // *Value_ChargingValue + // *Value_ShiftStateValue + // *Value_Invalid + // *Value_LaneAssistLevelValue + // *Value_ScheduledChargingModeValue + // *Value_SentryModeStateValue + // *Value_SpeedAssistLevelValue + // *Value_BmsStateValue + // *Value_BuckleStatusValue + // *Value_CarTypeValue + // *Value_ChargePortValue + // *Value_ChargePortLatchValue + // *Value_DoorValue + // *Value_DriveInverterStateValue + // *Value_HvilStatusValue + // *Value_WindowStateValue + // *Value_SeatFoldPositionValue + // *Value_TractorAirStatusValue + // *Value_FollowDistanceValue + // *Value_ForwardCollisionSensitivityValue + // *Value_GuestModeMobileAccessValue + // *Value_TrailerAirStatusValue + // *Value_TimeValue + // *Value_DetailedChargeStateValue + // *Value_HvacAutoModeValue + // *Value_CabinOverheatProtectionModeValue + // *Value_CabinOverheatProtectionTemperatureLimitValue + // *Value_DefrostModeValue + // *Value_ClimateKeeperModeValue + // *Value_HvacPowerValue + // *Value_TireLocationValue + // *Value_FastChargerValue + // *Value_CableTypeValue + // *Value_TonneauTentModeValue + // *Value_TonneauPositionValue + // *Value_PowershareTypeValue + // *Value_PowershareStateValue + // *Value_PowershareStopReasonValue + // *Value_DisplayStateValue + // *Value_DistanceUnitValue + // *Value_TemperatureUnitValue + // *Value_PressureUnitValue + // *Value_ChargeUnitPreferenceValue + // *Value_TurnSignalStateValue + // *Value_MediaStatusValue + // *Value_SunroofInstalledStateValue + // *Value_CabinPortKeepOnValue + // *Value_CruiseStateValue + // *Value_PowerTransferStatusValue + Value isValue_Value `protobuf_oneof:"value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Value) Reset() { + *x = Value{} + mi := &file_vehicle_data_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Value) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Value) ProtoMessage() {} + +func (x *Value) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_data_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Value.ProtoReflect.Descriptor instead. +func (*Value) Descriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{4} +} + +func (x *Value) GetValue() isValue_Value { + if x != nil { + return x.Value + } + return nil +} + +func (x *Value) GetStringValue() string { + if x != nil { + if x, ok := x.Value.(*Value_StringValue); ok { + return x.StringValue + } + } + return "" +} + +func (x *Value) GetIntValue() int32 { + if x != nil { + if x, ok := x.Value.(*Value_IntValue); ok { + return x.IntValue + } + } + return 0 +} + +func (x *Value) GetLongValue() int64 { + if x != nil { + if x, ok := x.Value.(*Value_LongValue); ok { + return x.LongValue + } + } + return 0 +} + +func (x *Value) GetFloatValue() float32 { + if x != nil { + if x, ok := x.Value.(*Value_FloatValue); ok { + return x.FloatValue + } + } + return 0 +} + +func (x *Value) GetDoubleValue() float64 { + if x != nil { + if x, ok := x.Value.(*Value_DoubleValue); ok { + return x.DoubleValue + } + } + return 0 +} + +func (x *Value) GetBooleanValue() bool { + if x != nil { + if x, ok := x.Value.(*Value_BooleanValue); ok { + return x.BooleanValue + } + } + return false +} + +func (x *Value) GetLocationValue() *LocationValue { + if x != nil { + if x, ok := x.Value.(*Value_LocationValue); ok { + return x.LocationValue + } + } + return nil +} + +func (x *Value) GetChargingValue() ChargingState { + if x != nil { + if x, ok := x.Value.(*Value_ChargingValue); ok { + return x.ChargingValue + } + } + return ChargingState_ChargeStateUnknown +} + +func (x *Value) GetShiftStateValue() ShiftState { + if x != nil { + if x, ok := x.Value.(*Value_ShiftStateValue); ok { + return x.ShiftStateValue + } + } + return ShiftState_ShiftStateUnknown +} + +func (x *Value) GetInvalid() bool { + if x != nil { + if x, ok := x.Value.(*Value_Invalid); ok { + return x.Invalid + } + } + return false +} + +func (x *Value) GetLaneAssistLevelValue() LaneAssistLevel { + if x != nil { + if x, ok := x.Value.(*Value_LaneAssistLevelValue); ok { + return x.LaneAssistLevelValue + } + } + return LaneAssistLevel_LaneAssistLevelUnknown +} + +func (x *Value) GetScheduledChargingModeValue() ScheduledChargingModeValue { + if x != nil { + if x, ok := x.Value.(*Value_ScheduledChargingModeValue); ok { + return x.ScheduledChargingModeValue + } + } + return ScheduledChargingModeValue_ScheduledChargingModeUnknown +} + +func (x *Value) GetSentryModeStateValue() SentryModeState { + if x != nil { + if x, ok := x.Value.(*Value_SentryModeStateValue); ok { + return x.SentryModeStateValue + } + } + return SentryModeState_SentryModeStateUnknown +} + +func (x *Value) GetSpeedAssistLevelValue() SpeedAssistLevel { + if x != nil { + if x, ok := x.Value.(*Value_SpeedAssistLevelValue); ok { + return x.SpeedAssistLevelValue + } + } + return SpeedAssistLevel_SpeedAssistLevelUnknown +} + +func (x *Value) GetBmsStateValue() BMSStateValue { + if x != nil { + if x, ok := x.Value.(*Value_BmsStateValue); ok { + return x.BmsStateValue + } + } + return BMSStateValue_BMSStateUnknown +} + +func (x *Value) GetBuckleStatusValue() BuckleStatus { + if x != nil { + if x, ok := x.Value.(*Value_BuckleStatusValue); ok { + return x.BuckleStatusValue + } + } + return BuckleStatus_BuckleStatusUnknown +} + +func (x *Value) GetCarTypeValue() CarTypeValue { + if x != nil { + if x, ok := x.Value.(*Value_CarTypeValue); ok { + return x.CarTypeValue + } + } + return CarTypeValue_CarTypeUnknown +} + +func (x *Value) GetChargePortValue() ChargePortValue { + if x != nil { + if x, ok := x.Value.(*Value_ChargePortValue); ok { + return x.ChargePortValue + } + } + return ChargePortValue_ChargePortUnknown +} + +func (x *Value) GetChargePortLatchValue() ChargePortLatchValue { + if x != nil { + if x, ok := x.Value.(*Value_ChargePortLatchValue); ok { + return x.ChargePortLatchValue + } + } + return ChargePortLatchValue_ChargePortLatchUnknown +} + +func (x *Value) GetDoorValue() *Doors { + if x != nil { + if x, ok := x.Value.(*Value_DoorValue); ok { + return x.DoorValue + } + } + return nil +} + +func (x *Value) GetDriveInverterStateValue() DriveInverterState { + if x != nil { + if x, ok := x.Value.(*Value_DriveInverterStateValue); ok { + return x.DriveInverterStateValue + } + } + return DriveInverterState_DriveInverterStateUnknown +} + +func (x *Value) GetHvilStatusValue() HvilStatus { + if x != nil { + if x, ok := x.Value.(*Value_HvilStatusValue); ok { + return x.HvilStatusValue + } + } + return HvilStatus_HvilStatusUnknown +} + +func (x *Value) GetWindowStateValue() WindowState { + if x != nil { + if x, ok := x.Value.(*Value_WindowStateValue); ok { + return x.WindowStateValue + } + } + return WindowState_WindowStateUnknown +} + +func (x *Value) GetSeatFoldPositionValue() SeatFoldPosition { + if x != nil { + if x, ok := x.Value.(*Value_SeatFoldPositionValue); ok { + return x.SeatFoldPositionValue + } + } + return SeatFoldPosition_SeatFoldPositionUnknown +} + +func (x *Value) GetTractorAirStatusValue() TractorAirStatus { + if x != nil { + if x, ok := x.Value.(*Value_TractorAirStatusValue); ok { + return x.TractorAirStatusValue + } + } + return TractorAirStatus_TractorAirStatusUnknown +} + +func (x *Value) GetFollowDistanceValue() FollowDistance { + if x != nil { + if x, ok := x.Value.(*Value_FollowDistanceValue); ok { + return x.FollowDistanceValue + } + } + return FollowDistance_FollowDistanceUnknown +} + +func (x *Value) GetForwardCollisionSensitivityValue() ForwardCollisionSensitivity { + if x != nil { + if x, ok := x.Value.(*Value_ForwardCollisionSensitivityValue); ok { + return x.ForwardCollisionSensitivityValue + } + } + return ForwardCollisionSensitivity_ForwardCollisionSensitivityUnknown +} + +func (x *Value) GetGuestModeMobileAccessValue() GuestModeMobileAccess { + if x != nil { + if x, ok := x.Value.(*Value_GuestModeMobileAccessValue); ok { + return x.GuestModeMobileAccessValue + } + } + return GuestModeMobileAccess_GuestModeMobileAccessUnknown +} + +func (x *Value) GetTrailerAirStatusValue() TrailerAirStatus { + if x != nil { + if x, ok := x.Value.(*Value_TrailerAirStatusValue); ok { + return x.TrailerAirStatusValue + } + } + return TrailerAirStatus_TrailerAirStatusUnknown +} + +func (x *Value) GetTimeValue() *Time { + if x != nil { + if x, ok := x.Value.(*Value_TimeValue); ok { + return x.TimeValue + } + } + return nil +} + +func (x *Value) GetDetailedChargeStateValue() DetailedChargeStateValue { + if x != nil { + if x, ok := x.Value.(*Value_DetailedChargeStateValue); ok { + return x.DetailedChargeStateValue + } + } + return DetailedChargeStateValue_DetailedChargeStateUnknown +} + +func (x *Value) GetHvacAutoModeValue() HvacAutoModeState { + if x != nil { + if x, ok := x.Value.(*Value_HvacAutoModeValue); ok { + return x.HvacAutoModeValue + } + } + return HvacAutoModeState_HvacAutoModeStateUnknown +} + +func (x *Value) GetCabinOverheatProtectionModeValue() CabinOverheatProtectionModeState { + if x != nil { + if x, ok := x.Value.(*Value_CabinOverheatProtectionModeValue); ok { + return x.CabinOverheatProtectionModeValue + } + } + return CabinOverheatProtectionModeState_CabinOverheatProtectionModeStateUnknown +} + +func (x *Value) GetCabinOverheatProtectionTemperatureLimitValue() ClimateOverheatProtectionTempLimit { + if x != nil { + if x, ok := x.Value.(*Value_CabinOverheatProtectionTemperatureLimitValue); ok { + return x.CabinOverheatProtectionTemperatureLimitValue + } + } + return ClimateOverheatProtectionTempLimit_ClimateOverheatProtectionTempLimitUnknown +} + +func (x *Value) GetDefrostModeValue() DefrostModeState { + if x != nil { + if x, ok := x.Value.(*Value_DefrostModeValue); ok { + return x.DefrostModeValue + } + } + return DefrostModeState_DefrostModeStateUnknown +} + +func (x *Value) GetClimateKeeperModeValue() ClimateKeeperModeState { + if x != nil { + if x, ok := x.Value.(*Value_ClimateKeeperModeValue); ok { + return x.ClimateKeeperModeValue + } + } + return ClimateKeeperModeState_ClimateKeeperModeStateUnknown +} + +func (x *Value) GetHvacPowerValue() HvacPowerState { + if x != nil { + if x, ok := x.Value.(*Value_HvacPowerValue); ok { + return x.HvacPowerValue + } + } + return HvacPowerState_HvacPowerStateUnknown +} + +func (x *Value) GetTireLocationValue() *TireLocation { + if x != nil { + if x, ok := x.Value.(*Value_TireLocationValue); ok { + return x.TireLocationValue + } + } + return nil +} + +func (x *Value) GetFastChargerValue() FastCharger { + if x != nil { + if x, ok := x.Value.(*Value_FastChargerValue); ok { + return x.FastChargerValue + } + } + return FastCharger_FastChargerUnknown +} + +func (x *Value) GetCableTypeValue() CableType { + if x != nil { + if x, ok := x.Value.(*Value_CableTypeValue); ok { + return x.CableTypeValue + } + } + return CableType_CableTypeUnknown +} + +func (x *Value) GetTonneauTentModeValue() TonneauTentModeState { + if x != nil { + if x, ok := x.Value.(*Value_TonneauTentModeValue); ok { + return x.TonneauTentModeValue + } + } + return TonneauTentModeState_TonneauTentModeStateUnknown +} + +func (x *Value) GetTonneauPositionValue() TonneauPositionState { + if x != nil { + if x, ok := x.Value.(*Value_TonneauPositionValue); ok { + return x.TonneauPositionValue + } + } + return TonneauPositionState_TonneauPositionStateUnknown +} + +func (x *Value) GetPowershareTypeValue() PowershareTypeStatus { + if x != nil { + if x, ok := x.Value.(*Value_PowershareTypeValue); ok { + return x.PowershareTypeValue + } + } + return PowershareTypeStatus_PowershareTypeStatusUnknown +} + +func (x *Value) GetPowershareStateValue() PowershareState { + if x != nil { + if x, ok := x.Value.(*Value_PowershareStateValue); ok { + return x.PowershareStateValue + } + } + return PowershareState_PowershareStateUnknown +} + +func (x *Value) GetPowershareStopReasonValue() PowershareStopReasonStatus { + if x != nil { + if x, ok := x.Value.(*Value_PowershareStopReasonValue); ok { + return x.PowershareStopReasonValue + } + } + return PowershareStopReasonStatus_PowershareStopReasonStatusUnknown +} + +func (x *Value) GetDisplayStateValue() DisplayState { + if x != nil { + if x, ok := x.Value.(*Value_DisplayStateValue); ok { + return x.DisplayStateValue + } + } + return DisplayState_DisplayStateUnknown +} + +func (x *Value) GetDistanceUnitValue() DistanceUnit { + if x != nil { + if x, ok := x.Value.(*Value_DistanceUnitValue); ok { + return x.DistanceUnitValue + } + } + return DistanceUnit_DistanceUnitUnknown +} + +func (x *Value) GetTemperatureUnitValue() TemperatureUnit { + if x != nil { + if x, ok := x.Value.(*Value_TemperatureUnitValue); ok { + return x.TemperatureUnitValue + } + } + return TemperatureUnit_TemperatureUnitUnknown +} + +func (x *Value) GetPressureUnitValue() PressureUnit { + if x != nil { + if x, ok := x.Value.(*Value_PressureUnitValue); ok { + return x.PressureUnitValue + } + } + return PressureUnit_PressureUnitUnknown +} + +func (x *Value) GetChargeUnitPreferenceValue() ChargeUnitPreference { + if x != nil { + if x, ok := x.Value.(*Value_ChargeUnitPreferenceValue); ok { + return x.ChargeUnitPreferenceValue + } + } + return ChargeUnitPreference_ChargeUnitUnknown +} + +func (x *Value) GetTurnSignalStateValue() TurnSignalState { + if x != nil { + if x, ok := x.Value.(*Value_TurnSignalStateValue); ok { + return x.TurnSignalStateValue + } + } + return TurnSignalState_TurnSignalStateUnknown +} + +func (x *Value) GetMediaStatusValue() MediaStatus { + if x != nil { + if x, ok := x.Value.(*Value_MediaStatusValue); ok { + return x.MediaStatusValue + } + } + return MediaStatus_MediaStatusUnknown +} + +func (x *Value) GetSunroofInstalledStateValue() SunroofInstalledState { + if x != nil { + if x, ok := x.Value.(*Value_SunroofInstalledStateValue); ok { + return x.SunroofInstalledStateValue + } + } + return SunroofInstalledState_SunroofInstalledStateUnknown +} + +func (x *Value) GetCabinPortKeepOnValue() CabinPortKeepOnState { + if x != nil { + if x, ok := x.Value.(*Value_CabinPortKeepOnValue); ok { + return x.CabinPortKeepOnValue + } + } + return CabinPortKeepOnState_CabinPortKeepOnStateUnknown +} + +func (x *Value) GetCruiseStateValue() CruiseStateValue { + if x != nil { + if x, ok := x.Value.(*Value_CruiseStateValue); ok { + return x.CruiseStateValue + } + } + return CruiseStateValue_CruiseStateUnknown +} + +func (x *Value) GetPowerTransferStatusValue() PowerTransferStatusValue { + if x != nil { + if x, ok := x.Value.(*Value_PowerTransferStatusValue); ok { + return x.PowerTransferStatusValue + } + } + return PowerTransferStatusValue_PowerTransferStatusUnknown +} + +type isValue_Value interface { + isValue_Value() +} + +type Value_StringValue struct { + StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof"` +} + +type Value_IntValue struct { + IntValue int32 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` +} + +type Value_LongValue struct { + LongValue int64 `protobuf:"varint,3,opt,name=long_value,json=longValue,proto3,oneof"` +} + +type Value_FloatValue struct { + FloatValue float32 `protobuf:"fixed32,4,opt,name=float_value,json=floatValue,proto3,oneof"` +} + +type Value_DoubleValue struct { + DoubleValue float64 `protobuf:"fixed64,5,opt,name=double_value,json=doubleValue,proto3,oneof"` +} + +type Value_BooleanValue struct { + BooleanValue bool `protobuf:"varint,6,opt,name=boolean_value,json=booleanValue,proto3,oneof"` +} + +type Value_LocationValue struct { + LocationValue *LocationValue `protobuf:"bytes,7,opt,name=location_value,json=locationValue,proto3,oneof"` +} + +type Value_ChargingValue struct { + ChargingValue ChargingState `protobuf:"varint,8,opt,name=charging_value,json=chargingValue,proto3,enum=telemetry.vehicle_data.ChargingState,oneof"` +} + +type Value_ShiftStateValue struct { + ShiftStateValue ShiftState `protobuf:"varint,9,opt,name=shift_state_value,json=shiftStateValue,proto3,enum=telemetry.vehicle_data.ShiftState,oneof"` +} + +type Value_Invalid struct { + Invalid bool `protobuf:"varint,10,opt,name=invalid,proto3,oneof"` +} + +type Value_LaneAssistLevelValue struct { + LaneAssistLevelValue LaneAssistLevel `protobuf:"varint,11,opt,name=lane_assist_level_value,json=laneAssistLevelValue,proto3,enum=telemetry.vehicle_data.LaneAssistLevel,oneof"` +} + +type Value_ScheduledChargingModeValue struct { + ScheduledChargingModeValue ScheduledChargingModeValue `protobuf:"varint,12,opt,name=scheduled_charging_mode_value,json=scheduledChargingModeValue,proto3,enum=telemetry.vehicle_data.ScheduledChargingModeValue,oneof"` +} + +type Value_SentryModeStateValue struct { + SentryModeStateValue SentryModeState `protobuf:"varint,13,opt,name=sentry_mode_state_value,json=sentryModeStateValue,proto3,enum=telemetry.vehicle_data.SentryModeState,oneof"` +} + +type Value_SpeedAssistLevelValue struct { + SpeedAssistLevelValue SpeedAssistLevel `protobuf:"varint,14,opt,name=speed_assist_level_value,json=speedAssistLevelValue,proto3,enum=telemetry.vehicle_data.SpeedAssistLevel,oneof"` +} + +type Value_BmsStateValue struct { + BmsStateValue BMSStateValue `protobuf:"varint,15,opt,name=bms_state_value,json=bmsStateValue,proto3,enum=telemetry.vehicle_data.BMSStateValue,oneof"` +} + +type Value_BuckleStatusValue struct { + BuckleStatusValue BuckleStatus `protobuf:"varint,16,opt,name=buckle_status_value,json=buckleStatusValue,proto3,enum=telemetry.vehicle_data.BuckleStatus,oneof"` +} + +type Value_CarTypeValue struct { + CarTypeValue CarTypeValue `protobuf:"varint,17,opt,name=car_type_value,json=carTypeValue,proto3,enum=telemetry.vehicle_data.CarTypeValue,oneof"` +} + +type Value_ChargePortValue struct { + ChargePortValue ChargePortValue `protobuf:"varint,18,opt,name=charge_port_value,json=chargePortValue,proto3,enum=telemetry.vehicle_data.ChargePortValue,oneof"` +} + +type Value_ChargePortLatchValue struct { + ChargePortLatchValue ChargePortLatchValue `protobuf:"varint,19,opt,name=charge_port_latch_value,json=chargePortLatchValue,proto3,enum=telemetry.vehicle_data.ChargePortLatchValue,oneof"` +} + +type Value_DoorValue struct { + DoorValue *Doors `protobuf:"bytes,21,opt,name=door_value,json=doorValue,proto3,oneof"` +} + +type Value_DriveInverterStateValue struct { + DriveInverterStateValue DriveInverterState `protobuf:"varint,22,opt,name=drive_inverter_state_value,json=driveInverterStateValue,proto3,enum=telemetry.vehicle_data.DriveInverterState,oneof"` +} + +type Value_HvilStatusValue struct { + HvilStatusValue HvilStatus `protobuf:"varint,23,opt,name=hvil_status_value,json=hvilStatusValue,proto3,enum=telemetry.vehicle_data.HvilStatus,oneof"` +} + +type Value_WindowStateValue struct { + WindowStateValue WindowState `protobuf:"varint,24,opt,name=window_state_value,json=windowStateValue,proto3,enum=telemetry.vehicle_data.WindowState,oneof"` +} + +type Value_SeatFoldPositionValue struct { + SeatFoldPositionValue SeatFoldPosition `protobuf:"varint,25,opt,name=seat_fold_position_value,json=seatFoldPositionValue,proto3,enum=telemetry.vehicle_data.SeatFoldPosition,oneof"` +} + +type Value_TractorAirStatusValue struct { + TractorAirStatusValue TractorAirStatus `protobuf:"varint,26,opt,name=tractor_air_status_value,json=tractorAirStatusValue,proto3,enum=telemetry.vehicle_data.TractorAirStatus,oneof"` +} + +type Value_FollowDistanceValue struct { + FollowDistanceValue FollowDistance `protobuf:"varint,27,opt,name=follow_distance_value,json=followDistanceValue,proto3,enum=telemetry.vehicle_data.FollowDistance,oneof"` +} + +type Value_ForwardCollisionSensitivityValue struct { + ForwardCollisionSensitivityValue ForwardCollisionSensitivity `protobuf:"varint,28,opt,name=forward_collision_sensitivity_value,json=forwardCollisionSensitivityValue,proto3,enum=telemetry.vehicle_data.ForwardCollisionSensitivity,oneof"` +} + +type Value_GuestModeMobileAccessValue struct { + GuestModeMobileAccessValue GuestModeMobileAccess `protobuf:"varint,29,opt,name=guest_mode_mobile_access_value,json=guestModeMobileAccessValue,proto3,enum=telemetry.vehicle_data.GuestModeMobileAccess,oneof"` +} + +type Value_TrailerAirStatusValue struct { + TrailerAirStatusValue TrailerAirStatus `protobuf:"varint,30,opt,name=trailer_air_status_value,json=trailerAirStatusValue,proto3,enum=telemetry.vehicle_data.TrailerAirStatus,oneof"` +} + +type Value_TimeValue struct { + TimeValue *Time `protobuf:"bytes,31,opt,name=time_value,json=timeValue,proto3,oneof"` +} + +type Value_DetailedChargeStateValue struct { + DetailedChargeStateValue DetailedChargeStateValue `protobuf:"varint,32,opt,name=detailed_charge_state_value,json=detailedChargeStateValue,proto3,enum=telemetry.vehicle_data.DetailedChargeStateValue,oneof"` +} + +type Value_HvacAutoModeValue struct { + HvacAutoModeValue HvacAutoModeState `protobuf:"varint,33,opt,name=hvac_auto_mode_value,json=hvacAutoModeValue,proto3,enum=telemetry.vehicle_data.HvacAutoModeState,oneof"` +} + +type Value_CabinOverheatProtectionModeValue struct { + CabinOverheatProtectionModeValue CabinOverheatProtectionModeState `protobuf:"varint,34,opt,name=cabin_overheat_protection_mode_value,json=cabinOverheatProtectionModeValue,proto3,enum=telemetry.vehicle_data.CabinOverheatProtectionModeState,oneof"` +} + +type Value_CabinOverheatProtectionTemperatureLimitValue struct { + CabinOverheatProtectionTemperatureLimitValue ClimateOverheatProtectionTempLimit `protobuf:"varint,35,opt,name=cabin_overheat_protection_temperature_limit_value,json=cabinOverheatProtectionTemperatureLimitValue,proto3,enum=telemetry.vehicle_data.ClimateOverheatProtectionTempLimit,oneof"` +} + +type Value_DefrostModeValue struct { + DefrostModeValue DefrostModeState `protobuf:"varint,36,opt,name=defrost_mode_value,json=defrostModeValue,proto3,enum=telemetry.vehicle_data.DefrostModeState,oneof"` +} + +type Value_ClimateKeeperModeValue struct { + ClimateKeeperModeValue ClimateKeeperModeState `protobuf:"varint,37,opt,name=climate_keeper_mode_value,json=climateKeeperModeValue,proto3,enum=telemetry.vehicle_data.ClimateKeeperModeState,oneof"` +} + +type Value_HvacPowerValue struct { + HvacPowerValue HvacPowerState `protobuf:"varint,38,opt,name=hvac_power_value,json=hvacPowerValue,proto3,enum=telemetry.vehicle_data.HvacPowerState,oneof"` +} + +type Value_TireLocationValue struct { + TireLocationValue *TireLocation `protobuf:"bytes,39,opt,name=tire_location_value,json=tireLocationValue,proto3,oneof"` +} + +type Value_FastChargerValue struct { + FastChargerValue FastCharger `protobuf:"varint,40,opt,name=fast_charger_value,json=fastChargerValue,proto3,enum=telemetry.vehicle_data.FastCharger,oneof"` +} + +type Value_CableTypeValue struct { + CableTypeValue CableType `protobuf:"varint,41,opt,name=cable_type_value,json=cableTypeValue,proto3,enum=telemetry.vehicle_data.CableType,oneof"` +} + +type Value_TonneauTentModeValue struct { + TonneauTentModeValue TonneauTentModeState `protobuf:"varint,42,opt,name=tonneau_tent_mode_value,json=tonneauTentModeValue,proto3,enum=telemetry.vehicle_data.TonneauTentModeState,oneof"` +} + +type Value_TonneauPositionValue struct { + TonneauPositionValue TonneauPositionState `protobuf:"varint,43,opt,name=tonneau_position_value,json=tonneauPositionValue,proto3,enum=telemetry.vehicle_data.TonneauPositionState,oneof"` +} + +type Value_PowershareTypeValue struct { + PowershareTypeValue PowershareTypeStatus `protobuf:"varint,44,opt,name=powershare_type_value,json=powershareTypeValue,proto3,enum=telemetry.vehicle_data.PowershareTypeStatus,oneof"` +} + +type Value_PowershareStateValue struct { + PowershareStateValue PowershareState `protobuf:"varint,45,opt,name=powershare_state_value,json=powershareStateValue,proto3,enum=telemetry.vehicle_data.PowershareState,oneof"` +} + +type Value_PowershareStopReasonValue struct { + PowershareStopReasonValue PowershareStopReasonStatus `protobuf:"varint,46,opt,name=powershare_stop_reason_value,json=powershareStopReasonValue,proto3,enum=telemetry.vehicle_data.PowershareStopReasonStatus,oneof"` +} + +type Value_DisplayStateValue struct { + DisplayStateValue DisplayState `protobuf:"varint,47,opt,name=display_state_value,json=displayStateValue,proto3,enum=telemetry.vehicle_data.DisplayState,oneof"` +} + +type Value_DistanceUnitValue struct { + DistanceUnitValue DistanceUnit `protobuf:"varint,48,opt,name=distance_unit_value,json=distanceUnitValue,proto3,enum=telemetry.vehicle_data.DistanceUnit,oneof"` +} + +type Value_TemperatureUnitValue struct { + TemperatureUnitValue TemperatureUnit `protobuf:"varint,49,opt,name=temperature_unit_value,json=temperatureUnitValue,proto3,enum=telemetry.vehicle_data.TemperatureUnit,oneof"` +} + +type Value_PressureUnitValue struct { + PressureUnitValue PressureUnit `protobuf:"varint,50,opt,name=pressure_unit_value,json=pressureUnitValue,proto3,enum=telemetry.vehicle_data.PressureUnit,oneof"` +} + +type Value_ChargeUnitPreferenceValue struct { + ChargeUnitPreferenceValue ChargeUnitPreference `protobuf:"varint,51,opt,name=charge_unit_preference_value,json=chargeUnitPreferenceValue,proto3,enum=telemetry.vehicle_data.ChargeUnitPreference,oneof"` +} + +type Value_TurnSignalStateValue struct { + TurnSignalStateValue TurnSignalState `protobuf:"varint,52,opt,name=turn_signal_state_value,json=turnSignalStateValue,proto3,enum=telemetry.vehicle_data.TurnSignalState,oneof"` +} + +type Value_MediaStatusValue struct { + MediaStatusValue MediaStatus `protobuf:"varint,53,opt,name=media_status_value,json=mediaStatusValue,proto3,enum=telemetry.vehicle_data.MediaStatus,oneof"` +} + +type Value_SunroofInstalledStateValue struct { + SunroofInstalledStateValue SunroofInstalledState `protobuf:"varint,54,opt,name=sunroof_installed_state_value,json=sunroofInstalledStateValue,proto3,enum=telemetry.vehicle_data.SunroofInstalledState,oneof"` +} + +type Value_CabinPortKeepOnValue struct { + CabinPortKeepOnValue CabinPortKeepOnState `protobuf:"varint,55,opt,name=cabin_port_keep_on_value,json=cabinPortKeepOnValue,proto3,enum=telemetry.vehicle_data.CabinPortKeepOnState,oneof"` +} + +type Value_CruiseStateValue struct { + CruiseStateValue CruiseStateValue `protobuf:"varint,56,opt,name=cruise_state_value,json=cruiseStateValue,proto3,enum=telemetry.vehicle_data.CruiseStateValue,oneof"` +} + +type Value_PowerTransferStatusValue struct { + PowerTransferStatusValue PowerTransferStatusValue `protobuf:"varint,57,opt,name=power_transfer_status_value,json=powerTransferStatusValue,proto3,enum=telemetry.vehicle_data.PowerTransferStatusValue,oneof"` +} + +func (*Value_StringValue) isValue_Value() {} + +func (*Value_IntValue) isValue_Value() {} + +func (*Value_LongValue) isValue_Value() {} + +func (*Value_FloatValue) isValue_Value() {} + +func (*Value_DoubleValue) isValue_Value() {} + +func (*Value_BooleanValue) isValue_Value() {} + +func (*Value_LocationValue) isValue_Value() {} + +func (*Value_ChargingValue) isValue_Value() {} + +func (*Value_ShiftStateValue) isValue_Value() {} + +func (*Value_Invalid) isValue_Value() {} + +func (*Value_LaneAssistLevelValue) isValue_Value() {} + +func (*Value_ScheduledChargingModeValue) isValue_Value() {} + +func (*Value_SentryModeStateValue) isValue_Value() {} + +func (*Value_SpeedAssistLevelValue) isValue_Value() {} + +func (*Value_BmsStateValue) isValue_Value() {} + +func (*Value_BuckleStatusValue) isValue_Value() {} + +func (*Value_CarTypeValue) isValue_Value() {} + +func (*Value_ChargePortValue) isValue_Value() {} + +func (*Value_ChargePortLatchValue) isValue_Value() {} + +func (*Value_DoorValue) isValue_Value() {} + +func (*Value_DriveInverterStateValue) isValue_Value() {} + +func (*Value_HvilStatusValue) isValue_Value() {} + +func (*Value_WindowStateValue) isValue_Value() {} + +func (*Value_SeatFoldPositionValue) isValue_Value() {} + +func (*Value_TractorAirStatusValue) isValue_Value() {} + +func (*Value_FollowDistanceValue) isValue_Value() {} + +func (*Value_ForwardCollisionSensitivityValue) isValue_Value() {} + +func (*Value_GuestModeMobileAccessValue) isValue_Value() {} + +func (*Value_TrailerAirStatusValue) isValue_Value() {} + +func (*Value_TimeValue) isValue_Value() {} + +func (*Value_DetailedChargeStateValue) isValue_Value() {} + +func (*Value_HvacAutoModeValue) isValue_Value() {} + +func (*Value_CabinOverheatProtectionModeValue) isValue_Value() {} + +func (*Value_CabinOverheatProtectionTemperatureLimitValue) isValue_Value() {} + +func (*Value_DefrostModeValue) isValue_Value() {} + +func (*Value_ClimateKeeperModeValue) isValue_Value() {} + +func (*Value_HvacPowerValue) isValue_Value() {} + +func (*Value_TireLocationValue) isValue_Value() {} + +func (*Value_FastChargerValue) isValue_Value() {} + +func (*Value_CableTypeValue) isValue_Value() {} + +func (*Value_TonneauTentModeValue) isValue_Value() {} + +func (*Value_TonneauPositionValue) isValue_Value() {} + +func (*Value_PowershareTypeValue) isValue_Value() {} + +func (*Value_PowershareStateValue) isValue_Value() {} + +func (*Value_PowershareStopReasonValue) isValue_Value() {} + +func (*Value_DisplayStateValue) isValue_Value() {} + +func (*Value_DistanceUnitValue) isValue_Value() {} + +func (*Value_TemperatureUnitValue) isValue_Value() {} + +func (*Value_PressureUnitValue) isValue_Value() {} + +func (*Value_ChargeUnitPreferenceValue) isValue_Value() {} + +func (*Value_TurnSignalStateValue) isValue_Value() {} + +func (*Value_MediaStatusValue) isValue_Value() {} + +func (*Value_SunroofInstalledStateValue) isValue_Value() {} + +func (*Value_CabinPortKeepOnValue) isValue_Value() {} + +func (*Value_CruiseStateValue) isValue_Value() {} + +func (*Value_PowerTransferStatusValue) isValue_Value() {} + +// Datum represents a single field and its value +type Datum struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key Field `protobuf:"varint,1,opt,name=key,proto3,enum=telemetry.vehicle_data.Field" json:"key,omitempty"` + Value *Value `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Datum) Reset() { + *x = Datum{} + mi := &file_vehicle_data_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Datum) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Datum) ProtoMessage() {} + +func (x *Datum) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_data_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Datum.ProtoReflect.Descriptor instead. +func (*Datum) Descriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{5} +} + +func (x *Datum) GetKey() Field { + if x != nil { + return x.Key + } + return Field_Unknown +} + +func (x *Datum) GetValue() *Value { + if x != nil { + return x.Value + } + return nil +} + +// Payload holds a collection of values, and may not have a vin +type Payload struct { + state protoimpl.MessageState `protogen:"open.v1"` + Data []*Datum `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + Vin string `protobuf:"bytes,3,opt,name=vin,proto3" json:"vin,omitempty"` + IsResend bool `protobuf:"varint,4,opt,name=is_resend,json=isResend,proto3" json:"is_resend,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Payload) Reset() { + *x = Payload{} + mi := &file_vehicle_data_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Payload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Payload) ProtoMessage() {} + +func (x *Payload) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_data_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Payload.ProtoReflect.Descriptor instead. +func (*Payload) Descriptor() ([]byte, []int) { + return file_vehicle_data_proto_rawDescGZIP(), []int{6} +} + +func (x *Payload) GetData() []*Datum { + if x != nil { + return x.Data + } + return nil +} + +func (x *Payload) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *Payload) GetVin() string { + if x != nil { + return x.Vin + } + return "" +} + +func (x *Payload) GetIsResend() bool { + if x != nil { + return x.IsResend + } + return false +} + +var File_vehicle_data_proto protoreflect.FileDescriptor + +const file_vehicle_data_proto_rawDesc = "" + + "\n" + + "\x12vehicle_data.proto\x12\x16telemetry.vehicle_data\x1a\x1fgoogle/protobuf/timestamp.proto\"I\n" + + "\rLocationValue\x12\x1a\n" + + "\blatitude\x18\x01 \x01(\x01R\blatitude\x12\x1c\n" + + "\tlongitude\x18\x02 \x01(\x01R\tlongitude\"\xd5\x01\n" + + "\x05Doors\x12 \n" + + "\vDriverFront\x18\x01 \x01(\bR\vDriverFront\x12\x1e\n" + + "\n" + + "DriverRear\x18\x02 \x01(\bR\n" + + "DriverRear\x12&\n" + + "\x0ePassengerFront\x18\x03 \x01(\bR\x0ePassengerFront\x12$\n" + + "\rPassengerRear\x18\x04 \x01(\bR\rPassengerRear\x12\x1e\n" + + "\n" + + "TrunkFront\x18\x05 \x01(\bR\n" + + "TrunkFront\x12\x1c\n" + + "\tTrunkRear\x18\x06 \x01(\bR\tTrunkRear\"\xbe\x03\n" + + "\fTireLocation\x12\x1d\n" + + "\n" + + "front_left\x18\x01 \x01(\bR\tfrontLeft\x12\x1f\n" + + "\vfront_right\x18\x02 \x01(\bR\n" + + "frontRight\x12\x1b\n" + + "\trear_left\x18\x03 \x01(\bR\brearLeft\x12\x1d\n" + + "\n" + + "rear_right\x18\x04 \x01(\bR\trearRight\x124\n" + + "\x17semi_middle_axle_left_2\x18\x05 \x01(\bR\x13semiMiddleAxleLeft2\x126\n" + + "\x18semi_middle_axle_right_2\x18\x06 \x01(\bR\x14semiMiddleAxleRight2\x12-\n" + + "\x13semi_rear_axle_left\x18\a \x01(\bR\x10semiRearAxleLeft\x12/\n" + + "\x14semi_rear_axle_right\x18\b \x01(\bR\x11semiRearAxleRight\x120\n" + + "\x15semi_rear_axle_left_2\x18\t \x01(\bR\x11semiRearAxleLeft2\x122\n" + + "\x16semi_rear_axle_right_2\x18\n" + + " \x01(\bR\x12semiRearAxleRight2\"J\n" + + "\x04Time\x12\x12\n" + + "\x04hour\x18\x01 \x01(\x05R\x04hour\x12\x16\n" + + "\x06minute\x18\x02 \x01(\x05R\x06minute\x12\x16\n" + + "\x06second\x18\x03 \x01(\x05R\x06second\"\xc3'\n" + + "\x05Value\x12#\n" + + "\fstring_value\x18\x01 \x01(\tH\x00R\vstringValue\x12\x1d\n" + + "\tint_value\x18\x02 \x01(\x05H\x00R\bintValue\x12\x1f\n" + + "\n" + + "long_value\x18\x03 \x01(\x03H\x00R\tlongValue\x12!\n" + + "\vfloat_value\x18\x04 \x01(\x02H\x00R\n" + + "floatValue\x12#\n" + + "\fdouble_value\x18\x05 \x01(\x01H\x00R\vdoubleValue\x12%\n" + + "\rboolean_value\x18\x06 \x01(\bH\x00R\fbooleanValue\x12N\n" + + "\x0elocation_value\x18\a \x01(\v2%.telemetry.vehicle_data.LocationValueH\x00R\rlocationValue\x12N\n" + + "\x0echarging_value\x18\b \x01(\x0e2%.telemetry.vehicle_data.ChargingStateH\x00R\rchargingValue\x12P\n" + + "\x11shift_state_value\x18\t \x01(\x0e2\".telemetry.vehicle_data.ShiftStateH\x00R\x0fshiftStateValue\x12\x1a\n" + + "\ainvalid\x18\n" + + " \x01(\bH\x00R\ainvalid\x12`\n" + + "\x17lane_assist_level_value\x18\v \x01(\x0e2'.telemetry.vehicle_data.LaneAssistLevelH\x00R\x14laneAssistLevelValue\x12w\n" + + "\x1dscheduled_charging_mode_value\x18\f \x01(\x0e22.telemetry.vehicle_data.ScheduledChargingModeValueH\x00R\x1ascheduledChargingModeValue\x12`\n" + + "\x17sentry_mode_state_value\x18\r \x01(\x0e2'.telemetry.vehicle_data.SentryModeStateH\x00R\x14sentryModeStateValue\x12c\n" + + "\x18speed_assist_level_value\x18\x0e \x01(\x0e2(.telemetry.vehicle_data.SpeedAssistLevelH\x00R\x15speedAssistLevelValue\x12O\n" + + "\x0fbms_state_value\x18\x0f \x01(\x0e2%.telemetry.vehicle_data.BMSStateValueH\x00R\rbmsStateValue\x12V\n" + + "\x13buckle_status_value\x18\x10 \x01(\x0e2$.telemetry.vehicle_data.BuckleStatusH\x00R\x11buckleStatusValue\x12L\n" + + "\x0ecar_type_value\x18\x11 \x01(\x0e2$.telemetry.vehicle_data.CarTypeValueH\x00R\fcarTypeValue\x12U\n" + + "\x11charge_port_value\x18\x12 \x01(\x0e2'.telemetry.vehicle_data.ChargePortValueH\x00R\x0fchargePortValue\x12e\n" + + "\x17charge_port_latch_value\x18\x13 \x01(\x0e2,.telemetry.vehicle_data.ChargePortLatchValueH\x00R\x14chargePortLatchValue\x12>\n" + + "\n" + + "door_value\x18\x15 \x01(\v2\x1d.telemetry.vehicle_data.DoorsH\x00R\tdoorValue\x12i\n" + + "\x1adrive_inverter_state_value\x18\x16 \x01(\x0e2*.telemetry.vehicle_data.DriveInverterStateH\x00R\x17driveInverterStateValue\x12P\n" + + "\x11hvil_status_value\x18\x17 \x01(\x0e2\".telemetry.vehicle_data.HvilStatusH\x00R\x0fhvilStatusValue\x12S\n" + + "\x12window_state_value\x18\x18 \x01(\x0e2#.telemetry.vehicle_data.WindowStateH\x00R\x10windowStateValue\x12c\n" + + "\x18seat_fold_position_value\x18\x19 \x01(\x0e2(.telemetry.vehicle_data.SeatFoldPositionH\x00R\x15seatFoldPositionValue\x12c\n" + + "\x18tractor_air_status_value\x18\x1a \x01(\x0e2(.telemetry.vehicle_data.TractorAirStatusH\x00R\x15tractorAirStatusValue\x12\\\n" + + "\x15follow_distance_value\x18\x1b \x01(\x0e2&.telemetry.vehicle_data.FollowDistanceH\x00R\x13followDistanceValue\x12\x84\x01\n" + + "#forward_collision_sensitivity_value\x18\x1c \x01(\x0e23.telemetry.vehicle_data.ForwardCollisionSensitivityH\x00R forwardCollisionSensitivityValue\x12s\n" + + "\x1eguest_mode_mobile_access_value\x18\x1d \x01(\x0e2-.telemetry.vehicle_data.GuestModeMobileAccessH\x00R\x1aguestModeMobileAccessValue\x12c\n" + + "\x18trailer_air_status_value\x18\x1e \x01(\x0e2(.telemetry.vehicle_data.TrailerAirStatusH\x00R\x15trailerAirStatusValue\x12=\n" + + "\n" + + "time_value\x18\x1f \x01(\v2\x1c.telemetry.vehicle_data.TimeH\x00R\ttimeValue\x12q\n" + + "\x1bdetailed_charge_state_value\x18 \x01(\x0e20.telemetry.vehicle_data.DetailedChargeStateValueH\x00R\x18detailedChargeStateValue\x12\\\n" + + "\x14hvac_auto_mode_value\x18! \x01(\x0e2).telemetry.vehicle_data.HvacAutoModeStateH\x00R\x11hvacAutoModeValue\x12\x8a\x01\n" + + "$cabin_overheat_protection_mode_value\x18\" \x01(\x0e28.telemetry.vehicle_data.CabinOverheatProtectionModeStateH\x00R cabinOverheatProtectionModeValue\x12\xa5\x01\n" + + "1cabin_overheat_protection_temperature_limit_value\x18# \x01(\x0e2:.telemetry.vehicle_data.ClimateOverheatProtectionTempLimitH\x00R,cabinOverheatProtectionTemperatureLimitValue\x12X\n" + + "\x12defrost_mode_value\x18$ \x01(\x0e2(.telemetry.vehicle_data.DefrostModeStateH\x00R\x10defrostModeValue\x12k\n" + + "\x19climate_keeper_mode_value\x18% \x01(\x0e2..telemetry.vehicle_data.ClimateKeeperModeStateH\x00R\x16climateKeeperModeValue\x12R\n" + + "\x10hvac_power_value\x18& \x01(\x0e2&.telemetry.vehicle_data.HvacPowerStateH\x00R\x0ehvacPowerValue\x12V\n" + + "\x13tire_location_value\x18' \x01(\v2$.telemetry.vehicle_data.TireLocationH\x00R\x11tireLocationValue\x12S\n" + + "\x12fast_charger_value\x18( \x01(\x0e2#.telemetry.vehicle_data.FastChargerH\x00R\x10fastChargerValue\x12M\n" + + "\x10cable_type_value\x18) \x01(\x0e2!.telemetry.vehicle_data.CableTypeH\x00R\x0ecableTypeValue\x12e\n" + + "\x17tonneau_tent_mode_value\x18* \x01(\x0e2,.telemetry.vehicle_data.TonneauTentModeStateH\x00R\x14tonneauTentModeValue\x12d\n" + + "\x16tonneau_position_value\x18+ \x01(\x0e2,.telemetry.vehicle_data.TonneauPositionStateH\x00R\x14tonneauPositionValue\x12b\n" + + "\x15powershare_type_value\x18, \x01(\x0e2,.telemetry.vehicle_data.PowershareTypeStatusH\x00R\x13powershareTypeValue\x12_\n" + + "\x16powershare_state_value\x18- \x01(\x0e2'.telemetry.vehicle_data.PowershareStateH\x00R\x14powershareStateValue\x12u\n" + + "\x1cpowershare_stop_reason_value\x18. \x01(\x0e22.telemetry.vehicle_data.PowershareStopReasonStatusH\x00R\x19powershareStopReasonValue\x12V\n" + + "\x13display_state_value\x18/ \x01(\x0e2$.telemetry.vehicle_data.DisplayStateH\x00R\x11displayStateValue\x12V\n" + + "\x13distance_unit_value\x180 \x01(\x0e2$.telemetry.vehicle_data.DistanceUnitH\x00R\x11distanceUnitValue\x12_\n" + + "\x16temperature_unit_value\x181 \x01(\x0e2'.telemetry.vehicle_data.TemperatureUnitH\x00R\x14temperatureUnitValue\x12V\n" + + "\x13pressure_unit_value\x182 \x01(\x0e2$.telemetry.vehicle_data.PressureUnitH\x00R\x11pressureUnitValue\x12o\n" + + "\x1ccharge_unit_preference_value\x183 \x01(\x0e2,.telemetry.vehicle_data.ChargeUnitPreferenceH\x00R\x19chargeUnitPreferenceValue\x12`\n" + + "\x17turn_signal_state_value\x184 \x01(\x0e2'.telemetry.vehicle_data.TurnSignalStateH\x00R\x14turnSignalStateValue\x12S\n" + + "\x12media_status_value\x185 \x01(\x0e2#.telemetry.vehicle_data.MediaStatusH\x00R\x10mediaStatusValue\x12r\n" + + "\x1dsunroof_installed_state_value\x186 \x01(\x0e2-.telemetry.vehicle_data.SunroofInstalledStateH\x00R\x1asunroofInstalledStateValue\x12f\n" + + "\x18cabin_port_keep_on_value\x187 \x01(\x0e2,.telemetry.vehicle_data.CabinPortKeepOnStateH\x00R\x14cabinPortKeepOnValue\x12X\n" + + "\x12cruise_state_value\x188 \x01(\x0e2(.telemetry.vehicle_data.CruiseStateValueH\x00R\x10cruiseStateValue\x12q\n" + + "\x1bpower_transfer_status_value\x189 \x01(\x0e20.telemetry.vehicle_data.PowerTransferStatusValueH\x00R\x18powerTransferStatusValueB\a\n" + + "\x05value\"m\n" + + "\x05Datum\x12/\n" + + "\x03key\x18\x01 \x01(\x0e2\x1d.telemetry.vehicle_data.FieldR\x03key\x123\n" + + "\x05value\x18\x02 \x01(\v2\x1d.telemetry.vehicle_data.ValueR\x05value\"\xa6\x01\n" + + "\aPayload\x121\n" + + "\x04data\x18\x01 \x03(\v2\x1d.telemetry.vehicle_data.DatumR\x04data\x129\n" + + "\n" + + "created_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x10\n" + + "\x03vin\x18\x03 \x01(\tR\x03vin\x12\x1b\n" + + "\tis_resend\x18\x04 \x01(\bR\bisResend*\xee3\n" + + "\x05Field\x12\v\n" + + "\aUnknown\x10\x00\x12\r\n" + + "\tDriveRail\x10\x01\x12\x0f\n" + + "\vChargeState\x10\x02\x12\x19\n" + + "\x15BmsFullchargecomplete\x10\x03\x12\x10\n" + + "\fVehicleSpeed\x10\x04\x12\f\n" + + "\bOdometer\x10\x05\x12\x0f\n" + + "\vPackVoltage\x10\x06\x12\x0f\n" + + "\vPackCurrent\x10\a\x12\a\n" + + "\x03Soc\x10\b\x12\x0e\n" + + "\n" + + "DCDCEnable\x10\t\x12\b\n" + + "\x04Gear\x10\n" + + "\x12\x17\n" + + "\x13IsolationResistance\x10\v\x12\x11\n" + + "\rPedalPosition\x10\f\x12\x0e\n" + + "\n" + + "BrakePedal\x10\r\x12\f\n" + + "\bDiStateR\x10\x0e\x12\x10\n" + + "\fDiHeatsinkTR\x10\x0f\x12\x10\n" + + "\fDiAxleSpeedR\x10\x10\x12\x11\n" + + "\rDiTorquemotor\x10\x11\x12\x11\n" + + "\rDiStatorTempR\x10\x12\x12\v\n" + + "\aDiVBatR\x10\x13\x12\x13\n" + + "\x0fDiMotorCurrentR\x10\x14\x12\f\n" + + "\bLocation\x10\x15\x12\f\n" + + "\bGpsState\x10\x16\x12\x0e\n" + + "\n" + + "GpsHeading\x10\x17\x12\x16\n" + + "\x12NumBrickVoltageMax\x10\x18\x12\x13\n" + + "\x0fBrickVoltageMax\x10\x19\x12\x16\n" + + "\x12NumBrickVoltageMin\x10\x1a\x12\x13\n" + + "\x0fBrickVoltageMin\x10\x1b\x12\x14\n" + + "\x10NumModuleTempMax\x10\x1c\x12\x11\n" + + "\rModuleTempMax\x10\x1d\x12\x14\n" + + "\x10NumModuleTempMin\x10\x1e\x12\x11\n" + + "\rModuleTempMin\x10\x1f\x12\x0e\n" + + "\n" + + "RatedRange\x10 \x12\b\n" + + "\x04Hvil\x10!\x12\x16\n" + + "\x12DCChargingEnergyIn\x10\"\x12\x13\n" + + "\x0fDCChargingPower\x10#\x12\x16\n" + + "\x12ACChargingEnergyIn\x10$\x12\x13\n" + + "\x0fACChargingPower\x10%\x12\x12\n" + + "\x0eChargeLimitSoc\x10&\x12\x16\n" + + "\x12FastChargerPresent\x10'\x12\x13\n" + + "\x0fEstBatteryRange\x10(\x12\x15\n" + + "\x11IdealBatteryRange\x10)\x12\x10\n" + + "\fBatteryLevel\x10*\x12\x14\n" + + "\x10TimeToFullCharge\x10+\x12\x1e\n" + + "\x1aScheduledChargingStartTime\x10,\x12\x1c\n" + + "\x18ScheduledChargingPending\x10-\x12\x1a\n" + + "\x16ScheduledDepartureTime\x10.\x12\x1a\n" + + "\x16PreconditioningEnabled\x10/\x12\x19\n" + + "\x15ScheduledChargingMode\x100\x12\x0e\n" + + "\n" + + "ChargeAmps\x101\x12\x17\n" + + "\x13ChargeEnableRequest\x102\x12\x11\n" + + "\rChargerPhases\x103\x12\x1d\n" + + "\x19ChargePortColdWeatherMode\x104\x12\x18\n" + + "\x14ChargeCurrentRequest\x105\x12\x1b\n" + + "\x17ChargeCurrentRequestMax\x106\x12\x13\n" + + "\x0fBatteryHeaterOn\x107\x12\x18\n" + + "\x14NotEnoughPowerToHeat\x108\x12\"\n" + + "\x1eSuperchargerSessionTripPlanner\x109\x12\r\n" + + "\tDoorState\x10:\x12\n" + + "\n" + + "\x06Locked\x10;\x12\f\n" + + "\bFdWindow\x10<\x12\f\n" + + "\bFpWindow\x10=\x12\f\n" + + "\bRdWindow\x10>\x12\f\n" + + "\bRpWindow\x10?\x12\x0f\n" + + "\vVehicleName\x10@\x12\x0e\n" + + "\n" + + "SentryMode\x10A\x12\x12\n" + + "\x0eSpeedLimitMode\x10B\x12\x13\n" + + "\x0fCurrentLimitMph\x10C\x12\v\n" + + "\aVersion\x10D\x12\x12\n" + + "\x0eTpmsPressureFl\x10E\x12\x12\n" + + "\x0eTpmsPressureFr\x10F\x12\x12\n" + + "\x0eTpmsPressureRl\x10G\x12\x12\n" + + "\x0eTpmsPressureRr\x10H\x12\x1e\n" + + "\x1aSemitruckTpmsPressureRe1L0\x10I\x12\x1e\n" + + "\x1aSemitruckTpmsPressureRe1L1\x10J\x12\x1e\n" + + "\x1aSemitruckTpmsPressureRe1R0\x10K\x12\x1e\n" + + "\x1aSemitruckTpmsPressureRe1R1\x10L\x12\x1e\n" + + "\x1aSemitruckTpmsPressureRe2L0\x10M\x12\x1e\n" + + "\x1aSemitruckTpmsPressureRe2L1\x10N\x12\x1e\n" + + "\x1aSemitruckTpmsPressureRe2R0\x10O\x12\x1e\n" + + "\x1aSemitruckTpmsPressureRe2R1\x10P\x12\x1e\n" + + "\x1aTpmsLastSeenPressureTimeFl\x10Q\x12\x1e\n" + + "\x1aTpmsLastSeenPressureTimeFr\x10R\x12\x1e\n" + + "\x1aTpmsLastSeenPressureTimeRl\x10S\x12\x1e\n" + + "\x1aTpmsLastSeenPressureTimeRr\x10T\x12\x0e\n" + + "\n" + + "InsideTemp\x10U\x12\x0f\n" + + "\vOutsideTemp\x10V\x12\x12\n" + + "\x0eSeatHeaterLeft\x10W\x12\x13\n" + + "\x0fSeatHeaterRight\x10X\x12\x16\n" + + "\x12SeatHeaterRearLeft\x10Y\x12\x17\n" + + "\x13SeatHeaterRearRight\x10Z\x12\x18\n" + + "\x14SeatHeaterRearCenter\x10[\x12\x17\n" + + "\x13AutoSeatClimateLeft\x10\\\x12\x18\n" + + "\x14AutoSeatClimateRight\x10]\x12\x12\n" + + "\x0eDriverSeatBelt\x10^\x12\x15\n" + + "\x11PassengerSeatBelt\x10_\x12\x16\n" + + "\x12DriverSeatOccupied\x10`\x12&\n" + + "\"SemitruckPassengerSeatFoldPosition\x10a\x12\x17\n" + + "\x13LateralAcceleration\x10b\x12\x1c\n" + + "\x18LongitudinalAcceleration\x10c\x12\x10\n" + + "\fDeprecated_2\x10d\x12\x12\n" + + "\x0eCruiseSetSpeed\x10e\x12\x16\n" + + "\x12LifetimeEnergyUsed\x10f\x12\x1b\n" + + "\x17LifetimeEnergyUsedDrive\x10g\x12#\n" + + "\x1fSemitruckTractorParkBrakeStatus\x10h\x12#\n" + + "\x1fSemitruckTrailerParkBrakeStatus\x10i\x12\x11\n" + + "\rBrakePedalPos\x10j\x12\x14\n" + + "\x10RouteLastUpdated\x10k\x12\r\n" + + "\tRouteLine\x10l\x12\x12\n" + + "\x0eMilesToArrival\x10m\x12\x14\n" + + "\x10MinutesToArrival\x10n\x12\x12\n" + + "\x0eOriginLocation\x10o\x12\x17\n" + + "\x13DestinationLocation\x10p\x12\v\n" + + "\aCarType\x10q\x12\b\n" + + "\x04Trim\x10r\x12\x11\n" + + "\rExteriorColor\x10s\x12\r\n" + + "\tRoofColor\x10t\x12\x0e\n" + + "\n" + + "ChargePort\x10u\x12\x13\n" + + "\x0fChargePortLatch\x10v\x12\x12\n" + + "\x0eExperimental_1\x10w\x12\x12\n" + + "\x0eExperimental_2\x10x\x12\x12\n" + + "\x0eExperimental_3\x10y\x12\x12\n" + + "\x0eExperimental_4\x10z\x12\x14\n" + + "\x10GuestModeEnabled\x10{\x12\x15\n" + + "\x11PinToDriveEnabled\x10|\x12\x1e\n" + + "\x1aPairedPhoneKeyAndKeyFobQty\x10}\x12\x18\n" + + "\x14CruiseFollowDistance\x10~\x12\x1c\n" + + "\x18AutomaticBlindSpotCamera\x10\x7f\x12#\n" + + "\x1eBlindSpotCollisionWarningChime\x10\x80\x01\x12\x16\n" + + "\x11SpeedLimitWarning\x10\x81\x01\x12\x1c\n" + + "\x17ForwardCollisionWarning\x10\x82\x01\x12\x1b\n" + + "\x16LaneDepartureAvoidance\x10\x83\x01\x12$\n" + + "\x1fEmergencyLaneDepartureAvoidance\x10\x84\x01\x12!\n" + + "\x1cAutomaticEmergencyBrakingOff\x10\x85\x01\x12\x1e\n" + + "\x19LifetimeEnergyGainedRegen\x10\x86\x01\x12\r\n" + + "\bDiStateF\x10\x87\x01\x12\x0f\n" + + "\n" + + "DiStateREL\x10\x88\x01\x12\x0f\n" + + "\n" + + "DiStateRER\x10\x89\x01\x12\x11\n" + + "\fDiHeatsinkTF\x10\x8a\x01\x12\x13\n" + + "\x0eDiHeatsinkTREL\x10\x8b\x01\x12\x13\n" + + "\x0eDiHeatsinkTRER\x10\x8c\x01\x12\x11\n" + + "\fDiAxleSpeedF\x10\x8d\x01\x12\x13\n" + + "\x0eDiAxleSpeedREL\x10\x8e\x01\x12\x13\n" + + "\x0eDiAxleSpeedRER\x10\x8f\x01\x12\x15\n" + + "\x10DiSlaveTorqueCmd\x10\x90\x01\x12\x14\n" + + "\x0fDiTorqueActualR\x10\x91\x01\x12\x14\n" + + "\x0fDiTorqueActualF\x10\x92\x01\x12\x16\n" + + "\x11DiTorqueActualREL\x10\x93\x01\x12\x16\n" + + "\x11DiTorqueActualRER\x10\x94\x01\x12\x12\n" + + "\rDiStatorTempF\x10\x95\x01\x12\x14\n" + + "\x0fDiStatorTempREL\x10\x96\x01\x12\x14\n" + + "\x0fDiStatorTempRER\x10\x97\x01\x12\f\n" + + "\aDiVBatF\x10\x98\x01\x12\x0e\n" + + "\tDiVBatREL\x10\x99\x01\x12\x0e\n" + + "\tDiVBatRER\x10\x9a\x01\x12\x14\n" + + "\x0fDiMotorCurrentF\x10\x9b\x01\x12\x16\n" + + "\x11DiMotorCurrentREL\x10\x9c\x01\x12\x16\n" + + "\x11DiMotorCurrentRER\x10\x9d\x01\x12\x14\n" + + "\x0fEnergyRemaining\x10\x9e\x01\x12\x10\n" + + "\vServiceMode\x10\x9f\x01\x12\r\n" + + "\bBMSState\x10\xa0\x01\x12\x1f\n" + + "\x1aGuestModeMobileAccessState\x10\xa1\x01\x12\x11\n" + + "\fDeprecated_1\x10\xa2\x01\x12\x14\n" + + "\x0fDestinationName\x10\xa3\x01\x12\x11\n" + + "\fDiInverterTR\x10\xa4\x01\x12\x11\n" + + "\fDiInverterTF\x10\xa5\x01\x12\x13\n" + + "\x0eDiInverterTREL\x10\xa6\x01\x12\x13\n" + + "\x0eDiInverterTRER\x10\xa7\x01\x12\x13\n" + + "\x0eExperimental_5\x10\xa8\x01\x12\x13\n" + + "\x0eExperimental_6\x10\xa9\x01\x12\x13\n" + + "\x0eExperimental_7\x10\xaa\x01\x12\x13\n" + + "\x0eExperimental_8\x10\xab\x01\x12\x13\n" + + "\x0eExperimental_9\x10\xac\x01\x12\x14\n" + + "\x0fExperimental_10\x10\xad\x01\x12\x14\n" + + "\x0fExperimental_11\x10\xae\x01\x12\x14\n" + + "\x0fExperimental_12\x10\xaf\x01\x12\x14\n" + + "\x0fExperimental_13\x10\xb0\x01\x12\x14\n" + + "\x0fExperimental_14\x10\xb1\x01\x12\x14\n" + + "\x0fExperimental_15\x10\xb2\x01\x12\x18\n" + + "\x13DetailedChargeState\x10\xb3\x01\x12 \n" + + "\x1bCabinOverheatProtectionMode\x10\xb4\x01\x12,\n" + + "'CabinOverheatProtectionTemperatureLimit\x10\xb5\x01\x12\x12\n" + + "\rCenterDisplay\x10\xb6\x01\x12\x17\n" + + "\x12ChargePortDoorOpen\x10\xb7\x01\x12\x13\n" + + "\x0eChargerVoltage\x10\xb8\x01\x12\x16\n" + + "\x11ChargingCableType\x10\xb9\x01\x12\x16\n" + + "\x11ClimateKeeperMode\x10\xba\x01\x12\x1e\n" + + "\x19DefrostForPreconditioning\x10\xbb\x01\x12\x10\n" + + "\vDefrostMode\x10\xbc\x01\x12\x16\n" + + "\x11EfficiencyPackage\x10\xbd\x01\x12&\n" + + "!EstimatedHoursToChargeTermination\x10\xbe\x01\x12\x12\n" + + "\rEuropeVehicle\x10\xbf\x01\x12'\n" + + "\"ExpectedEnergyPercentAtTripArrival\x10\xc0\x01\x12\x14\n" + + "\x0fFastChargerType\x10\xc1\x01\x12\x18\n" + + "\x13HomelinkDeviceCount\x10\xc2\x01\x12\x13\n" + + "\x0eHomelinkNearby\x10\xc3\x01\x12\x12\n" + + "\rHvacACEnabled\x10\xc4\x01\x12\x11\n" + + "\fHvacAutoMode\x10\xc5\x01\x12\x11\n" + + "\fHvacFanSpeed\x10\xc6\x01\x12\x12\n" + + "\rHvacFanStatus\x10\xc7\x01\x12\x1f\n" + + "\x1aHvacLeftTemperatureRequest\x10\xc8\x01\x12\x0e\n" + + "\tHvacPower\x10\xc9\x01\x12 \n" + + "\x1bHvacRightTemperatureRequest\x10\xca\x01\x12\x1e\n" + + "\x19HvacSteeringWheelHeatAuto\x10\xcb\x01\x12\x1f\n" + + "\x1aHvacSteeringWheelHeatLevel\x10\xcc\x01\x12\x1b\n" + + "\x16OffroadLightbarPresent\x10\xcd\x01\x12\x18\n" + + "\x13PowershareHoursLeft\x10\xce\x01\x12#\n" + + "\x1ePowershareInstantaneousPowerKW\x10\xcf\x01\x12\x15\n" + + "\x10PowershareStatus\x10\xd0\x01\x12\x19\n" + + "\x14PowershareStopReason\x10\xd1\x01\x12\x13\n" + + "\x0ePowershareType\x10\xd2\x01\x12\x1b\n" + + "\x16RearDisplayHvacEnabled\x10\xd3\x01\x12\x14\n" + + "\x0fRearSeatHeaters\x10\xd4\x01\x12\x17\n" + + "\x12RemoteStartEnabled\x10\xd5\x01\x12\x13\n" + + "\x0eRightHandDrive\x10\xd6\x01\x12\x1d\n" + + "\x18RouteTrafficMinutesDelay\x10\xd7\x01\x12*\n" + + "%SoftwareUpdateDownloadPercentComplete\x10\xd8\x01\x12*\n" + + "%SoftwareUpdateExpectedDurationMinutes\x10\xd9\x01\x12.\n" + + ")SoftwareUpdateInstallationPercentComplete\x10\xda\x01\x12%\n" + + " SoftwareUpdateScheduledStartTime\x10\xdb\x01\x12\x1a\n" + + "\x15SoftwareUpdateVersion\x10\xdc\x01\x12\x17\n" + + "\x12TonneauOpenPercent\x10\xdd\x01\x12\x14\n" + + "\x0fTonneauPosition\x10\xde\x01\x12\x14\n" + + "\x0fTonneauTentMode\x10\xdf\x01\x12\x15\n" + + "\x10TpmsHardWarnings\x10\xe0\x01\x12\x15\n" + + "\x10TpmsSoftWarnings\x10\xe1\x01\x12\x15\n" + + "\x10ValetModeEnabled\x10\xe2\x01\x12\x0e\n" + + "\tWheelType\x10\xe3\x01\x12\x15\n" + + "\x10WiperHeatEnabled\x10\xe4\x01\x12\x12\n" + + "\rLocatedAtHome\x10\xe5\x01\x12\x12\n" + + "\rLocatedAtWork\x10\xe6\x01\x12\x16\n" + + "\x11LocatedAtFavorite\x10\xe7\x01\x12\x18\n" + + "\x13SettingDistanceUnit\x10\xe8\x01\x12\x1b\n" + + "\x16SettingTemperatureUnit\x10\xe9\x01\x12\x16\n" + + "\x11Setting24HourTime\x10\xea\x01\x12\x1c\n" + + "\x17SettingTirePressureUnit\x10\xeb\x01\x12\x16\n" + + "\x11SettingChargeUnit\x10\xec\x01\x12 \n" + + "\x1bClimateSeatCoolingFrontLeft\x10\xed\x01\x12!\n" + + "\x1cClimateSeatCoolingFrontRight\x10\xee\x01\x12\x18\n" + + "\x13LightsHazardsActive\x10\xef\x01\x12\x15\n" + + "\x10LightsTurnSignal\x10\xf0\x01\x12\x14\n" + + "\x0fLightsHighBeams\x10\xf1\x01\x12\x18\n" + + "\x13MediaPlaybackStatus\x10\xf2\x01\x12\x18\n" + + "\x13MediaPlaybackSource\x10\xf3\x01\x12\x15\n" + + "\x10MediaAudioVolume\x10\xf4\x01\x12\x1c\n" + + "\x17MediaNowPlayingDuration\x10\xf5\x01\x12\x1b\n" + + "\x16MediaNowPlayingElapsed\x10\xf6\x01\x12\x1a\n" + + "\x15MediaNowPlayingArtist\x10\xf7\x01\x12\x19\n" + + "\x14MediaNowPlayingTitle\x10\xf8\x01\x12\x19\n" + + "\x14MediaNowPlayingAlbum\x10\xf9\x01\x12\x1b\n" + + "\x16MediaNowPlayingStation\x10\xfa\x01\x12\x1e\n" + + "\x19MediaAudioVolumeIncrement\x10\xfb\x01\x12\x18\n" + + "\x13MediaAudioVolumeMax\x10\xfc\x01\x12\x15\n" + + "\x10SunroofInstalled\x10\xfd\x01\x12\x14\n" + + "\x0fSeatVentEnabled\x10\xfe\x01\x12\x17\n" + + "\x12RearDefrostEnabled\x10\xff\x01\x12\x1a\n" + + "\x15ChargeRateMilePerHour\x10\x80\x02\x12\x11\n" + + "\fDeprecated_3\x10\x81\x02\x12\x14\n" + + "\x0fMilesSinceReset\x10\x82\x02\x12\x1f\n" + + "\x1aSelfDrivingMilesSinceReset\x10\x83\x02\x12\x16\n" + + "\x11GpsAccuracyMeters\x10\x84\x02\x12\x1d\n" + + "\x18LifetimeEnergyChargedKwh\x10\x85\x02\x12\x17\n" + + "\x12BrickSocMinPercent\x10\x86\x02\x12\x1d\n" + + "\x18NominalFullPackEnergyKwh\x10\x87\x02\x12\x19\n" + + "\x14GradeEstimatePercent\x10\x88\x02\x12\"\n" + + "\x1dMaxSpeedToReachDestinationMph\x10\x89\x02\x12\x1c\n" + + "\x17SoftwareUpdateAvailable\x10\x8a\x02\x12\x1d\n" + + "\x18SoftwareUpdateInProgress\x10\x8b\x02\x12\x16\n" + + "\x11RemoteStartActive\x10\x8c\x02\x12\x1c\n" + + "\x17SemiCruiseSpeedLimitMph\x10\x8d\x02\x12\x17\n" + + "\x12Cabin12vPortKeepOn\x10\x8e\x02\x12\x17\n" + + "\x12Cabin48vPortKeepOn\x10\x8f\x02\x12\f\n" + + "\aAccRail\x10\x90\x02\x12\x18\n" + + "\x13PowerTransferStatus\x10\x91\x02\x12#\n" + + "\x1eAutomaticEmergencyBrakingState\x10\x92\x02\x12!\n" + + "\x1cRollingResistanceCoefficient\x10\x93\x02\x12\x10\n" + + "\vCruiseState\x10\x94\x02\x12\x1e\n" + + "\x19LifetimeDcChargeEnergyKwh\x10\x95\x02\x12\x12\n" + + "\rVehicleMassKg\x10\x96\x02*\xbf\x01\n" + + "\rChargingState\x12\x16\n" + + "\x12ChargeStateUnknown\x10\x00\x12\x1b\n" + + "\x17ChargeStateDisconnected\x10\x01\x12\x16\n" + + "\x12ChargeStateNoPower\x10\x02\x12\x17\n" + + "\x13ChargeStateStarting\x10\x03\x12\x17\n" + + "\x13ChargeStateCharging\x10\x04\x12\x17\n" + + "\x13ChargeStateComplete\x10\x05\x12\x16\n" + + "\x12ChargeStateStopped\x10\x06*\xa6\x02\n" + + "\x18DetailedChargeStateValue\x12\x1e\n" + + "\x1aDetailedChargeStateUnknown\x10\x00\x12#\n" + + "\x1fDetailedChargeStateDisconnected\x10\x01\x12\x1e\n" + + "\x1aDetailedChargeStateNoPower\x10\x02\x12\x1f\n" + + "\x1bDetailedChargeStateStarting\x10\x03\x12\x1f\n" + + "\x1bDetailedChargeStateCharging\x10\x04\x12\x1f\n" + + "\x1bDetailedChargeStateComplete\x10\x05\x12\x1e\n" + + "\x1aDetailedChargeStateStopped\x10\x06\x12\"\n" + + "\x1eDetailedChargeStateCalibrating\x10\a*\x91\x01\n" + + "\n" + + "ShiftState\x12\x15\n" + + "\x11ShiftStateUnknown\x10\x00\x12\x15\n" + + "\x11ShiftStateInvalid\x10\x01\x12\x0f\n" + + "\vShiftStateP\x10\x02\x12\x0f\n" + + "\vShiftStateR\x10\x03\x12\x0f\n" + + "\vShiftStateN\x10\x04\x12\x0f\n" + + "\vShiftStateD\x10\x05\x12\x11\n" + + "\rShiftStateSNA\x10\x06*\xbe\x01\n" + + "\x0eFollowDistance\x12\x19\n" + + "\x15FollowDistanceUnknown\x10\x00\x12\x13\n" + + "\x0fFollowDistance1\x10\x01\x12\x13\n" + + "\x0fFollowDistance2\x10\x02\x12\x13\n" + + "\x0fFollowDistance3\x10\x03\x12\x13\n" + + "\x0fFollowDistance4\x10\x04\x12\x13\n" + + "\x0fFollowDistance5\x10\x05\x12\x13\n" + + "\x0fFollowDistance6\x10\x06\x12\x13\n" + + "\x0fFollowDistance7\x10\a*\xdc\x01\n" + + "\x1bForwardCollisionSensitivity\x12&\n" + + "\"ForwardCollisionSensitivityUnknown\x10\x00\x12\"\n" + + "\x1eForwardCollisionSensitivityOff\x10\x01\x12#\n" + + "\x1fForwardCollisionSensitivityLate\x10\x02\x12&\n" + + "\"ForwardCollisionSensitivityAverage\x10\x03\x12$\n" + + " ForwardCollisionSensitivityEarly\x10\x04*\xe4\x06\n" + + "\x15GuestModeMobileAccess\x12 \n" + + "\x1cGuestModeMobileAccessUnknown\x10\x00\x12\x1d\n" + + "\x19GuestModeMobileAccessInit\x10\x01\x12)\n" + + "%GuestModeMobileAccessNotAuthenticated\x10\x02\x12&\n" + + "\"GuestModeMobileAccessAuthenticated\x10\x03\x12'\n" + + "#GuestModeMobileAccessAbortedDriving\x10\x04\x120\n" + + ",GuestModeMobileAccessAbortedUsingRemoteStart\x10\x05\x12,\n" + + "(GuestModeMobileAccessAbortedUsingBLEKeys\x10\x06\x12)\n" + + "%GuestModeMobileAccessAbortedValetMode\x10\a\x12,\n" + + "(GuestModeMobileAccessAbortedGuestModeOff\x10\b\x125\n" + + "1GuestModeMobileAccessAbortedDriveAuthTimeExceeded\x10\t\x12.\n" + + "*GuestModeMobileAccessAbortedNoDataReceived\x10\n" + + "\x121\n" + + "-GuestModeMobileAccessRequestingFromMothership\x10\v\x12,\n" + + "(GuestModeMobileAccessRequestingFromAuthD\x10\f\x12+\n" + + "'GuestModeMobileAccessAbortedFetchFailed\x10\r\x12/\n" + + "+GuestModeMobileAccessAbortedBadDataReceived\x10\x0e\x12&\n" + + "\"GuestModeMobileAccessShowingQRCode\x10\x0f\x12#\n" + + "\x1fGuestModeMobileAccessSwipedAway\x10\x10\x12/\n" + + "+GuestModeMobileAccessDismissedQRCodeExpired\x10\x11\x121\n" + + "-GuestModeMobileAccessSucceededPairedNewBLEKey\x10\x12*}\n" + + "\x0fLaneAssistLevel\x12\x1a\n" + + "\x16LaneAssistLevelUnknown\x10\x00\x12\x17\n" + + "\x13LaneAssistLevelNone\x10\x01\x12\x1a\n" + + "\x16LaneAssistLevelWarning\x10\x02\x12\x19\n" + + "\x15LaneAssistLevelAssist\x10\x03*\xa1\x01\n" + + "\x1aScheduledChargingModeValue\x12 \n" + + "\x1cScheduledChargingModeUnknown\x10\x00\x12\x1c\n" + + "\x18ScheduledChargingModeOff\x10\x01\x12 \n" + + "\x1cScheduledChargingModeStartAt\x10\x02\x12!\n" + + "\x1dScheduledChargingModeDepartBy\x10\x03*\xc6\x01\n" + + "\x0fSentryModeState\x12\x1a\n" + + "\x16SentryModeStateUnknown\x10\x00\x12\x16\n" + + "\x12SentryModeStateOff\x10\x01\x12\x17\n" + + "\x13SentryModeStateIdle\x10\x02\x12\x18\n" + + "\x14SentryModeStateArmed\x10\x03\x12\x18\n" + + "\x14SentryModeStateAware\x10\x04\x12\x18\n" + + "\x14SentryModeStatePanic\x10\x05\x12\x18\n" + + "\x14SentryModeStateQuiet\x10\x06*\x81\x01\n" + + "\x10SpeedAssistLevel\x12\x1b\n" + + "\x17SpeedAssistLevelUnknown\x10\x00\x12\x18\n" + + "\x14SpeedAssistLevelNone\x10\x01\x12\x1b\n" + + "\x17SpeedAssistLevelDisplay\x10\x02\x12\x19\n" + + "\x15SpeedAssistLevelChime\x10\x03*\xe7\x01\n" + + "\rBMSStateValue\x12\x13\n" + + "\x0fBMSStateUnknown\x10\x00\x12\x13\n" + + "\x0fBMSStateStandby\x10\x01\x12\x11\n" + + "\rBMSStateDrive\x10\x02\x12\x13\n" + + "\x0fBMSStateSupport\x10\x03\x12\x12\n" + + "\x0eBMSStateCharge\x10\x04\x12\x10\n" + + "\fBMSStateFEIM\x10\x05\x12\x16\n" + + "\x12BMSStateClearFault\x10\x06\x12\x11\n" + + "\rBMSStateFault\x10\a\x12\x10\n" + + "\fBMSStateWeld\x10\b\x12\x10\n" + + "\fBMSStateTest\x10\t\x12\x0f\n" + + "\vBMSStateSNA\x10\n" + + "*\x89\x01\n" + + "\fBuckleStatus\x12\x17\n" + + "\x13BuckleStatusUnknown\x10\x00\x12\x19\n" + + "\x15BuckleStatusUnlatched\x10\x01\x12\x17\n" + + "\x13BuckleStatusLatched\x10\x02\x12\x17\n" + + "\x13BuckleStatusFaulted\x10\x03\x12\x13\n" + + "\x0fBuckleStatusSNA\x10\x04*\xc8\x01\n" + + "\fCarTypeValue\x12\x12\n" + + "\x0eCarTypeUnknown\x10\x00\x12\x11\n" + + "\rCarTypeModelS\x10\x01\x12\x11\n" + + "\rCarTypeModelX\x10\x02\x12\x11\n" + + "\rCarTypeModel3\x10\x03\x12\x11\n" + + "\rCarTypeModelY\x10\x04\x12\x14\n" + + "\x10CarTypeSemiTruck\x10\x05\x12\x15\n" + + "\x11CarTypeCybertruck\x10\x06\x12\x16\n" + + "\x12CarTypeSemiTruckV2\x10\a\x12\x13\n" + + "\x0fCarTypeCybercab\x10\b*q\n" + + "\x0fChargePortValue\x12\x15\n" + + "\x11ChargePortUnknown\x10\x00\x12\x10\n" + + "\fChargePortUS\x10\x01\x12\x10\n" + + "\fChargePortEU\x10\x02\x12\x10\n" + + "\fChargePortGB\x10\x03\x12\x11\n" + + "\rChargePortCCS\x10\x04*\xa2\x01\n" + + "\x14ChargePortLatchValue\x12\x1a\n" + + "\x16ChargePortLatchUnknown\x10\x00\x12\x16\n" + + "\x12ChargePortLatchSNA\x10\x01\x12\x1d\n" + + "\x19ChargePortLatchDisengaged\x10\x02\x12\x1a\n" + + "\x16ChargePortLatchEngaged\x10\x03\x12\x1b\n" + + "\x17ChargePortLatchBlocking\x10\x04*\xcd\x01\n" + + "\x12DriveInverterState\x12\x1d\n" + + "\x19DriveInverterStateUnknown\x10\x00\x12!\n" + + "\x1dDriveInverterStateUnavailable\x10\x01\x12\x1d\n" + + "\x19DriveInverterStateStandby\x10\x02\x12\x1b\n" + + "\x17DriveInverterStateFault\x10\x03\x12\x1b\n" + + "\x17DriveInverterStateAbort\x10\x04\x12\x1c\n" + + "\x18DriveInverterStateEnable\x10\x05*J\n" + + "\n" + + "HvilStatus\x12\x15\n" + + "\x11HvilStatusUnknown\x10\x00\x12\x13\n" + + "\x0fHvilStatusFault\x10\x01\x12\x10\n" + + "\fHvilStatusOK\x10\x02*q\n" + + "\vWindowState\x12\x16\n" + + "\x12WindowStateUnknown\x10\x00\x12\x15\n" + + "\x11WindowStateClosed\x10\x01\x12\x1c\n" + + "\x18WindowStatePartiallyOpen\x10\x02\x12\x15\n" + + "\x11WindowStateOpened\x10\x03*\xc2\x01\n" + + "\x10SeatFoldPosition\x12\x1b\n" + + "\x17SeatFoldPositionUnknown\x10\x00\x12\x17\n" + + "\x13SeatFoldPositionSNA\x10\x01\x12\x1b\n" + + "\x17SeatFoldPositionFaulted\x10\x02\x12!\n" + + "\x1dSeatFoldPositionNotConfigured\x10\x03\x12\x1a\n" + + "\x16SeatFoldPositionFolded\x10\x04\x12\x1c\n" + + "\x18SeatFoldPositionUnfolded\x10\x05*\x8e\x02\n" + + "\x10TractorAirStatus\x12\x1b\n" + + "\x17TractorAirStatusUnknown\x10\x00\x12 \n" + + "\x1cTractorAirStatusNotAvailable\x10\x01\x12\x19\n" + + "\x15TractorAirStatusError\x10\x02\x12\x1b\n" + + "\x17TractorAirStatusCharged\x10\x03\x120\n" + + ",TractorAirStatusBuildingPressureIntermediate\x10\x04\x122\n" + + ".TractorAirStatusExhaustingPressureIntermediate\x10\x05\x12\x1d\n" + + "\x19TractorAirStatusExhausted\x10\x06*\xa8\x02\n" + + "\x10TrailerAirStatus\x12\x1b\n" + + "\x17TrailerAirStatusUnknown\x10\x00\x12\x17\n" + + "\x13TrailerAirStatusSNA\x10\x01\x12\x1b\n" + + "\x17TrailerAirStatusInvalid\x10\x02\x12\x1f\n" + + "\x1bTrailerAirStatusBobtailMode\x10\x03\x12\x1b\n" + + "\x17TrailerAirStatusCharged\x10\x04\x120\n" + + ",TrailerAirStatusBuildingPressureIntermediate\x10\x05\x122\n" + + ".TrailerAirStatusExhaustingPressureIntermediate\x10\x06\x12\x1d\n" + + "\x19TrailerAirStatusExhausted\x10\a*i\n" + + "\x11HvacAutoModeState\x12\x1c\n" + + "\x18HvacAutoModeStateUnknown\x10\x00\x12\x17\n" + + "\x13HvacAutoModeStateOn\x10\x01\x12\x1d\n" + + "\x19HvacAutoModeStateOverride\x10\x02*\xcd\x01\n" + + " CabinOverheatProtectionModeState\x12+\n" + + "'CabinOverheatProtectionModeStateUnknown\x10\x00\x12'\n" + + "#CabinOverheatProtectionModeStateOff\x10\x01\x12&\n" + + "\"CabinOverheatProtectionModeStateOn\x10\x02\x12+\n" + + "'CabinOverheatProtectionModeStateFanOnly\x10\x03*\xd8\x01\n" + + "\"ClimateOverheatProtectionTempLimit\x12-\n" + + ")ClimateOverheatProtectionTempLimitUnknown\x10\x00\x12*\n" + + "&ClimateOverheatProtectionTempLimitHigh\x10\x01\x12,\n" + + "(ClimateOverheatProtectionTempLimitMedium\x10\x02\x12)\n" + + "%ClimateOverheatProtectionTempLimitLow\x10\x03*\x9c\x01\n" + + "\x10DefrostModeState\x12\x1b\n" + + "\x17DefrostModeStateUnknown\x10\x00\x12\x17\n" + + "\x13DefrostModeStateOff\x10\x01\x12\x1a\n" + + "\x16DefrostModeStateNormal\x10\x02\x12\x17\n" + + "\x13DefrostModeStateMax\x10\x03\x12\x1d\n" + + "\x19DefrostModeStateAutoDefog\x10\x04*\xb8\x01\n" + + "\x16ClimateKeeperModeState\x12!\n" + + "\x1dClimateKeeperModeStateUnknown\x10\x00\x12\x1d\n" + + "\x19ClimateKeeperModeStateOff\x10\x01\x12\x1c\n" + + "\x18ClimateKeeperModeStateOn\x10\x02\x12\x1d\n" + + "\x19ClimateKeeperModeStateDog\x10\x03\x12\x1f\n" + + "\x1bClimateKeeperModeStateParty\x10\x04*\x9b\x01\n" + + "\x0eHvacPowerState\x12\x19\n" + + "\x15HvacPowerStateUnknown\x10\x00\x12\x15\n" + + "\x11HvacPowerStateOff\x10\x01\x12\x14\n" + + "\x10HvacPowerStateOn\x10\x02\x12\x1e\n" + + "\x1aHvacPowerStatePrecondition\x10\x03\x12!\n" + + "\x1dHvacPowerStateOverheatProtect\x10\x04*\xed\x01\n" + + "\vFastCharger\x12\x16\n" + + "\x12FastChargerUnknown\x10\x00\x12\x1b\n" + + "\x17FastChargerSupercharger\x10\x01\x12\x16\n" + + "\x12FastChargerCHAdeMO\x10\x02\x12\x11\n" + + "\rFastChargerGB\x10\x03\x12\x1e\n" + + "\x1aFastChargerACSingleWireCAN\x10\x04\x12\x14\n" + + "\x10FastChargerCombo\x10\x05\x12\x1e\n" + + "\x1aFastChargerMCSingleWireCAN\x10\x06\x12\x14\n" + + "\x10FastChargerOther\x10\a\x12\x12\n" + + "\x0eFastChargerSNA\x10\b*\x7f\n" + + "\tCableType\x12\x14\n" + + "\x10CableTypeUnknown\x10\x00\x12\x10\n" + + "\fCableTypeIEC\x10\x01\x12\x10\n" + + "\fCableTypeSAE\x10\x02\x12\x12\n" + + "\x0eCableTypeGB_AC\x10\x03\x12\x12\n" + + "\x0eCableTypeGB_DC\x10\x04\x12\x10\n" + + "\fCableTypeSNA\x10\x05*\xb9\x01\n" + + "\x14TonneauTentModeState\x12\x1f\n" + + "\x1bTonneauTentModeStateUnknown\x10\x00\x12 \n" + + "\x1cTonneauTentModeStateInactive\x10\x01\x12\x1e\n" + + "\x1aTonneauTentModeStateMoving\x10\x02\x12\x1e\n" + + "\x1aTonneauTentModeStateFailed\x10\x03\x12\x1e\n" + + "\x1aTonneauTentModeStateActive\x10\x04*\xc2\x01\n" + + "\x14TonneauPositionState\x12\x1f\n" + + "\x1bTonneauPositionStateUnknown\x10\x00\x12\x1f\n" + + "\x1bTonneauPositionStateInvalid\x10\x01\x12\x1e\n" + + "\x1aTonneauPositionStateClosed\x10\x02\x12%\n" + + "!TonneauPositionStatePartiallyOpen\x10\x03\x12!\n" + + "\x1dTonneauPositionStateFullyOpen\x10\x04*\xe7\x01\n" + + "\x0fPowershareState\x12\x1a\n" + + "\x16PowershareStateUnknown\x10\x00\x12\x1b\n" + + "\x17PowershareStateInactive\x10\x01\x12\x1e\n" + + "\x1aPowershareStateHandshaking\x10\x02\x12\x17\n" + + "\x13PowershareStateInit\x10\x03\x12\x1a\n" + + "\x16PowershareStateEnabled\x10\x04\x12*\n" + + "&PowershareStateEnabledReconnectingSoon\x10\x05\x12\x1a\n" + + "\x16PowershareStateStopped\x10\x06*\xe4\x02\n" + + "\x1aPowershareStopReasonStatus\x12%\n" + + "!PowershareStopReasonStatusUnknown\x10\x00\x12\"\n" + + "\x1ePowershareStopReasonStatusNone\x10\x01\x12'\n" + + "#PowershareStopReasonStatusSOCTooLow\x10\x02\x12#\n" + + "\x1fPowershareStopReasonStatusRetry\x10\x03\x12#\n" + + "\x1fPowershareStopReasonStatusFault\x10\x04\x12\"\n" + + "\x1ePowershareStopReasonStatusUser\x10\x05\x12*\n" + + "&PowershareStopReasonStatusReconnecting\x10\x06\x12,\n" + + "(PowershareStopReasonStatusAuthentication\x10\a\"\x04\b\b\x10\b\"\x04\b\t\x10\t*\x97\x01\n" + + "\x14PowershareTypeStatus\x12\x1f\n" + + "\x1bPowershareTypeStatusUnknown\x10\x00\x12\x1c\n" + + "\x18PowershareTypeStatusNone\x10\x01\x12\x1c\n" + + "\x18PowershareTypeStatusLoad\x10\x02\x12\x1c\n" + + "\x18PowershareTypeStatusHome\x10\x03\"\x04\b\x04\x10\x04*\x95\x02\n" + + "\fDisplayState\x12\x17\n" + + "\x13DisplayStateUnknown\x10\x00\x12\x13\n" + + "\x0fDisplayStateOff\x10\x01\x12\x13\n" + + "\x0fDisplayStateDim\x10\x02\x12\x19\n" + + "\x15DisplayStateAccessory\x10\x03\x12\x12\n" + + "\x0eDisplayStateOn\x10\x04\x12\x17\n" + + "\x13DisplayStateDriving\x10\x05\x12\x18\n" + + "\x14DisplayStateCharging\x10\x06\x12\x14\n" + + "\x10DisplayStateLock\x10\a\x12\x16\n" + + "\x12DisplayStateSentry\x10\b\x12\x13\n" + + "\x0fDisplayStateDog\x10\t\x12\x1d\n" + + "\x19DisplayStateEntertainment\x10\n" + + "*Z\n" + + "\fDistanceUnit\x12\x17\n" + + "\x13DistanceUnitUnknown\x10\x00\x12\x15\n" + + "\x11DistanceUnitMiles\x10\x01\x12\x1a\n" + + "\x16DistanceUnitKilometers\x10\x02*h\n" + + "\x0fTemperatureUnit\x12\x1a\n" + + "\x16TemperatureUnitUnknown\x10\x00\x12\x1d\n" + + "\x19TemperatureUnitFahrenheit\x10\x01\x12\x1a\n" + + "\x16TemperatureUnitCelsius\x10\x02*Q\n" + + "\fPressureUnit\x12\x17\n" + + "\x13PressureUnitUnknown\x10\x00\x12\x13\n" + + "\x0fPressureUnitPsi\x10\x01\x12\x13\n" + + "\x0fPressureUnitBar\x10\x02*\\\n" + + "\x14ChargeUnitPreference\x12\x15\n" + + "\x11ChargeUnitUnknown\x10\x00\x12\x16\n" + + "\x12ChargeUnitDistance\x10\x01\x12\x15\n" + + "\x11ChargeUnitPercent\x10\x02*\xb0\x01\n" + + "\x15SunroofInstalledState\x12 \n" + + "\x1cSunroofInstalledStateUnknown\x10\x00\x12%\n" + + "!SunroofInstalledStateNotInstalled\x10\x01\x12&\n" + + "\"SunroofInstalledStateGen1Installed\x10\x02\x12&\n" + + "\"SunroofInstalledStateGen2Installed\x10\x03*p\n" + + "\x14CabinPortKeepOnState\x12\x1f\n" + + "\x1bCabinPortKeepOnStateUnknown\x10\x00\x12\x1b\n" + + "\x17CabinPortKeepOnStateOff\x10\x01\x12\x1a\n" + + "\x16CabinPortKeepOnStateOn\x10\x02*\xe6\x01\n" + + "\x10CruiseStateValue\x12\x16\n" + + "\x12CruiseStateUnknown\x10\x00\x12\x12\n" + + "\x0eCruiseStateOff\x10\x01\x12\x16\n" + + "\x12CruiseStateStandby\x10\x02\x12\x11\n" + + "\rCruiseStateOn\x10\x03\x12\x19\n" + + "\x15CruiseStateStandstill\x10\x04\x12\x17\n" + + "\x13CruiseStateOverride\x10\x05\x12\x14\n" + + "\x10CruiseStateFault\x10\x06\x12\x17\n" + + "\x13CruiseStatePreFault\x10\a\x12\x18\n" + + "\x14CruiseStatePreCancel\x10\b*\x91\x03\n" + + "\x18PowerTransferStatusValue\x12\x1e\n" + + "\x1aPowerTransferStatusUnknown\x10\x00\x12\x1e\n" + + "\x1aPowerTransferStatusStandby\x10\x01\x12\x1e\n" + + "\x1aPowerTransferStatusFaulted\x10\x02\x12(\n" + + "$PowerTransferStatusEmergencyShutdown\x10\x03\x12)\n" + + "%PowerTransferStatusExtEvseTestAllowed\x10\x04\x12*\n" + + "&PowerTransferStatusExtPrechargeAllowed\x10\x05\x12%\n" + + "!PowerTransferStatusChargeEnabling\x10\x06\x12$\n" + + " PowerTransferStatusChargeEnabled\x10\a\x12'\n" + + "#PowerTransferStatusGracefulShutdown\x10\b\x12\x1e\n" + + "\x1aPowerTransferStatusBlocked\x10\t*\x91\x01\n" + + "\x0fTurnSignalState\x12\x1a\n" + + "\x16TurnSignalStateUnknown\x10\x00\x12\x16\n" + + "\x12TurnSignalStateOff\x10\x01\x12\x17\n" + + "\x13TurnSignalStateLeft\x10\x02\x12\x18\n" + + "\x14TurnSignalStateRight\x10\x03\x12\x17\n" + + "\x13TurnSignalStateBoth\x10\x04*l\n" + + "\vMediaStatus\x12\x16\n" + + "\x12MediaStatusUnknown\x10\x00\x12\x16\n" + + "\x12MediaStatusStopped\x10\x01\x12\x16\n" + + "\x12MediaStatusPlaying\x10\x02\x12\x15\n" + + "\x11MediaStatusPaused\x10\x03B/Z-github.com/teslamotors/fleet-telemetry/protosb\x06proto3" + +var ( + file_vehicle_data_proto_rawDescOnce sync.Once + file_vehicle_data_proto_rawDescData []byte +) + +func file_vehicle_data_proto_rawDescGZIP() []byte { + file_vehicle_data_proto_rawDescOnce.Do(func() { + file_vehicle_data_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_vehicle_data_proto_rawDesc), len(file_vehicle_data_proto_rawDesc))) + }) + return file_vehicle_data_proto_rawDescData +} + +var file_vehicle_data_proto_enumTypes = make([]protoimpl.EnumInfo, 46) +var file_vehicle_data_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_vehicle_data_proto_goTypes = []any{ + (Field)(0), // 0: telemetry.vehicle_data.Field + (ChargingState)(0), // 1: telemetry.vehicle_data.ChargingState + (DetailedChargeStateValue)(0), // 2: telemetry.vehicle_data.DetailedChargeStateValue + (ShiftState)(0), // 3: telemetry.vehicle_data.ShiftState + (FollowDistance)(0), // 4: telemetry.vehicle_data.FollowDistance + (ForwardCollisionSensitivity)(0), // 5: telemetry.vehicle_data.ForwardCollisionSensitivity + (GuestModeMobileAccess)(0), // 6: telemetry.vehicle_data.GuestModeMobileAccess + (LaneAssistLevel)(0), // 7: telemetry.vehicle_data.LaneAssistLevel + (ScheduledChargingModeValue)(0), // 8: telemetry.vehicle_data.ScheduledChargingModeValue + (SentryModeState)(0), // 9: telemetry.vehicle_data.SentryModeState + (SpeedAssistLevel)(0), // 10: telemetry.vehicle_data.SpeedAssistLevel + (BMSStateValue)(0), // 11: telemetry.vehicle_data.BMSStateValue + (BuckleStatus)(0), // 12: telemetry.vehicle_data.BuckleStatus + (CarTypeValue)(0), // 13: telemetry.vehicle_data.CarTypeValue + (ChargePortValue)(0), // 14: telemetry.vehicle_data.ChargePortValue + (ChargePortLatchValue)(0), // 15: telemetry.vehicle_data.ChargePortLatchValue + (DriveInverterState)(0), // 16: telemetry.vehicle_data.DriveInverterState + (HvilStatus)(0), // 17: telemetry.vehicle_data.HvilStatus + (WindowState)(0), // 18: telemetry.vehicle_data.WindowState + (SeatFoldPosition)(0), // 19: telemetry.vehicle_data.SeatFoldPosition + (TractorAirStatus)(0), // 20: telemetry.vehicle_data.TractorAirStatus + (TrailerAirStatus)(0), // 21: telemetry.vehicle_data.TrailerAirStatus + (HvacAutoModeState)(0), // 22: telemetry.vehicle_data.HvacAutoModeState + (CabinOverheatProtectionModeState)(0), // 23: telemetry.vehicle_data.CabinOverheatProtectionModeState + (ClimateOverheatProtectionTempLimit)(0), // 24: telemetry.vehicle_data.ClimateOverheatProtectionTempLimit + (DefrostModeState)(0), // 25: telemetry.vehicle_data.DefrostModeState + (ClimateKeeperModeState)(0), // 26: telemetry.vehicle_data.ClimateKeeperModeState + (HvacPowerState)(0), // 27: telemetry.vehicle_data.HvacPowerState + (FastCharger)(0), // 28: telemetry.vehicle_data.FastCharger + (CableType)(0), // 29: telemetry.vehicle_data.CableType + (TonneauTentModeState)(0), // 30: telemetry.vehicle_data.TonneauTentModeState + (TonneauPositionState)(0), // 31: telemetry.vehicle_data.TonneauPositionState + (PowershareState)(0), // 32: telemetry.vehicle_data.PowershareState + (PowershareStopReasonStatus)(0), // 33: telemetry.vehicle_data.PowershareStopReasonStatus + (PowershareTypeStatus)(0), // 34: telemetry.vehicle_data.PowershareTypeStatus + (DisplayState)(0), // 35: telemetry.vehicle_data.DisplayState + (DistanceUnit)(0), // 36: telemetry.vehicle_data.DistanceUnit + (TemperatureUnit)(0), // 37: telemetry.vehicle_data.TemperatureUnit + (PressureUnit)(0), // 38: telemetry.vehicle_data.PressureUnit + (ChargeUnitPreference)(0), // 39: telemetry.vehicle_data.ChargeUnitPreference + (SunroofInstalledState)(0), // 40: telemetry.vehicle_data.SunroofInstalledState + (CabinPortKeepOnState)(0), // 41: telemetry.vehicle_data.CabinPortKeepOnState + (CruiseStateValue)(0), // 42: telemetry.vehicle_data.CruiseStateValue + (PowerTransferStatusValue)(0), // 43: telemetry.vehicle_data.PowerTransferStatusValue + (TurnSignalState)(0), // 44: telemetry.vehicle_data.TurnSignalState + (MediaStatus)(0), // 45: telemetry.vehicle_data.MediaStatus + (*LocationValue)(nil), // 46: telemetry.vehicle_data.LocationValue + (*Doors)(nil), // 47: telemetry.vehicle_data.Doors + (*TireLocation)(nil), // 48: telemetry.vehicle_data.TireLocation + (*Time)(nil), // 49: telemetry.vehicle_data.Time + (*Value)(nil), // 50: telemetry.vehicle_data.Value + (*Datum)(nil), // 51: telemetry.vehicle_data.Datum + (*Payload)(nil), // 52: telemetry.vehicle_data.Payload + (*timestamppb.Timestamp)(nil), // 53: google.protobuf.Timestamp +} +var file_vehicle_data_proto_depIdxs = []int32{ + 46, // 0: telemetry.vehicle_data.Value.location_value:type_name -> telemetry.vehicle_data.LocationValue + 1, // 1: telemetry.vehicle_data.Value.charging_value:type_name -> telemetry.vehicle_data.ChargingState + 3, // 2: telemetry.vehicle_data.Value.shift_state_value:type_name -> telemetry.vehicle_data.ShiftState + 7, // 3: telemetry.vehicle_data.Value.lane_assist_level_value:type_name -> telemetry.vehicle_data.LaneAssistLevel + 8, // 4: telemetry.vehicle_data.Value.scheduled_charging_mode_value:type_name -> telemetry.vehicle_data.ScheduledChargingModeValue + 9, // 5: telemetry.vehicle_data.Value.sentry_mode_state_value:type_name -> telemetry.vehicle_data.SentryModeState + 10, // 6: telemetry.vehicle_data.Value.speed_assist_level_value:type_name -> telemetry.vehicle_data.SpeedAssistLevel + 11, // 7: telemetry.vehicle_data.Value.bms_state_value:type_name -> telemetry.vehicle_data.BMSStateValue + 12, // 8: telemetry.vehicle_data.Value.buckle_status_value:type_name -> telemetry.vehicle_data.BuckleStatus + 13, // 9: telemetry.vehicle_data.Value.car_type_value:type_name -> telemetry.vehicle_data.CarTypeValue + 14, // 10: telemetry.vehicle_data.Value.charge_port_value:type_name -> telemetry.vehicle_data.ChargePortValue + 15, // 11: telemetry.vehicle_data.Value.charge_port_latch_value:type_name -> telemetry.vehicle_data.ChargePortLatchValue + 47, // 12: telemetry.vehicle_data.Value.door_value:type_name -> telemetry.vehicle_data.Doors + 16, // 13: telemetry.vehicle_data.Value.drive_inverter_state_value:type_name -> telemetry.vehicle_data.DriveInverterState + 17, // 14: telemetry.vehicle_data.Value.hvil_status_value:type_name -> telemetry.vehicle_data.HvilStatus + 18, // 15: telemetry.vehicle_data.Value.window_state_value:type_name -> telemetry.vehicle_data.WindowState + 19, // 16: telemetry.vehicle_data.Value.seat_fold_position_value:type_name -> telemetry.vehicle_data.SeatFoldPosition + 20, // 17: telemetry.vehicle_data.Value.tractor_air_status_value:type_name -> telemetry.vehicle_data.TractorAirStatus + 4, // 18: telemetry.vehicle_data.Value.follow_distance_value:type_name -> telemetry.vehicle_data.FollowDistance + 5, // 19: telemetry.vehicle_data.Value.forward_collision_sensitivity_value:type_name -> telemetry.vehicle_data.ForwardCollisionSensitivity + 6, // 20: telemetry.vehicle_data.Value.guest_mode_mobile_access_value:type_name -> telemetry.vehicle_data.GuestModeMobileAccess + 21, // 21: telemetry.vehicle_data.Value.trailer_air_status_value:type_name -> telemetry.vehicle_data.TrailerAirStatus + 49, // 22: telemetry.vehicle_data.Value.time_value:type_name -> telemetry.vehicle_data.Time + 2, // 23: telemetry.vehicle_data.Value.detailed_charge_state_value:type_name -> telemetry.vehicle_data.DetailedChargeStateValue + 22, // 24: telemetry.vehicle_data.Value.hvac_auto_mode_value:type_name -> telemetry.vehicle_data.HvacAutoModeState + 23, // 25: telemetry.vehicle_data.Value.cabin_overheat_protection_mode_value:type_name -> telemetry.vehicle_data.CabinOverheatProtectionModeState + 24, // 26: telemetry.vehicle_data.Value.cabin_overheat_protection_temperature_limit_value:type_name -> telemetry.vehicle_data.ClimateOverheatProtectionTempLimit + 25, // 27: telemetry.vehicle_data.Value.defrost_mode_value:type_name -> telemetry.vehicle_data.DefrostModeState + 26, // 28: telemetry.vehicle_data.Value.climate_keeper_mode_value:type_name -> telemetry.vehicle_data.ClimateKeeperModeState + 27, // 29: telemetry.vehicle_data.Value.hvac_power_value:type_name -> telemetry.vehicle_data.HvacPowerState + 48, // 30: telemetry.vehicle_data.Value.tire_location_value:type_name -> telemetry.vehicle_data.TireLocation + 28, // 31: telemetry.vehicle_data.Value.fast_charger_value:type_name -> telemetry.vehicle_data.FastCharger + 29, // 32: telemetry.vehicle_data.Value.cable_type_value:type_name -> telemetry.vehicle_data.CableType + 30, // 33: telemetry.vehicle_data.Value.tonneau_tent_mode_value:type_name -> telemetry.vehicle_data.TonneauTentModeState + 31, // 34: telemetry.vehicle_data.Value.tonneau_position_value:type_name -> telemetry.vehicle_data.TonneauPositionState + 34, // 35: telemetry.vehicle_data.Value.powershare_type_value:type_name -> telemetry.vehicle_data.PowershareTypeStatus + 32, // 36: telemetry.vehicle_data.Value.powershare_state_value:type_name -> telemetry.vehicle_data.PowershareState + 33, // 37: telemetry.vehicle_data.Value.powershare_stop_reason_value:type_name -> telemetry.vehicle_data.PowershareStopReasonStatus + 35, // 38: telemetry.vehicle_data.Value.display_state_value:type_name -> telemetry.vehicle_data.DisplayState + 36, // 39: telemetry.vehicle_data.Value.distance_unit_value:type_name -> telemetry.vehicle_data.DistanceUnit + 37, // 40: telemetry.vehicle_data.Value.temperature_unit_value:type_name -> telemetry.vehicle_data.TemperatureUnit + 38, // 41: telemetry.vehicle_data.Value.pressure_unit_value:type_name -> telemetry.vehicle_data.PressureUnit + 39, // 42: telemetry.vehicle_data.Value.charge_unit_preference_value:type_name -> telemetry.vehicle_data.ChargeUnitPreference + 44, // 43: telemetry.vehicle_data.Value.turn_signal_state_value:type_name -> telemetry.vehicle_data.TurnSignalState + 45, // 44: telemetry.vehicle_data.Value.media_status_value:type_name -> telemetry.vehicle_data.MediaStatus + 40, // 45: telemetry.vehicle_data.Value.sunroof_installed_state_value:type_name -> telemetry.vehicle_data.SunroofInstalledState + 41, // 46: telemetry.vehicle_data.Value.cabin_port_keep_on_value:type_name -> telemetry.vehicle_data.CabinPortKeepOnState + 42, // 47: telemetry.vehicle_data.Value.cruise_state_value:type_name -> telemetry.vehicle_data.CruiseStateValue + 43, // 48: telemetry.vehicle_data.Value.power_transfer_status_value:type_name -> telemetry.vehicle_data.PowerTransferStatusValue + 0, // 49: telemetry.vehicle_data.Datum.key:type_name -> telemetry.vehicle_data.Field + 50, // 50: telemetry.vehicle_data.Datum.value:type_name -> telemetry.vehicle_data.Value + 51, // 51: telemetry.vehicle_data.Payload.data:type_name -> telemetry.vehicle_data.Datum + 53, // 52: telemetry.vehicle_data.Payload.created_at:type_name -> google.protobuf.Timestamp + 53, // [53:53] is the sub-list for method output_type + 53, // [53:53] is the sub-list for method input_type + 53, // [53:53] is the sub-list for extension type_name + 53, // [53:53] is the sub-list for extension extendee + 0, // [0:53] is the sub-list for field type_name +} + +func init() { file_vehicle_data_proto_init() } +func file_vehicle_data_proto_init() { + if File_vehicle_data_proto != nil { + return + } + file_vehicle_data_proto_msgTypes[4].OneofWrappers = []any{ + (*Value_StringValue)(nil), + (*Value_IntValue)(nil), + (*Value_LongValue)(nil), + (*Value_FloatValue)(nil), + (*Value_DoubleValue)(nil), + (*Value_BooleanValue)(nil), + (*Value_LocationValue)(nil), + (*Value_ChargingValue)(nil), + (*Value_ShiftStateValue)(nil), + (*Value_Invalid)(nil), + (*Value_LaneAssistLevelValue)(nil), + (*Value_ScheduledChargingModeValue)(nil), + (*Value_SentryModeStateValue)(nil), + (*Value_SpeedAssistLevelValue)(nil), + (*Value_BmsStateValue)(nil), + (*Value_BuckleStatusValue)(nil), + (*Value_CarTypeValue)(nil), + (*Value_ChargePortValue)(nil), + (*Value_ChargePortLatchValue)(nil), + (*Value_DoorValue)(nil), + (*Value_DriveInverterStateValue)(nil), + (*Value_HvilStatusValue)(nil), + (*Value_WindowStateValue)(nil), + (*Value_SeatFoldPositionValue)(nil), + (*Value_TractorAirStatusValue)(nil), + (*Value_FollowDistanceValue)(nil), + (*Value_ForwardCollisionSensitivityValue)(nil), + (*Value_GuestModeMobileAccessValue)(nil), + (*Value_TrailerAirStatusValue)(nil), + (*Value_TimeValue)(nil), + (*Value_DetailedChargeStateValue)(nil), + (*Value_HvacAutoModeValue)(nil), + (*Value_CabinOverheatProtectionModeValue)(nil), + (*Value_CabinOverheatProtectionTemperatureLimitValue)(nil), + (*Value_DefrostModeValue)(nil), + (*Value_ClimateKeeperModeValue)(nil), + (*Value_HvacPowerValue)(nil), + (*Value_TireLocationValue)(nil), + (*Value_FastChargerValue)(nil), + (*Value_CableTypeValue)(nil), + (*Value_TonneauTentModeValue)(nil), + (*Value_TonneauPositionValue)(nil), + (*Value_PowershareTypeValue)(nil), + (*Value_PowershareStateValue)(nil), + (*Value_PowershareStopReasonValue)(nil), + (*Value_DisplayStateValue)(nil), + (*Value_DistanceUnitValue)(nil), + (*Value_TemperatureUnitValue)(nil), + (*Value_PressureUnitValue)(nil), + (*Value_ChargeUnitPreferenceValue)(nil), + (*Value_TurnSignalStateValue)(nil), + (*Value_MediaStatusValue)(nil), + (*Value_SunroofInstalledStateValue)(nil), + (*Value_CabinPortKeepOnValue)(nil), + (*Value_CruiseStateValue)(nil), + (*Value_PowerTransferStatusValue)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_vehicle_data_proto_rawDesc), len(file_vehicle_data_proto_rawDesc)), + NumEnums: 46, + NumMessages: 7, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_vehicle_data_proto_goTypes, + DependencyIndexes: file_vehicle_data_proto_depIdxs, + EnumInfos: file_vehicle_data_proto_enumTypes, + MessageInfos: file_vehicle_data_proto_msgTypes, + }.Build() + File_vehicle_data_proto = out.File + file_vehicle_data_proto_goTypes = nil + file_vehicle_data_proto_depIdxs = nil +} diff --git a/internal/protos/vehicle_error.pb.go b/internal/protos/vehicle_error.pb.go new file mode 100644 index 0000000..e8bc5e5 --- /dev/null +++ b/internal/protos/vehicle_error.pb.go @@ -0,0 +1,233 @@ +// UPSTREAM-SOURCE: teslamotors/fleet-telemetry +// UPSTREAM-PATH: protos/vehicle_error.proto +// UPSTREAM-COMMIT: see upstream.json +// This file tracks upstream verbatim; no Teslemetry extensions. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc v7.36.2 +// source: vehicle_error.proto + +package protos + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// VehicleErrors is a collection of errors for a single vehicle. +type VehicleErrors struct { + state protoimpl.MessageState `protogen:"open.v1"` + Errors []*VehicleError `protobuf:"bytes,1,rep,name=errors,proto3" json:"errors,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + Vin string `protobuf:"bytes,3,opt,name=vin,proto3" json:"vin,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VehicleErrors) Reset() { + *x = VehicleErrors{} + mi := &file_vehicle_error_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VehicleErrors) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VehicleErrors) ProtoMessage() {} + +func (x *VehicleErrors) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_error_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VehicleErrors.ProtoReflect.Descriptor instead. +func (*VehicleErrors) Descriptor() ([]byte, []int) { + return file_vehicle_error_proto_rawDescGZIP(), []int{0} +} + +func (x *VehicleErrors) GetErrors() []*VehicleError { + if x != nil { + return x.Errors + } + return nil +} + +func (x *VehicleErrors) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *VehicleErrors) GetVin() string { + if x != nil { + return x.Vin + } + return "" +} + +// VehicleError is a single error +type VehicleError struct { + state protoimpl.MessageState `protogen:"open.v1"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Tags map[string]string `protobuf:"bytes,3,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Body string `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VehicleError) Reset() { + *x = VehicleError{} + mi := &file_vehicle_error_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VehicleError) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VehicleError) ProtoMessage() {} + +func (x *VehicleError) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_error_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VehicleError.ProtoReflect.Descriptor instead. +func (*VehicleError) Descriptor() ([]byte, []int) { + return file_vehicle_error_proto_rawDescGZIP(), []int{1} +} + +func (x *VehicleError) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *VehicleError) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *VehicleError) GetTags() map[string]string { + if x != nil { + return x.Tags + } + return nil +} + +func (x *VehicleError) GetBody() string { + if x != nil { + return x.Body + } + return "" +} + +var File_vehicle_error_proto protoreflect.FileDescriptor + +const file_vehicle_error_proto_rawDesc = "" + + "\n" + + "\x13vehicle_error.proto\x12\x17telemetry.vehicle_error\x1a\x1fgoogle/protobuf/timestamp.proto\"\x9b\x01\n" + + "\rVehicleErrors\x12=\n" + + "\x06errors\x18\x01 \x03(\v2%.telemetry.vehicle_error.VehicleErrorR\x06errors\x129\n" + + "\n" + + "created_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x10\n" + + "\x03vin\x18\x03 \x01(\tR\x03vin\"\xef\x01\n" + + "\fVehicleError\x129\n" + + "\n" + + "created_at\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12C\n" + + "\x04tags\x18\x03 \x03(\v2/.telemetry.vehicle_error.VehicleError.TagsEntryR\x04tags\x12\x12\n" + + "\x04body\x18\x04 \x01(\tR\x04body\x1a7\n" + + "\tTagsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B/Z-github.com/teslamotors/fleet-telemetry/protosb\x06proto3" + +var ( + file_vehicle_error_proto_rawDescOnce sync.Once + file_vehicle_error_proto_rawDescData []byte +) + +func file_vehicle_error_proto_rawDescGZIP() []byte { + file_vehicle_error_proto_rawDescOnce.Do(func() { + file_vehicle_error_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_vehicle_error_proto_rawDesc), len(file_vehicle_error_proto_rawDesc))) + }) + return file_vehicle_error_proto_rawDescData +} + +var file_vehicle_error_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_vehicle_error_proto_goTypes = []any{ + (*VehicleErrors)(nil), // 0: telemetry.vehicle_error.VehicleErrors + (*VehicleError)(nil), // 1: telemetry.vehicle_error.VehicleError + nil, // 2: telemetry.vehicle_error.VehicleError.TagsEntry + (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp +} +var file_vehicle_error_proto_depIdxs = []int32{ + 1, // 0: telemetry.vehicle_error.VehicleErrors.errors:type_name -> telemetry.vehicle_error.VehicleError + 3, // 1: telemetry.vehicle_error.VehicleErrors.created_at:type_name -> google.protobuf.Timestamp + 3, // 2: telemetry.vehicle_error.VehicleError.created_at:type_name -> google.protobuf.Timestamp + 2, // 3: telemetry.vehicle_error.VehicleError.tags:type_name -> telemetry.vehicle_error.VehicleError.TagsEntry + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name +} + +func init() { file_vehicle_error_proto_init() } +func file_vehicle_error_proto_init() { + if File_vehicle_error_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_vehicle_error_proto_rawDesc), len(file_vehicle_error_proto_rawDesc)), + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_vehicle_error_proto_goTypes, + DependencyIndexes: file_vehicle_error_proto_depIdxs, + MessageInfos: file_vehicle_error_proto_msgTypes, + }.Build() + File_vehicle_error_proto = out.File + file_vehicle_error_proto_goTypes = nil + file_vehicle_error_proto_depIdxs = nil +} diff --git a/internal/protos/vehicle_metric.pb.go b/internal/protos/vehicle_metric.pb.go new file mode 100644 index 0000000..bb5d6f3 --- /dev/null +++ b/internal/protos/vehicle_metric.pb.go @@ -0,0 +1,222 @@ +// UPSTREAM-SOURCE: teslamotors/fleet-telemetry +// UPSTREAM-PATH: protos/vehicle_metric.proto +// UPSTREAM-COMMIT: see upstream.json +// This file tracks upstream verbatim; no Teslemetry extensions. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.12 +// protoc v7.36.2 +// source: vehicle_metric.proto + +package protos + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// VehicleMetrics is a collection of metrics for a single vehicle. +type VehicleMetrics struct { + state protoimpl.MessageState `protogen:"open.v1"` + Metrics []*Metric `protobuf:"bytes,1,rep,name=metrics,proto3" json:"metrics,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + Vin string `protobuf:"bytes,3,opt,name=vin,proto3" json:"vin,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *VehicleMetrics) Reset() { + *x = VehicleMetrics{} + mi := &file_vehicle_metric_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VehicleMetrics) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VehicleMetrics) ProtoMessage() {} + +func (x *VehicleMetrics) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_metric_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VehicleMetrics.ProtoReflect.Descriptor instead. +func (*VehicleMetrics) Descriptor() ([]byte, []int) { + return file_vehicle_metric_proto_rawDescGZIP(), []int{0} +} + +func (x *VehicleMetrics) GetMetrics() []*Metric { + if x != nil { + return x.Metrics + } + return nil +} + +func (x *VehicleMetrics) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *VehicleMetrics) GetVin() string { + if x != nil { + return x.Vin + } + return "" +} + +// Metric is a single metric value with a name, tags, and a value. +type Metric struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Tags map[string]string `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Value float64 `protobuf:"fixed64,3,opt,name=value,proto3" json:"value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Metric) Reset() { + *x = Metric{} + mi := &file_vehicle_metric_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Metric) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Metric) ProtoMessage() {} + +func (x *Metric) ProtoReflect() protoreflect.Message { + mi := &file_vehicle_metric_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Metric.ProtoReflect.Descriptor instead. +func (*Metric) Descriptor() ([]byte, []int) { + return file_vehicle_metric_proto_rawDescGZIP(), []int{1} +} + +func (x *Metric) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Metric) GetTags() map[string]string { + if x != nil { + return x.Tags + } + return nil +} + +func (x *Metric) GetValue() float64 { + if x != nil { + return x.Value + } + return 0 +} + +var File_vehicle_metric_proto protoreflect.FileDescriptor + +const file_vehicle_metric_proto_rawDesc = "" + + "\n" + + "\x14vehicle_metric.proto\x12\x19telemetry.vehicle_metrics\x1a\x1fgoogle/protobuf/timestamp.proto\"\x9a\x01\n" + + "\x0eVehicleMetrics\x12;\n" + + "\ametrics\x18\x01 \x03(\v2!.telemetry.vehicle_metrics.MetricR\ametrics\x129\n" + + "\n" + + "created_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x10\n" + + "\x03vin\x18\x03 \x01(\tR\x03vin\"\xac\x01\n" + + "\x06Metric\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12?\n" + + "\x04tags\x18\x02 \x03(\v2+.telemetry.vehicle_metrics.Metric.TagsEntryR\x04tags\x12\x14\n" + + "\x05value\x18\x03 \x01(\x01R\x05value\x1a7\n" + + "\tTagsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B/Z-github.com/teslamotors/fleet-telemetry/protosb\x06proto3" + +var ( + file_vehicle_metric_proto_rawDescOnce sync.Once + file_vehicle_metric_proto_rawDescData []byte +) + +func file_vehicle_metric_proto_rawDescGZIP() []byte { + file_vehicle_metric_proto_rawDescOnce.Do(func() { + file_vehicle_metric_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_vehicle_metric_proto_rawDesc), len(file_vehicle_metric_proto_rawDesc))) + }) + return file_vehicle_metric_proto_rawDescData +} + +var file_vehicle_metric_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_vehicle_metric_proto_goTypes = []any{ + (*VehicleMetrics)(nil), // 0: telemetry.vehicle_metrics.VehicleMetrics + (*Metric)(nil), // 1: telemetry.vehicle_metrics.Metric + nil, // 2: telemetry.vehicle_metrics.Metric.TagsEntry + (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp +} +var file_vehicle_metric_proto_depIdxs = []int32{ + 1, // 0: telemetry.vehicle_metrics.VehicleMetrics.metrics:type_name -> telemetry.vehicle_metrics.Metric + 3, // 1: telemetry.vehicle_metrics.VehicleMetrics.created_at:type_name -> google.protobuf.Timestamp + 2, // 2: telemetry.vehicle_metrics.Metric.tags:type_name -> telemetry.vehicle_metrics.Metric.TagsEntry + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_vehicle_metric_proto_init() } +func file_vehicle_metric_proto_init() { + if File_vehicle_metric_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_vehicle_metric_proto_rawDesc), len(file_vehicle_metric_proto_rawDesc)), + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_vehicle_metric_proto_goTypes, + DependencyIndexes: file_vehicle_metric_proto_depIdxs, + MessageInfos: file_vehicle_metric_proto_msgTypes, + }.Build() + File_vehicle_metric_proto = out.File + file_vehicle_metric_proto_goTypes = nil + file_vehicle_metric_proto_depIdxs = nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..489fb71 --- /dev/null +++ b/main.go @@ -0,0 +1,75 @@ +// telemetry-decoder decodes Tesla Fleet Telemetry protobuf payloads into JSON +// events for the NATS Add-on for Splunk: it reads one request per line on stdin +// and writes one event per line on stdout until stdin closes. +package main + +import ( + "flag" + "fmt" + "os" + "runtime/debug" + + "github.com/Teslemetry/telemetry-decoder/internal/decoder" + "github.com/Teslemetry/telemetry-decoder/internal/protos" +) + +// version is set at build time with -ldflags "-X main.version=..." +var version = "" + +func main() { + os.Exit(run(os.Args[1:])) +} + +func run(args []string) int { + flags := flag.NewFlagSet("telemetry-decoder", flag.ContinueOnError) + flags.Usage = func() { + _, _ = fmt.Fprintf(flags.Output(), `Usage: telemetry-decoder [options] + +Decodes Tesla Fleet Telemetry protobuf payloads for the NATS Add-on for Splunk. +Reads one JSON request per line on stdin ({"subject":..., "headers":..., "payload":}) +and writes one JSON event per line on stdout, or an empty line when a payload +cannot be decoded (the reason goes to stderr). Exits when stdin closes. + +Options: +`) + flags.PrintDefaults() + } + format := flags.String("format", string(decoder.FormatFlat), + `vehicle data event shape: "flat" (one field per signal) or "protojson" (data as a list of key/value pairs, as fleet-telemetry writes it)`) + protoNames := flags.Bool("proto-names", false, "use proto field names (created_at) instead of JSON names (createdAt)") + showVersion := flags.Bool("version", false, "print the version and exit") + if err := flags.Parse(args); err != nil { + if err == flag.ErrHelp { + return 0 + } + return 2 + } + if flags.NArg() > 0 { + fmt.Fprintf(os.Stderr, "telemetry-decoder: unexpected argument %q\n", flags.Arg(0)) + return 2 + } + if *showVersion { + fmt.Printf("telemetry-decoder %s (tesla-protocol %s)\n", buildVersion(), protos.TeslaProtocolCommit) + return 0 + } + d, err := decoder.New(decoder.Options{Format: decoder.Format(*format), ProtoNames: *protoNames}) + if err != nil { + fmt.Fprintf(os.Stderr, "telemetry-decoder: %v\n", err) + return 2 + } + if err := d.Run(os.Stdin, os.Stdout, os.Stderr); err != nil { + fmt.Fprintf(os.Stderr, "telemetry-decoder: %v\n", err) + return 1 + } + return 0 +} + +func buildVersion() string { + if version != "" { + return version + } + if info, ok := debug.ReadBuildInfo(); ok && info.Main.Version != "" { + return info.Main.Version + } + return "dev" +} diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..18ae152 --- /dev/null +++ b/main_test.go @@ -0,0 +1,105 @@ +package main + +import ( + "bufio" + "encoding/json" + "io" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + "time" +) + +// TestBinary runs the built decoder as the add-on does: it starts it once, sends +// a request, waits for the event, and closes stdin to stop it. +func TestBinary(t *testing.T) { + bin := filepath.Join(t.TempDir(), "telemetry-decoder") + build := exec.Command("go", "build", "-o", bin, ".") + build.Env = append(os.Environ(), "CGO_ENABLED=0") + if out, err := build.CombinedOutput(); err != nil { + t.Fatalf("go build: %v\n%s", err, out) + } + requests, err := filepath.Glob("internal/decoder/testdata/golden/*.request") + if err != nil || len(requests) == 0 { + t.Fatalf("no fixtures: %v", err) + } + + cmd := exec.Command(bin) + stdin, _ := cmd.StdinPipe() + stdoutPipe, _ := cmd.StdoutPipe() + var stderr strings.Builder + cmd.Stderr = &stderr + if err := cmd.Start(); err != nil { + t.Fatal(err) + } + stdout := bufio.NewReader(stdoutPipe) + exchange := func(request string) string { + t.Helper() + if _, err := io.WriteString(stdin, request); err != nil { + t.Fatal(err) + } + line := make(chan string, 1) + go func() { + s, _ := stdout.ReadString('\n') + line <- s + }() + select { + case s := <-line: + if !strings.HasSuffix(s, "\n") { + t.Fatalf("no complete line for %q: %q", request, s) + } + return strings.TrimSuffix(s, "\n") + case <-time.After(10 * time.Second): + t.Fatalf("no answer within 10s for %q", request) + return "" + } + } + for _, path := range requests { + request, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + event := exchange(string(request)) + var object map[string]any + if err := json.Unmarshal([]byte(event), &object); err != nil || object["vin"] != "TESTVIN0000000001" { + t.Errorf("%s: event %q (%v)", path, event, err) + } + } + if event := exchange(`{"subject":"telemetry.V.data","headers":{},"payload":"%%%"}` + "\n"); event != "" { + t.Errorf("bad request answered %q, want an empty line", event) + } + _ = stdin.Close() + done := make(chan error, 1) + go func() { done <- cmd.Wait() }() + select { + case err := <-done: + if err != nil { + t.Errorf("exit after stdin closed: %v", err) + } + case <-time.After(10 * time.Second): + _ = cmd.Process.Kill() + t.Fatal("decoder did not exit after stdin closed") + } + if !strings.Contains(stderr.String(), "telemetry.V.data: invalid payload: illegal base64") || strings.Count(stderr.String(), "\n") != 1 { + t.Errorf("stderr %q, want one line about the bad request", stderr.String()) + } +} + +func TestArguments(t *testing.T) { + for _, tc := range []struct { + args []string + want int + }{ + {[]string{"-version"}, 0}, + {[]string{"-h"}, 0}, + {[]string{"-format", "xml"}, 2}, + {[]string{"-nope"}, 2}, + {[]string{"extra"}, 2}, + } { + if got := run(tc.args); got != tc.want { + t.Errorf("run(%q) = %d, want %d", tc.args, got, tc.want) + } + } +} diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..7296055 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# Builds static telemetry-decoder binaries for each release platform into dist/, +# with a SHA256SUMS file. +# +# Usage: scripts/build.sh [version] (version defaults to git describe) +set -euo pipefail + +root="$(cd "$(dirname "$0")/.." && pwd)" +version="${1:-$(git -C "$root" describe --tags --always --dirty 2>/dev/null || echo dev)}" +platforms=(linux/amd64 linux/arm64 darwin/amd64 darwin/arm64) + +rm -rf "$root/dist" +mkdir -p "$root/dist" +for platform in "${platforms[@]}"; do + os="${platform%/*}" arch="${platform#*/}" + out="dist/telemetry-decoder-$os-$arch" + (cd "$root" && CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" \ + go build -trimpath -ldflags "-s -w -buildid= -X main.version=$version" -o "$out" .) + echo "built $out" +done +(cd "$root/dist" && sha256sum telemetry-decoder-* >SHA256SUMS) +cat "$root/dist/SHA256SUMS" diff --git a/scripts/e2e-splunk.sh b/scripts/e2e-splunk.sh new file mode 100755 index 0000000..100482e --- /dev/null +++ b/scripts/e2e-splunk.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# End-to-end check of telemetry-decoder in a disposable Splunk container with the +# NATS Add-on for Splunk, against live Tesla Fleet Telemetry on NATS. +# +# NATS_URL=nats://host.docker.internal:4222 NATS_USERNAME=... NATS_PASSWORD=... \ +# scripts/e2e-splunk.sh [splunk image] [seconds] +# +# Installs the add-on and the decoder (as local/decoders/telemetry-decoder), runs +# a natssubscribe search with decoder=telemetry-decoder, then indexes +# telemetry.> with a NATS Subscribe input for the given seconds (default 300) and +# checks that every message was decoded: no base64 fallback events and no +# "failed to decode" in splunkd.log. Prints decoded fields per record type, +# aggregated so no VIN or location is printed. +# +# The NATS credentials reach Splunk's REST API through curl's stdin, never argv +# or disk. The container and its volumes are always removed. +set -euo pipefail + +package=$(realpath "${1:?usage: $0 [splunk image] [seconds]}") +decoder=$(realpath "${2:?decoder binary required}") +image=${3:-splunk/splunk:latest} +seconds=${4:-300} +: "${NATS_URL:?}" "${NATS_USERNAME:?}" "${NATS_PASSWORD:?}" + +name=telemetry-decoder-e2e-$$ +admin_pw="E2e-$(od -An -N12 -tx1 /dev/urandom | tr -d ' \n')" +cleanup() { docker rm -fv "$name" >/dev/null 2>&1 || true; } +trap cleanup EXIT + +echo "== Starting $image" +docker run -d --name "$name" --add-host=host.docker.internal:host-gateway -p 127.0.0.1::8089 \ + -e SPLUNK_START_ARGS=--accept-license -e SPLUNK_GENERAL_TERMS=--accept-sgt-current-at-splunk-com \ + -e SPLUNK_PASSWORD="$admin_pw" -e SPLUNK_APPS_URL=/tmp/nats.tgz \ + -v "$package:/tmp/nats.tgz:ro" "$image" >/dev/null +for _ in $(seq 120); do + [ "$(docker inspect -f '{{.State.Health.Status}}' "$name")" = healthy ] && break + sleep 5 +done +[ "$(docker inspect -f '{{.State.Health.Status}}' "$name")" = healthy ] +base="https://127.0.0.1:$(docker port "$name" 8089/tcp | head -1 | sed 's/.*://')" +docker exec "$name" /opt/splunk/bin/splunk version 2>/dev/null | tail -1 + +# The admin password goes through a curl config on a pipe, never argv +rest() { + local path=$1 + shift + curl -sSk --fail-with-body --config <(printf 'user = "admin:%s"\n' "$admin_pw") "$@" "$base$path" +} +search() { + rest /services/search/v2/jobs/export -d output_mode=csv -d earliest_time=0 \ + --data-urlencode "search=$1" | tr -d '\r' +} + +echo "== Installing the decoder" +decoders=/opt/splunk/etc/apps/nats/local/decoders +docker exec -u root "$name" mkdir -p "$decoders" +docker cp "$decoder" "$name:$decoders/telemetry-decoder" +docker exec -u root "$name" sh -c "chown -R splunk:splunk /opt/splunk/etc/apps/nats/local && chmod 755 $decoders/telemetry-decoder" +docker exec -u splunk "$name" "$decoders/telemetry-decoder" -version + +echo "== Creating the account" +rest /services/data/indexes -d name=telemetry >/dev/null +printf '%s' "$NATS_PASSWORD" | rest /servicesNS/nobody/nats/nats_account -d name=live \ + --data-urlencode "servers=$NATS_URL" --data-urlencode "username=$NATS_USERNAME" \ + --data-urlencode password@- >/dev/null + +echo "== natssubscribe with decoder=telemetry-decoder (30s, up to 2000 messages)" +search '| natssubscribe subject="telemetry.>" account=live count=2000 duration=30 decoder=telemetry-decoder + | eval type=mvindex(split(source, "."), -1), decoded=if(isnull(decode_error), "decoded", "failed") + | spath | stats count by type decoded sourcetype' +search '| natssubscribe subject="telemetry.>" account=live count=2000 duration=30 decoder=telemetry-decoder + | spath | eval type=mvindex(split(source, "."), -1) + | stats count(VehicleSpeed) as VehicleSpeed count(Location.latitude) as Location.latitude + count(BatteryLevel) as BatteryLevel count(createdAt) as createdAt count(vin) as vin by type' + +echo "== NATS Subscribe input on telemetry.> for ${seconds}s" +rest /servicesNS/nobody/nats/nats_nats_subscribe -d name=telemetry -d account=live \ + -d 'subject=telemetry.>' -d index=telemetry -d decoder=telemetry-decoder >/dev/null +start=$(date +%s) +sleep "$seconds" +rest /servicesNS/nobody/nats/nats_nats_subscribe/telemetry -d disabled=1 >/dev/null +sleep 10 # let the last events reach the index +echo "indexed for $(($(date +%s) - start))s" + +echo "-- events by record type and sourcetype (nats:json = decoded, nats:message = base64 fallback)" +search 'search index=telemetry | eval type=mvindex(split(source, "."), -1) | stats count by type sourcetype' +echo "-- data: events carrying common signals" +search 'search index=telemetry sourcetype=nats:json source=*.data + | stats count as events count(vin) as vin count(createdAt) as createdAt count(VehicleSpeed) as VehicleSpeed + count(Location.latitude) as Location.latitude count(BatteryLevel) as BatteryLevel count(Gear) as Gear + count(DoorState.DriverFront) as DoorState.DriverFront count(invalid{}) as invalid dc(vin) as vehicles' +echo "-- data: average speed and battery, Gear values" +search 'search index=telemetry sourcetype=nats:json source=*.data | stats avg(VehicleSpeed) as avg_VehicleSpeed avg(BatteryLevel) as avg_BatteryLevel values(Gear) as Gear' +echo "-- connectivity" +search 'search index=telemetry sourcetype=nats:json source=*.connectivity | stats count by status networkInterface' +echo "-- alerts (top names)" +search 'search index=telemetry sourcetype=nats:json source=*.alerts | stats count as events | appendcols [search index=telemetry sourcetype=nats:json source=*.alerts | top limit=5 alerts{}.name]' +echo "-- errors" +search 'search index=telemetry sourcetype=nats:json source=*.errors | stats count as events values(errors{}.name) as names' + +failed_events=$(search 'search index=telemetry sourcetype!=nats:json | stats count' | tail -1) +failed_log=$(search 'search index=_internal sourcetype=splunkd "failed to decode" | stats count' | tail -1) +total=$(search 'search index=telemetry | stats count' | tail -1) +echo "== $total events, $failed_events not decoded, $failed_log decode failures logged" +[ "$total" -gt 0 ] && [ "$failed_events" = 0 ] && [ "$failed_log" = 0 ] +echo PASS diff --git a/scripts/generate.sh b/scripts/generate.sh new file mode 100755 index 0000000..d3e788c --- /dev/null +++ b/scripts/generate.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +# Regenerates internal/protos from the Tesla Fleet Telemetry protos in +# Teslemetry/tesla-protocol at a pinned commit, with pinned protoc and +# protoc-gen-go versions, so the generated code is reproducible. +# +# Usage: scripts/generate.sh [tesla-protocol commit] +# +# To move to a newer tesla-protocol commit, run it with that commit, then update +# TESLA_PROTOCOL_COMMIT below to match and commit both. +set -euo pipefail + +TESLA_PROTOCOL_COMMIT="${1:-e6f7afb1b633d7215e34d0cdac66dab983c6ae78}" +PROTOC_VERSION="36.2" +# protoc-gen-go is pinned by the "tool" directive in go.mod, at the same version +# as the google.golang.org/protobuf runtime the decoder links. + +MODULE="github.com/Teslemetry/telemetry-decoder" +PACKAGE="internal/protos" +PROTOS=(vehicle_alert vehicle_connectivity vehicle_data vehicle_error vehicle_metric) + +root="$(cd "$(dirname "$0")/.." && pwd)" +cache="${XDG_CACHE_HOME:-$HOME/.cache}/telemetry-decoder" +work="$(mktemp -d)" +trap 'rm -rf "$work"' EXIT + +case "$(uname -s)-$(uname -m)" in + Linux-x86_64) platform=linux-x86_64 sha256=121f6c7afe1d4d0e3ea6aab9432038599250134cbf4474cb1167d2c7decd4278 ;; + Linux-aarch64 | Linux-arm64) platform=linux-aarch_64 sha256=8b8f18bd2b30346efbc698dd5a73dd7c805f3ef8380f6dfc95c768f3f1852f6a ;; + Darwin-*) platform=osx-universal_binary sha256=83d0dc80672f53486f54299bca6177159f9cad1fd54d4d3143eeea53c4423e1b ;; + *) echo "generate.sh: no pinned protoc for $(uname -s)-$(uname -m)" >&2; exit 1 ;; +esac + +protoc_dir="$cache/protoc-$PROTOC_VERSION-$platform" +if [[ ! -x "$protoc_dir/bin/protoc" ]]; then + zip="$work/protoc.zip" + curl -sSfL -o "$zip" \ + "https://github.com/protocolbuffers/protobuf/releases/download/v$PROTOC_VERSION/protoc-$PROTOC_VERSION-$platform.zip" + echo "$sha256 $zip" | sha256sum -c --quiet - 2>/dev/null || echo "$sha256 $zip" | shasum -a 256 -c --quiet - + rm -rf "$protoc_dir" + mkdir -p "$protoc_dir" + unzip -q "$zip" -d "$protoc_dir" +fi + +curl -sSfL "https://codeload.github.com/Teslemetry/tesla-protocol/tar.gz/$TESLA_PROTOCOL_COMMIT" | + tar -xz -C "$work" --strip-components=3 "tesla-protocol-$TESLA_PROTOCOL_COMMIT/proto/telemetry" + +(cd "$root" && go build -o "$work/protoc-gen-go" google.golang.org/protobuf/cmd/protoc-gen-go) + +# All the protos declare the fleet-telemetry go_package; map them to this module. +mappings=() +files=() +for proto in "${PROTOS[@]}"; do + mappings+=("--go_opt=M$proto.proto=$MODULE/$PACKAGE;protos") + files+=("$proto.proto") +done + +rm -f "$root/$PACKAGE"/*.pb.go +mkdir -p "$root/$PACKAGE" +"$protoc_dir/bin/protoc" \ + --plugin=protoc-gen-go="$work/protoc-gen-go" \ + -I "$work" -I "$protoc_dir/include" \ + --go_out="$root" --go_opt=module="$MODULE" "${mappings[@]}" \ + "${files[@]}" + +cat >"$root/$PACKAGE/source.go" < countData(best.payload)) + for _, d := range p.Data { + switch { + case d.GetValue().GetInvalid(): + pick("data-invalid", c, false) + case d.GetKey() == protos.Field_Location: + pick("data-location", c, false) + case d.GetValue().GetDoorValue() != nil: + pick("data-doors", c, false) + } + } + if p.IsResend { + pick("data-resend", c, false) + } + case "alerts": + var a protos.VehicleAlerts + if proto.Unmarshal(payload, &a) != nil { + continue + } + for _, alert := range a.Alerts { + if alert.EndedAt == nil { + // the smallest payload with an active alert + best, ok := picked["alerts"] + pick("alerts", c, ok && len(c.payload) < len(best.payload)) + break + } + } + case "errors": + var e protos.VehicleErrors + if proto.Unmarshal(payload, &e) != nil { + continue + } + if len(e.Errors) > 0 { + pick("errors", c, false) + } else { + pick("errors-empty", c, false) + } + case "connectivity": + var v protos.VehicleConnectivity + if proto.Unmarshal(payload, &v) != nil { + continue + } + pick("connectivity-"+strings.ToLower(v.Status.String()), c, false) + } + } + if err := scanner.Err(); err != nil { + return err + } + if err := os.MkdirAll(out, 0o755); err != nil { + return err + } + names := make([]string, 0, len(picked)) + for name := range picked { + names = append(names, name) + } + sort.Strings(names) + for _, name := range names { + c := picked[name] + payload, err := anonymize(c.subject, c.payload) + if err != nil { + return fmt.Errorf("%s: %w", name, err) + } + recordType := decoder.RecordType(c.subject) + request, err := json.Marshal(map[string]any{ + "subject": "telemetry." + fakeVIN + "." + recordType, + "headers": map[string]string{"traceparent": fakeTraceparent}, + "payload": payload, + }) + if err != nil { + return err + } + if vinPattern.Match(payload) && !strings.Contains(string(payload), fakeVIN) { + return fmt.Errorf("%s: payload still contains a VIN-like string", name) + } + path := filepath.Join(out, name+".request") + if err := os.WriteFile(path, append(request, '\n'), 0o644); err != nil { + return err + } + fmt.Println("wrote", path) + } + return nil +} + +func countData(payload []byte) int { + var p protos.Payload + _ = proto.Unmarshal(payload, &p) + return len(p.Data) +} + +func anonymize(subject string, payload []byte) ([]byte, error) { + var message proto.Message + switch decoder.RecordType(subject) { + case "data": + p := &protos.Payload{} + if err := proto.Unmarshal(payload, p); err != nil { + return nil, err + } + p.Vin = fakeVIN + for _, d := range p.Data { + if loc := d.GetValue().GetLocationValue(); loc != nil { + // Tesla Fremont Factory + loc.Latitude, loc.Longitude = 37.4919, -121.9447 + } + if fake, ok := personalStrings[d.GetKey()]; ok && d.GetValue().GetStringValue() != "" { + d.Value = &protos.Value{Value: &protos.Value_StringValue{StringValue: fake}} + } + } + message = p + case "alerts": + a := &protos.VehicleAlerts{} + if err := proto.Unmarshal(payload, a); err != nil { + return nil, err + } + a.Vin = fakeVIN + message = a + case "errors": + e := &protos.VehicleErrors{} + if err := proto.Unmarshal(payload, e); err != nil { + return nil, err + } + e.Vin = fakeVIN + for _, err := range e.Errors { + for k, v := range err.Tags { + err.Tags[k] = uuidPattern.ReplaceAllString(vinPattern.ReplaceAllString(v, fakeVIN), fakeConnectionID) + } + err.Body = vinPattern.ReplaceAllString(err.Body, fakeVIN) + } + message = e + case "connectivity": + v := &protos.VehicleConnectivity{} + if err := proto.Unmarshal(payload, v); err != nil { + return nil, err + } + v.Vin = fakeVIN + v.ConnectionId = fakeConnectionID + message = v + default: + return nil, fmt.Errorf("unknown subject %q", subject) + } + return proto.MarshalOptions{Deterministic: true}.Marshal(message) +} From 67edffaa0d72b702f01bf912ba7030940ee35653 Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Thu, 15 Oct 2026 10:47:09 +1000 Subject: [PATCH 2/2] Put vin and createdAt first in every flat event Alerts and errors carry vin and createdAt after a long array (alert events reach 16 KB), past where Splunk stops extracting fields at search time: a live natssubscribe sample had an alert event without vin. The flat format now starts every record type with vin and createdAt; -format protojson keeps proto order. The Splunk E2E checks every indexed event has both. --- README.md | 16 ++--- internal/decoder/decoder.go | 59 ++++++++++++++++++- internal/decoder/decoder_test.go | 12 ++-- internal/decoder/protocol_test.go | 2 +- .../decoder/testdata/golden/alerts.flat.json | 2 +- .../golden/alerts.flat.proto-names.json | 2 +- .../golden/connectivity-connected.flat.json | 2 +- ...nnectivity-connected.flat.proto-names.json | 2 +- .../connectivity-disconnected.flat.json | 2 +- ...ctivity-disconnected.flat.proto-names.json | 2 +- .../testdata/golden/errors-empty.flat.json | 2 +- .../golden/errors-empty.flat.proto-names.json | 2 +- .../decoder/testdata/golden/errors.flat.json | 2 +- .../golden/errors.flat.proto-names.json | 2 +- scripts/e2e-splunk.sh | 8 ++- 15 files changed, 89 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 083d49a..f9a1ab9 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Set these as the input's **Decoder Arguments** (or `decoder_args=` on | Argument | Default | Effect | |---|---|---| | `-format flat` | yes | Vehicle data has one top-level field per signal (see below). | -| `-format protojson` | | Vehicle data is the protobuf JSON mapping, the same JSON fleet-telemetry writes with `transmit_decoded_records`: `"data":[{"key":"VehicleSpeed","value":{"floatValue":28.6}}]`. | +| `-format protojson` | | Vehicle data is the protobuf JSON mapping, the same JSON fleet-telemetry writes with `transmit_decoded_records`, for every record type: fields in proto order, and vehicle data as `"data":[{"key":"VehicleSpeed","value":{"floatValue":28.6}}]`. | | `-proto-names` | | Proto field names (`created_at`, `network_interface`, `is_resend`) instead of the JSON names (`createdAt`, `networkInterface`, `isResend`). | | `-version` | | Prints the version and the tesla-protocol commit, then exits. | @@ -58,8 +58,10 @@ Set these as the input's **Decoder Arguments** (or `decoder_args=` on Every event is one line of JSON. Field names follow the protobuf JSON mapping, as fleet-telemetry's own JSON output does (lowerCamel, enums by name, timestamps in RFC 3339 UTC), and every field is present even when unset (`null`, `false`, -`0`, `""`), so an alert without `endedAt` is visibly still active. The VIN comes -from the message, or from the subject when the message has none. +`0`, `""`), so an alert without `endedAt` is visibly still active. Every event +starts with `vin` and `createdAt`, so Splunk extracts them even from large alert +events. The VIN comes from the message, or from the subject when the message has +none. **Vehicle data** (`telemetry..data`), with the default `-format flat`: @@ -80,23 +82,23 @@ from the message, or from the subject when the message has none. **Alerts** (`telemetry..alerts`): ```json -{"alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"startedAt":"2026-10-15T00:14:55.164Z","endedAt":null}],"createdAt":"2026-10-15T00:15:05.180915260Z","vin":"TESTVIN0000000001"} +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:15:05.180915260Z","alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"startedAt":"2026-10-15T00:14:55.164Z","endedAt":null}]} ``` **Errors** (`telemetry..errors`): ```json -{"errors":[{"createdAt":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen"},"body":""}],"createdAt":"2026-10-15T00:10:12.617991348Z","vin":"TESTVIN0000000001"} +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:10:12.617991348Z","errors":[{"createdAt":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen"},"body":""}]} ``` **Connectivity** (`telemetry..connectivity`): ```json -{"vin":"TESTVIN0000000001","connectionId":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","createdAt":"2026-10-15T00:13:22.426862796Z","networkInterface":"wifi"} +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:22.426862796Z","connectionId":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","networkInterface":"wifi"} ``` **Metrics** (`telemetry..metrics`) follow the same mapping: -`{"metrics":[{"name":...,"tags":{...},"value":...}],"createdAt":...,"vin":...}`. +`{"vin":...,"createdAt":...,"metrics":[{"name":...,"tags":{...},"value":...}]}`. Example searches (with an input indexing into `index=nats`): diff --git a/internal/decoder/decoder.go b/internal/decoder/decoder.go index 0d01d4d..14ab144 100644 --- a/internal/decoder/decoder.go +++ b/internal/decoder/decoder.go @@ -105,10 +105,13 @@ func (d *Decoder) Decode(dst []byte, subject string, payload []byte) ([]byte, er return dst, fmt.Errorf("cannot decode %s payload: %w", recordType, err) } fillVIN(message, subject) - if payload, ok := message.(*protos.Payload); ok && d.format == FormatFlat { + if d.format == FormatProtoJSON { + return d.appendProtoJSON(dst, message) + } + if payload, ok := message.(*protos.Payload); ok { return d.appendFlatPayload(dst, payload) } - return d.appendProtoJSON(dst, message) + return d.appendIdentityFirst(dst, message) } // fillVIN sets the VIN from the subject (telemetry..) when the @@ -135,6 +138,58 @@ func (d *Decoder) appendProtoJSON(dst []byte, message proto.Message) ([]byte, er return appendCompact(dst, &d.scratch, b) } +// appendIdentityFirst appends the message in the protobuf JSON mapping with vin +// and createdAt as its first fields. Alerts and errors list them after a long +// array (alert events reach 16 KB), past the point where Splunk stops extracting +// fields at search time. +func (d *Decoder) appendIdentityFirst(dst []byte, message proto.Message) ([]byte, error) { + b, err := d.json.Marshal(message) + if err != nil { + return dst, err + } + type member struct { + key string + value json.RawMessage + } + var members []member + dec := json.NewDecoder(bytes.NewReader(b)) + if _, err := dec.Token(); err != nil { // { + return dst, err + } + for dec.More() { + key, err := dec.Token() + if err != nil { + return dst, err + } + var value json.RawMessage + if err := dec.Decode(&value); err != nil { + return dst, err + } + members = append(members, member{key.(string), value}) + } + ordered := make([]byte, 0, len(b)) + ordered = append(ordered, '{') + write := func(m member) { + if len(ordered) > 1 { + ordered = append(ordered, ',') + } + ordered = append(appendKey(ordered, m.key), m.value...) + } + for _, first := range []string{d.names.vin, d.names.createdAt} { + for _, m := range members { + if m.key == first { + write(m) + } + } + } + for _, m := range members { + if m.key != d.names.vin && m.key != d.names.createdAt { + write(m) + } + } + return appendCompact(dst, &d.scratch, append(ordered, '}')) +} + func appendCompact(dst []byte, scratch *bytes.Buffer, b []byte) ([]byte, error) { scratch.Reset() if err := json.Compact(scratch, b); err != nil { diff --git a/internal/decoder/decoder_test.go b/internal/decoder/decoder_test.go index 2a5a965..319a29c 100644 --- a/internal/decoder/decoder_test.go +++ b/internal/decoder/decoder_test.go @@ -154,19 +154,19 @@ func TestRecordTypes(t *testing.T) { want string }{ {"telemetry.V.alerts", &protos.VehicleAlerts{Alerts: []*protos.VehicleAlert{{Name: "A", Audiences: []protos.Audience{protos.Audience_Customer}}}}, - `{"alerts":[{"name":"A","audiences":["Customer"],"startedAt":null,"endedAt":null}],"createdAt":null,"vin":"V"}`}, + `{"vin":"V","createdAt":null,"alerts":[{"name":"A","audiences":["Customer"],"startedAt":null,"endedAt":null}]}`}, {"telemetry.V.errors", &protos.VehicleErrors{Errors: []*protos.VehicleError{{Name: "E", Tags: map[string]string{"k": "v"}}}}, - `{"errors":[{"createdAt":null,"name":"E","tags":{"k":"v"},"body":""}],"createdAt":null,"vin":"V"}`}, + `{"vin":"V","createdAt":null,"errors":[{"createdAt":null,"name":"E","tags":{"k":"v"},"body":""}]}`}, {"telemetry.V.connectivity", &protos.VehicleConnectivity{Status: protos.ConnectivityEvent_CONNECTED, NetworkInterface: "wifi"}, - `{"vin":"V","connectionId":"","status":"CONNECTED","createdAt":null,"networkInterface":"wifi"}`}, + `{"vin":"V","createdAt":null,"connectionId":"","status":"CONNECTED","networkInterface":"wifi"}`}, {"telemetry.V.metrics", &protos.VehicleMetrics{Metrics: []*protos.Metric{{Name: "m", Value: 1.5}}}, - `{"metrics":[{"name":"m","tags":{},"value":1.5}],"createdAt":null,"vin":"V"}`}, + `{"vin":"V","createdAt":null,"metrics":[{"name":"m","tags":{},"value":1.5}]}`}, // The VIN in the message wins over the subject {"telemetry.OTHER.connectivity", &protos.VehicleConnectivity{Vin: "V", Status: protos.ConnectivityEvent_DISCONNECTED}, - `{"vin":"V","connectionId":"","status":"DISCONNECTED","createdAt":null,"networkInterface":""}`}, + `{"vin":"V","createdAt":null,"connectionId":"","status":"DISCONNECTED","networkInterface":""}`}, // No VIN anywhere {"connectivity", &protos.VehicleConnectivity{Status: protos.ConnectivityEvent_DISCONNECTED}, - `{"vin":"","connectionId":"","status":"DISCONNECTED","createdAt":null,"networkInterface":""}`}, + `{"vin":"","createdAt":null,"connectionId":"","status":"DISCONNECTED","networkInterface":""}`}, } { if got := decode(t, d, tc.subject, tc.message); got != tc.want { t.Errorf("%s:\ngot %s\nwant %s", tc.subject, got, tc.want) diff --git a/internal/decoder/protocol_test.go b/internal/decoder/protocol_test.go index f063dcb..9283b70 100644 --- a/internal/decoder/protocol_test.go +++ b/internal/decoder/protocol_test.go @@ -42,7 +42,7 @@ func run(t *testing.T, input string) (out []string, diag string) { func TestProtocol(t *testing.T) { good := request("telemetry.V.connectivity", connectivityPayload(t)) - wantGood := `{"vin":"V","connectionId":"","status":"CONNECTED","createdAt":null,"networkInterface":""}` + wantGood := `{"vin":"V","createdAt":null,"connectionId":"","status":"CONNECTED","networkInterface":""}` for _, tc := range []struct { name string request string diff --git a/internal/decoder/testdata/golden/alerts.flat.json b/internal/decoder/testdata/golden/alerts.flat.json index 7df3848..723bc72 100644 --- a/internal/decoder/testdata/golden/alerts.flat.json +++ b/internal/decoder/testdata/golden/alerts.flat.json @@ -1 +1 @@ -{"alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"startedAt":"2026-10-15T00:14:55.164Z","endedAt":null}],"createdAt":"2026-10-15T00:15:05.180915260Z","vin":"TESTVIN0000000001"} +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:15:05.180915260Z","alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"startedAt":"2026-10-15T00:14:55.164Z","endedAt":null}]} diff --git a/internal/decoder/testdata/golden/alerts.flat.proto-names.json b/internal/decoder/testdata/golden/alerts.flat.proto-names.json index e5ad497..1ba3637 100644 --- a/internal/decoder/testdata/golden/alerts.flat.proto-names.json +++ b/internal/decoder/testdata/golden/alerts.flat.proto-names.json @@ -1 +1 @@ -{"alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"started_at":"2026-10-15T00:14:55.164Z","ended_at":null}],"created_at":"2026-10-15T00:15:05.180915260Z","vin":"TESTVIN0000000001"} +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:15:05.180915260Z","alerts":[{"name":"CP_a101_wcFoldbackActive","audiences":["Customer","Service"],"started_at":"2026-10-15T00:14:55.164Z","ended_at":null}]} diff --git a/internal/decoder/testdata/golden/connectivity-connected.flat.json b/internal/decoder/testdata/golden/connectivity-connected.flat.json index 420bf59..790a41e 100644 --- a/internal/decoder/testdata/golden/connectivity-connected.flat.json +++ b/internal/decoder/testdata/golden/connectivity-connected.flat.json @@ -1 +1 @@ -{"vin":"TESTVIN0000000001","connectionId":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","createdAt":"2026-10-15T00:13:22.426862796Z","networkInterface":"wifi"} +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:22.426862796Z","connectionId":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","networkInterface":"wifi"} diff --git a/internal/decoder/testdata/golden/connectivity-connected.flat.proto-names.json b/internal/decoder/testdata/golden/connectivity-connected.flat.proto-names.json index cc33ec5..d2944bb 100644 --- a/internal/decoder/testdata/golden/connectivity-connected.flat.proto-names.json +++ b/internal/decoder/testdata/golden/connectivity-connected.flat.proto-names.json @@ -1 +1 @@ -{"vin":"TESTVIN0000000001","connection_id":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","created_at":"2026-10-15T00:13:22.426862796Z","network_interface":"wifi"} +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:13:22.426862796Z","connection_id":"00000000-0000-4000-8000-000000000001","status":"CONNECTED","network_interface":"wifi"} diff --git a/internal/decoder/testdata/golden/connectivity-disconnected.flat.json b/internal/decoder/testdata/golden/connectivity-disconnected.flat.json index f63e59e..cac2d00 100644 --- a/internal/decoder/testdata/golden/connectivity-disconnected.flat.json +++ b/internal/decoder/testdata/golden/connectivity-disconnected.flat.json @@ -1 +1 @@ -{"vin":"TESTVIN0000000001","connectionId":"00000000-0000-4000-8000-000000000001","status":"DISCONNECTED","createdAt":"2026-10-15T00:13:19.375925589Z","networkInterface":"cellular"} +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:19.375925589Z","connectionId":"00000000-0000-4000-8000-000000000001","status":"DISCONNECTED","networkInterface":"cellular"} diff --git a/internal/decoder/testdata/golden/connectivity-disconnected.flat.proto-names.json b/internal/decoder/testdata/golden/connectivity-disconnected.flat.proto-names.json index a3f00ff..66e8139 100644 --- a/internal/decoder/testdata/golden/connectivity-disconnected.flat.proto-names.json +++ b/internal/decoder/testdata/golden/connectivity-disconnected.flat.proto-names.json @@ -1 +1 @@ -{"vin":"TESTVIN0000000001","connection_id":"00000000-0000-4000-8000-000000000001","status":"DISCONNECTED","created_at":"2026-10-15T00:13:19.375925589Z","network_interface":"cellular"} +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:13:19.375925589Z","connection_id":"00000000-0000-4000-8000-000000000001","status":"DISCONNECTED","network_interface":"cellular"} diff --git a/internal/decoder/testdata/golden/errors-empty.flat.json b/internal/decoder/testdata/golden/errors-empty.flat.json index 5059a30..23bdb80 100644 --- a/internal/decoder/testdata/golden/errors-empty.flat.json +++ b/internal/decoder/testdata/golden/errors-empty.flat.json @@ -1 +1 @@ -{"errors":[],"createdAt":"2026-10-15T00:13:21.673998462Z","vin":"TESTVIN0000000001"} +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:13:21.673998462Z","errors":[]} diff --git a/internal/decoder/testdata/golden/errors-empty.flat.proto-names.json b/internal/decoder/testdata/golden/errors-empty.flat.proto-names.json index c61e608..9da5709 100644 --- a/internal/decoder/testdata/golden/errors-empty.flat.proto-names.json +++ b/internal/decoder/testdata/golden/errors-empty.flat.proto-names.json @@ -1 +1 @@ -{"errors":[],"created_at":"2026-10-15T00:13:21.673998462Z","vin":"TESTVIN0000000001"} +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:13:21.673998462Z","errors":[]} diff --git a/internal/decoder/testdata/golden/errors.flat.json b/internal/decoder/testdata/golden/errors.flat.json index 97c820e..4e1108b 100644 --- a/internal/decoder/testdata/golden/errors.flat.json +++ b/internal/decoder/testdata/golden/errors.flat.json @@ -1 +1 @@ -{"errors":[{"createdAt":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen","name":"00000000-0000-4000-8000-000000000001"},"body":""}],"createdAt":"2026-10-15T00:10:12.617991348Z","vin":"TESTVIN0000000001"} +{"vin":"TESTVIN0000000001","createdAt":"2026-10-15T00:10:12.617991348Z","errors":[{"createdAt":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen","name":"00000000-0000-4000-8000-000000000001"},"body":""}]} diff --git a/internal/decoder/testdata/golden/errors.flat.proto-names.json b/internal/decoder/testdata/golden/errors.flat.proto-names.json index 5d108b3..3717d77 100644 --- a/internal/decoder/testdata/golden/errors.flat.proto-names.json +++ b/internal/decoder/testdata/golden/errors.flat.proto-names.json @@ -1 +1 @@ -{"errors":[{"created_at":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen","name":"00000000-0000-4000-8000-000000000001"},"body":""}],"created_at":"2026-10-15T00:10:12.617991348Z","vin":"TESTVIN0000000001"} +{"vin":"TESTVIN0000000001","created_at":"2026-10-15T00:10:12.617991348Z","errors":[{"created_at":"2026-10-14T23:45:04.404614863Z","name":"unsupported_field","tags":{"field_name":"LifetimeEnergyGainedRegen","name":"00000000-0000-4000-8000-000000000001"},"body":""}]} diff --git a/scripts/e2e-splunk.sh b/scripts/e2e-splunk.sh index 100482e..225e90b 100755 --- a/scripts/e2e-splunk.sh +++ b/scripts/e2e-splunk.sh @@ -84,6 +84,10 @@ echo "indexed for $(($(date +%s) - start))s" echo "-- events by record type and sourcetype (nats:json = decoded, nats:message = base64 fallback)" search 'search index=telemetry | eval type=mvindex(split(source, "."), -1) | stats count by type sourcetype' +echo "-- vin and createdAt extracted from every event" +search 'search index=telemetry | eval type=mvindex(split(source, "."), -1) + | stats count as events count(vin) as vin count(createdAt) as createdAt by type' +missing=$(search 'search index=telemetry | where isnull(vin) OR isnull(createdAt) | stats count' | tail -1) echo "-- data: events carrying common signals" search 'search index=telemetry sourcetype=nats:json source=*.data | stats count as events count(vin) as vin count(createdAt) as createdAt count(VehicleSpeed) as VehicleSpeed @@ -101,6 +105,6 @@ search 'search index=telemetry sourcetype=nats:json source=*.errors | stats coun failed_events=$(search 'search index=telemetry sourcetype!=nats:json | stats count' | tail -1) failed_log=$(search 'search index=_internal sourcetype=splunkd "failed to decode" | stats count' | tail -1) total=$(search 'search index=telemetry | stats count' | tail -1) -echo "== $total events, $failed_events not decoded, $failed_log decode failures logged" -[ "$total" -gt 0 ] && [ "$failed_events" = 0 ] && [ "$failed_log" = 0 ] +echo "== $total events, $failed_events not decoded, $failed_log decode failures logged, $missing without vin or createdAt" +[ "$total" -gt 0 ] && [ "$failed_events" = 0 ] && [ "$failed_log" = 0 ] && [ "$missing" = 0 ] echo PASS