Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added second websocket to get the Challenge ws. #223

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
59 changes: 59 additions & 0 deletions pyhilo/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
API_NOTIFICATIONS_ENDPOINT,
API_REGISTRATION_ENDPOINT,
API_REGISTRATION_HEADERS,
AUTOMATION_CHALLENGE_ENDPOINT,
AUTOMATION_DEVICEHUB_ENDPOINT,
DEFAULT_STATE_FILE,
DEFAULT_USER_AGENT,
Expand Down Expand Up @@ -82,6 +83,7 @@ def __init__(
self.session: ClientSession = session
self._oauth_session = oauth_session
self.websocket: WebsocketClient
self.websocket2: WebsocketClient
self.log_traces = log_traces
self._get_device_callbacks: list[Callable[..., Any]] = []

Expand Down Expand Up @@ -227,6 +229,10 @@ async def _async_request(
kwargs["headers"]["authorization"] = f"Bearer {access_token}"
kwargs["headers"]["Host"] = host

if endpoint.startswith(AUTOMATION_CHALLENGE_ENDPOINT):
# remove Ocp-Apim-Subscription-Key header to avoid 401 error
kwargs["headers"].pop("Ocp-Apim-Subscription-Key", None)
Comment on lines +232 to +234
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for removing the 'Ocp-Apim-Subscription-Key' header should be documented with a rationale or alternatively, a reference to a relevant section of the API documentation if available. This will help future developers understand the necessity of this operation in the context of API interactions.

Suggested change
if endpoint.startswith(AUTOMATION_CHALLENGE_ENDPOINT):
# remove Ocp-Apim-Subscription-Key header to avoid 401 error
kwargs["headers"].pop("Ocp-Apim-Subscription-Key", None)
# remove Ocp-Apim-Subscription-Key header based on API requirements to avoid 401 error


data: dict[str, Any] = {}
url = parse.urljoin(f"https://{host}", endpoint)
if self.log_traces:
Expand Down Expand Up @@ -356,6 +362,11 @@ async def _async_post_init(self) -> None:
await self._get_device_token()
await self.refresh_ws_token()
self.websocket = WebsocketClient(self)
LOG.debug("Websocket2 postinit")
await self._get_fid()
await self._get_device_token()
await self.refresh_ws2_token()
self.websocket2 = WebsocketClient(self)

async def refresh_ws_token(self) -> None:
(self.ws_url, self.ws_token) = await self.post_devicehub_negociate()
Expand All @@ -379,6 +390,28 @@ async def post_devicehub_negociate(self) -> tuple[str, str]:
)
return (ws_url, ws_token)

async def refresh_ws2_token(self) -> None:
(self.ws2_url, self.ws2_token) = await self.post_challengehub_negociate()
await self.get_websocket2_params()

async def post_challengehub_negociate(self) -> tuple[str, str]:
LOG.debug("Getting websocket2 url")
url = f"{AUTOMATION_CHALLENGE_ENDPOINT}/negotiate"
LOG.debug(f"challengehub URL is {url}")
resp = await self.async_request("post", url)
ws_url = resp.get("url")
ws_token = resp.get("accessToken")
LOG.debug("Calling set_state challengehub_negotiate")
await set_state(
self._state_yaml,
"websocket2",
{
"url": ws_url,
"token": ws_token,
},
)
return (ws_url, ws_token)

async def get_websocket_params(self) -> None:
uri = parse.urlparse(self.ws_url)
LOG.debug("Getting websocket params")
Expand All @@ -405,6 +438,32 @@ async def get_websocket_params(self) -> None:
LOG.debug("Calling set_state websocket_params")
await set_state(self._state_yaml, "websocket", websocket_dict)

async def get_websocket2_params(self) -> None:
uri = parse.urlparse(self.ws2_url)
LOG.debug("Getting websocket2 params")
LOG.debug(f"Getting uri {uri}")
resp: dict[str, Any] = await self.async_request(
"post",
f"{uri.path}negotiate?{uri.query}",
host=uri.netloc,
headers={
"authorization": f"Bearer {self.ws2_token}",
},
)
conn_id: str = resp.get("connectionId", "")
self.full_ws2_url = f"{self.ws2_url}&id={conn_id}&access_token={self.ws2_token}"
LOG.debug(f"Getting full ws2 URL {self.full_ws2_url}")
transport_dict: list[WebsocketTransportsDict] = resp.get(
"availableTransports", []
)
websocket_dict: WebsocketDict = {
"connection_id": conn_id,
"available_transports": transport_dict,
"full_ws_url": self.full_ws2_url,
}
LOG.debug("Calling set_state websocket2_params")
await set_state(self._state_yaml, "websocket2", websocket_dict)

async def fb_install(self, fb_id: str) -> None:
LOG.debug("Posting firebase install")
body = {
Expand Down
2 changes: 2 additions & 0 deletions pyhilo/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

# Automation server constant
AUTOMATION_DEVICEHUB_ENDPOINT: Final = "/DeviceHub"
AUTOMATION_CHALLENGE_ENDPOINT: Final = "/ChallengeHub"


# Request constants
DEFAULT_USER_AGENT: Final = f"PyHilo/{PYHILO_VERSION} HomeAssistant/{homeassistant.core.__version__} aiohttp/{aiohttp.__version__} Python/{platform.python_version()}"
Expand Down