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

Add sdp m line index to WebRtc Ice Candidates #129879

Draft
wants to merge 4 commits into
base: dev
Choose a base branch
from
Draft
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: 3 additions & 3 deletions homeassistant/components/camera/webrtc.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def as_dict(self) -> dict[str, Any]:
"""Return a dict representation of the message."""
return {
"type": self._get_type(),
"candidate": self.candidate.candidate,
"candidate": self.candidate.to_dict(),
}


Expand Down Expand Up @@ -307,7 +307,7 @@ async def ws_get_client_config(
vol.Required("type"): "camera/webrtc/candidate",
vol.Required("entity_id"): cv.entity_id,
vol.Required("session_id"): str,
vol.Required("candidate"): str,
vol.Required("candidate"): dict,
}
)
@websocket_api.async_response
Expand All @@ -329,7 +329,7 @@ async def ws_candidate(
return

await camera.async_on_webrtc_candidate(
msg["session_id"], RTCIceCandidate(msg["candidate"])
msg["session_id"], RTCIceCandidate.from_dict(msg["candidate"])
)
connection.send_message(websocket_api.result_message(msg["id"]))

Expand Down
4 changes: 3 additions & 1 deletion homeassistant/components/go2rtc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ def on_messages(message: ReceiveMessages) -> None:
value: WebRTCMessage
match message:
case WebRTCCandidate():
value = HAWebRTCCandidate(RTCIceCandidate(message.candidate))
value = HAWebRTCCandidate(
RTCIceCandidate(message.candidate, sdp_mid="0")
)
case WebRTCAnswer():
value = HAWebRTCAnswer(message.sdp)
case WsError():
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/package_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ uv==0.4.28
voluptuous-openapi==0.0.5
voluptuous-serialize==2.6.0
voluptuous==0.15.2
webrtc-models==0.2.0
webrtc-models==0.3.0
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be done in a separate PR upfront

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will break things if it goes in up front as according to spec either sdpMLineIndex or sdpMid must be set.

yarl==1.17.1
zeroconf==0.136.0

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ dependencies = [
"voluptuous-serialize==2.6.0",
"voluptuous-openapi==0.0.5",
"yarl==1.17.1",
"webrtc-models==0.2.0",
"webrtc-models==0.3.0",
]

[project.urls]
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ voluptuous==0.15.2
voluptuous-serialize==2.6.0
voluptuous-openapi==0.0.5
yarl==1.17.1
webrtc-models==0.2.0
webrtc-models==0.3.0
34 changes: 23 additions & 11 deletions tests/components/camera/test_webrtc.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,16 +529,26 @@ async def test_websocket_webrtc_offer(
("message", "expected_frontend_message"),
[
(
WebRTCCandidate(RTCIceCandidate("candidate")),
{"type": "candidate", "candidate": "candidate"},
WebRTCCandidate(RTCIceCandidate("candidate", sdp_m_line_index=0)),
{
"type": "candidate",
"candidate": {"candidate": "candidate", "sdpMLineIndex": 0},
},
),
(
WebRTCCandidate(RTCIceCandidate("candidate", sdp_mid="0")),
{
"type": "candidate",
"candidate": {"candidate": "candidate", "sdpMid": "0"},
},
),
(
WebRTCError("webrtc_offer_failed", "error"),
{"type": "error", "code": "webrtc_offer_failed", "message": "error"},
),
(WebRTCAnswer("answer"), {"type": "answer", "answer": "answer"}),
],
ids=["candidate", "error", "answer"],
ids=["candidate-mlineindex", "candidate-mid", "error", "answer"],
)
@pytest.mark.usefixtures("mock_stream_source", "mock_camera")
async def test_websocket_webrtc_offer_webrtc_provider(
Expand Down Expand Up @@ -1011,14 +1021,14 @@ async def test_ws_webrtc_candidate(
"type": "camera/webrtc/candidate",
"entity_id": "camera.demo_camera",
"session_id": session_id,
"candidate": candidate,
"candidate": {"candidate": candidate, "sdpMLineIndex": 1},
}
)
response = await client.receive_json()
assert response["type"] == TYPE_RESULT
assert response["success"]
mock_on_webrtc_candidate.assert_called_once_with(
session_id, RTCIceCandidate(candidate)
session_id, RTCIceCandidate(candidate, sdp_m_line_index=1)
)


Expand All @@ -1033,7 +1043,7 @@ async def test_ws_webrtc_candidate_not_supported(
"type": "camera/webrtc/candidate",
"entity_id": "camera.demo_camera",
"session_id": "session_id",
"candidate": "candidate",
"candidate": {"candidate": "candidate", "sdpMLineIndex": 1},
}
)
response = await client.receive_json()
Expand Down Expand Up @@ -1063,14 +1073,14 @@ async def test_ws_webrtc_candidate_webrtc_provider(
"type": "camera/webrtc/candidate",
"entity_id": "camera.demo_camera",
"session_id": session_id,
"candidate": candidate,
"candidate": {"candidate": candidate, "sdpMLineIndex": 1},
}
)
response = await client.receive_json()
assert response["type"] == TYPE_RESULT
assert response["success"]
mock_on_webrtc_candidate.assert_called_once_with(
session_id, RTCIceCandidate(candidate)
session_id, RTCIceCandidate(candidate, sdp_m_line_index=1)
)


