Skip to content

Add camera motion detection, kiosk wake on motion and MJPEG camera stream#5140

Open
bemble wants to merge 13 commits into
home-assistant:mainfrom
bemble:feat/kiosk-camera-motion-and-mjpeg-stream
Open

Add camera motion detection, kiosk wake on motion and MJPEG camera stream#5140
bemble wants to merge 13 commits into
home-assistant:mainfrom
bemble:feat/kiosk-camera-motion-and-mjpeg-stream

Conversation

@bemble

@bemble bemble commented Jul 17, 2026

Copy link
Copy Markdown

Add camera motion detection, kiosk wake on motion, and MJPEG camera stream

Summary

Turns the device's front camera into a presence/motion source for kiosk devices (wall-mounted iPads), with three related features:

1. Camera Motion sensor (binary_sensor, device class motion, id camera_motion)
A new MotionDetectionManager runs the front camera through a lightweight frame-differencing pipeline (VGA capture, luminance plane only, 1-in-8 pixel subsampling — no color conversion, no Vision framework). A new CameraMotionSensor reports transitions immediately via the existing update-signaler pattern. Sensor settings expose detection frame rate (slider, 1–30 fps, default 8), changed-area threshold (slider, default 40%), and clear delay / hysteresis (predefined durations, default 15 s). Defaults were tuned on a wall-mounted iPad.

2. Kiosk mode: "Wake on camera motion"
New opt-in toggle in kiosk screensaver settings. When enabled, camera motion is treated as user activity, exactly like touches:

  • the screensaver never starts while motion is ongoing (the idle timer is held, and restarts with its full interval once the motion detector reports clear);
  • motion dismisses an active screensaver, through the same path as the kiosk_hide_screensaver remote command — no server round-trip, works without push.

The screensaver idle-timer logic stays fully owned by KioskScreensaverController; it simply registers as a motion observer while the option is on. Note that with this option enabled the camera runs for the whole kiosk session (iOS shows the green camera indicator throughout — enforced by the system, and called out in the setting's footer text). Persisted as a new tolerant-decoded field in KioskScreensaverSettings (no migration needed).

3. Camera Stream sensor + embedded MJPEG server
A new CameraStreamServer (NWListener, no dependencies) serves the camera as multipart/x-mixed-replace MJPEG, consumable by Home Assistant's MJPEG camera integration at http://<device-ip>:<port>/camera (advertised in the sensor's attributes; any path is accepted). A new Camera Stream sensor controls it: enabling the sensor starts the listener and keeps the capture session alive; state reports streaming/idle, attributes expose port, client count, and the ready-to-paste stream URL. Settings expose the stream frame rate (slider, default 15) and the port (numeric field, number-pad keyboard).

4. New sensor-setting UI types
WebhookSensorSetting gains slider (value committed at end of drag), options (predefined values as a menu picker) and numericField (number-pad text input) alongside the existing switch/stepper, plus an optional subtitle caption — used here for a performance/heat warning under both frame-rate sliders. All are reusable by other sensors.

Design notes

  • The camera never turns on without explicit opt-in. Both camera-based sensors start disabled via SensorContainer.disableInitially (one-time, preserving later user choice), so existing users see no camera permission prompt after updating. The kiosk toggle is off by default as well.
  • The capture session is shared and reference-counted through observer registration: it runs only while at least one consumer (motion sensor, stream client, kiosk wake-on-motion) needs it, foreground only.
  • Each consumer has its own frame rate; the capture session runs at the highest rate among active consumers, and the detection pipeline samples frames down to its own rate. Streaming at 30 fps doesn't make motion detection work harder, and with the stream off the camera falls back to the low-power detection rate.
  • Effective screensaver delay with wake-on-motion = motion clear delay (sensor setting, default 15 s) + screensaver "time to start"; both are user-tunable.
  • watchOS/Catalyst get compile-safe stubs; the feature is iOS/iPadOS only.
  • The MJPEG stream is plain HTTP on the LAN, like typical MJPEG IP cameras.

Screenshots

IMG_2701.mp4
Sensor list Camera motion Camera stream Screensaver options

Testing

  • Tested on iPad (iPadOS 26) as a wall kiosk: screensaver held while someone is in front of the device, starts clear delay + time to start after the room empties, dismissed on motion (clock and blank modes); binary_sensor transitions in HA; MJPEG stream viewed simultaneously in HA dashboard and browser.
  • Threshold/fps tuning verified via the sensor's Last Changed Ratio attribute.

Notes for reviewers

  • Strings are added to en.lproj/Localizable.strings (Lokalise flow).
  • Frame differencing intentionally trades accuracy for power: it reacts to any visual change (light switches, TV). The changed-area threshold mitigates this; a Vision-based person-detection mode could be a follow-up.
  • Unit tests cover the two sensor providers, their signalers, the opt-in default, and the frame-differencing ratio (thanks @bgoncal for the refactor and coverage).

Copilot AI review requested due to automatic review settings July 17, 2026 01:17

@home-assistant home-assistant Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hello @bemble,

When attempting to inspect the commits of your pull request for CLA signature status among all authors we encountered commit(s) which were not linked to a GitHub account, thus not allowing us to determine their status(es).

