Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ uv run pyright tesla_fleet_api
# Linting
uv run ruff check tesla_fleet_api
uv run ruff format tesla_fleet_api

# Tests
uv run pytest tests
```

No test suite exists in this repo.
Tests live in `tests/` and use `unittest.IsolatedAsyncioTestCase` (collected and
run natively by pytest — `pytest-asyncio` is not required).

## API References

Expand Down
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ dependencies = [
"Homepage" = "https://github.com/Teslemetry/python-tesla-fleet-api"

[dependency-groups]
dev = ["pyright>=1.1.399"]
dev = ["pyright>=1.1.399", "pytest>=8.0"]

[tool.setuptools.packages.find]
include = ["tesla_fleet_api*"]
Expand All @@ -44,3 +44,6 @@ exclude = ["tesla_fleet_api/tesla/vehicle/proto/*"]
include = ["tesla_fleet_api"]
typeCheckingMode = "strict"
exclude = ["tesla_fleet_api/tesla/vehicle/proto/*"]

[tool.pytest.ini_options]
testpaths = ["tests"]
2 changes: 1 addition & 1 deletion tesla_fleet_api.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: tesla_fleet_api
Version: 1.4.6
Version: 1.4.7
Summary: Tesla Fleet API library for Python
Author-email: Brett Adams <hello@teslemetry.com>
License-Expression: Apache-2.0
Expand Down
34 changes: 26 additions & 8 deletions tesla_fleet_api/tesla/energysite.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from __future__ import annotations

import base64
from typing import Any, TYPE_CHECKING
from typing import TYPE_CHECKING, Any

from tesla_fleet_api.const import (
Method,
EnergyOperationMode,
AuthorizedClientKeyType,
AuthorizedClientType,
EnergyDeviceIdentifierType,
EnergyExportMode,
EnergyIslandMode,
EnergyOperationMode,
Method,
TeslaEnergyPeriod,
EnergyDeviceIdentifierType,
AuthorizedClientKeyType,
AuthorizedClientType,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -53,9 +55,21 @@ async def get_system_info(self) -> dict[str, Any]:
"""Get energy device system information including firmware version, device type, part number, serial number, and DIN."""
return await self._command("common", "get_system_info_request")

async def raw_networking_status(self) -> dict[str, Any]:
"""Get raw energy device networking status including WiFi, Ethernet, and cellular connectivity."""
return await self._command("common", "get_networking_status_request")

async def get_networking_status(self) -> dict[str, Any]:
"""Get energy device networking status including WiFi, Ethernet, and cellular connectivity."""
return await self._command("common", "get_networking_status_request")
result = await self.raw_networking_status()
return (
result.get("response", {})
.get("message", {})
.get("Payload", {})
.get("Common", {})
.get("Message", {})
.get("GetNetworkingStatusResponse", {})
)

async def wifi_scan(self) -> dict[str, Any]:
"""Scan for available WiFi networks from the energy gateway."""
Expand Down Expand Up @@ -160,7 +174,11 @@ async def schedule_backup_event(
priority: Priority level for the backup event.
"""
params: dict[str, Any] = {}
if start_time is not None or duration_seconds is not None or priority is not None:
if (
start_time is not None
or duration_seconds is not None
or priority is not None
):
scheduling_info: dict[str, Any] = {}
if start_time is not None:
scheduling_info["start_time"] = start_time
Expand Down
648 changes: 334 additions & 314 deletions tesla_fleet_api/tesla/vehicle/proto/car_server_pb2.py

Large diffs are not rendered by default.

773 changes: 240 additions & 533 deletions tesla_fleet_api/tesla/vehicle/proto/car_server_pb2.pyi

Large diffs are not rendered by default.

70 changes: 45 additions & 25 deletions tesla_fleet_api/tesla/vehicle/proto/common_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 14 additions & 27 deletions tesla_fleet_api/tesla/vehicle/proto/common_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from collections.abc import Mapping as _Mapping
from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union

DESCRIPTOR: _descriptor.FileDescriptor

class Invalid(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
Expand Down Expand Up @@ -32,22 +33,18 @@ StwHeatLevel_High: StwHeatLevel

class Void(_message.Message):
__slots__ = ()

def __init__(self) -> None:
...
def __init__(self) -> None: ...

class LatLong(_message.Message):
__slots__ = ('latitude', 'longitude')
__slots__ = ("latitude", "longitude")
LATITUDE_FIELD_NUMBER: _ClassVar[int]
LONGITUDE_FIELD_NUMBER: _ClassVar[int]
latitude: float
longitude: float

def __init__(self, latitude: _Optional[float]=..., longitude: _Optional[float]=...) -> None:
...
def __init__(self, latitude: _Optional[float] = ..., longitude: _Optional[float] = ...) -> None: ...

class ChargePortLatchState(_message.Message):
__slots__ = ('SNA', 'Disengaged', 'Engaged', 'Blocking')
__slots__ = ("SNA", "Disengaged", "Engaged", "Blocking")
SNA_FIELD_NUMBER: _ClassVar[int]
DISENGAGED_FIELD_NUMBER: _ClassVar[int]
ENGAGED_FIELD_NUMBER: _ClassVar[int]
Expand All @@ -56,32 +53,26 @@ class ChargePortLatchState(_message.Message):
Disengaged: Void
Engaged: Void
Blocking: Void

def __init__(self, SNA: _Optional[_Union[Void, _Mapping]]=..., Disengaged: _Optional[_Union[Void, _Mapping]]=..., Engaged: _Optional[_Union[Void, _Mapping]]=..., Blocking: _Optional[_Union[Void, _Mapping]]=...) -> None:
...
def __init__(self, SNA: _Optional[_Union[Void, _Mapping]] = ..., Disengaged: _Optional[_Union[Void, _Mapping]] = ..., Engaged: _Optional[_Union[Void, _Mapping]] = ..., Blocking: _Optional[_Union[Void, _Mapping]] = ...) -> None: ...

class PreconditioningTimes(_message.Message):
__slots__ = ('all_week', 'weekdays')
__slots__ = ("all_week", "weekdays")
ALL_WEEK_FIELD_NUMBER: _ClassVar[int]
WEEKDAYS_FIELD_NUMBER: _ClassVar[int]
all_week: Void
weekdays: Void

def __init__(self, all_week: _Optional[_Union[Void, _Mapping]]=..., weekdays: _Optional[_Union[Void, _Mapping]]=...) -> None:
...
def __init__(self, all_week: _Optional[_Union[Void, _Mapping]] = ..., weekdays: _Optional[_Union[Void, _Mapping]] = ...) -> None: ...

class OffPeakChargingTimes(_message.Message):
__slots__ = ('all_week', 'weekdays')
__slots__ = ("all_week", "weekdays")
ALL_WEEK_FIELD_NUMBER: _ClassVar[int]
WEEKDAYS_FIELD_NUMBER: _ClassVar[int]
all_week: Void
weekdays: Void

def __init__(self, all_week: _Optional[_Union[Void, _Mapping]]=..., weekdays: _Optional[_Union[Void, _Mapping]]=...) -> None:
...
def __init__(self, all_week: _Optional[_Union[Void, _Mapping]] = ..., weekdays: _Optional[_Union[Void, _Mapping]] = ...) -> None: ...

class ChargeSchedule(_message.Message):
__slots__ = ('id', 'name', 'days_of_week', 'start_enabled', 'start_time', 'end_enabled', 'end_time', 'one_time', 'enabled', 'latitude', 'longitude')
__slots__ = ("id", "name", "days_of_week", "start_enabled", "start_time", "end_enabled", "end_time", "one_time", "enabled", "latitude", "longitude")
ID_FIELD_NUMBER: _ClassVar[int]
NAME_FIELD_NUMBER: _ClassVar[int]
DAYS_OF_WEEK_FIELD_NUMBER: _ClassVar[int]
Expand All @@ -104,12 +95,10 @@ class ChargeSchedule(_message.Message):
enabled: bool
latitude: float
longitude: float

def __init__(self, id: _Optional[int]=..., name: _Optional[str]=..., days_of_week: _Optional[int]=..., start_enabled: bool=..., start_time: _Optional[int]=..., end_enabled: bool=..., end_time: _Optional[int]=..., one_time: bool=..., enabled: bool=..., latitude: _Optional[float]=..., longitude: _Optional[float]=...) -> None:
...
def __init__(self, id: _Optional[int] = ..., name: _Optional[str] = ..., days_of_week: _Optional[int] = ..., start_enabled: _Optional[bool] = ..., start_time: _Optional[int] = ..., end_enabled: _Optional[bool] = ..., end_time: _Optional[int] = ..., one_time: _Optional[bool] = ..., enabled: _Optional[bool] = ..., latitude: _Optional[float] = ..., longitude: _Optional[float] = ...) -> None: ...

class PreconditionSchedule(_message.Message):
__slots__ = ('id', 'name', 'days_of_week', 'precondition_time', 'one_time', 'enabled', 'latitude', 'longitude')
__slots__ = ("id", "name", "days_of_week", "precondition_time", "one_time", "enabled", "latitude", "longitude")
ID_FIELD_NUMBER: _ClassVar[int]
NAME_FIELD_NUMBER: _ClassVar[int]
DAYS_OF_WEEK_FIELD_NUMBER: _ClassVar[int]
Expand All @@ -126,6 +115,4 @@ class PreconditionSchedule(_message.Message):
enabled: bool
latitude: float
longitude: float

def __init__(self, id: _Optional[int]=..., name: _Optional[str]=..., days_of_week: _Optional[int]=..., precondition_time: _Optional[int]=..., one_time: bool=..., enabled: bool=..., latitude: _Optional[float]=..., longitude: _Optional[float]=...) -> None:
...
def __init__(self, id: _Optional[int] = ..., name: _Optional[str] = ..., days_of_week: _Optional[int] = ..., precondition_time: _Optional[int] = ..., one_time: _Optional[bool] = ..., enabled: _Optional[bool] = ..., latitude: _Optional[float] = ..., longitude: _Optional[float] = ...) -> None: ...
Loading
Loading