헤드리스 Pi 콘솔/journalctl에서 한글이 깨져 보이는 문제로, Pi 번들(02/03/04)에 들어가는 모든 소스의 사람-대상 텍스트를 영어로 전환. 코드·식별자·설정키·경로·숫자·hex·서명 스킴·f-string 플레이스홀더는 불변. - raspberry_pi4/, raspberry_pi4_sht30/: 로그·주석·문서·센서명·위치 영어화 - tools/make_deploy_bundles.py: 생성 템플릿(config_local.py/setup.sh/SETUP.md/PI_META 위치) 영어화 - tools/harden_pi.sh, tools/set_network.sh: echo/주석 영어화 - WIRING.html: 영어화 + SHT30 전압 경고 정정 반영 - 서버 번들(01, php/)은 한글 유지(브라우저 대시보드, Pi에서 안 깨짐) - 전 파이썬/셸 문법검사 통과, JSON 본문 서명 무영향
118 lines
4.8 KiB
Bash
118 lines
4.8 KiB
Bash
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# Leak Detection Sensor v2 (Raspberry Pi 4 Model B) install script
|
|
# Target OS: Raspberry Pi OS Bookworm (64-bit, aarch64)
|
|
#
|
|
# Air-gapped support:
|
|
# - If debs/ or wheelhouse/ is present, automatically switch to "offline mode".
|
|
# - In offline mode, never access the network. If the bundle is only partial,
|
|
# do not silently fall back to online; abort with a clear error (air-gap rule:
|
|
# if the network is needed, always FLAG it). Pre-download is done on the build
|
|
# machine via vendor.sh.
|
|
# - Can be forced with the OFFLINE=1/0 environment variable.
|
|
# - Log file owner: SERVICE_USER (default pi).
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
SERVICE_USER="${SERVICE_USER:-pi}"
|
|
|
|
echo "=========================================="
|
|
echo " Leak Detection Sensor v2 (Pi 4) install"
|
|
echo "=========================================="
|
|
|
|
# 0) Board model notice (not enforced)
|
|
if [ -r /proc/device-tree/model ]; then
|
|
MODEL="$(tr -d '\0' < /proc/device-tree/model)"
|
|
echo "[INFO] Board: ${MODEL}"
|
|
case "${MODEL}" in
|
|
*"Raspberry Pi 4"*) : ;;
|
|
*) echo "[WARN] This folder is intended for the Raspberry Pi 4 Model B only (continuing is possible)." ;;
|
|
esac
|
|
fi
|
|
|
|
# Determine offline mode
|
|
OFFLINE="${OFFLINE:-}"
|
|
if [ -z "${OFFLINE}" ]; then
|
|
if compgen -G "debs/*.deb" >/dev/null || [ -d wheelhouse ]; then
|
|
OFFLINE=1
|
|
echo "[INFO] Offline bundle detected -> air-gapped offline install mode (no network)"
|
|
else
|
|
OFFLINE=0
|
|
echo "[INFO] No offline bundle -> online install mode (internet required)"
|
|
fi
|
|
fi
|
|
|
|
# 1) System packages: RPi.GPIO replacement (lgpio) + requests + venv + camera app
|
|
echo "[1/3] Installing system packages..."
|
|
if [ "${OFFLINE}" = "1" ]; then
|
|
if ! compgen -G "debs/*.deb" >/dev/null; then
|
|
echo "[ERROR] Offline mode but debs/ is empty. Place the vendor.sh output (debs/) in this folder and re-run." >&2
|
|
exit 1
|
|
fi
|
|
echo " Installing offline .deb (apt-get --no-download - automatic dependency ordering/resolution, no network)"
|
|
# --no-install-recommends: vendor.sh does not include Recommends (--no-recommends), so match that.
|
|
sudo apt-get install -y --no-install-recommends --no-download ./debs/*.deb
|
|
else
|
|
echo " Online apt install (internet required)"
|
|
sudo apt-get update
|
|
if apt-cache show rpicam-apps >/dev/null 2>&1; then CAM=rpicam-apps; else CAM=libcamera-apps; fi
|
|
sudo apt-get install -y python3-rpi-lgpio python3-requests python3-venv "${CAM}"
|
|
fi
|
|
|
|
# 2) Python venv + requests
|
|
echo "[2/3] Setting up Python virtual environment..."
|
|
if [ ! -d venv ]; then
|
|
python3 -m venv --system-site-packages venv
|
|
echo " venv created"
|
|
else
|
|
echo " venv already exists - skipping"
|
|
fi
|
|
# shellcheck disable=SC1091
|
|
source venv/bin/activate
|
|
if [ "${OFFLINE}" = "1" ]; then
|
|
if [ ! -d wheelhouse ]; then
|
|
echo "[ERROR] Offline mode but wheelhouse/ is missing. Place the vendor.sh output (wheelhouse/) and re-run." >&2
|
|
exit 1
|
|
fi
|
|
echo " Installing offline wheels (--no-index - no network)"
|
|
pip install --no-index --find-links=wheelhouse -r requirements.txt
|
|
else
|
|
echo " Online pip install (internet required)"
|
|
pip install --upgrade pip
|
|
pip install -r requirements.txt
|
|
fi
|
|
echo " Package installation complete"
|
|
|
|
# 3) Log file (least privilege: owner write only - leak_sensor is the sole writer)
|
|
echo "[3/3] Creating log file..."
|
|
sudo mkdir -p /var/log
|
|
sudo touch /var/log/leak_sensor.log
|
|
if ! sudo chown "${SERVICE_USER}:${SERVICE_USER}" /var/log/leak_sensor.log; then
|
|
echo "[WARN] chown failed - check whether SERVICE_USER=${SERVICE_USER} exists (must match the service user for file logging to work)"
|
|
fi
|
|
sudo chmod 640 /var/log/leak_sensor.log
|
|
|
|
# 3.5) Lock config_local.py immediately (contains API_KEY - prevent world-readable until harden)
|
|
# Hardening (harden_pi.sh) tightens this again later, but lock it to 600 right at install
|
|
# time so it is not exposed even in the window between. Protected regardless of harden.
|
|
if [ -f config_local.py ]; then
|
|
chmod 600 config_local.py
|
|
sudo chown "${SERVICE_USER}:${SERVICE_USER}" config_local.py 2>/dev/null || true
|
|
echo " config_local.py permissions set to 600 (owner ${SERVICE_USER})"
|
|
fi
|
|
|
|
# 4) config_local notice (fail closed - if missing, execution aborts immediately)
|
|
if [ ! -f config_local.py ]; then
|
|
echo ""
|
|
echo "[!] config_local.py is missing. Run the following, then fill in the real values:"
|
|
echo " cp config_local.example.py config_local.py"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo " Installation complete! (OFFLINE=${OFFLINE})"
|
|
echo "=========================================="
|
|
echo " Run: source venv/bin/activate && python3 leak_sensor.py"
|
|
echo " Service: see the systemd section in README.md"
|
|
echo ""
|