TeslaMate Database Schema for Drives, Charges, and Positions: A Complete Technical Guide
TeslaMate stores vehicle telemetry in four core Ecto schemas—drives, positions, charges, and charging_processes—with foreign-key relationships linking drives to their start/end coordinates, charging sessions to location data, and individual charge readings to aggregated processes.
TeslaMate, the popular open-source Tesla data logger built with Elixir and Phoenix, persists high-granularity vehicle telemetry using a carefully normalized PostgreSQL schema. Understanding the database schema for drives, charges, and positions is essential for custom analytics, third-party integrations, or troubleshooting data integrity issues. The schema definitions reside in the teslamate-org/teslamate repository and leverage Ecto's relational mapping to maintain referential integrity between vehicle sessions and geographic coordinates.
Core Schema Architecture
TeslaMate organizes historical vehicle data into four primary tables defined in lib/teslamate/log/. Each schema uses Ecto's schema/2 macro and establishes associations via belongs_to/3 and has_many/2, with foreign-key constraints enforced at the changeset level.
The logical model separates discrete events (individual charge readings, GPS waypoints) from aggregate sessions (complete drives, charging processes), enabling efficient querying of both summary statistics and granular telemetry.
The Drives Schema
The drives table captures complete vehicle trips with temporal, spatial, and efficiency metrics. Defined in lib/teslamate/log/drive.ex, the schema tracks mileage deltas, energy consumption, and environmental conditions during travel.
Key fields include:
- Temporal:
start_date,end_date,duration_min - Spatial:
start_km,end_km,distance,ascent,descent - Environmental: Temperature averages, speed limits, power limits, and range columns
Relationships (as implemented in lib/teslamate/log/drive.ex lines 8-38):
belongs_to :car→ carsbelongs_to :start_position→ positionsbelongs_to :end_position→ positionsbelongs_to :start_address→ addressesbelongs_to :end_address→ addressesbelongs_to :start_geofence→ geofencesbelongs_to :end_geofence→ geofenceshas_many :positions→ all GPS waypoints belonging to the drive
The Positions Schema
Individual telemetry points are stored in the positions table, defined in lib/teslamate/log/position.ex. These records represent the granular GPS and vehicle-state snapshots captured during drives.
Primary fields:
- Geographic:
latitude,longitude,elevation - Vehicle state:
speed,power,odometer, battery level, range columns - Climate:
outside_temp, TPMS pressures, HVAC data
Relationships:
belongs_to :car→ carsbelongs_to :drive→ drives (nullable for positions captured outside of trips)
Charges and Charging Processes
TeslaMate distinguishes between individual charge measurements and aggregated charging sessions using two separate schemas.
The Charges Schema
Defined in lib/teslamate/log/charge.ex, this schema stores discrete readings from the vehicle's charging port. It tracks instantaneous values such as charger_current, charger_voltage, charger_power, and charger_phases, alongside battery_level, charge_energy_added, and cable connection status.
Relationship:
belongs_to :charging_process→ charging_processes
The ChargingProcess Schema
The charging_processes table (defined in lib/teslamate/log/charging_process.ex) aggregates multiple charges into a single session, calculating cumulative statistics like total charge_energy_added, duration_min, and average outside_temp.
Key fields: start_date, end_date, cost, battery level deltas, and range columns.
Relationships:
belongs_to :car→ carsbelongs_to :position→ positions (the GPS coordinates where charging began)belongs_to :address→ addressesbelongs_to :geofence→ geofenceshas_many :charges→ individual charge readings belonging to the session
Entity Relationship Model
The schemas form a directed graph connecting temporal sessions to spatial data:
- Drives link to Positions via
start_position_idandend_position_idforeign keys, while also maintaining ahas_manyassociation to all intermediate waypoints. - ChargingProcesses link to Positions via
position_id, capturing the geographic context of where charging occurred. - Charges link to ChargingProcesses via
charging_process_id, creating a parent-child relationship between aggregated sessions and raw measurements. - Both Drives and ChargingProcesses reference addresses and geofences, enabling location-based filtering without expensive coordinate calculations.
Foreign-key constraints are enforced through Ecto changesets, ensuring referential integrity across the priv/repo/migrations/ directory's migration files.
Querying the Schema with Ecto
Fetching a Drive with Full Geographic Context
To retrieve a drive complete with its start/end positions, addresses, and geofences:
drive =
TeslaMate.Repo.get!(TeslaMate.Log.Drive, drive_id)
|> TeslaMate.Repo.preload([
:start_position,
:end_position,
:start_address,
:end_address,
:start_geofence,
:end_geofence,
:car,
:positions
])
Retrieving Charging Session Details
To load a charging process with all individual measurements and location data:
charging_process =
TeslaMate.Repo.get!(TeslaMate.Log.ChargingProcess, cp_id)
|> TeslaMate.Repo.preload([
:car,
:position,
:address,
:geofence,
:charges
])
Querying Positions for Map Rendering
To fetch all GPS waypoints for a specific drive, ordered chronologically:
positions =
TeslaMate.Repo.all(
from p in TeslaMate.Log.Position,
where: p.drive_id == ^drive_id,
order_by: p.date,
preload: [:car]
)
Creating Linked Records
When inserting a new drive with associated positions:
%TeslaMate.Log.Drive{}
|> TeslaMate.Log.Drive.changeset(%{
start_date: DateTime.utc_now(),
car_id: car_id,
start_position_id: start_pos_id,
end_position_id: end_pos_id,
start_address_id: start_addr_id,
end_address_id: end_addr_id
})
|> TeslaMate.Repo.insert()
Summary
- Four core schemas power TeslaMate's data model:
drives,positions,charges, andcharging_processes, defined inlib/teslamate/log/. - Drives maintain dual relationships to positions (start and end) and aggregate all intermediate waypoints via
has_many :positions. - ChargingProcesses serve as the aggregation point for
charges, linking energy data to specific geographic coordinates viabelongs_to :position. - Referential integrity is enforced through Ecto changesets and PostgreSQL foreign-key constraints established in
priv/repo/migrations/. - Geographic normalization occurs through separate
addressesandgeofencestables, allowing drives and charging sessions to share location metadata.
Frequently Asked Questions
How does TeslaMate associate GPS coordinates with a specific drive?
Each drive record stores start_position_id and end_position_id foreign keys referencing the positions table, along with a has_many :positions association that captures all intermediate waypoints between start and end timestamps. This design allows the application to render complete trip paths while efficiently querying start and end locations without scanning all GPS points.
What is the difference between the charges and charging_processes tables?
The charges table stores discrete, high-frequency measurements (voltage, current, power) captured during charging, while charging_processes aggregates these into session-level summaries with calculated totals for energy added, duration, and cost. A charging_process has_many :charges, and each charge belongs_to :charging_process, creating a one-to-many relationship between sessions and individual readings.
Can I query all positions for a specific drive using Ecto?
Yes, you can query the positions table filtering by drive_id and ordering by date. The Drive schema also supports preloading all positions via Repo.preload(drive, :positions), which executes a single query to fetch the drive and all associated GPS waypoints for map visualization or efficiency analysis.
How are geofences linked to drives and charging sessions?
Both the Drive and ChargingProcess schemas include belongs_to associations for geofences. Drives track start_geofence and end_geofence separately, while charging processes link to a single geofence representing the charging location. These associations enable automatic location tagging and statistics aggregation by frequently visited locations without requiring expensive coordinate-based queries.
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 →