Skip to content

feat: allow HASS to close its own page via POST /close-hass and make Chromium fullscreen - #22

Merged
gmglbn-0 merged 4 commits into
mainfrom
close-hass
Apr 26, 2026
Merged

feat: allow HASS to close its own page via POST /close-hass and make Chromium fullscreen#22
gmglbn-0 merged 4 commits into
mainfrom
close-hass

Conversation

@gmglbn-0

Copy link
Copy Markdown
Member

closes #11

  • Add HTTP listener on configurable port (default 8321) accepting POST /close-hass
  • Add public Slint function close-hass-remote() for Rust to trigger page navigation
  • Replace --window-size with --start-fullscreen for Chromium
  • Update HA page UI to show 'Home Assistant Opened!' status with troubleshooting hints
  • Add hass_api_port to Config
  • Add python3 to shell.nix for skia-bindings build

…Chromium fullscreen

- Add HTTP listener on configurable port (default 8321) accepting POST /close-hass
- Add public Slint function close-hass-remote() for Rust to trigger page navigation
- Replace --window-size with --start-fullscreen for Chromium
- Update HA page UI to show 'Home Assistant Opened!' status with troubleshooting hints
- Add hass_api_port to Config
- Add python3 to shell.nix for skia-bindings build

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

This PR adds a small remote-control mechanism so the Home Assistant (HASS) page can dismiss itself (addressing the “kiosk escape” issue) and adjusts the kiosk UX by running Chromium fullscreen and updating the on-screen HASS status panel.

Changes:

  • Add a TCP-based HTTP listener that accepts POST /close-hass and triggers UI navigation back to the main page.
  • Add a public Slint function (close-hass-remote()) that Rust can invoke to close the HASS page.
  • Switch Chromium launch flags to fullscreen and update the HASS status/troubleshooting UI.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
ui/pages/home_assistant.slint Updates HASS page UI to a status/troubleshooting panel behind fullscreen Chromium.
ui/main_window.slint Adds a public Slint function callable from Rust to close HASS and navigate home.
src/main.rs Wires the close-listener signal into the Slint UI (currently via polling timer).
src/home_assistant.rs Switches Chromium to fullscreen; introduces the POST /close-hass listener implementation.
src/config.rs Adds hass_api_port config with a default value.
shell.nix Adds python3 to dev shell inputs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main.rs Outdated
Comment thread src/home_assistant.rs
Comment on lines +117 to +126
pub fn start_close_listener(port: u16, tx: Sender<()>) {
let addr = format!("0.0.0.0:{}", port);
let listener = match TcpListener::bind(&addr) {
Ok(l) => l,
Err(e) => {
error!("Failed to bind HASS close listener on {}: {}", addr, e);
return;
}
};
info!("🏠 Home Assistant close listener on port {}", port);

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

The close listener binds to 0.0.0.0, exposing POST /close-hass on all interfaces with no authentication. This allows any host that can reach the device to remotely navigate the kiosk UI. If Home Assistant is the only intended caller, bind to 127.0.0.1/localhost by default and/or require a shared secret (header/token) before accepting the request.

Copilot uses AI. Check for mistakes.
Comment thread src/home_assistant.rs
Comment on lines +138 to +145

if first_line.starts_with("POST /close-hass") {
info!("🏠 Received remote close-hass request");
let _ = tx.send(());
let _ = stream.write_all(
b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: 2\r\n\r\nOK",
);
} else if first_line.starts_with("OPTIONS") {

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

Request routing is currently based on first_line.starts_with("POST /close-hass"), which will also match unintended paths like /close-hass-foo and doesn’t validate the HTTP method/path tokens. Parse the first line into METHOD path VERSION and require an exact POST + /close-hass match (and similarly scope OPTIONS handling to the same path).

Suggested change
if first_line.starts_with("POST /close-hass") {
info!("🏠 Received remote close-hass request");
let _ = tx.send(());
let _ = stream.write_all(
b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: 2\r\n\r\nOK",
);
} else if first_line.starts_with("OPTIONS") {
let mut parts = first_line.split_whitespace();
let request_line = match (parts.next(), parts.next(), parts.next(), parts.next()) {
(Some(method), Some(path), Some(version), None) => Some((method, path, version)),
_ => None,
};
if let Some(("POST", "/close-hass", _version)) = request_line {
info!("🏠 Received remote close-hass request");
let _ = tx.send(());
let _ = stream.write_all(
b"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nContent-Length: 2\r\n\r\nOK",
);
} else if let Some(("OPTIONS", "/close-hass", _version)) = request_line {

Copilot uses AI. Check for mistakes.
Comment thread src/home_assistant.rs
Comment on lines +128 to +135
for stream in listener.incoming() {
let Ok(mut stream) = stream else {
continue;
};
let mut buf = [0u8; 512];
let Ok(n) = stream.read(&mut buf) else {
continue;
};

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

The listener processes connections sequentially and does a blocking stream.read(...) without a timeout. A client that connects and never sends data can stall the entire listener (preventing legitimate close requests). Consider setting a short read timeout and/or handling each connection in a separate thread/task so one slow client can’t block the service.

Copilot uses AI. Check for mistakes.
Text {
text: "if hass did not started,\nconfigure the iframe URL in .config/dramma.toml\nor install chromium huh";
font-size: 12px;
text: "• Make sure chromium is installed\n• Check .config/dramma.toml has the correct home_assistant_url\n• You can close this page with POST /close-hass";

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

The troubleshooting text says the page can be closed with POST /close-hass, but the listener is on a configurable port (hass_api_port, default 8321). Consider including the full endpoint (e.g., POST http://localhost:<port>/close-hass) or at least mention the port/config key so the hint is actionable when debugging.

Suggested change
text: "• Make sure chromium is installed\n• Check .config/dramma.toml has the correct home_assistant_url\n• You can close this page with POST /close-hass";
text: "• Make sure chromium is installed\n• Check .config/dramma.toml has the correct home_assistant_url\n• You can close this page with POST http://localhost:<hass_api_port>/close-hass (default port 8321; configurable via hass_api_port)";

Copilot uses AI. Check for mistakes.
@eupn eupn mentioned this pull request Apr 21, 2026
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gmglbn-0
gmglbn-0 merged commit bd90dee into main Apr 26, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Kiosk escape using the HASS button

3 participants