Default APS ack on no-reply frames causes false delivery failures and duplicate commands for sleepy end devices behind routers
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 5/5
- Tempo estimado
- Mais de uma semana
- Facilidade para iniciantes
- 12/100
- Tipo de issue
- Bug
- Clareza
- Razoavelmente clara
- Status de atividade
- Ativa
- Stack de tecnologia
- python
- Domínio
- embedded-iot, networking
Direção de pesquisa
The ack request is set in ControllerApplication.request in zigpy/application.py, the reply default is Cluster.reply in zigpy/zcl/init.py, and the retry loop is Device.request in zigpy/device.py (DEFAULT_REQUEST_RETRIES). This needs a maintainer decision on the ack policy and on how radio libraries report an APS ack timeout, so there is no single first edit. Done means that decision is recorded and the chosen change is agreed with the radio-library maintainers.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Found while investigating #1891. The full analysis, including how each radio stack times its APS acks, is in https://github.com/zigpy/zigpy/issues/1891#issuecomment-5925240976.
By default, zigpy requests an APS ack for every frame that expects no ZCL response, and it retries a failed send twice, each time as a new frame. For sleepy end devices behind a router, the coordinator can report a missing APS ack while the frame is still queued at the device's parent. zigpy then sees a false failure, and its retries can make the device receive and act on the same command up to three times.
Details
- Which frames ask for an APS ack:
ControllerApplication.requestsetsTransmitOptions.ACKwhenask_for_ackisn't given andexpect_replyis false (application.py#L1148-L1153).Cluster.reply()defaults toexpect_reply=False(zcl/__init__.py#L871), so Default Responses, other ZCL responses, OTA responses and the unsolicited Image Notify all ask for one. - Why the ack comes too late: the APS ack comes from the end device itself, after it has polled its parent for the frame. The parent holds the frame for about 7.68 s, but with Koenkk's Z-Stack firmware and with EmberZNet under bellows, the coordinator waits much less for the ack:
- Koenkk's Z-Stack coordinator firmware waits 1 s for the ack after each of three transmissions (about 3 s in total; the value in effect comes from NV, see zigpy/zigpy-znp#283).
- EmberZNet, as bellows configures it, waits 1.6 s after each of three transmissions (about 5 s), because bellows clears EmberZNet's extended timeout for acked sends.
- If the device polls between that point and the end of the parent's hold, the failure is false. The coordinator's own sleepy children are mostly covered by the stacks themselves (apart from a bellows host timeout, see zigpy/bellows#764); the gap is devices behind a router.
- Retries become duplicates:
Device.requestretries a failed attempt twice, unless it failed with a parsing error (DEFAULT_REQUEST_RETRIES = 2, device.py#L68). Each retry is a new frame with a new APS counter, so the device's APS duplicate rejection can't drop it, while earlier copies may still be queued at the parent. The ZCL TSN stays the same, but the ZCL spec defines it for matching responses to requests and defines no duplicate rejection on it. extended_timeoutcovers more than sleepy devices: it's set for every end device, including ones that keep their radio on, and for devices without a node descriptor (device.py#L924-L927). For always-on end devices, this only slows down failure detection: zigpy's reply timeout goes from 5 s to 28 s, zigpy-znp's confirm wait from 8 s to 30 s, and bellows' send wait from 3 s to 8 s.
For comparison
zigbee-herdsman never requests an APS ack on Z-Stack: its dataRequest sends every unicast without the ack option. On EmberZNet, for ZCL frames, it requests one only when a specific or default response is expected. It sends the Image Notify as a single request (sendPolicy: "immediate"), without an APS ack, and then waits up to 60 s for the device's Query Next Image.
Possible changes
- Send the Image Notify (at least) without an APS ack request. With the fix proposed in #1891 (branch zigpy-bot/ota-notify-non-fatal, not merged yet), what matters is whether the device sends its Query Next Image, not the notify's delivery status. On bellows, the first attempt would then lose EmberZNet's own APS retries. Without an APS ack, zigpy only retries if the send itself raises an error (e.g. a MAC/NWK-level failure or a host-side timeout), and those retries force route discovery, which bellows sends with APS retries again (unless source routing is enabled).
- After an APS ack timeout to an end device, don't retry with a new frame, to avoid duplicate execution. The trade-off is losing a frame the parent really dropped. This needs the radio libraries to report an APS ack timeout in a way zigpy can tell apart: today,
DeliveryError.statusis the radio's raw status code, and it may not separate an ack timeout from MAC failures on every stack. - Optionally, only set
extended_timeoutfor end devices that don't keep their radio on (NodeDescriptor.is_receiver_on_when_idle).
- Linguagem predominante
- Python
- Estrelas
- 1.1k
- Forks
- 217
- Merge médio
- 4d 8h
- PRs com merge (30d)
- 4
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Sem modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de zigpy/zigpy
-
code quality
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
Mantenedores costumam responder em até 1 dia
-
code quality
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 65/100
Mantenedores costumam responder em até 1 dia
-
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 72/100
zigpy/zigpy#1821 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 22/100
zigpy/zigpy#1917 · 2 comentários ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 35/100
Mantenedores costumam responder em até 1 dia
Todas as issues de zigpy/zigpy
Issues semelhantes
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 77/100
lidofinance/diffyscan#239 ·
Mantenedores costumam responder em até 1 dia
-
docs: the dev-setup table and AGENTS.md name the reviewed_by guard that CI's Changelog job runsAbertaarea: tools documentation good first issue ready for a contributor
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
eyalgolan/statecraft-israel#873 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
GET rooms API returns 500 due to nonexistent Room.is_active attributeTalvez já em andamento @Mars-60 assumiu hoje. Abertabug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
Mantenedores costumam responder em até 1 dia
-
Add cover art to song rowsAbertaenhancement
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
Mantenedores costumam responder em até 5 dias
-
Harmony OPeNDAP SubSetter (HOSS) Geographic production rssmif16d 7 XYZ_PROV
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 62/100
nasa/harmony-autotester#341 ·