A complete Home Assistant integration for OVMS (Open Vehicles Monitoring System) written in Python.
This integration provides seamless Home Assistant support for OVMS-equipped vehicles by communicating with the OVMS Server using:
- REST API (HTTP/HTTPS on ports 6868/6869) - for data retrieval
- Binary Protocol v2 (TCP on ports 6867/6870) - for real-time vehicle commands
- Real-time Status - Battery SOC, range, temperatures, door status, speed
- Charging Information - Current charging state, power, estimated time remaining
- Location Tracking - GPS coordinates, altitude, driving mode
- Tire Pressure (TPMS) - Individual tire pressures and temperatures
- Connection Status - Monitor OVMS module connectivity
- AC On - Turn on AC via button (use
send_commandservice to turn off) - Charging - Start/stop charging, set charge limits and current
- Door Locks - Lock/unlock vehicle doors (Lock entity)
- Cooldown - Activate battery/cabin cooling (Switch entity)
- Vehicle Wake - Wake vehicle from sleep mode
- HomeLink - Activate garage door openers
- Module Reset - Restart OVMS module remotely
| Entity Type | Count | Examples |
|---|---|---|
lock |
1 | Door Locks (lock/unlock) |
device_tracker |
1 | GPS Location with battery & accuracy |
switch |
2 | Cooldown, Valet Mode |
number |
3 | Charge Limit (50-100%), Charge Current, GPS Interval |
binary_sensor |
14 | Doors, Bonnet, Trunk, Charge Port, Parking Brake, Pilot Present, Car On, Headlights, Alarm, GPS Lock, CAN Write |
sensor |
50+ | Battery, Charging, Temperature, Power, Location, Diagnostics |
button |
8 | Refresh, Wake Up, AC On, HomeLink 1-3, Module Reset, TPMS Reset |
| Binary Sensor | Default State | Purpose |
|---|---|---|
| Front Left/Right Door | Enabled | Security monitoring |
| Rear Left/Right Door | Disabled | Less common usage |
| Bonnet/Hood | Enabled | Security monitoring |
| Trunk | Enabled | Security monitoring |
| Charge Port | Enabled | Charging workflows |
| Parking Brake | Disabled | Technical monitoring |
| Pilot Present | Enabled | Charger plugged in status |
| Car On/Started | Enabled | Vehicle state for automations |
| Headlights | Disabled | Less common monitoring |
| Alarm Sounding | Enabled | Security alert |
| GPS Lock | Disabled | Technical diagnostics |
| CAN Write Active | Disabled | Technical diagnostics |
Battery & Range (enabled by default):
- State of Charge (SOC), State of Health (SOH)
- Estimated Range, Battery Capacity (kWh)
- Battery Voltage, 12V Battery Voltage & Current
- CAC (Calculated Amp Capacity) - disabled
Temperature (enabled by default):
- Ambient, Cabin, Battery, Motor
- PEM Temperature - disabled (technical)
- Charger Temperature - disabled (technical)
Charging (enabled by default):
- Charging State, Power, Current
- Charger Power Input, Charge Type
- Time to Full, Charge Session Energy (kWh)
- Charge Limit Range - disabled
- Grid kWh (session & total) - disabled (technical)
- Charger Efficiency - disabled (technical)
Driving & Power (enabled by default):
- Odometer, Speed, Trip Meter
- Power (instantaneous), Energy Used/Recovered
- Drive Mode - disabled
- Inverter Power & Efficiency - disabled (technical)
Location (enabled by default):
- Latitude, Longitude, Altitude, Direction
Connectivity & Diagnostics:
- Last Seen, GSM Signal, WiFi Signal, Connection Status
- Firmware Version - disabled (diagnostic)
- Hardware Version - disabled (diagnostic)
- Modem Mode - disabled (diagnostic)
- Service Range/Time - disabled (diagnostic)
- Refresh Data - Force immediate data update
- Wake Up - Wake sleeping vehicle
- AC On - Send AC ON command to vehicle (Command 26,1)
- HomeLink 1-3 - Activate garage door openers
- Module Reset - Restart OVMS module
- TPMS Reset - Auto-learn tire pressure sensors (disabled by default)
Nine advanced services for vehicle control:
ovms_hass.send_command- Send generic OVMS commandsovms_hass.send_sms- Send SMS via vehicle modemovms_hass.set_charge_timer- Configure charging scheduleovms_hass.wakeup_subsystem- Wake specific vehicle subsystemovms_hass.tpms_map_wheel- Map TPMS sensor to wheel positionovms_hass.get_feature/ovms_hass.set_feature- Module features (0-15)ovms_hass.get_parameter/ovms_hass.set_parameter- Module parameters (0-31)
- Open HACS in your Home Assistant
- Click on "Integrations"
- Click the three dots menu in the top right
- Select "Custom repositories"
- Add
https://github.com/majorfrog/ovms-hasswith category "Integration" - Click "Add"
- Search for "OVMS" and install it
- Restart Home Assistant
- Download the latest release from GitHub Releases
- Extract the
ovms_hassfolder to yourcustom_componentsdirectory:custom_components/ └── ovms_hass/ ├── __init__.py ├── manifest.json └── ... - Restart Home Assistant
- Go to Settings → Devices & Services
- Click Add Integration
- Search for "OVMS"
- Enter your OVMS server credentials:
- Server Host:
api.openvehicles.com(default) - Port:
6869(HTTPS, default) - Username: Your OVMS account username
- Password: Your OVMS REST API password
- Vehicle ID: Your vehicle ID (e.g., DEMO)
- Vehicle Password: Password configured in your OVMS module (required for commands)
- Server Host:
After setup, you can configure additional options:
- Update Interval: How often to fetch data (60-3600 seconds, default: 300)
For advanced users, YAML configuration is also supported:
ovms_hass:
host: api.openvehicles.com
port: 6869 # 6869 for HTTPS, 6868 for HTTP
username: your_ovms_username
password: your_ovms_rest_api_password
vehicles:
- vehicle_id: DEMO
name: My Tesla
vehicle_password: demo_module_password # Password configured in the OVMS module
scan_interval: 300 # seconds
- vehicle_id: TEST
name: Work Vehicle
vehicle_password: test_module_password # Different password per vehicle
scan_interval: 600Settings → Devices & Services → Add Integration → Search "OVMS"
The integration provides nine advanced services for direct OVMS control:
Send a generic OVMS command to the vehicle.
service: ovms_hass.send_command
data:
vehicle_id: "DEMO"
command: "stat" # Request status updateSend an SMS message via the vehicle's modem.
service: ovms_hass.send_sms
data:
vehicle_id: "DEMO"
phone_number: "+1234567890"
message: "Hello from my vehicle!"Configure the vehicle's charge timer.
service: ovms_hass.set_charge_timer
data:
vehicle_id: "DEMO"
start_time: "23:00"
enabled: trueWake a specific vehicle subsystem.
service: ovms_hass.wakeup_subsystem
data:
vehicle_id: "DEMO"
subsystem: 0Map a TPMS sensor to a specific wheel position.
service: ovms_hass.tpms_map_wheel
data:
vehicle_id: "DEMO"
wheel: "fl" # fl, fr, rl, rr
sensor_id: "12345678"Read or write OVMS module features (0-15).
service: ovms_hass.set_feature
data:
vehicle_id: "DEMO"
feature_number: 8 # GPS streaming interval
value: "60"Read or write OVMS module parameters (0-31).
service: ovms_hass.set_parameter
data:
vehicle_id: "DEMO"
parameter_number: 0
value: "custom_value"- Full type hints on all functions and methods
- Dataclasses for structured data
- Enums for command codes
- Async/await throughout for non-blocking I/O
- Context managers for resource cleanup
- Exception hierarchy for error handling
- Comprehensions and modern Python patterns
- Comprehensive docstrings (Google style)
- Module-level documentation
- Parameter descriptions
- Return value documentation
- Clear separation of concerns (API, commands, entities, coordination)
- No circular dependencies
- Extensible command and entity systems
- Reusable base classes
from ha_ovms.api import OVMSApiClient
async with OVMSApiClient(
host="api.openvehicles.com",
username="user",
password="pass"
) as client:
# Get vehicles
vehicles = await client.list_vehicles()
# Get vehicle data
status = await client.get_status("DEMO")
charge = await client.get_charge("DEMO")
location = await client.get_location("DEMO")
tpms = await client.get_tpms("DEMO")from ha_ovms.commands import (
OVMSCommandBuilder,
ChargingCommand
)
# Build commands
ac_on = OVMSCommandBuilder.climate_on() # "MP-0 C26,1"
ac_off = OVMSCommandBuilder.climate_off() # "MP-0 C26,0"
cooldown = OVMSCommandBuilder.cooldown() # "MP-0 C25"
# Charging commands
charging = ChargingCommand()
start = charging.start() # "MP-0 C11"
stop = charging.stop() # "MP-0 C12"automation:
- trigger:
platform: numeric_state
entity_id: sensor.my_tesla_cabin_temperature
above: 35
action:
service: button.press
target:
entity_id: button.my_tesla_ac_onautomation:
- trigger:
platform: state
entity_id: input_boolean.ac_off_trigger
to: "on"
action:
service: ovms_hass.send_command
data:
vehicle_id: "DEMO"
command: "26,0" # AC OFFautomation:
- trigger:
platform: time
at: "22:00:00"
action:
service: lock.lock
target:
entity_id: lock.my_tesla_door_lockautomation:
- trigger:
platform: state
entity_id: sensor.my_tesla_charging_state
to: "charging"
action:
service: number.set_value
target:
entity_id: number.my_tesla_charge_limit
data:
value: 80automation:
- trigger:
platform: state
entity_id: binary_sensor.my_tesla_front_left_door
to: "on"
condition:
- condition: state
entity_id: person.owner
state: "not_home"
action:
service: notify.mobile_app
data:
message: "Vehicle door opened while you're away!"
title: "Security Alert"automation:
- trigger:
platform: state
entity_id: person.visitor
to: "home"
action:
service: switch.turn_on
target:
entity_id: switch.my_tesla_valet_modeautomation:
- trigger:
platform: zone
entity_id: device_tracker.my_tesla_location
zone: zone.home
event: enter
action:
service: button.press
target:
entity_id: button.my_tesla_homelink_1automation:
- trigger:
platform: state
entity_id: sensor.my_tesla_connection_status
to: "disconnected"
for: "00:05:00"
action:
service: notify.mobile_app
data:
message: "Vehicle connection lost!"
title: "OVMS Alert"automation:
- trigger:
platform: state
entity_id: device_tracker.my_tesla_location
from: "home"
action:
service: number.set_value
target:
entity_id: number.my_tesla_gps_streaming_interval
data:
value: 60 # Update every 60 secondsautomation:
- trigger:
platform: state
entity_id: input_boolean.custom_command_trigger
to: "on"
action:
service: ovms_hass.send_command
data:
vehicle_id: "DEMO"
command: "stat"automation:
- trigger:
platform: time
at: "20:00:00"
action:
service: ovms_hass.set_charge_timer
data:
vehicle_id: "DEMO"
start_time: "23:00"
enabled: trueautomation:
- trigger:
platform: numeric_state
entity_id: sensor.my_tesla_last_seen
attribute: age_seconds
above: 600 # 10 minutes
action:
- service: button.press
target:
entity_id: button.my_tesla_module_reset
- service: notify.mobile_app
data:
message: "OVMS module reset due to inactivity"The integration provides an AC On button to turn on the vehicle's air conditioning.
The climate entity was intentionally removed because the HVAC state reporting (v.e.hvac)
does not work reliably on all vehicle types, which caused the climate entity to show
incorrect state for many users.
- The HVAC status field is not available on all cars, so the climate entity often showed "OFF" even when AC was running
- A simple button is more reliable — it sends the command without depending on state feedback
- Users who need AC state can check the cabin temperature sensor or any available HVAC sensors
Simply press the AC On button entity, or use an automation:
automation:
- trigger:
platform: numeric_state
entity_id: sensor.my_vehicle_cabin_temperature
above: 30
action:
service: button.press
target:
entity_id: button.my_vehicle_ac_onUse the ovms_hass.send_command service with OVMS Command 26 (climate control), parameter 0 (off):
service: ovms_hass.send_command
data:
vehicle_id: "YOUR_VEHICLE_ID"
command: "26,0"Automation example:
automation:
- alias: "Turn off AC when cabin is cool"
trigger:
platform: numeric_state
entity_id: sensor.my_vehicle_cabin_temperature
below: 22
action:
service: ovms_hass.send_command
data:
vehicle_id: "YOUR_VEHICLE_ID"
command: "26,0"If you want a toggle switch for AC, you can create a template switch in your
configuration.yaml. This uses the AC On button for turning on, and the
send_command service for turning off:
switch:
- platform: template
switches:
vehicle_ac:
friendly_name: "Vehicle AC"
icon_template: mdi:air-conditioner
turn_on:
service: button.press
target:
entity_id: button.my_vehicle_ac_on
turn_off:
service: ovms_hass.send_command
data:
vehicle_id: "YOUR_VEHICLE_ID"
command: "26,0"Note: This template switch does not track the actual AC state — it will appear as the last action you triggered. If you need real state tracking, you can add a
value_templatethat reads from a sensor if your vehicle supports HVAC status reporting.
The ovms_hass.send_command service can send any OVMS command. Useful examples:
| Command | Description |
|---|---|
26,1 |
AC on |
26,0 |
AC off |
25 |
Cooldown |
11 |
Start charge |
12 |
Stop charge |
18 |
Wake up vehicle |
stat |
Request status |
location |
Request GPS location |
service: ovms_hass.send_command
data:
vehicle_id: "YOUR_VEHICLE_ID"
command: "stat"- Polling-based updates: The REST API requires periodic polling (default 5 minutes) rather than real-time push notifications
- Rate limiting: OVMS server implements rate limits (60 requests/minute, 120 burst)
- Data availability: Not all OVMS protocol v2 features are exposed via the REST API
Some vehicles may report 0% SOC even when the battery is charged:
- Nissan Leaf ZE0 (2018-2020): Requires specific OVMS firmware configuration
- Set correct vehicle type:
config set vehicle type NL - Configure model year:
config set auto leaf.modelyear 2018 - Set battery capacity:
config set auto leaf.soh.newcar 40000(40kWh) or62000(e+) - Update firmware if running old version:
ota flash vfs
- Set correct vehicle type:
- Workaround: Integration includes fallback logic checking
charge.socwhenstatus.socis unavailable - Diagnostic: Check SOC sensor attributes in HA for
status_soc_rawandcharge_soc_rawvalues
Not all vehicles support all commands:
- AC/Climate Control (Command 26): Not all vehicles support HVAC state reporting. The AC On button sends the command but the HVAC state may not be available on all cars. Use
ovms_hass.send_commandwith command26,0to turn AC off. Seres (SQ) uses Command 24 - Cooldown (Command 25): Support varies by vehicle model
- Wake-up (Command 18): May not work on all vehicle types
- Charge Limits: Some vehicles don't support setting charge limits via OVMS
Device details depend on OVMS firmware version and configuration:
- Vehicle Type (
car_type): Requires OVMS firmware to provide this field - Firmware Version (
m_firmware,m_version): May not be available on older OVMS versions - Hardware Info (
m_hardware): Depends on OVMS configuration - VIN (
car_vin): Must be configured in OVMS module - GSM/WiFi Signal: Only available if OVMS is connected via cellular or WiFi
- Fallback: Shows "Unknown" when data unavailable
- OVMS Module: Must be powered and connected to OVMS server
- Server Access: Integration requires network access to OVMS server (default: api.openvehicles.com)
- Vehicle State: Some commands require vehicle to be awake and online
- Command Timeout: Protocol v2 commands have 30-second timeout (configurable)
- Message Age: Check
m_msgage_sattribute to see data staleness in seconds - Stale Data Flags:
staletemps,stalegps,staletpmsindicate outdated information - Last Seen: Use the "Last Seen" sensor to monitor OVMS connectivity
- GPS Accuracy: Device tracker accuracy based on GPS lock status (
gpslockfield)
- Encryption: Uses RC4 with HMAC-MD5 (implementation included)
- Read-Only API: This integration uses REST API for reading, binary protocol only for commands
- No Push Updates: Does not maintain persistent TCP connection for real-time updates
- Server Relay: Commands go through OVMS server, not directly to vehicle
- Single Vehicle Entry: One config entry per vehicle (prevents duplicates)
- No Historical Data UI: Historical data endpoints implemented but not exposed in UI
- Limited TPMS: Basic tire pressure support, advanced TPMS features not implemented
- No Valet Mode: Valet mode endpoints exist but not implemented in entities
- Scan Interval: Lower intervals increase server load and may hit rate limits
- Parallel API Calls: Integration fetches status/charge/location/tpms in parallel for efficiency
- Error Handling: Temporary API failures don't disable entities, will retry on next update
- Connection Pooling: Uses aiohttp session for connection reuse
- Entity Defaults: Technical/diagnostic sensors disabled by default to reduce UI clutter
Many sensors include diagnostic attributes:
- SOC Sensor: Shows
source,status_soc_raw,charge_soc_raw,battery_health - Last Seen: Shows
age_secondsfor data staleness - Connection Status: Shows
car_connections,app_connections,batch_connections
Monitor when vehicle service is due:
- Service Range: Kilometers until service required
- Service Time: Days until service required
- Both disabled by default (enable via entity settings)
Shows cellular network type (2G/3G/4G):
- Useful for diagnosing connectivity issues
- Disabled by default (diagnostic category)
- Check OVMS server is reachable:
ping api.openvehicles.com - Verify username/password in Home Assistant logs
- Ensure port 6869 is accessible (or 6868 for HTTP)
- Check OVMS server status at https://www.openvehicles.com
- Verify vehicle password: Commands require the vehicle module password, not the REST API password
- Check integration configuration has the correct vehicle_password set
- This is the password configured in your OVMS module (Config → Server v2 → Password)
- Look for "vehicle_password configured: YES" in Home Assistant logs
- Vehicle must be online and connected to OVMS server
- Some commands require vehicle to be awake (try wake-up button first)
- Check OVMS app to verify vehicle supports command
- Review Home Assistant logs for command errors (look for "Protocol v2 client" messages)
- Verify vehicle type supports the command (see Limitations section)
- Default scan interval is 300 seconds (5 minutes)
- Check vehicle is actually connected to OVMS server
- Review Home Assistant logs for API errors
- Check "Last Seen" sensor for OVMS connectivity
- Verify message age (
m_msgage_s) isn't excessively high
- See "State of Charge (SOC) Reporting" in Limitations section
- Check SOC sensor attributes for diagnostic information
- Verify OVMS firmware configuration matches vehicle model
- Update OVMS firmware to latest version
- Check OVMS mobile app to confirm issue is integration vs. OVMS configuration
- OVMS firmware may not provide device information fields
- Check if
car_type,m_firmware,m_hardwarefields are in API response - Update OVMS firmware to latest version
- Configure vehicle type in OVMS module settings
custom_components/ovms_hass/
├── __init__.py # Integration setup & entry point
├── manifest.json # Integration metadata
├── config_flow.py # UI configuration flow
├── coordinator.py # Data update coordinator
├── api.py # REST API client
├── commands.py # Binary protocol commands
├── entities.py # Entity class definitions
├── services.py # Service implementations
├── services.yaml # Service schemas
├── strings.json # UI strings
├── binary_sensor.py # Binary sensor platform
├── sensor.py # Sensor platform
├── button.py # Button platform (includes AC On)
├── lock.py # Lock platform
├── switch.py # Switch platform
├── number.py # Number platform
├── device_tracker.py # Device tracker platform
├── diagnostics.py # Diagnostic data export
└── translations/ # Localization files
├── en.json
└── sv.json
- Create entity class in
entities.py:
class MyNewBinarySensor(OVMSEntity, BinarySensorEntity):
_attr_device_class = BinarySensorDeviceClass.DOOR
_attr_entity_registry_enabled_default = True # or False
def __init__(self, coordinator, vehicle_id):
config = EntityConfig(
unique_id="my_binary_sensor",
name="My Binary Sensor",
icon="mdi:my-icon",
)
super().__init__(coordinator, config, vehicle_id)
@property
def is_on(self):
return self.coordinator.data.get("status", {}).get("my_field")- Add to
binary_sensor.py:
from .entities import MyNewBinarySensor
entities = [
# ... existing entities
MyNewBinarySensor(coordinator, coordinator.vehicle_id),
]- Add translations to
strings.jsonandtranslations/*.json:
"binary_sensor": {
"my_binary_sensor": {
"name": "My Binary Sensor"
}
}- Create entity class in
entities.py:
class MyNewSensor(OVMSEntity, SensorEntity):
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_native_unit_of_measurement = "unit"
_attr_device_class = SensorDeviceClass.TEMPERATURE
_attr_entity_registry_enabled_default = True # or False
def __init__(self, coordinator, vehicle_id):
config = EntityConfig(
unique_id="my_sensor",
name="My Sensor",
icon="mdi:my-icon",
)
super().__init__(coordinator, config, vehicle_id)
@property
def native_value(self):
return self.coordinator.data.get("status", {}).get("my_field")-
Add to
sensor.pyplatform file -
Add translations
- Add service handler in
services.py:
async def async_my_service(hass: HomeAssistant, call: ServiceCall) -> None:
"""Handle my_service call."""
vehicle_id = call.data["vehicle_id"]
coordinator = _get_coordinator(hass, vehicle_id)
if coordinator and coordinator.ovms_client:
await coordinator.ovms_client.send_command("my_command")- Register service in
async_setup_services():
hass.services.async_register(
DOMAIN,
"my_service",
lambda call: async_my_service(hass, call),
schema=MY_SERVICE_SCHEMA,
)- Add service schema to
services.yamlfor UI support
- Add to
CommandCodeenum incommands.py - Add static method to
OVMSCommandBuilder - Optionally add convenience class
MIT License
- Issues: GitHub issue tracker
- Documentation: Inline code documentation and README
- Testing: Submit PR with tests
- OVMS Project: https://www.openvehicles.com
- Home Assistant: https://www.home-assistant.io