Understanding the TeslaMate Vehicle State Machine: The 5 Core States Explained
The TeslaMate vehicle state machine consists of five distinct sub-states—Charge, Climate, Drive, VehicleConfig, and VehicleState—that transform raw Tesla API JSON into typed Elixir structs through pure-functional mapping functions.
The teslamate-org/teslamate repository implements a sophisticated vehicle state machine to model real-time Tesla telemetry. At its core, the TeslaApi.Vehicle.State module orchestrates five specialized sub-states, each responsible for parsing specific categories of vehicle data from the Tesla API into strongly-typed Elixir structures. This pure-functional approach enables reliable unit testing and seamless integration with the application’s database, MQTT publisher, and LiveView dashboards.
What Is the TeslaMate Vehicle State Machine?
The TeslaMate vehicle state machine is a pure-functional state transformer implemented primarily in lib/tesla_api/vehicle/state.ex. Unlike traditional GenServer-based state machines, this implementation uses lightweight "mapper" functions (result/1) to convert raw JSON payloads into Elixir structs without side effects. The module aggregates disparate telemetry streams—battery metrics, cabin climate, navigation data, and vehicle configuration—into a unified, type-safe representation that powers the dashboard, database layer, and MQTT integrations.
The Five Sub-States of the TeslaMate State Machine
The state machine decomposes vehicle telemetry into five coherent domains. Each sub-state is defined by its own struct and mapping logic in lib/tesla_api/vehicle/state.ex.
Charge State
The Charge state captures battery-related telemetry including state of charge, charger power, charging limits, and time-to-full calculations. The TeslaApi.Vehicle.State.Charge struct exposes these fields through the Charge.result/1 mapper function, which ingests the raw charge_state JSON node from the Tesla API response.
Climate State
The Climate state manages cabin temperature controls, fan status, seat heater levels, defrost settings, and pre-conditioning schedules. The TeslaApi.Vehicle.State.Climate struct normalizes this environmental data via Climate.result/1, processing the climate_state API payload.
Drive State
The Drive state handles real-time navigation and motion data including GPS coordinates, vehicle speed, compass heading, and shift state (Park, Reverse, Neutral, Drive). The TeslaApi.Vehicle.State.Drive struct and Drive.result/1 function transform the drive_state JSON into usable Elixir types for tracking trips and location.
VehicleConfig State
The VehicleConfig state stores static configuration data that rarely changes, including vehicle model, trim options, hardware variants, and factory-installed features. The TeslaApi.Vehicle.State.VehicleConfig struct persists these immutable attributes through VehicleConfig.result/1.
VehicleState
The VehicleState represents high-level vehicle status including door locks, window positions, trunk and frunk status, software update progress, TPMS tire pressure readings, and Sentry Mode activation. This state includes a nested SoftwareUpdate struct specifically for tracking OTA update progress, mapped via VehicleState.result/1.
How the State Machine Transforms API Data
The state machine operates as a pure transformation pipeline. When TeslaApi.Vehicle.get/2 retrieves fresh telemetry from Tesla’s cloud endpoint, each sub-state’s result/1 function extracts and types its relevant subset of the JSON payload.
# 1️⃣ Pull the raw vehicle data from the Tesla API
{:ok, raw_vehicle} = TeslaApi.Vehicle.get(vin, token)
# 2️⃣ Convert the nested maps into typed structs
charge_state = TeslaApi.Vehicle.State.Charge.result(raw_vehicle["charge_state"])
climate_state = TeslaApi.Vehicle.State.Climate.result(raw_vehicle["climate_state"])
drive_state = TeslaApi.Vehicle.State.Drive.result(raw_vehicle["drive_state"])
config_state = TeslaApi.Vehicle.State.VehicleConfig.result(raw_vehicle["vehicle_config"])
state_state = TeslaApi.Vehicle.State.VehicleState.result(raw_vehicle["vehicle_state"])
# 3️⃣ Assemble the full vehicle snapshot (simplified)
vehicle_snapshot = %{
charge: charge_state,
climate: climate_state,
drive: drive_state,
config: config_state,
state: state_state
}
# 4️⃣ Store / broadcast the snapshot
TeslaMate.Vehicles.update(vin, vehicle_snapshot)
You can then access specific metrics directly from the typed structs:
# 👀 Example: Inspect the charger power from the state machine
%TeslaApi.Vehicle.State.Charge{charger_power: power} = charge_state
IO.puts("Current charger power: #{power} kW")
Integration with TeslaMate Consumers
Once transformed, the unified state feeds multiple consumers across the application according to the teslamate-org/teslamate source code. The TeslaMate.Vehicles.Vehicle module (in lib/teslamate/vehicles/vehicle.ex) aggregates these structs for database persistence. Simultaneously, TeslaMate.Mqtt.Pubsub.VehicleSubscriber (in lib/teslamate/mqtt/pubsub/vehicle_subscriber.ex) broadcasts state updates over MQTT for external integrations. The LiveView components in lib/teslamate_web/live/car_live/summary.ex render real-time dashboards from this normalized state without directly parsing raw API responses.
Summary
- The TeslaMate vehicle state machine comprises five sub-states: Charge, Climate, Drive, VehicleConfig, and VehicleState.
- Each sub-state uses a dedicated struct and
result/1mapper function inlib/tesla_api/vehicle/state.exto parse raw Tesla API JSON. - The implementation is pure-functional, not a GenServer, enabling side-effect-free transformation and easy unit testing.
- Mapped structs flow to the database layer (
TeslaMate.Vehicles.Vehicle), MQTT broker (VehicleSubscriber), and web interface (car_live/summary.ex).
Frequently Asked Questions
What are the five states in the TeslaMate vehicle state machine?
The TeslaMate vehicle state machine defines five sub-states: Charge (battery metrics), Climate (cabin controls), Drive (navigation and motion), VehicleConfig (static configuration), and VehicleState (doors, locks, and software updates). Each corresponds to a specific struct in TeslaApi.Vehicle.State that maps raw Tesla API JSON into typed Elixir data.
How does TeslaMate convert Tesla API JSON into Elixir structs?
TeslaMate uses pure-functional mapper functions named result/1 defined in each sub-state module. For example, TeslaApi.Vehicle.State.Charge.result/1 takes the raw charge_state JSON map and returns a populated %TeslaApi.Vehicle.State.Charge{} struct with typed fields for charger power, battery level, and charging limits.
Is the TeslaMate vehicle state machine implemented as a GenServer?
No. Unlike traditional Elixir state machines that run as GenServer processes, the TeslaMate vehicle state machine is a pure-functional transformer. The TeslaApi.Vehicle.State module acts as a library of functions that transform data without maintaining process state or side effects, making it lightweight and easy to test.
Which TeslaMate modules consume the output of the vehicle state machine?
The mapped structs flow to three primary consumers: TeslaMate.Vehicles.Vehicle for database persistence, TeslaMate.Mqtt.Pubsub.VehicleSubscriber for MQTT broadcasting, and TeslaMateWeb.Live.CarLive.Summary for the real-time web dashboard. These consumers receive normalized data without needing to parse raw Tesla API responses.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →