# Core Components of TeslaMate: Architecture and Source Code Guide

> Explore TeslaMate core components: OTP supervision tree, API client, GenStateMachine, Ecto logging, MQTT, and Phoenix LiveView. Understand the architecture and source code.

- Repository: [TeslaMate/teslamate](https://github.com/teslamate-org/teslamate)
- Tags: architecture
- Published: 2026-06-18

---

**TeslaMate is built around a fault-tolerant OTP supervision tree that coordinates an API client, per-vehicle GenStateMachine processes, an Ecto-based logging layer, an optional MQTT bridge, and a Phoenix LiveView web interface.**

TeslaMate is a self-hosted telemetry collector for Tesla vehicles written in Elixir. Understanding the core components of TeslaMate reveals how it authenticates with Tesla's cloud API, manages state machines for multiple vehicles, and persists high-frequency telemetry data to PostgreSQL. The architecture follows OTP principles, organizing functionality into isolated processes under a unified supervision tree defined in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex).

## Application and Supervision Tree

The entry point `TeslaMate.Application` constructs the supervision tree at runtime. It dynamically builds a list of child processes based on configuration, including the Ecto repository, vault, HTTP client, API client, and optional MQTT connector.

```elixir
defp children do
  [
    TeslaMate.Repo,
    TeslaMate.Vault,
    TeslaMate.HTTP,
    TeslaMate.Api,
    TeslaMate.Updater,
    {Phoenix.PubSub, name: TeslaMate.PubSub},
    TeslaMateWeb.Endpoint,
    TeslaMate.Terrain,
    TeslaMate.Vehicles,
    if(mqtt_config, do: {TeslaMate.Mqtt, mqtt_config}),
    TeslaMate.Repair
  ]
  |> Enum.reject(&is_nil/1)
end

```

This structure ensures that if the API client or a vehicle process crashes, the supervisor restarts it according to the defined strategy. The `TeslaMate.Vehicles` supervisor, stored in the `@name` module attribute, spawns child processes dynamically after discovering vehicles via the API.

## API Client and Token Management

`TeslaMate.Api` is a `GenServer` that manages authentication with Tesla's cloud services. It stores the current `TeslaApi.Auth` struct in an ETS table and automatically refreshes access tokens before expiration.

```elixir
def handle_call({:sign_in, args}, _, %State{} = state) do
  # … perform Auth.refresh/1, store new tokens, restart vehicle registry …

end

```

The module proxies all API calls—including `list_vehicles/0`, `get_vehicle/2`, and `stream/3`—and implements circuit breaker logic. When the API returns `:unauthorized`, the process triggers a fuse that forces a sign-out and token refresh. Secure encryption of refresh and access tokens is handled by `TeslaMate.Vault` using the `:crypto` module, while `TeslaMate.Auth` and `TeslaMate.Auth.Tokens` manage the encryption/decryption logic.

## Vehicle Registry and State Machines

The `TeslaMate.Vehicles` module acts as a supervisor that discovers vehicles via `Api.list_vehicles/0` and spawns a dedicated process for each car. It provides public helper functions like `list/0`, `summary/1`, and `suspend_logging/1` that forward calls to the respective vehicle processes.

```elixir
def list do
  Supervisor.which_children(@name)
  |> Task.async_stream(fn {_, pid, _, _} -> Vehicle.summary(pid) end, ...)
  |> Enum.map(&elem(&1, 1))
  |> Enum.sort_by(&{&1.car.display_priority, &1.car.id})
end

```

### Per-Vehicle GenStateMachine

Each vehicle runs an isolated `GenStateMachine` implemented in `TeslaMate.Vehicles.Vehicle`. This process maintains the car's current state and transitions between:

- **`:asleep`** / **`:offline`** – Low-frequency polling while waiting for wake-up
- **`:online`** – Regular polling or streaming API connection when the vehicle is awake
- **`{:driving, …}`** – Active drive session with GPS tracking
- **`{:charging, …}`** – Charging process with energy monitoring
- **`{:suspended, …}`** – Logging temporarily disabled by user settings
- **`{:updating, …}`** – Firmware update in progress

Key callbacks include `handle_event(:internal, {:update, {:online, vehicle}}, state, data)` which processes incoming telemetry and decides whether to initiate a drive or charging session. The process also installs per-vehicle fuses (`:vehicle_not_found`, `:api_error`) to protect against repeated API failures.

## Data Persistence with Ecto

All telemetry is persisted through the `TeslaMate.Log` context, which uses Ecto to write to PostgreSQL. The logging system creates records for every state change, drive, charge session, and GPS position.

Important functions include:

- **`Log.start_state/3`** – Begins a new state entry (e.g., transitioning to `:online`)
- **`Log.insert_position/2`** – Stores GPS coordinates, battery level, temperature, and other telemetry points
- **`Log.start_charging_process/3`** – Creates a charging session record with location data
- **`Log.close_drive/2`** – Finalizes a drive record with calculated distance and duration

Schema files are located in `lib/teslamate/log/` and define tables for cars, drives, charges, and positions. The repository `TeslaMate.Repo` is configured in `config/*.exs` and supervised by the root application.

## MQTT Bridge for External Systems

When configured, `TeslaMate.Mqtt` publishes live vehicle data to an MQTT broker. The module subscribes to internal Phoenix PubSub topics and forwards updates to topics like `teslamate/<car_id>/summary`. It also subscribes to command topics (e.g., `wake_up`) and forwards incoming commands to the appropriate vehicle process, enabling integration with home automation systems.

## Configuration and Settings

User preferences are managed through the `TeslaMate.Settings` context. The `CarSettings` struct contains configurable fields such as `suspend_min`, `use_streaming_api`, and custom polling intervals. When settings change, the `Vehicle` process receives a message containing the `%CarSettings{}` struct and reconfigures its timers or streaming connection accordingly.

## Phoenix LiveView Web Interface

The web layer resides in `lib/teslamate_web` and provides real-time visualization. The router ([`lib/teslamate_web/router.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate_web/router.ex)) mounts LiveViews for car overviews, drive details, and settings panels. These LiveViews subscribe to the same Phoenix PubSub topics used by the vehicle processes, ensuring the browser receives instant updates when telemetry changes.

```elixir
def mount(_params, _session, socket) do
  car_id = socket.assigns[:car_id]
  Phoenix.PubSub.subscribe(TeslaMate.PubSub, TeslaMate.Vehicles.Vehicle.summary_topic(car_id))
  {:ok, assign(socket, :summary, nil)}
end

def handle_info({:summary, summary}, socket) do
  {:noreply, assign(socket, :summary, summary)}
end

```

## Supporting Infrastructure

### Terrain and Geofencing

`TeslaMate.Terrain` lazily downloads SRTM elevation tiles and caches them to provide altitude data for drives. The `TeslaMate.Locations` context resolves GPS coordinates to human-readable addresses and evaluates whether positions fall within user-defined geofences.

### CSV Import Pipeline

`TeslaMate.Import` handles batch ingestion of historic CSV files exported from older TeslaMate instances. It uses `Import.Csv` to read rows and `Import.LineParser` to transform them before writing to the standard log tables.

### Secure Updates and Token Vault

`TeslaMate.Updater` can download newer releases from GitHub and replace the current binary, while `TeslaMate.Vault` securely encrypts API tokens using the Erlang `:crypto` module, keeping credentials safe on disk.

## Summary

- **TeslaMate.Application** builds a dynamic supervision tree that orchestrates all components
- **TeslaMate.Api** manages Tesla cloud authentication and token refresh via `GenServer`
- **TeslaMate.Vehicles** supervises a `GenStateMachine` per vehicle to handle state transitions like driving and charging
- **TeslaMate.Log** provides the Ecto context for persisting all telemetry to PostgreSQL
- **TeslaMate.Mqtt** optionally bridges live data to external MQTT brokers
- **TeslaMateWeb** delivers real-time visualization through Phoenix LiveView
- Supporting modules handle terrain data, CSV imports, self-updates, and secure token storage

## Frequently Asked Questions

### How does TeslaMate handle authentication with Tesla's API?

TeslaMate uses `TeslaMate.Api` to store the `TeslaApi.Auth` struct in an ETS table and automatically refreshes access tokens before they expire. The `TeslaMate.Vault` module encrypts tokens using Erlang's `:crypto` module, while `TeslaMate.Auth` handles the encryption/decryption logic, ensuring credentials remain secure on disk.

### What database does TeslaMate use for data persistence?

TeslaMate uses **PostgreSQL** accessed through Ecto. The `TeslaMate.Log` context provides functions like `insert_position/2` and `start_charging_process/3` to write telemetry data, while `TeslaMate.Repo` manages the database connection pool under the OTP supervision tree.

### How does TeslaMate support multiple vehicles?

The `TeslaMate.Vehicles` supervisor discovers all vehicles via the API and spawns a separate `GenStateMachine` process for each car using `Vehicle.child_spec/1`. Each process maintains independent state (asleep, driving, charging) and publishes updates to unique Phoenix PubSub topics, allowing the system to track an unlimited number of vehicles concurrently.

### What is the purpose of the MQTT bridge in TeslaMate?

The optional `TeslaMate.Mqtt` component publishes live telemetry to an MQTT broker on topics like `teslamate/<car_id>/summary`, enabling integration with home automation platforms. It also subscribes to command topics, allowing external systems to send commands such as wake-up requests back to the vehicle processes.