J’aimerais pouvoir désactiver une caméra (par bouton ou mieux, via une scène également) sans la supprimer.
Cas d’usage :
L’hiver, les caméras des nichoirs sont déconnectées et renvoient donc des erreurs dans les logs car le poll à toujours lieu.
Quand nous sommes à la maison, j’aimerais avoir un ‹ mode privé › (pas besoin que mes enfants qui font la fête sachent que nous aussi, et inversement)
Certains clients viennent en toute discrétion, pas besoin qu’ils apparaissent sur le dashboard du salon…
Excellent besoin !! J’ai accepté
tu as l’option de mettre une prise connectée qui allume/coupe quand tu en as besoin, et ça permet d’être sûr à 100% que la cam ne filme pas.
Bon si la caméra est sur pile c’est plus compliqué de couper le câble
C’est plus compliqué que ça… Les caméras des nichoirs sont sur des RPi0 et couper le courant est plutôt à éviter (d’ailleurs, est-ce qu’espionner des oiseaux peut être considéré comme du voyeurisme ?)
Mais oui, je pourrais ajouter du MQTT etc. mais ça ne règle pas le problème du poll et erreurs dans les logs…
Salut tout le monde !
Ce sujet est désormais en cours de développement .
Une PR a été ouverte pour désactiver une caméra (mode privé) sans la supprimer :
master ← claude/camera-disable-private-mode
ouvert 02:45AM - 18 Aug 26 UTC
Implements feature request: https://community.gladysassistant.com/t/desactiver-u… ne-camera-mode-prive/10645
### Description
A camera can now be turned **off** from the UI or from a scene, without being deleted.
The state is one new device feature on the camera itself: `camera` / `enabled` (`DEVICE_FEATURE_TYPES.CAMERA.ENABLED`), a binary read/write feature (`1` = enabled, the default, `0` = disabled). Modeling it as a feature is what makes it work everywhere for free: it renders as a toggle in the device rows, and the existing `device.set-value` scene action turns it on/off from a scene with no new plumbing — which is how the requested "private mode when we are home" is built.
**A camera without the feature is always considered enabled**, so existing installs are unaffected.
#### What happens when a camera is disabled (all gated in the core, so every camera integration benefits)
| Path | Behavior |
|---|---|
| `device.poll` | The device is skipped before the service is even looked up — no image fetch, no error log. This is the concrete pain point of the request (nest-box cameras unplugged for the winter flooding the logs every minute). |
| `camera.getImage` (dashboard snapshot) | Rejects with `Camera is disabled`. The **last known image is never served** — serving it would defeat the privacy purpose. |
| `camera.getLiveImage` (live snapshot, chat intent, scene "send camera image") | Rejects with `Camera is disabled` before reaching the integration. |
| `camera.getImagesInRoom` (chat "show me the cameras in the living room", MCP tool) | Disabled cameras are excluded from the query. |
| `rtsp-camera` `startStreaming` | Rejects with `CAMERA_IS_DISABLED`. |
| `rtsp-camera` `setValue` (new) | RTSP has no control channel, so `enabled` is its only writable feature; setting it to `0` **stops the running live stream immediately**, so a dashboard already streaming stops right away. |
#### Frontend
- **Camera widget**: loads the camera device, and when disabled renders a clear "camera disabled" placeholder instead of the image, requests no image and offers no live button. It listens to the feature's state over the WebSocket, so turning the camera off from a scene or another dashboard clears the image and stops an ongoing live view without a page reload; turning it back on refreshes the image.
- **Device rows** (`device-in-room`): `camera`/`enabled` joins the supported-types allowlist and renders as a plain on/off toggle.
- MQTT device page defaults, feature icon and translations (`en`, `fr`, `de`).
#### Feature creation / backward compatibility
- New RTSP cameras are created with the feature (enabled).
- Migration `20260818090000-add-camera-enabled-feature` adds it (enabled, `last_value = 1`) to RTSP cameras created before this change. It is idempotent and a no-op when the service is not installed.
- Other integrations (MQTT cameras, external integrations) declare the feature themselves — nothing is auto-created for them, since a feature the owning integration does not know about would have no owner.
#### Standard alignment and taxonomy
Matter 1.4's Camera AV Stream Management cluster models privacy with three attributes (`SoftRecordingPrivacyModeEnabled`, `SoftLivestreamPrivacyModeEnabled`, `HardPrivacyModeOn`). This PR deliberately diverges with **one inverted boolean**, and the justification (plus the full `docs/specs/device-feature-categories.md` checklist) is written up in the new living spec `docs/specs/camera-enable-disable.md`, added in this same diff and registered in `AGENTS.md`.
#### Out of scope (deliberately)
- Per-camera scheduling ("disable every evening"): a scene with a time trigger already does it.
- A global "disable all cameras" switch: a scene acting on several `enabled` features covers it.
- Deleting images already recorded when a camera is disabled (the stored image is simply never served again).
- A read-only "hard privacy" feedback feature (physical shutter): no integration exposes one today.
This pull request was created by an automated Claude Code run.
## Forum
Forum: https://community.gladysassistant.com/t/desactiver-une-camera-mode-prive/10645
### Checklist
- [x] Tests pass: `cd server && npm run coverage` (Codecov requires 100% coverage on changed lines) and Cypress (`npm run cypress:run`) if the UI changed
- [x] Linter and prettier pass on both front and server (`npm run eslint`, `npm run prettier`)
- [x] No undocumented breaking change
<sub>Notes on the checklist: the full server suite was run locally (`npm test`) — the only failures are pre-existing environment ones in this sandbox (no `sqlite3` binary, no Docker, no outbound network for the Gladys Plus gateway tests), identical to the failures on `master`. Coverage of every changed server file was verified at 100% with `c8`. Front: `prettier-check`, `eslint`, `compare-translations` and `npm run build` all pass. Cypress was **not** run (binary not installed in this environment).</sub>
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---
_Generated by [Claude Code](https://claude.ai/code/session_01YXRz5JiaM9N42djviseBRu)_
N’hésitez pas à suivre la PR, à tester (optionnel, surtout pour les petites demandes) et à faire vos retours ici si besoin.