Add service to 17track to get packages (#116067)
* Add service to 17track * Add service to 17track change to select selector add snapshot test * Add service to 17track use strings for the selector * Add service to 17track fix test
This commit is contained in:
parent
24a1f0712f
commit
1f4585cc9e
8 changed files with 262 additions and 11 deletions
|
@ -4,16 +4,81 @@ from py17track import Client as SeventeenTrackClient
|
|||
from py17track.errors import SeventeenTrackError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.const import (
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_LOCATION,
|
||||
CONF_PASSWORD,
|
||||
CONF_USERNAME,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import (
|
||||
HomeAssistant,
|
||||
ServiceCall,
|
||||
ServiceResponse,
|
||||
SupportsResponse,
|
||||
)
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from .const import DOMAIN
|
||||
from .const import (
|
||||
ATTR_CONFIG_ENTRY_ID,
|
||||
ATTR_INFO_TEXT,
|
||||
ATTR_PACKAGE_STATE,
|
||||
ATTR_STATUS,
|
||||
ATTR_TIMESTAMP,
|
||||
ATTR_TRACKING_NUMBER,
|
||||
DOMAIN,
|
||||
SERVICE_GET_PACKAGES,
|
||||
)
|
||||
from .coordinator import SeventeenTrackCoordinator
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
|
||||
CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the 17Track component."""
|
||||
|
||||
async def get_packages(call: ServiceCall) -> ServiceResponse:
|
||||
"""Get packages from 17Track."""
|
||||
config_entry_id = call.data[ATTR_CONFIG_ENTRY_ID]
|
||||
package_states = call.data.get(ATTR_PACKAGE_STATE, [])
|
||||
seventeen_coordinator: SeventeenTrackCoordinator = hass.data[DOMAIN][
|
||||
config_entry_id
|
||||
]
|
||||
live_packages = sorted(
|
||||
await seventeen_coordinator.client.profile.packages(
|
||||
show_archived=seventeen_coordinator.show_archived
|
||||
)
|
||||
)
|
||||
|
||||
return {
|
||||
"packages": [
|
||||
{
|
||||
ATTR_TRACKING_NUMBER: package.tracking_number,
|
||||
ATTR_LOCATION: package.location,
|
||||
ATTR_STATUS: package.status,
|
||||
ATTR_TIMESTAMP: package.timestamp,
|
||||
ATTR_INFO_TEXT: package.info_text,
|
||||
ATTR_FRIENDLY_NAME: package.friendly_name,
|
||||
}
|
||||
for package in live_packages
|
||||
if slugify(package.status) in package_states or package_states == []
|
||||
]
|
||||
}
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_GET_PACKAGES,
|
||||
get_packages,
|
||||
supports_response=SupportsResponse.ONLY,
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up 17Track from a config entry."""
|
||||
|
@ -26,10 +91,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
except SeventeenTrackError as err:
|
||||
raise ConfigEntryNotReady from err
|
||||
|
||||
coordinator = SeventeenTrackCoordinator(hass, client)
|
||||
seventeen_coordinator = SeventeenTrackCoordinator(hass, client)
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
await seventeen_coordinator.async_config_entry_first_refresh()
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = seventeen_coordinator
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
return True
|
||||
|
|
|
@ -40,3 +40,8 @@ NOTIFICATION_DELIVERED_MESSAGE = (
|
|||
)
|
||||
|
||||
VALUE_DELIVERED = "Delivered"
|
||||
|
||||
SERVICE_GET_PACKAGES = "get_packages"
|
||||
|
||||
ATTR_PACKAGE_STATE = "package_state"
|
||||
ATTR_CONFIG_ENTRY_ID = "config_entry_id"
|
||||
|
|
|
@ -45,19 +45,19 @@ class SeventeenTrackCoordinator(DataUpdateCoordinator[SeventeenTrackData]):
|
|||
self.show_delivered = self.config_entry.options[CONF_SHOW_DELIVERED]
|
||||
self.account_id = client.profile.account_id
|
||||
|
||||
self._show_archived = self.config_entry.options[CONF_SHOW_ARCHIVED]
|
||||
self._client = client
|
||||
self.show_archived = self.config_entry.options[CONF_SHOW_ARCHIVED]
|
||||
self.client = client
|
||||
|
||||
async def _async_update_data(self) -> SeventeenTrackData:
|
||||
"""Fetch data from 17Track API."""
|
||||
|
||||
try:
|
||||
summary = await self._client.profile.summary(
|
||||
show_archived=self._show_archived
|
||||
summary = await self.client.profile.summary(
|
||||
show_archived=self.show_archived
|
||||
)
|
||||
|
||||
live_packages = set(
|
||||
await self._client.profile.packages(show_archived=self._show_archived)
|
||||
await self.client.profile.packages(show_archived=self.show_archived)
|
||||
)
|
||||
|
||||
except SeventeenTrackError as err:
|
||||
|
|
|
@ -26,5 +26,8 @@
|
|||
"default": "mdi:package"
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"get_packages": "mdi:package"
|
||||
}
|
||||
}
|
||||
|
|
20
homeassistant/components/seventeentrack/services.yaml
Normal file
20
homeassistant/components/seventeentrack/services.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
get_packages:
|
||||
fields:
|
||||
package_state:
|
||||
selector:
|
||||
select:
|
||||
multiple: true
|
||||
options:
|
||||
- "not_found"
|
||||
- "in_transit"
|
||||
- "expired"
|
||||
- "ready_to_be_picked_up"
|
||||
- "undelivered"
|
||||
- "delivered"
|
||||
- "returned"
|
||||
translation_key: package_state
|
||||
config_entry_id:
|
||||
required: true
|
||||
selector:
|
||||
config_entry:
|
||||
integration: seventeentrack
|
|
@ -66,5 +66,34 @@
|
|||
"name": "Package {name}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"get_packages": {
|
||||
"name": "Get packages",
|
||||
"description": "Get packages from 17Track",
|
||||
"fields": {
|
||||
"package_state": {
|
||||
"name": "Package states",
|
||||
"description": "Only return packages with the specified states. Returns all packages if not specified."
|
||||
},
|
||||
"config_entry_id": {
|
||||
"name": "17Track service",
|
||||
"description": "The packages will be retrieved for the selected service."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"selector": {
|
||||
"package_state": {
|
||||
"options": {
|
||||
"not_found": "[%key:component::seventeentrack::entity::sensor::not_found::name%]",
|
||||
"in_transit": "[%key:component::seventeentrack::entity::sensor::in_transit::name%]",
|
||||
"expired": "[%key:component::seventeentrack::entity::sensor::expired::name%]",
|
||||
"ready_to_be_picked_up": "[%key:component::seventeentrack::entity::sensor::ready_to_be_picked_up::name%]",
|
||||
"undelivered": "[%key:component::seventeentrack::entity::sensor::undelivered::name%]",
|
||||
"delivered": "[%key:component::seventeentrack::entity::sensor::delivered::name%]",
|
||||
"returned": "[%key:component::seventeentrack::entity::sensor::returned::name%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
53
tests/components/seventeentrack/snapshots/test_services.ambr
Normal file
53
tests/components/seventeentrack/snapshots/test_services.ambr
Normal file
|
@ -0,0 +1,53 @@
|
|||
# serializer version: 1
|
||||
# name: test_get_all_packages
|
||||
dict({
|
||||
'packages': list([
|
||||
dict({
|
||||
'friendly_name': 'friendly name 3',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'status': 'Expired',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_number': '123',
|
||||
}),
|
||||
dict({
|
||||
'friendly_name': 'friendly name 1',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'status': 'In Transit',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_number': '456',
|
||||
}),
|
||||
dict({
|
||||
'friendly_name': 'friendly name 2',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'status': 'Delivered',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_number': '789',
|
||||
}),
|
||||
]),
|
||||
})
|
||||
# ---
|
||||
# name: test_get_packages_from_list
|
||||
dict({
|
||||
'packages': list([
|
||||
dict({
|
||||
'friendly_name': 'friendly name 1',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'status': 'In Transit',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_number': '456',
|
||||
}),
|
||||
dict({
|
||||
'friendly_name': 'friendly name 2',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'status': 'Delivered',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_number': '789',
|
||||
}),
|
||||
]),
|
||||
})
|
||||
# ---
|
76
tests/components/seventeentrack/test_services.py
Normal file
76
tests/components/seventeentrack/test_services.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
"""Tests for the seventeentrack service."""
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.seventeentrack import DOMAIN, SERVICE_GET_PACKAGES
|
||||
from homeassistant.core import HomeAssistant, SupportsResponse
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.components.seventeentrack import init_integration
|
||||
from tests.components.seventeentrack.conftest import get_package
|
||||
|
||||
|
||||
async def test_get_packages_from_list(
|
||||
hass: HomeAssistant,
|
||||
mock_seventeentrack: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Ensure service returns only the packages in the list."""
|
||||
await _mock_packages(mock_seventeentrack)
|
||||
await init_integration(hass, mock_config_entry)
|
||||
service_response = await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_GET_PACKAGES,
|
||||
{
|
||||
"config_entry_id": mock_config_entry.entry_id,
|
||||
"package_state": ["in_transit", "delivered"],
|
||||
},
|
||||
blocking=True,
|
||||
return_response=SupportsResponse.ONLY,
|
||||
)
|
||||
|
||||
assert service_response == snapshot
|
||||
|
||||
|
||||
async def test_get_all_packages(
|
||||
hass: HomeAssistant,
|
||||
mock_seventeentrack: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Ensure service returns all packages when non provided."""
|
||||
await _mock_packages(mock_seventeentrack)
|
||||
await init_integration(hass, mock_config_entry)
|
||||
service_response = await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_GET_PACKAGES,
|
||||
{
|
||||
"config_entry_id": mock_config_entry.entry_id,
|
||||
},
|
||||
blocking=True,
|
||||
return_response=SupportsResponse.ONLY,
|
||||
)
|
||||
|
||||
assert service_response == snapshot
|
||||
|
||||
|
||||
async def _mock_packages(mock_seventeentrack):
|
||||
package1 = get_package(status=10)
|
||||
package2 = get_package(
|
||||
tracking_number="789",
|
||||
friendly_name="friendly name 2",
|
||||
status=40,
|
||||
)
|
||||
package3 = get_package(
|
||||
tracking_number="123",
|
||||
friendly_name="friendly name 3",
|
||||
status=20,
|
||||
)
|
||||
mock_seventeentrack.return_value.profile.packages.return_value = [
|
||||
package1,
|
||||
package2,
|
||||
package3,
|
||||
]
|
Loading…
Add table
Reference in a new issue