Skip to content

Kiosk mode: camera motion detection for screen wake#4497

Draft
nstefanelli wants to merge 17 commits into
home-assistant:mainfrom
nstefanelli:kiosk-pr2-camera-detection
Draft

Kiosk mode: camera motion detection for screen wake#4497
nstefanelli wants to merge 17 commits into
home-assistant:mainfrom
nstefanelli:kiosk-pr2-camera-detection

Conversation

@nstefanelli
Copy link
Copy Markdown
Contributor

Summary

Adds camera-based motion and presence detection to kiosk mode (PR2 of kiosk series, per discussion #2403).

  • Motion detection: CoreImage pixel-diff at 5 fps with configurable sensitivity (low/medium/high)
  • Presence detection: Vision framework person/face detection with hysteresis (2-frame confirm, 10s absence timeout)
  • Screen wake: Configurable wake-on-motion and wake-on-presence triggers
  • Settings UI: New "Camera Detection" section with toggles, sensitivity picker
  • macCatalyst: Camera detection excluded on Mac

Builds on #4422 (PR1: core kiosk infrastructure).

Architecture

KioskCameraDetectionManager (coordinator)
├── KioskCameraMotionDetector (CoreImage pixel-diff, 5 fps, .low preset)
└── KioskPresenceDetector (Vision person/face detection, 3-10 fps, .medium preset)
         │
         ▼
KioskModeManager.wakeScreen(source:)
  • Frame processing runs on dedicated serial queues, not the main thread
  • State updates dispatched to MainActor via Combine publishers
  • Presence activity timer keeps screen awake while person is present

New files

File Lines Purpose
Camera/KioskCameraDetectionManager.swift ~200 Coordinator singleton
Camera/KioskCameraMotionDetector.swift ~250 CoreImage motion detection
Camera/KioskPresenceDetector.swift ~300 Vision presence/face detection
KioskCameraDetection.test.swift ~115 MotionSensitivity + settings tests

Test plan

  • MotionSensitivity enum: threshold values, Codable roundtrip, ordering
  • Camera settings: defaults, roundtrip, backwards compatibility with pre-camera JSON
  • Enable motion detection → wave hand → screen wakes from screensaver
  • Enable presence detection → walk up → screen wakes; walk away → screensaver resumes
  • Deny camera permission → detection doesn't start, no crash
  • Both detectors simultaneously → no conflict
  • macCatalyst build → camera section not visible

Related

Adds 11 kiosk.camera.* keys covering motion detection, presence detection,
face detection, sensitivity (low/medium/high), wake triggers, and footer copy.
Regenerates SwiftGen output with updated Strings.swift accessors under
L10n.Kiosk.Camera and L10n.Kiosk.Camera.Sensitivity.
…ings

Adds MotionSensitivity enum (low/medium/high with threshold values) and 6
camera detection properties to KioskSettings: cameraMotionEnabled,
cameraMotionSensitivity, wakeOnCameraMotion, cameraPresenceEnabled,
cameraFaceDetectionEnabled, wakeOnCameraPresence. Replaces synthesized
Codable with a custom init(from:) for backwards-compatible decoding so
existing persisted settings without camera fields decode without error.
- Make processFrame/calculateDifference nonisolated in motion detector
  so CIFilter and CIContext.render run on processingQueue, not MainActor
- Make processFrame nonisolated in presence detector so Vision requests
  run on processingQueue; settings read on MainActor then dispatched
- Mark previousFrame, ciContext, and Vision requests as nonisolated(unsafe)
  since they are only accessed from their respective processing queues
- Remove @published from errorMessage (internal debugging state, not UI)
- Replace PR-specific comments in tests with neutral wording
Custom init(from:) suppresses the synthesized default initializer.
Add explicit public init() so KioskSettings() continues to work.
Copilot AI review requested due to automatic review settings April 10, 2026 03:33
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@7ac3faf). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4497   +/-   ##
=======================================
  Coverage        ?   43.28%           
=======================================
  Files           ?      275           
  Lines           ?    16694           
  Branches        ?        0           