Expand All @@ -1085,7 +1095,7 @@ async def test_ws_webrtc_candidate_invalid_entity(
"type": "camera/webrtc/candidate",
"entity_id": "camera.does_not_exist",
"session_id": "session_id",
"candidate": "candidate",
"candidate": {"candidate": "candidate", "sdpMLineIndex": 1},
}
)
response = await client.receive_json()
Expand Down Expand Up @@ -1129,7 +1139,7 @@ async def test_ws_webrtc_candidate_invalid_stream_type(
"type": "camera/webrtc/candidate",
"entity_id": "camera.demo_camera",
"session_id": "session_id",
"candidate": "candidate",
"candidate": {"candidate": "candidate", "sdp_m_line_index": 0},
}
)
response = await client.receive_json()
Expand Down Expand Up @@ -1182,7 +1192,9 @@ async def async_on_webrtc_candidate(
await provider.async_handle_async_webrtc_offer(
Mock(), "offer_sdp", "session_id", Mock()
)
await provider.async_on_webrtc_candidate("session_id", RTCIceCandidate("candidate"))
await provider.async_on_webrtc_candidate(
"session_id", RTCIceCandidate("candidate", sdp_m_line_index=0)
)
provider.async_close_session("session_id")


Expand Down
10 changes: 7 additions & 3 deletions tests/components/go2rtc/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ async def message_callbacks(
[
(
WebRTCCandidate("candidate"),
HAWebRTCCandidate(RTCIceCandidate("candidate")),
HAWebRTCCandidate(RTCIceCandidate("candidate", sdp_mid="0")),
),
(
WebRTCAnswer(ANSWER_SDP),
Expand Down Expand Up @@ -428,7 +428,9 @@ async def test_on_candidate(
session_id = "session_id"

# Session doesn't exist
await camera.async_on_webrtc_candidate(session_id, RTCIceCandidate("candidate"))
await camera.async_on_webrtc_candidate(
session_id, RTCIceCandidate("candidate", sdp_mid="0")
)
assert (
"homeassistant.components.go2rtc",
logging.DEBUG,
Expand All @@ -448,7 +450,9 @@ async def test_on_candidate(
)
ws_client.reset_mock()

await camera.async_on_webrtc_candidate(session_id, RTCIceCandidate("candidate"))
await camera.async_on_webrtc_candidate(
session_id, RTCIceCandidate("candidate", sdp_mid="0")
)
ws_client.send.assert_called_once_with(WebRTCCandidate("candidate"))
assert caplog.record_tuples == []

Expand Down
Loading