POSA_LEAKSMS/raspberry_pi4_sht30/test_sensor.py
cw2007 a72ea18130 i18n(pi): Raspberry Pi 번들 소스 한글 → 영어 (콘솔 mojibake 해소)
헤드리스 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 본문 서명 무영향
2026-07-10 10:44:13 +09:00

87 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""Sensor/format self-check — Pi 4 SHT30 (Sensor 2) module.
1) Unit-check that CRC-8 / fixed2 / body format match the firmware and server spec
2) Take one real (or simulated) SHT30 measurement -> print converted values
Step 1) must always pass even without hardware (core guarantee of signature compatibility).
"""
import sys
import wire
from sht30_driver import crc8, parse_frame, SHT30, SMBUS_AVAILABLE
# The format/CRC self-check must work even without secrets (config_local.py).
# Since config.py fails closed and aborts on import when config_local.py is missing,
# fall back to defaults for dev-PC checks (server connection is handled by test_connection.py).
try:
from config import I2C_BUS, I2C_ADDR, FORCE_SIMULATION
except RuntimeError:
I2C_BUS, I2C_ADDR, FORCE_SIMULATION = 1, 0x44, False
print(" [info] config_local.py missing -> checking with I2C defaults (bus=1, 0x44)")
def check(name, got, want):
ok = got == want
print(f" [{'OK ' if ok else 'FAIL'}] {name}: got={got!r} want={want!r}")
return ok
print("=" * 50)
print(" SHT30 self-check (Sensor 2 module)")
print("=" * 50)
passed = True
# ── 1) CRC-8 check (Sensirion standard vector 0xBEEF → 0x92) ──
print("\n[1] CRC-8 (poly 0x31, init 0xFF):")
passed &= check("crc8(0xBEEF)", crc8(b"\xBE\xEF"), 0x92)
# ── 2) fixed2 check (round-half-up, same as reference.py/jb_fixed2) ──
print("\n[2] fixed2 (2 decimal places, round-half-up):")
passed &= check("24.0", wire.fixed2(24.0), "24.00")
passed &= check("48.5", wire.fixed2(48.5), "48.50")
passed &= check("-3.245", wire.fixed2(-3.245), "-3.25")
passed &= check("0.0", wire.fixed2(0.0), "0.00")
# ── 3) Frame parsing check (synthetic frame including CRC) ──
print("\n[3] parse_frame (synthetic frame conversion):")
raw_t, raw_rh = 0x6400, 0x8000 # arbitrary raw values
frame = bytes([
raw_t >> 8, raw_t & 0xFF, crc8(bytes([raw_t >> 8, raw_t & 0xFF])),
raw_rh >> 8, raw_rh & 0xFF, crc8(bytes([raw_rh >> 8, raw_rh & 0xFF])),
])
t, rh = parse_frame(frame)
exp_t = -45.0 + 175.0 * (raw_t / 65535.0)
exp_rh = 100.0 * (raw_rh / 65535.0)
passed &= check("temp_c", round(t, 4), round(exp_t, 4))
passed &= check("rh", round(rh, 4), round(exp_rh, 4))
# ── 4) Body format check (field order/type) ──
print("\n[4] Body format (fixed field order):")
body = wire.sht30_event_body("dev", "loc", 2, "s2", "periodic",
1700000000, 24.0, 48.0, "normal", "vX")
expected = ('{"device_id":"dev","device_location":"loc","sensor_id":2,'
'"sensor_name":"s2","event_type":"periodic","timestamp":1700000000,'
'"metric_type":"sht30","temperature_c":24.00,"humidity_percent":48.00,'
'"metric_status":"normal","app_version":"vX"}')
passed &= check("body", body, expected)
print(f" Signature(key=test): {wire.sign_raw('test', body)[:16]}...")
# ── 5) One real/simulated measurement ──
print("\n[5] One measurement:")
sim = FORCE_SIMULATION or not SMBUS_AVAILABLE
print(f" Mode: {'simulation' if sim else f'real I2C(bus={I2C_BUS},0x{I2C_ADDR:02X})'}")
try:
with SHT30(bus_num=I2C_BUS, addr=I2C_ADDR, simulate=sim) as s:
t, rh = s.measure()
print(f" Reading: T={t:.2f}C RH={rh:.2f}%")
except Exception as e:
print(f" Measurement failed: {e}")
if not sim:
print(" (check 0x44 response with i2cdetect -y 1 / check wiring, pull-ups, I2C enabled)")
print("\n" + "=" * 50)
print(f" Result: {'ALL PASSED ✅' if passed else 'SOME FAILED ❌'}")
print("=" * 50)
sys.exit(0 if passed else 1)