=======================================
  Hits            ?     7226           
  Misses          ?     9468           
  Partials        ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Apr 13, 2026

Sorry the delay to pickup this review, I will still need a bit more time since I am working on something else right now, meanwhile I noticed that after releasing the foundation for kiosk mode, lots of questions about how it works and comparisons to the famous "Fully Kiosk browser" popped up in the community, so it would be nice if we created a documentation page for this in out companion app docs, could you propose it?

Reference: https://companion.home-assistant.io/docs/getting_started/

We need to make it clear things like... in iOS we cannot lock the user in a single app (from Home Assistant) and that the closest way possible to that is if the user uses iOS "guided access". So it needs to explain the difference of the "lock" that we mention inside Home Assistant app and the "lock" that the user may be expecting.

@bgoncal bgoncal requested review from Copilot and removed request for Copilot April 13, 2026 19:14
@Macstar1601
Copy link
Copy Markdown

Sorry the delay to pickup this review, I will still need a bit more time since I am working on something else right now, meanwhile I noticed that after releasing the foundation for kiosk mode, lots of questions about how it works and comparisons to the famous "Fully Kiosk browser" popped up in the community, so it would be nice if we created a documentation page for this in out companion app docs, could you propose it?

Reference: https://companion.home-assistant.io/docs/getting_started/

We need to make it clear things like... in iOS we cannot lock the user in a single app (from Home Assistant) and that the closest way possible to that is if the user uses iOS "guided access". So it needs to explain the difference of the "lock" that we mention inside Home Assistant app and the "lock" that the user may be expecting.

The Kiosk Mode feature is really great. But for me, it’s not important to be locked into Kiosk Mode. It’s much more important that the Dashboard can be accessed more quickly and that you don’t have to unlock the iPad first. A true lock within an app also leads to other problems, such as not being able to use other apps at the same time, e.g., intercom apps. I opened an issue about this today: #4506

Comment thread Sources/App/Kiosk/Camera/KioskCameraDetectionManager.swift Outdated
@home-assistant home-assistant Bot marked this pull request as draft April 13, 2026 19:16
@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.

@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Apr 13, 2026

@Macstar1601 thanks for sharing, we dont need to worry about that because the app is not able to lock itself as the only app, iOS doesn't allow that, the maximum we can do is to prevent the screen to turn off.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds camera-based motion and presence detection to kiosk mode, wiring new detection settings into the kiosk settings model/UI and integrating camera-driven screen wake triggers into KioskModeManager.

Changes:

  • Introduces camera motion (CoreImage pixel-diff) and presence/face detection (Vision) components plus a coordinator manager.
  • Extends KioskSettings + settings UI with a new “Camera Detection” section and persistence/backwards-compat decoding.
  • Regenerates SwiftGen string accessors to include explicit fallback values for Frontend/Core strings, and adds SwiftUI helpers to SwiftGen assets.

Reviewed changes

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

Show a summary per file
File Description
Tests/App/Kiosk/KioskCameraDetection.test.swift Adds Swift Testing coverage for MotionSensitivity and camera-related KioskSettings fields (defaults/roundtrip/back-compat).
Sources/Shared/Resources/Swiftgen/FrontendStrings.swift SwiftGen output updated to provide fallback strings for Frontend keys; tr implementation changed accordingly.
Sources/Shared/Resources/Swiftgen/CoreStrings.swift SwiftGen output updated to provide fallback strings for Core keys; tr implementation changed accordingly.
Sources/Shared/Assets/Assets.swift Adds SwiftUI Image convenience initializers and a swiftUIImage accessor for ImageAsset.
Sources/App/Resources/en.lproj/Localizable.strings Adds new kiosk camera detection strings (section labels, sensitivity labels, footer).
Sources/App/Kiosk/Settings/KioskSettingsView.swift Adds a camera detection settings section (excluded on macCatalyst).
Sources/App/Kiosk/KioskSettings.swift Adds camera detection settings fields, MotionSensitivity, and backwards-compatible decoding.
Sources/App/Kiosk/KioskModeManager.swift Starts/stops camera detection with kiosk mode and restarts detection on relevant settings changes.
Sources/App/Kiosk/Camera/KioskPresenceDetector.swift New Vision-based presence + face detection implementation.
Sources/App/Kiosk/Camera/KioskCameraMotionDetector.swift New CoreImage motion detection implementation.
Sources/App/Kiosk/Camera/KioskCameraDetectionManager.swift New coordinator that binds detectors and exposes callbacks + state.
HomeAssistant.xcodeproj/project.pbxproj Adds new kiosk camera source files and test file to the project.

