헤드리스 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 본문 서명 무영향
150 lines
6 KiB
Bash
150 lines
6 KiB
Bash
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# Temp/humidity (SHT30) module v2 (Raspberry Pi 4 Model B) install script — module 2
|
|
# 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; stop with a clear error (air-gapped rule). Pre-
|
|
# download is done on the build machine via vendor.sh.
|
|
# - Can be forced via the OFFLINE=1/0 environment variable.
|
|
# - Log file owner: SERVICE_USER (default pi).
|
|
#
|
|
# This script also enables I2C (dtparam=i2c_arm=on + i2c-dev load + i2c group).
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
SERVICE_USER="${SERVICE_USER:-pi}"
|
|
|
|
echo "=========================================="
|
|
echo " Temp/humidity (SHT30) module v2 (Pi 4) install — module 2"
|
|
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 for Raspberry Pi 4 Model B only (you may continue anyway)." ;;
|
|
esac
|
|
fi
|
|
|
|
# Offline mode detection
|
|
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: requests + venv + i2c-tools
|
|
echo "[1/4] 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 " Offline .deb install (apt-get --no-download — dependency ordering/resolution automatic, no network)"
|
|
# --no-install-recommends: vendor.sh does not bundle 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
|
|
sudo apt-get install -y python3-requests python3-venv i2c-tools
|
|
fi
|
|
|
|
# 2) Enable I2C (dtparam + module load + group)
|
|
echo "[2/4] Enabling I2C..."
|
|
# Boot config path: Bookworm=/boot/firmware/config.txt, older=/boot/config.txt
|
|
BOOT_CFG=""
|
|
for c in /boot/firmware/config.txt /boot/config.txt; do
|
|
if [ -f "$c" ]; then BOOT_CFG="$c"; break; fi
|
|
done
|
|
if [ -n "${BOOT_CFG}" ]; then
|
|
if ! grep -q "^dtparam=i2c_arm=on" "${BOOT_CFG}"; then
|
|
echo " Adding dtparam=i2c_arm=on to ${BOOT_CFG} (applied after reboot)"
|
|
echo "dtparam=i2c_arm=on" | sudo tee -a "${BOOT_CFG}" >/dev/null
|
|
NEED_REBOOT=1
|
|
else
|
|
echo " dtparam=i2c_arm=on already set"
|
|
fi
|
|
else
|
|
echo "[WARN] config.txt not found — enable I2C manually via raspi-config"
|
|
fi
|
|
# Load the i2c-dev module immediately + register it for auto-load at boot
|
|
sudo modprobe i2c-dev 2>/dev/null || echo "[WARN] i2c-dev immediate load failed (may apply after reboot)"
|
|
if [ -d /etc/modules-load.d ] && ! grep -qrs "i2c-dev" /etc/modules-load.d/ 2>/dev/null; then
|
|
echo "i2c-dev" | sudo tee /etc/modules-load.d/i2c.conf >/dev/null
|
|
fi
|
|
# Add the service user to the i2c group (/dev/i2c-1 access permission)
|
|
if getent group i2c >/dev/null 2>&1; then
|
|
sudo usermod -aG i2c "${SERVICE_USER}" || echo "[WARN] usermod failed — check SERVICE_USER=${SERVICE_USER}"
|
|
fi
|
|
|
|
# 3) Python venv + requests + smbus2
|
|
echo "[3/4] 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 " Offline wheel install (--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 " Packages installed"
|
|
|
|
# 4) Log file (least privilege: owner-only write)
|
|
echo "[4/4] Creating log file..."
|
|
sudo mkdir -p /var/log
|
|
sudo touch /var/log/sht30_sensor.log
|
|
if ! sudo chown "${SERVICE_USER}:${SERVICE_USER}" /var/log/sht30_sensor.log; then
|
|
echo "[WARN] chown failed — check whether SERVICE_USER=${SERVICE_USER} exists"
|
|
fi
|
|
sudo chmod 640 /var/log/sht30_sensor.log
|
|
|
|
# Lock config_local.py immediately (contains API_KEY — prevent world-readable until harden)
|
|
# Hardening (harden_pi.sh) tightens it again later, but to avoid exposure even in
|
|
# that window, lock it to 600 right at install time. 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 set to permission 600 (owner ${SERVICE_USER})"
|
|
fi
|
|
|
|
# config_local notice (fail closed — if missing, execution stops immediately)
|
|
if [ ! -f config_local.py ]; then
|
|
echo ""
|
|
echo "[!] config_local.py is missing. Run the following, then fill in real values:"
|
|
echo " cp config_local.example.py config_local.py"
|
|
fi
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo " Install complete! (OFFLINE=${OFFLINE})"
|
|
echo "=========================================="
|
|
if [ "${NEED_REBOOT:-0}" = "1" ]; then
|
|
echo " ⚠️ I2C was just enabled → the sensor is recognized after 'sudo reboot'."
|
|
fi
|
|
echo " Sensor check: i2cdetect -y 1 (should show 0x44 or 0x45)"
|
|
echo " Run: source venv/bin/activate && python3 sht30_sensor.py"
|
|
echo " Service: see the systemd section in README.md"
|
|
echo ""
|