Fix/cocoa doorbell v5 support - #518
Conversation
…nt parsing - Add cocoa_doorbell_v5 to DOORBELL_PRO_3_KINDS in const.py - Map model name 'Doorbell Pro (3rd Gen)' and capabilities in doorbot.py - Fix KeyError: 'id' in _get_ring_event when ding object has no id field (newer Ring firmware omits ding.id; use eventito.timestamp as fallback) - Add fixture files and tests for the no-ding-id FCM payload format
|
@iweinzierl, wouldnt |
@AMoo-Miki , I thought the same when I started working on the PR, but when I analyzed multiple events, I figured out that the value of the |
|
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. |
|
@iweinzierl Do you think we could reopen this or create a new PR with your fixes? |
### Summary
When a Ring device with newer firmware (observed on cocoa_doorbell_v5) sends a push notification via FCM, the event listener raises a KeyError: 'id' and shuts down after 3 errors. As a result, motion and ding events are never delivered.
Root cause
_get_ring_event() in eventlistener.py unconditionally accesses event["ding"]["id"]:
event_id = int(ding["id"]) # KeyError if "id" is absentNewer Ring firmware sends FCM notifications in the modern (non-gcmData) format where the ding object does not include an "id" field. Instead, a unique per-event identifier is available as event["eventito"]["timestamp"] (millisecond epoch).
Example payload (relevant excerpt)
{ "event": { "ding": { "created_at": "2026-03-06T12:27:09Z", "subtype": "human", "detection_type": "human" }, "eventito": { "timestamp": 1772800029955, "type": "human" } } }Note: ding has no "id" field.
Observed error
KeyError: 'id' File ".../eventlistener.py", line NNN, in _get_ring_event event_id = int(ding["id"])After 3 such errors the listener stops receiving events (ErrorType.NOTIFY).
Suggested fix
Fall back to eventito["timestamp"] when ding["id"] is absent:
eventito = event.get("eventito", {}) if "id" in ding: event_id = int(ding["id"]) elif "timestamp" in eventito: event_id = int(eventito["timestamp"]) else: event_id = int(time.time() * 1000)eventito["timestamp"] is unique per event and suitable for deduplication. Using the device ID as a fallback would be incorrect because it would treat every subsequent event from the same device as an update rather than a new event.
The bug issue is the more impactful one — it completely breaks real-time event delivery for affected devices. I'd suggest opening the bug report first and referencing it from the PR.> DOORBELL_PRO_3_KINDS = ["cocoa_doorbell_v5"]