Skip to content

Commit

Permalink
Allow pairing an on network device
Browse files Browse the repository at this point in the history
  • Loading branch information
balloob committed Sep 17, 2022
1 parent f8e9044 commit 875c0f1
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 0 deletions.
16 changes: 16 additions & 0 deletions custom_components/matter_experimental/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,22 @@ async def commission(call: ServiceCall) -> None:
vol.Schema({"code": str}),
)

async def accept_shared_device(call: ServiceCall) -> None:
"""Accept a shared device."""
matter: Matter = list(hass.data[DOMAIN].values())[0]
try:
await matter.commission_on_network(call.data["pin"])
except FailedCommand as err:
raise HomeAssistantError(str(err)) from err

async_register_admin_service(
hass,
DOMAIN,
"accept_shared_device",
accept_shared_device,
vol.Schema({"pin": vol.Coerce(int)}),
)

async def set_wifi(call: ServiceCall) -> None:
"""Handle set wifi creds."""
matter: Matter = list(hass.data[DOMAIN].values())[0]
Expand Down
11 changes: 11 additions & 0 deletions custom_components/matter_experimental/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ commission:
required: true
selector:
text:
accept_shared_device:
name: Accept shared device
description: >
Add a shared device to your Matter network.
fields:
pin:
name: Pin code
required: true
selector:
text:

set_wifi:
name: Set Wi-Fi credentials
description: >
Expand Down
19 changes: 19 additions & 0 deletions matter_server/client/matter.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,25 @@ async def commission(self, code: str):

await self._interview_node(node_id)

async def commission_on_network(self, pin: int) -> bool:
"""Commission a new device."""
if self._commission_lock is None:
self._commission_lock = asyncio.Lock()

async with self._commission_lock:
node_id = self.next_node_id
if not await self.client.driver.device_controller.commission_on_network(
node_id, pin
):
return False
self._nodes[node_id] = None
self.next_node_id += 1
# Save right away because we don't want to lose node IDs
await self.adapter.save_data(self._data_to_save())

await self._interview_node(node_id)
return True

async def delete_node(self, node_id: int) -> None:
"""Delete a node."""
# TODO notify anyone using MatterNode
Expand Down
9 changes: 9 additions & 0 deletions matter_server/client/model/device_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ async def commission_with_code(self, setupPayload: str, nodeid: int):
},
)

async def commission_on_network(self, nodeId: int, setupPinCode: int):
return await self._async_send_command(
"CommissionOnNetwork",
{
"nodeId": nodeId,
"setupPinCode": setupPinCode,
},
)

async def set_wifi_credentials(self, ssid: str, credentials: str):
return await self._async_send_command(
"SetWiFiCredentials",
Expand Down
18 changes: 18 additions & 0 deletions matter_server/server/active_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ async def _handle_server_GetInfo(self, msg: CommandMessage):

@commands.register("device_controller.CommissionWithCode")
async def _handle_device_controller_CommissionWithCode(self, msg: CommandMessage):
"""Commission a device.
Return boolean if successful.
"""
if not self.server.stack.wifi_cred_set:
self.logger.warning("Received commissioning without Wi-Fi set")

Expand All @@ -123,6 +127,20 @@ async def _handle_device_controller_CommissionWithCode(self, msg: CommandMessage
)
self._send_message(SuccessResultMessage(msg.messageId, {"raw": result}))

@commands.register("device_controller.CommissionOnNetwork")
async def _handle_device_controller_CommissionOnNetwork(self, msg: CommandMessage):
"""Commission a device already connected to the network.
Return boolean if successful.
"""
result = await self.loop.run_in_executor(
None,
partial(
self.server.stack.device_controller.CommissionOnNetwork, **msg.args
),
)
self._send_message(SuccessResultMessage(msg.messageId, {"raw": result}))

@commands.register("device_controller.Read")
async def _handle_device_controller_Read(self, msg: CommandMessage):
if isinstance(msg.args.get("attributes"), list):
Expand Down

0 comments on commit 875c0f1

Please sign in to comment.