센서1·3(누수 노드)에 PMS7003 를 온습도와 동일 sensor_id 로 통합하고 metric_type='pms7003'
로 구분해 수집한다. LED 는 스위칭 없이 상시 점등 방식으로 확정.
- raspberry_pi4_pms7003/: PMS7003 노드 풀세트(드라이버·센서·install·systemd·vendor·배선·연결테스트·프레임 단위테스트)
- 서버: evaluate_metric_thresholds() 에 pm25/pm10 선택 인자 추가(온습도 전용 호출 후방호환),
sensor_data.php 수집 경로에 pms7003 metric 반영, config.php/예시에 PM 임계 추가
- SQL: migration_pms7003.sql · schema_sht30.sql 정합, tools/migration_leak_add_{pms7003,sht30} 마이그레이터
- tests/pm_threshold_test.php + run_tests.sh 러너 등록
- .gitignore: 노드별 config_local.py 커밋 차단
75 lines
3.8 KiB
Bash
75 lines
3.8 KiB
Bash
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# vendor.sh - Pre-download dependencies for air-gapped install (PMS7003 particulate-matter module)
|
|
# Run this on a build/staging machine that has internet access.
|
|
# Outputs: wheelhouse/ (pip wheel + sdist), debs/ (apt .deb) -> transfer to the target Pi 4.
|
|
#
|
|
# requests has few arch dependencies, and pyserial is pure Python (py3-none-any), so it works
|
|
# on the Pi 4 no matter which build machine downloads it. Pin wheels to the target
|
|
# (Bookworm 64-bit, aarch64, Python 3.11). The .deb files are safest downloaded on the target OS/arch.
|
|
# Env vars: TARGET_PLATFORM (default manylinux2014_aarch64), TARGET_PYVER (default 311)
|
|
# =============================================================================
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
TARGET_PLATFORM="${TARGET_PLATFORM:-manylinux2014_aarch64}"
|
|
TARGET_PYVER="${TARGET_PYVER:-311}"
|
|
TARGET_ABI="${TARGET_ABI:-cp${TARGET_PYVER}}"
|
|
|
|
echo "[vendor] (1/2) Python wheel -> wheelhouse/ (platform=${TARGET_PLATFORM}, py=${TARGET_PYVER})"
|
|
mkdir -p wheelhouse
|
|
# requests and other arch-dependent wheels: pin the explicit target platform.
|
|
python3 -m pip download -r requirements.txt -d wheelhouse \
|
|
--only-binary=:all: \
|
|
--platform "${TARGET_PLATFORM}" \
|
|
--python-version "${TARGET_PYVER}" \
|
|
--implementation cp \
|
|
--abi "${TARGET_ABI}" \
|
|
|| echo "[WARN] Target-platform pin failed for some wheels - pure-Python (any) fallback is downloaded below."
|
|
# pyserial (py3-none-any) and other pure-Python wheels plus sdist fallback.
|
|
python3 -m pip download -r requirements.txt -d wheelhouse \
|
|
|| echo "[WARN] Some sdist/any fallbacks failed (safe to ignore if all binary wheels are present)"
|
|
WHEEL_COUNT="$(ls -A wheelhouse 2>/dev/null | wc -l)"
|
|
echo " wheelhouse file count: ${WHEEL_COUNT}"
|
|
[ "${WHEEL_COUNT}" -gt 0 ] || { echo "[ERROR] wheelhouse is empty"; exit 1; }
|
|
|
|
echo "[vendor] (2/2) apt .deb -> debs/"
|
|
mkdir -p debs
|
|
# nftables and unattended-upgrades are included too -> harden_pi.sh can run offline in the air-gapped env.
|
|
BASE_PKGS="python3-requests python3-venv nftables unattended-upgrades"
|
|
DEPS="$(apt-cache depends --recurse --no-recommends --no-suggests \
|
|
--no-conflicts --no-breaks --no-replaces --no-enhances ${BASE_PKGS} \
|
|
| awk '/^\w/{print $1}' | sort -u)"
|
|
( cd debs && apt-get download ${BASE_PKGS} ${DEPS} ) 2>/dev/null \
|
|
|| echo "[WARN] Some .deb downloads failed (may be virtual/transitive deps - required packages are verified below)"
|
|
|
|
MISS=0
|
|
for p in ${BASE_PKGS}; do
|
|
if ! ls debs/"${p}"_*.deb >/dev/null 2>&1; then
|
|
echo "[ERROR] Required package .deb missing: ${p}"
|
|
MISS=1
|
|
fi
|
|
done
|
|
[ "${MISS}" = 0 ] || { echo "[ERROR] Required .deb missing - you must run vendor.sh on the target arch (aarch64 Bookworm)."; exit 1; }
|
|
echo " debs file count: $(ls debs/*.deb 2>/dev/null | wc -l) (all required packages verified)"
|
|
|
|
# Real architecture check - verify the target (arm64/all) via the .deb's internal Architecture field, not the filename.
|
|
# (If the host is amd64, apt-get download fetches amd64 .deb files, and dpkg on the target Pi
|
|
# breaks with "wrong architecture". A filename-only check can't catch this.)
|
|
BAD_ARCH=0
|
|
for deb in debs/*.deb; do
|
|
[ -e "$deb" ] || continue
|
|
arch="$(dpkg-deb --field "$deb" Architecture 2>/dev/null || echo '?')"
|
|
case "$arch" in
|
|
arm64|all) : ;;
|
|
*) echo "[ERROR] arch mismatch: $(basename "$deb") = ${arch} (not arm64/all)"; BAD_ARCH=1 ;;
|
|
esac
|
|
done
|
|
if [ "${BAD_ARCH}" != 0 ]; then
|
|
echo "[ERROR] There are .deb files that are not the target (aarch64/arm64). host arch=$(dpkg --print-architecture 2>/dev/null || echo unknown)." >&2
|
|
echo " You must run vendor.sh on an arm64 Pi (or an arm64 chroot/qemu)." >&2
|
|
exit 1
|
|
fi
|
|
echo " arch check passed (all .deb = arm64/all)"
|
|
|
|
echo "[vendor] Done. Transfer wheelhouse/ and debs/ to the target Pi 4, then run install.sh."
|