Comment thread Sources/Shared/Resources/Swiftgen/FrontendStrings.swift Outdated
Comment thread Sources/Shared/Resources/Swiftgen/CoreStrings.swift Outdated
Comment thread Sources/App/Kiosk/Settings/KioskSettingsView.swift Outdated
Comment thread Sources/App/Kiosk/Camera/KioskCameraDetectionManager.swift
Comment thread Sources/App/Kiosk/Camera/KioskCameraMotionDetector.swift Outdated
Comment thread Sources/App/Kiosk/Camera/KioskPresenceDetector.swift Outdated
Comment thread Sources/App/Kiosk/KioskModeManager.swift Outdated
Comment thread Sources/App/Kiosk/KioskSettings.swift Outdated
Per bgoncal review on home-assistant#4497, ship motion detection first and
defer presence/face detection to a follow-up PR for simpler
review scope. Drops KioskPresenceDetector and the presence/face
settings, UI toggles, manager wiring, and L10n keys.
Earlier SwiftGen run added a 'fallback:' arg to tr() calls that
LocalizedManager doesn't accept (won't compile), reordered
unrelated Strings entries, and added unused SwiftUI Image
helpers to Assets.swift. Re-run with the project's existing
template so the diff vs main is just the new kiosk.camera keys.
- KioskCameraDetectionManager.isActive now mirrors the underlying
  motion detector instead of being set from settings, so denied
  camera permission no longer leaves the manager stuck active.
- Move previousFrame=nil into the processingQueue.async block to
  match its 'processingQueue-only' invariant.
- Drop wakeOnCameraMotion from the settings-restart comparison;
  the closure already reads it at fire time, no need to recreate
  the capture session when only the wake flag toggles.
- Toggling cameraMotionEnabled now requests camera permission and
  surfaces a denial alert that deep-links to iOS Settings, so the
  motion detector actually has something to start with.
@nstefanelli
Copy link
Copy Markdown
Contributor Author

Stripped face/presence so this PR is motion-only. The inline items are addressed in the latest commits. Companion-app docs proposal coming in a separate issue.

@nstefanelli nstefanelli marked this pull request as ready for review April 26, 2026 04:12
@home-assistant home-assistant Bot requested a review from bgoncal April 26, 2026 04:12
@nstefanelli nstefanelli changed the title Kiosk mode: camera motion/presence detection for screen wake Kiosk mode: camera motion detection for screen wake Apr 26, 2026
@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented Apr 28, 2026

Thanks for that, let me know whenever you have the docs PR so we can review that first before adding more features

Copy link
Copy Markdown
Member

@bgoncal bgoncal left a comment

Choose a reason for hiding this comment

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

Let's keep it in draft while we don't have the docs

@home-assistant home-assistant Bot marked this pull request as draft April 28, 2026 11:29
@bgoncal
Copy link
Copy Markdown
Member

bgoncal commented May 4, 2026

@nstefanelli Do you need some help with the docs? Or if you have created already and I missed it please tag me and I'll review asap

@nstefanelli
Copy link
Copy Markdown
Contributor Author

Thanks @bgoncal — opened the docs PR over at home-assistant/companion.home-assistant#1323. It covers kiosk mode end-to-end (PR1 + this PR), flagged as BETA, with screenshot placeholders left in for you to flag whichever captures you want included. Happy to mark this PR ready for review whenever the docs side looks good to you, or earlier if that's easier on your end.

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.

4 participants