Describe the bug
simplipy hardcodes "playback/hls" when constructing WebsocketEvent.media_urls, but SimpliSafe has started sending "playback/flv" instead for some camera events. This causes a KeyError that crashes the entire websocket loop, meaning no further events are received.
To Reproduce
- Have a SimpliSafe camera that returns
playback/flv instead of playback/hls
- Trigger any camera event (motion detection, doorbell press, etc.)
- Observe the
KeyError: 'playback/hls' in logs
Expected behavior
The websocket should gracefully handle video payloads with either playback/hls or playback/flv links (or neither), and the websocket loop should continue receiving events.
Screenshots
Logger: homeassistant.components.simplisafe
Source: components/simplisafe/__init__.py:492
Integration: SimpliSafe (documentation, issues)
First occurred: 11:01:56 AM (1 occurrence)
Last logged: 11:01:56 AM
Unexpected error in websocket loop: 'playback/hls'
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/simplisafe/__init__.py", line 492, in _async_websocket_loop
await self._api.websocket.async_listen()
File "/usr/local/lib/python3.14/site-packages/simplipy/websocket.py", line 457, in async_listen
self._parse_payload(message)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/local/lib/python3.14/site-packages/simplipy/websocket.py", line 352, in _parse_payload
event = websocket_event_from_payload(payload)
File "/usr/local/lib/python3.14/site-packages/simplipy/websocket.py", line 225, in websocket_event_from_payload
return WebsocketEvent(
payload["data"]["eventCid"],
...<8 lines>...
sensor_type=payload["data"]["sensorType"],
)
File "/usr/local/lib/python3.14/site-packages/simplipy/websocket.py", line 207, in __post_init__
"hls_url": self._video[self._vid]["_links"]["playback/hls"]["href"],
KeyError: 'playback/hls'
Additional context
SimpliSafe appears to have changed their video API for some camera models (confirmed on model SS001). The _links dict in the video payload now contains playback/flv instead of playback/hls. A sample payload _links:
{
"_self": { "href": "https://[REDACTED].us-east-1.prd.cam.simplisafe.com/v1/recordings/[REDACTED]", "method": "GET" },
"playback/flv": { "href": "https://media.simplisafe.com/v1/[REDACTED]/flv?ts=[REDACTED]&postroll=60", "method": "GET" },
"preview/mjpg": { "href": "https://media.simplisafe.com/v1/[REDACTED]/mjpg?ts=[REDACTED]&duration=65", "method": "GET" },
"snapshot/mjpg": { "href": "https://media.simplisafe.com/v1/[REDACTED]/mjpg?ts=[REDACTED]&duration=10", "method": "GET" },
"snapshot/jpg": { "href": "https://media.simplisafe.com/v1/[REDACTED]/snapshot?ts=[REDACTED]", "method": "GET" },
"download/mp4": { "href": "https://media.simplisafe.com/v1/[REDACTED]/mp4?ts=[REDACTED]&duration=65", "method": "GET" },
"share": { "href": "https://media.simplisafe.com/v1/[REDACTED]/share?ts=[REDACTED]&duration=65", "method": "POST" }
}
Note the absence of playback/hls and presence of playback/flv. This causes the KeyError in __post_init__ at websocket.py:207. The error also kills the entire websocket loop since the KeyError propagates up and is caught by the broad except Exception handler.
Disclosure
Drafted by Kimi K2.6 with human oversight
Describe the bug
simplipyhardcodes"playback/hls"when constructingWebsocketEvent.media_urls, but SimpliSafe has started sending"playback/flv"instead for some camera events. This causes aKeyErrorthat crashes the entire websocket loop, meaning no further events are received.To Reproduce
playback/flvinstead ofplayback/hlsKeyError: 'playback/hls'in logsExpected behavior
The websocket should gracefully handle video payloads with either
playback/hlsorplayback/flvlinks (or neither), and the websocket loop should continue receiving events.Screenshots
Additional context
SimpliSafe appears to have changed their video API for some camera models (confirmed on model
SS001). The_linksdict in the video payload now containsplayback/flvinstead ofplayback/hls. A sample payload_links:{ "_self": { "href": "https://[REDACTED].us-east-1.prd.cam.simplisafe.com/v1/recordings/[REDACTED]", "method": "GET" }, "playback/flv": { "href": "https://media.simplisafe.com/v1/[REDACTED]/flv?ts=[REDACTED]&postroll=60", "method": "GET" }, "preview/mjpg": { "href": "https://media.simplisafe.com/v1/[REDACTED]/mjpg?ts=[REDACTED]&duration=65", "method": "GET" }, "snapshot/mjpg": { "href": "https://media.simplisafe.com/v1/[REDACTED]/mjpg?ts=[REDACTED]&duration=10", "method": "GET" }, "snapshot/jpg": { "href": "https://media.simplisafe.com/v1/[REDACTED]/snapshot?ts=[REDACTED]", "method": "GET" }, "download/mp4": { "href": "https://media.simplisafe.com/v1/[REDACTED]/mp4?ts=[REDACTED]&duration=65", "method": "GET" }, "share": { "href": "https://media.simplisafe.com/v1/[REDACTED]/share?ts=[REDACTED]&duration=65", "method": "POST" } }Note the absence of
playback/hlsand presence ofplayback/flv. This causes theKeyErrorin__post_init__atwebsocket.py:207. The error also kills the entire websocket loop since theKeyErrorpropagates up and is caught by the broadexcept Exceptionhandler.Disclosure
Drafted by Kimi K2.6 with human oversight