Skip to content

Commit

Permalink
feat: add valet mode switch (#405)
Browse files Browse the repository at this point in the history
closes #355
  • Loading branch information
InTheDaylight14 committed Dec 9, 2022
1 parent 108567c commit 01116d1
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 7 deletions.
2 changes: 1 addition & 1 deletion custom_components/tesla_custom/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"documentation": "https://github.com/alandtse/tesla/wiki",
"issue_tracker": "https://github.com/alandtse/tesla/issues",
"requirements": [
"teslajsonpy==3.3.0"
"teslajsonpy==3.4.1"
],
"codeowners": [
"@alandtse"
Expand Down
37 changes: 37 additions & 0 deletions custom_components/tesla_custom/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry, async_add_entitie
entities.append(TeslaCarSentryMode(hass, car, coordinator))
entities.append(TeslaCarPolling(hass, car, coordinator))
entities.append(TeslaCarCharger(hass, car, coordinator))
entities.append(TeslaCarValetMode(hass, car, coordinator))

async_add_entities(entities, True)

Expand Down Expand Up @@ -173,3 +174,39 @@ async def async_turn_off(self, **kwargs):
"""Send the off command."""
await self._car.set_sentry_mode(False)
await self.async_update_ha_state()


class TeslaCarValetMode(TeslaCarEntity, SwitchEntity):
"""Representation of a Tesla car valet mode switch."""

def __init__(
self,
hass: HomeAssistant,
car: TeslaCar,
coordinator: TeslaDataUpdateCoordinator,
) -> None:
"""Initialize valet mode switch entity."""
super().__init__(hass, car, coordinator)
self.type = "valet mode"
self._attr_icon = "mdi:room-service"

@property
def is_on(self):
"""Return valet mode state."""
return self._car.is_valet_mode

async def async_turn_on(self, **kwargs):
"""Send the on command."""
if self._car._vehicle_data.get("vehicle_state", {}).get("valet_pin_needed"):
_LOGGER.debug("Pin required for valet mode, set pin in vehicle or app.")
else:
await self._car.valet_mode(True)
await self.async_update_ha_state()

async def async_turn_off(self, **kwargs):
"""Send the off command."""
if self._car._vehicle_data.get("vehicle_state", {}).get("valet_pin_needed"):
_LOGGER.debug("Pin required for valet mode, set pin in vehicle or app.")
else:
await self._car.valet_mode(False)
await self.async_update_ha_state()
8 changes: 4 additions & 4 deletions poetry.lock

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

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ license = "Apache-2.0"

[tool.poetry.dependencies]
python = "^3.10"
teslajsonpy = "^3.3.0"
teslajsonpy = "^3.4.1"

[tool.poetry.dev-dependencies]
homeassistant = ">=2021.10.0"
Expand Down
2 changes: 1 addition & 1 deletion tests/mock_data/car.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@
"tpms_soft_warning_rl": False,
"tpms_soft_warning_rr": False,
"valet_mode": False,
"valet_pin_needed": True,
"valet_pin_needed": False,
"vehicle_name": "My Model S",
"sentry_mode": True,
"sentry_mode_available": True,
Expand Down
48 changes: 48 additions & 0 deletions tests/test_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ async def test_registry_entries(hass: HomeAssistant) -> None:
entry = entity_registry.async_get("switch.my_model_s_sentry_mode")
assert entry.unique_id == f"{car_mock_data.VIN.lower()}_sentry_mode"

entry = entity_registry.async_get("switch.my_model_s_valet_mode")
assert entry.unique_id == f"{car_mock_data.VIN.lower()}_valet_mode"


async def test_enabled_by_default(hass: HomeAssistant) -> None:
"""Tests devices are registered in the entity registry."""
Expand All @@ -45,6 +48,9 @@ async def test_enabled_by_default(hass: HomeAssistant) -> None:
entry = entity_registry.async_get("switch.my_model_s_sentry_mode")
assert not entry.disabled

entry = entity_registry.async_get("switch.my_model_s_valet_mode")
assert not entry.disabled


async def test_disabled_by_default(hass: HomeAssistant) -> None:
"""Tests devices are disabled by default when appropriate."""
Expand Down Expand Up @@ -150,3 +156,45 @@ async def test_sentry_mode(hass: HomeAssistant) -> None:
blocking=True,
)
mock_set_sentry_mode.assert_awaited_with(False)


async def test_valet_mode(hass: HomeAssistant) -> None:
"""Tests car valet mode switch."""
car_mock_data.VEHICLE_DATA["vehicle_state"]["sentry_mode_available"] = True
await setup_platform(hass, SWITCH_DOMAIN)

with patch("teslajsonpy.car.TeslaCar.valet_mode") as mock_valet_mode:
# Test switch on
assert await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.my_model_s_valet_mode"},
blocking=True,
)
mock_valet_mode.assert_awaited_once_with(True)
# Test switch off
assert await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.my_model_s_valet_mode"},
blocking=True,
)
mock_valet_mode.assert_awaited_with(False)

with patch("teslajsonpy.car.TeslaCar.valet_mode") as mock_pin_required:
# Test pin required
car_mock_data.VEHICLE_DATA["vehicle_state"]["valet_pin_needed"] = True
assert await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.my_model_s_valet_mode"},
blocking=True,
)
mock_pin_required.assert_not_awaited()
assert await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.my_model_s_valet_mode"},
blocking=True,
)
mock_pin_required.assert_not_awaited()

0 comments on commit 01116d1

Please sign in to comment.