mirror of
https://github.com/karl0ss/AnotterKiosk.git
synced 2025-06-18 16:49:12 +01:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
968a171c6f | |||
3581873b41 | |||
5934a79525 | |||
28d7d22cd5 | |||
81385f2f0e | |||
cdd2bc2d02 | |||
8f4762a32d | |||
17913a5da3 | |||
dee5a36fda |
36
.github/workflows/main.yml
vendored
36
.github/workflows/main.yml
vendored
@ -1,43 +1,14 @@
|
|||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
create: { }
|
push:
|
||||||
pull_request: { }
|
tags:
|
||||||
|
- '*' # Triggers on any tag push
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
x86:
|
|
||||||
runs-on: [ubuntu-latest]
|
|
||||||
|
|
||||||
outputs:
|
|
||||||
pkgfile: ${{ steps.pkgname.outputs.pkgfile }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out repo
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt update -qq
|
|
||||||
sudo apt install -yqq libguestfs-tools qemu-utils qemu-system-x86 ovmf qemu-block-extra qemu-user-static binfmt-support rsync sudo wget xz-utils pigz mount dosfstools libarchive-tools
|
|
||||||
|
|
||||||
- name: Build firmware
|
|
||||||
run: |
|
|
||||||
./build_x86.sh
|
|
||||||
|
|
||||||
- name: Release build artifacts
|
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
|
||||||
append_body: true
|
|
||||||
body_path: ./version-info
|
|
||||||
files: |
|
|
||||||
./anotterkiosk-*
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
raspberrypi:
|
raspberrypi:
|
||||||
runs-on: [self-hosted]
|
runs-on: [self-hosted]
|
||||||
|
|
||||||
@ -59,7 +30,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Release build artifacts
|
- name: Release build artifacts
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
with:
|
||||||
append_body: true
|
append_body: true
|
||||||
body_path: ./version-info
|
body_path: ./version-info
|
||||||
|
61
README.md
61
README.md
@ -1,13 +1,23 @@
|
|||||||
AnotterKiosk
|
N-AnotterKiosk (Not-AnotterKiosk)
|
||||||
=============================
|
=================================
|
||||||
|
|
||||||
|
### I have hacked this about alot from the main branch, mainly Raspberry Pi changes
|
||||||
|
|
||||||
|
- Removed x86 support
|
||||||
|
- Added scheduled screen on/off
|
||||||
|
- Added scheduled chrome page refresh
|
||||||
|
- Rpi3 Overclock settings
|
||||||
|
- Disabled KMS driver for HW screen rotation (screen rotated portrait by default)
|
||||||
|
|
||||||
### Overview
|
### Overview
|
||||||
|
|
||||||
Another kiosk browser OS? Yes, this one is a little bit opinionated :)
|
Another kiosk browser OS? Yes, this one is a little bit opinionated :)
|
||||||
|
|
||||||
The author ran several similar setups in production for years and has seen a lot of problems and strange failure modes.
|
The author ran several similar setups in production for years and has seen a lot of problems and strange failure modes.
|
||||||
This project aims to solve a lot of those (at least for the author), it might also be useful for others :)
|
This project aims to solve a lot of those (at least for the author), it might also be useful for others :)
|
||||||
|
|
||||||
#### Key features
|
#### Key features
|
||||||
|
|
||||||
- [Images built via CI](https://github.com/Manawyrm/AnotterKiosk/blob/main/.github/workflows/main.yml)
|
- [Images built via CI](https://github.com/Manawyrm/AnotterKiosk/blob/main/.github/workflows/main.yml)
|
||||||
- WiFi connection support
|
- WiFi connection support
|
||||||
- Raspberry Pi (Arm64) compatibility
|
- Raspberry Pi (Arm64) compatibility
|
||||||
@ -22,18 +32,22 @@ This project aims to solve a lot of those (at least for the author), it might al
|
|||||||
- SSH support
|
- SSH support
|
||||||
- VNC support
|
- VNC support
|
||||||
- SSH tunneling support (for remote-access without port-forwarding, etc.)
|
- SSH tunneling support (for remote-access without port-forwarding, etc.)
|
||||||
|
- Basic API for Rpi Actions
|
||||||
|
|
||||||
#### Planned features:
|
#### Planned features:
|
||||||
|
|
||||||
- Raspberry Pi PXE/network boot support
|
- Raspberry Pi PXE/network boot support
|
||||||
- Network connectivity watchdog (configurable ping, etc. timeout)
|
- Network connectivity watchdog (configurable ping, etc. timeout)
|
||||||
- Automatic reboot at specified time
|
- Automatic reboot at specified time
|
||||||
|
|
||||||
#### Security considerations:
|
#### Security considerations:
|
||||||
|
|
||||||
- Autossh does not check SSH host keys. This is okay-ish as long as the target server only allows tunneling, nothing else.
|
- Autossh does not check SSH host keys. This is okay-ish as long as the target server only allows tunneling, nothing else.
|
||||||
- nginx/PHP are allowed to use sudo/NOPASSWD (because it needs to query the VideoCore, manage service, etc.), more priviledge seperation would be nice
|
- nginx/PHP are allowed to use sudo/NOPASSWD (because it needs to query the VideoCore, manage service, etc.), more priviledge seperation would be nice
|
||||||
- due to the skeleton mechanism, the system has some ... creative permissions. some cleanup required.
|
- due to the skeleton mechanism, the system has some ... creative permissions. some cleanup required.
|
||||||
|
|
||||||
### How-To Use
|
### How-To Use
|
||||||
|
|
||||||
Like any other Raspberry Pi image: download the current .img file from the [Releases](https://github.com/Manawyrm/AnotterKiosk/releases) page and flash it to a storage device of your choice.
|
Like any other Raspberry Pi image: download the current .img file from the [Releases](https://github.com/Manawyrm/AnotterKiosk/releases) page and flash it to a storage device of your choice.
|
||||||
SD cards, USB flash drives, USB SSDs, SATA SSDs, NVMe SSDs are all good options.
|
SD cards, USB flash drives, USB SSDs, SATA SSDs, NVMe SSDs are all good options.
|
||||||
You can use a tool like the [Raspberry Pi Imager](https://www.raspberrypi.com/software/), [BalenaEtcher](https://etcher.balena.io/), [Win32DiskImager](https://sourceforge.net/projects/win32diskimager/) or plain "dd" on \*nix-like systems.
|
You can use a tool like the [Raspberry Pi Imager](https://www.raspberrypi.com/software/), [BalenaEtcher](https://etcher.balena.io/), [Win32DiskImager](https://sourceforge.net/projects/win32diskimager/) or plain "dd" on \*nix-like systems.
|
||||||
@ -46,15 +60,18 @@ Adding your own SSH keys can be done by creating a authorized_keys file.
|
|||||||
If you want to use the autossh tunneling features, copy an SSH private key as either "id_rsa" or "id_ed25519".
|
If you want to use the autossh tunneling features, copy an SSH private key as either "id_rsa" or "id_ed25519".
|
||||||
|
|
||||||
### HTTP watchdog functionality
|
### HTTP watchdog functionality
|
||||||
|
|
||||||
Browsers are complex, networks are unstable and software can be buggy.
|
Browsers are complex, networks are unstable and software can be buggy.
|
||||||
In order to get the highest reliability possible, self-hosted websites can be modified to include a heartbeat/watchdog functionality.
|
In order to get the highest reliability possible, self-hosted websites can be modified to include a heartbeat/watchdog functionality.
|
||||||
This works by requesting a certain http-endpoint from the website at some interval.
|
This works by requesting a certain http-endpoint from the website at some interval.
|
||||||
If your page is being reloaded often (like with a <meta refresh=-header), you can just load the heartbeat-URL as an image:
|
If your page is being reloaded often (like with a <meta refresh=-header), you can just load the heartbeat-URL as an image:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<img src="http://localhost/heartbeat.php" style="display: none;">
|
<img src="http://localhost/heartbeat.php" style="display: none;">
|
||||||
```
|
```
|
||||||
|
|
||||||
If your page stays on one page for a long time (or is just a single-page application), you might want to use AJAX requests to send a heartbeat:
|
If your page stays on one page for a long time (or is just a single-page application), you might want to use AJAX requests to send a heartbeat:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script>
|
<script>
|
||||||
const req = new XMLHttpRequest();
|
const req = new XMLHttpRequest();
|
||||||
@ -67,6 +84,46 @@ setInterval(function() {
|
|||||||
|
|
||||||
Whenever the heartbeat stops (for whatever reason), the device will first restart the X11 environment (browser, window manager, etc.) and later (if it hasn't recovered) the whole system by rebooting.
|
Whenever the heartbeat stops (for whatever reason), the device will first restart the X11 environment (browser, window manager, etc.) and later (if it hasn't recovered) the whole system by rebooting.
|
||||||
|
|
||||||
|
### API
|
||||||
|
|
||||||
|
Lightweight HTTP API for controlling and monitoring a Raspberry Pi-based kiosk system. It exposes several endpoints that allow you to query system status, control the display, refresh the screen, and reboot the device — all protected by an API key.
|
||||||
|
|
||||||
|
API key will be loaded from `/boot/kioskbrowser.ini`
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[api]
|
||||||
|
key = "My Key"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Endpoints
|
||||||
|
|
||||||
|
All requests must include a key query parameter matching the API key from the INI file.
|
||||||
|
|
||||||
|
`GET /script.php?action=status&key=YOUR_API_KEY`
|
||||||
|
Returns system status:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"temperature": "temp=48.0'C",
|
||||||
|
"voltage": "volt=1.2000V",
|
||||||
|
"throttled": "throttled=0x0",
|
||||||
|
"heartbeat": "2025-06-09 14:33:12"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`GET /script.php?action=screen_off&key=YOUR_API_KEY`
|
||||||
|
Turns off the screen.
|
||||||
|
|
||||||
|
`GET /script.php?action=screen_on&key=YOUR_API_KEY`
|
||||||
|
Turns on the screen.
|
||||||
|
|
||||||
|
`GET /script.php?action=screen_refresh&key=YOUR_API_KEY`
|
||||||
|
Starts the screen-refresh.service to refresh the screen.
|
||||||
|
|
||||||
|
`GET /script.php?action=reboot&key=YOUR_API_KEY`
|
||||||
|
Reboots the Raspberry Pi.
|
||||||
|
|
||||||
### Inspiration / Other Kiosk-OSes:
|
### Inspiration / Other Kiosk-OSes:
|
||||||
|
|
||||||
- https://github.com/jareware/chilipie-kiosk/
|
- https://github.com/jareware/chilipie-kiosk/
|
||||||
- https://github.com/guysoft/FullPageOS
|
- https://github.com/guysoft/FullPageOS
|
@ -7,10 +7,10 @@ SCRIPT_DIR="$(dirname "$(realpath "$0")")"
|
|||||||
BUILD_DIR="${SCRIPT_DIR}/work/root/"
|
BUILD_DIR="${SCRIPT_DIR}/work/root/"
|
||||||
|
|
||||||
# cleanup any previous build attempts
|
# cleanup any previous build attempts
|
||||||
umount -fl "${BUILD_DIR}" || true
|
sudo umount -fl "${BUILD_DIR}" || true
|
||||||
losetup -D /dev/loop0 || true
|
sudo losetup -D /dev/loop0 || true
|
||||||
rm -rf "${BUILD_DIR}" || true
|
sudo rm -rf "${BUILD_DIR}" || true
|
||||||
mkdir -p "${BUILD_DIR}"
|
sudo mkdir -p "${BUILD_DIR}"
|
||||||
|
|
||||||
# download a modern RaspiOS build
|
# download a modern RaspiOS build
|
||||||
if [ ! -f raspios.img.xz ]
|
if [ ! -f raspios.img.xz ]
|
||||||
@ -51,7 +51,7 @@ sed -i 's/vfat defaults/vfat ro,defaults/g' "${BUILD_DIR}/etc/fstab"
|
|||||||
sed -i 's/ext4 defaults/ext4 ro,defaults/g' "${BUILD_DIR}/etc/fstab"
|
sed -i 's/ext4 defaults/ext4 ro,defaults/g' "${BUILD_DIR}/etc/fstab"
|
||||||
|
|
||||||
# Include git repo version info
|
# Include git repo version info
|
||||||
echo -n "AnotterKiosk Raspberry Pi version: " > "${BUILD_DIR}/version-info"
|
echo -n "N-AnotterKiosk Raspberry Pi version: " > "${BUILD_DIR}/version-info"
|
||||||
git describe --abbrev=4 --dirty --always --tags >> "${BUILD_DIR}/version-info"
|
git describe --abbrev=4 --dirty --always --tags >> "${BUILD_DIR}/version-info"
|
||||||
|
|
||||||
# Mount system partitions (from the build host)
|
# Mount system partitions (from the build host)
|
||||||
@ -84,5 +84,5 @@ sudo umount "${BUILD_DIR}"
|
|||||||
sudo losetup -D /dev/loop0
|
sudo losetup -D /dev/loop0
|
||||||
|
|
||||||
tag=$(git describe --abbrev=4 --dirty --always --tags)
|
tag=$(git describe --abbrev=4 --dirty --always --tags)
|
||||||
mv raspikiosk.img anotterkiosk-${tag}-arm64-raspberrypi.img
|
mv raspikiosk.img n-anotterkiosk-${tag}-arm64-raspberrypi.img
|
||||||
pigz -4 anotterkiosk-${tag}-arm64-raspberrypi.img
|
pigz -4 n-anotterkiosk-${tag}-arm64-raspberrypi.img
|
@ -20,6 +20,10 @@ reboot_time = 04:00
|
|||||||
; configure chrome to refresh the page every x minutes
|
; configure chrome to refresh the page every x minutes
|
||||||
;refresh_screen_every_x_min=15
|
;refresh_screen_every_x_min=15
|
||||||
|
|
||||||
|
[api]
|
||||||
|
; apikey to be sent with commands to /api.php
|
||||||
|
key = "MyKey"
|
||||||
|
|
||||||
[wifi]
|
[wifi]
|
||||||
; If you need more complex WiFi settings (like WPA2-Enterprise, hidden SSIDs, etc.)
|
; If you need more complex WiFi settings (like WPA2-Enterprise, hidden SSIDs, etc.)
|
||||||
; create a file called wpa_supplicant.conf on this partition.
|
; create a file called wpa_supplicant.conf on this partition.
|
||||||
|
@ -80,8 +80,7 @@ systemctl enable nginx
|
|||||||
systemctl enable ssh
|
systemctl enable ssh
|
||||||
systemctl enable kiosk-sechedule-screen.service
|
systemctl enable kiosk-sechedule-screen.service
|
||||||
systemctl enable schedule-reboot.service
|
systemctl enable schedule-reboot.service
|
||||||
systemctl enable screen-refresh.service
|
systemctl enable setup-refresh-timer.service
|
||||||
systemctl enable setup-screen-refresh.service
|
|
||||||
|
|
||||||
|
|
||||||
# generate a version info/build info file
|
# generate a version info/build info file
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Refresh Screen
|
|
||||||
After=graphical.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
User=pi
|
|
||||||
Environment=DISPLAY=:0
|
|
||||||
Environment=XAUTHORITY=/home/pi/.Xauthority
|
|
||||||
ExecStart=/usr/bin/refresh-screen
|
|
@ -1,6 +1,16 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
INI_FILE="/boot/kioskbrowser.ini"
|
INI_FILE="/boot/kioskbrowser.ini"
|
||||||
|
|
||||||
|
remount_root() {
|
||||||
|
local mode=$1
|
||||||
|
echo "Remounting root filesystem as $mode..."
|
||||||
|
mount -o remount,"$mode" / || {
|
||||||
|
echo "Failed to remount root as $mode"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
REBOOT_ENABLED=$(awk -F '=' '/^\[reboot\]/ { in_reboot=1; next }
|
REBOOT_ENABLED=$(awk -F '=' '/^\[reboot\]/ { in_reboot=1; next }
|
||||||
in_reboot && /^\[/ { in_reboot=0 }
|
in_reboot && /^\[/ { in_reboot=0 }
|
||||||
in_reboot && $1 ~ /enabled/ { gsub(/ /, "", $2); print $2 }' "$INI_FILE")
|
in_reboot && $1 ~ /enabled/ { gsub(/ /, "", $2); print $2 }' "$INI_FILE")
|
||||||
@ -12,6 +22,8 @@ REBOOT_TIME=$(awk -F '=' '/^\[reboot\]/ { in_reboot=1; next }
|
|||||||
if [[ "$REBOOT_ENABLED" -eq 1 ]] && [[ "$REBOOT_TIME" =~ ^[0-2][0-9]:[0-5][0-9]$ ]]; then
|
if [[ "$REBOOT_ENABLED" -eq 1 ]] && [[ "$REBOOT_TIME" =~ ^[0-2][0-9]:[0-5][0-9]$ ]]; then
|
||||||
echo "Scheduling reboot for $REBOOT_TIME..."
|
echo "Scheduling reboot for $REBOOT_TIME..."
|
||||||
|
|
||||||
|
remount_root rw
|
||||||
|
|
||||||
TARGET_TIME=$(date -d "$REBOOT_TIME" +%s)
|
TARGET_TIME=$(date -d "$REBOOT_TIME" +%s)
|
||||||
NOW=$(date +%s)
|
NOW=$(date +%s)
|
||||||
|
|
||||||
@ -34,7 +46,6 @@ Persistent=false
|
|||||||
WantedBy=timers.target
|
WantedBy=timers.target
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Create the associated service
|
|
||||||
cat <<EOF > /etc/systemd/system/reboot-at.service
|
cat <<EOF > /etc/systemd/system/reboot-at.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Scheduled Reboot
|
Description=Scheduled Reboot
|
||||||
@ -46,6 +57,8 @@ EOF
|
|||||||
|
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable --now reboot-at.timer
|
systemctl enable --now reboot-at.timer
|
||||||
|
|
||||||
|
remount_root ro
|
||||||
else
|
else
|
||||||
echo "Reboot not scheduled (disabled or invalid time)"
|
echo "Reboot not scheduled (disabled or invalid time)"
|
||||||
fi
|
fi
|
||||||
|
@ -3,6 +3,18 @@
|
|||||||
INI_FILE="/boot/kioskbrowser.ini"
|
INI_FILE="/boot/kioskbrowser.ini"
|
||||||
SYSTEMD_DIR="/etc/systemd/system"
|
SYSTEMD_DIR="/etc/systemd/system"
|
||||||
|
|
||||||
|
|
||||||
|
# Function to safely remount root FS
|
||||||
|
remount_root() {
|
||||||
|
local mode=$1
|
||||||
|
echo "Remounting root filesystem as $mode..."
|
||||||
|
mount -o remount,"$mode" / || {
|
||||||
|
echo "Failed to remount root as $mode"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
get_ini_value() {
|
get_ini_value() {
|
||||||
local section=$1 key=$2
|
local section=$1 key=$2
|
||||||
awk -F '=' -v sec="$section" -v k="$key" '
|
awk -F '=' -v sec="$section" -v k="$key" '
|
||||||
@ -17,6 +29,17 @@ get_ini_value() {
|
|||||||
create_recurring_timer() {
|
create_recurring_timer() {
|
||||||
local action=$1
|
local action=$1
|
||||||
local time=$2
|
local time=$2
|
||||||
|
local value
|
||||||
|
|
||||||
|
if [[ "$action" == "on" ]]; then
|
||||||
|
value=1
|
||||||
|
elif [[ "$action" == "off" ]]; then
|
||||||
|
value=0
|
||||||
|
else
|
||||||
|
echo "Invalid action: $action"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
local name="screen-${action}"
|
local name="screen-${action}"
|
||||||
|
|
||||||
echo "Setting daily screen ${action} at ${time}"
|
echo "Setting daily screen ${action} at ${time}"
|
||||||
@ -39,9 +62,7 @@ Description=Turn screen ${action}
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
Environment=DISPLAY=:0
|
ExecStart=/usr/bin/vcgencmd display_power ${value}
|
||||||
ExecStart=/usr/bin/xset dpms force ${action}
|
|
||||||
Environment=XAUTHORITY=/home/pi/.Xauthority
|
|
||||||
User=pi
|
User=pi
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
@ -49,6 +70,7 @@ EOF
|
|||||||
systemctl enable --now "${name}.timer"
|
systemctl enable --now "${name}.timer"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cleanup_screen_timers() {
|
cleanup_screen_timers() {
|
||||||
for action in on off; do
|
for action in on off; do
|
||||||
systemctl disable --now screen-${action}.timer 2>/dev/null
|
systemctl disable --now screen-${action}.timer 2>/dev/null
|
||||||
@ -57,6 +79,8 @@ cleanup_screen_timers() {
|
|||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remount_root rw
|
||||||
|
|
||||||
# === MAIN ===
|
# === MAIN ===
|
||||||
SCREEN_ON=$(get_ini_value screen screen_on_time)
|
SCREEN_ON=$(get_ini_value screen screen_on_time)
|
||||||
SCREEN_OFF=$(get_ini_value screen screen_off_time)
|
SCREEN_OFF=$(get_ini_value screen screen_off_time)
|
||||||
@ -65,3 +89,5 @@ cleanup_screen_timers
|
|||||||
|
|
||||||
[[ "$SCREEN_ON" =~ ^[0-2][0-9]:[0-5][0-9]$ ]] && create_recurring_timer on "$SCREEN_ON"
|
[[ "$SCREEN_ON" =~ ^[0-2][0-9]:[0-5][0-9]$ ]] && create_recurring_timer on "$SCREEN_ON"
|
||||||
[[ "$SCREEN_OFF" =~ ^[0-2][0-9]:[0-5][0-9]$ ]] && create_recurring_timer off "$SCREEN_OFF"
|
[[ "$SCREEN_OFF" =~ ^[0-2][0-9]:[0-5][0-9]$ ]] && create_recurring_timer off "$SCREEN_OFF"
|
||||||
|
|
||||||
|
remount_root ro
|
||||||
|
@ -29,9 +29,13 @@ if [[ "$REFRESH_INTERVAL" =~ ^[0-9]+$ ]] && (( REFRESH_INTERVAL > 0 )); then
|
|||||||
cat <<EOF | tee "$SERVICE_UNIT" > /dev/null
|
cat <<EOF | tee "$SERVICE_UNIT" > /dev/null
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Refresh Screen
|
Description=Refresh Screen
|
||||||
|
After=graphical.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
User=pi
|
||||||
|
Environment=DISPLAY=:0
|
||||||
|
Environment=XAUTHORITY=/home/pi/.Xauthority
|
||||||
ExecStart=/usr/bin/refresh-screen
|
ExecStart=/usr/bin/refresh-screen
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
60
kiosk_skeleton/var/www/html/api.php
Normal file
60
kiosk_skeleton/var/www/html/api.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
// Load API key from INI file
|
||||||
|
$iniFile = '/boot/kioskbrowser.ini';
|
||||||
|
if (!file_exists($iniFile)) {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(["error" => "INI file not found"]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = parse_ini_file($iniFile, true);
|
||||||
|
$API_KEY = trim($config['api']['key'], "\"'"); // Remove any surrounding quotes
|
||||||
|
|
||||||
|
// API key check
|
||||||
|
if (!isset($_GET['key']) || $_GET['key'] !== $API_KEY) {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(["error" => "Forbidden"]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get action
|
||||||
|
$action = $_GET['action'] ?? '';
|
||||||
|
|
||||||
|
switch ($action) {
|
||||||
|
case 'status':
|
||||||
|
echo json_encode([
|
||||||
|
'temperature' => trim(shell_exec("sudo vcgencmd measure_temp")),
|
||||||
|
'voltage' => trim(shell_exec("sudo vcgencmd measure_volts")),
|
||||||
|
'throttled' => trim(shell_exec("sudo vcgencmd get_throttled")),
|
||||||
|
'heartbeat' => date("Y-m-d H:i:s", filemtime("/dev/shm/heartbeat")),
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'screen_off':
|
||||||
|
shell_exec("sudo vcgencmd display_power 0");
|
||||||
|
echo json_encode(["message" => "Screen turned off"]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'screen_on':
|
||||||
|
shell_exec("sudo vcgencmd display_power 1");
|
||||||
|
echo json_encode(["message" => "Screen turned on"]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'screen_refresh':
|
||||||
|
shell_exec("sudo systemctl start screen-refresh.service");
|
||||||
|
echo json_encode(["message" => "Screen refreshed"]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'reboot':
|
||||||
|
shell_exec("sudo reboot");
|
||||||
|
echo json_encode(["message" => "Rebooting"]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(["error" => "Invalid action"]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
?>
|
@ -1 +1 @@
|
|||||||
console=serial0,115200 console=tty1 root=PARTUUID=544c6228-02 rootfstype=ext4 rw rootwait logo.nologo consoleblank=0 loglevel=0 quiet
|
console=serial0,115200 console=tty1 root=PARTUUID=544c6228-02 rootfstype=ext4 ro rootwait logo.nologo consoleblank=0 loglevel=0 quiet
|
Loading…
x
Reference in New Issue
Block a user