The commits that are missing a linked GitHub account are the following:

Unfortunately, we are unable to accept this pull request until this situation is corrected.

Here are your options:

  1. If you had an email address set for the commit that simply wasn't linked to your GitHub account you can link that email now and it will retroactively apply to your commits. The simplest way to do this is to click the link to one of the above commits and look for a blue question mark in a blue circle in the top left. Hovering over that bubble will show you what email address you used. Clicking on that button will take you to your email address settings on GitHub. Just add the email address on that page and you're all set. GitHub has more information about this option in their help center.

  2. If you didn't use an email address at all, it was an invalid email, or it's one you can't link to your GitHub, you will need to change the authorship information of the commit and your global Git settings so this doesn't happen again going forward. GitHub provides some great instructions on how to change your authorship information in their help center.

    • If you only made a single commit you should be able to run
      git commit --amend --author="Author Name <email@address.com>"
      
      (substituting "Author Name" and "email@address.com" for your actual information) to set the authorship information.
    • If you made more than one commit and the commit with the missing authorship information is not the most recent one you have two options:
      1. You can re-create all commits missing authorship information. This is going to be the easiest solution for developers that aren't extremely confident in their Git and command line skills.
      2. You can use this script that GitHub provides to rewrite history. Please note: this should be used only if you are very confident in your abilities and understand its impacts.
    • Whichever method you choose, I will come by to re-check the pull request once you push the fixes to this branch.

We apologize for this inconvenience, especially since it usually bites new contributors to Home Assistant. We hope you understand the need for us to protect ourselves and the great community we all have built legally. The best thing to come out of this is that you only need to fix this once and it benefits the entire Home Assistant and GitHub community.

Thanks, I look forward to checking this PR again soon! ❤️

@home-assistant
home-assistant Bot marked this pull request as draft July 17, 2026 01:17
@home-assistant

Copy link
Copy Markdown

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an iOS-only, opt-in camera-based motion pipeline that can (a) publish a binary_sensor motion entity, (b) wake/hide the kiosk screensaver on motion, and (c) expose the front camera as a LAN-accessible MJPEG stream via an embedded HTTP server.

Changes:

  • Introduces MotionDetectionManager and hooks it into kiosk mode (wake on motion) and new sensor providers.
  • Adds CameraStreamServer (NWListener-based) plus a new “Camera Stream” sensor to control/report streaming.
  • Extends kiosk screensaver settings + localization to support “Wake on camera motion”.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
Sources/Shared/Resources/Swiftgen/Strings.swift Adds SwiftGen string accessors for new motion/stream settings and kiosk toggle text.
Sources/Shared/Environment/MotionDetectionManager.swift New camera frame-differencing motion detector and shared capture output for streaming.
Sources/Shared/Environment/KioskModeManager.swift Observes motion while screensaver is visible to dismiss screensaver on motion.
Sources/Shared/Environment/Environment.swift Registers new sensor providers and adds environment singletons for motion + stream server.
Sources/Shared/Environment/CameraStreamServer.swift New embedded MJPEG-over-HTTP stream server driven by sensor enablement.
Sources/Shared/API/Webhook/WebhookSensorId.swift Adds motion and camera_stream sensor IDs.
Sources/Shared/API/Webhook/Sensors/MotionSensor.swift New binary_sensor provider that reports camera motion + exposes tuning settings.
Sources/Shared/API/Webhook/Sensors/CameraStreamSensor.swift New sensor provider that starts/stops MJPEG server and reports stream status/attributes.
Sources/HAModels/Sources/KioskSettings.swift Persists the new wakeOnCameraMotion screensaver setting with tolerant decode.
Sources/App/Settings/Kiosk/KioskScreensaverSettingsView.swift Adds UI toggle + footer text for “Wake on camera motion”.
Sources/App/Resources/en.lproj/Localizable.strings Adds English strings for the new toggle and sensor setting titles.

Comment thread Sources/Shared/Environment/CameraStreamServer.swift
Comment thread Sources/Shared/Environment/CameraStreamServer.swift
Comment thread Sources/Shared/Environment/CameraStreamServer.swift
Comment thread Sources/Shared/Environment/CameraStreamServer.swift
Comment thread Sources/Shared/API/Webhook/WebhookSensorId.swift Outdated
Comment thread Sources/Shared/Environment/MotionDetectionManager.swift
Comment thread Sources/Shared/Environment/MotionDetectionManager.swift Outdated
Comment thread Sources/Shared/Environment/MotionDetectionManager.swift Outdated
@bemble
bemble force-pushed the feat/kiosk-camera-motion-and-mjpeg-stream branch from f93feb6 to 12b79c0 Compare July 17, 2026 08:46
@bemble
bemble marked this pull request as ready for review July 17, 2026 08:51
@home-assistant
home-assistant Bot dismissed their stale review July 17, 2026 08:51

Stale

@bgoncal bgoncal removed the cla-error label Jul 17, 2026
@bgoncal

bgoncal commented Jul 17, 2026

Copy link
Copy Markdown
Member

pending finalize basic Auth for camera stream, I'll keep working on it on the next days

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants