sl-webui e2587b60fb feat: SaltyFace web app UI for Chromium kiosk (Issue #370)
Animated robot expression interface as lightweight web application:

**Architecture:**
- HTML5 Canvas rendering engine
- Node.js HTTP server (localhost:3000)
- ROSLIB WebSocket bridge for ROS2 topics
- Fullscreen responsive design (1024×600)

**Features:**
- 8 emotional states (happy, alert, confused, sleeping, excited, emergency, listening, talking)
- Real-time ROS2 subscriptions:
  - /saltybot/state (emotion triggers)
  - /saltybot/battery (status display)
  - /saltybot/target_track (EXCITED emotion)
  - /saltybot/obstacles (ALERT emotion)
  - /social/speech/is_speaking (TALKING emotion)
  - /social/speech/is_listening (LISTENING emotion)
- Tap-to-toggle status overlay
- 60fps Canvas animation on Wayland
- ~80MB total memory (Node.js + browser)

**Files:**
- public/index.html — Main page (1024×600 fullscreen)
- public/salty-face.js — Canvas rendering + ROS2 integration
- server.js — Node.js HTTP server with CORS support
- systemd/salty-face-server.service — Auto-start systemd service
- docs/SALTY_FACE_WEB_APP.md — Complete setup & API documentation

**Integration:**
- Runs in Chromium kiosk (Issue #374)
- Depends on rosbridge_server for WebSocket bridge
- Serves on localhost:3000 (configurable)

**Next:** Issue #371 (Accessibility enhancements)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-03 16:42:41 -05:00

43 lines
818 B
Desktop File

[Unit]
Description=SaltyFace Web App Server (Node.js)
Documentation=https://github.com/saltytech/saltylab-firmware/issues/370
After=network.target
Before=chromium-kiosk.service
Requires=chromium-kiosk.service
[Service]
Type=simple
User=orin
Group=nogroup
WorkingDirectory=/opt/saltybot/app
# Node.js server
ExecStart=/usr/bin/node server.js --port 3000 --host 0.0.0.0
# Environment
Environment="NODE_ENV=production"
Environment="NODE_OPTIONS=--max-old-space-size=256"
# Restart policy
Restart=on-failure
RestartSec=3s
# Resource limits
MemoryMax=256M
CPUQuota=50%
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=salty-face-server
# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/saltybot/logs
[Install]
WantedBy=multi-user.target