#!/usr/bin/env python3 """Server connection test — run on the Pi 4 SHT30 (Sensor 2) module. Builds the body with wire.py, attaches a raw-body HMAC (X-Signature), and actually sends one signed POST. Secrets (API_URL/API_KEY) are loaded from config_local.py. """ import sys import time import subprocess import requests signed_ok = False # whether the signed POST returned 200 — setup.sh gates hardening on this exit code from config import ( API_URL, API_KEY, DEVICE_ID, DEVICE_LOCATION, SENSOR_ID, SENSOR_NAME, APP_VERSION, ) import wire API_BASE = API_URL.rsplit("/", 1)[0] print("=" * 50) print(" Server connection test (Pi 4 SHT30 / Sensor 2 module)") print("=" * 50) print(f" API_URL = {API_URL}") # ── Step 1: check endpoint reachability with curl (no signature → 403 auth failure is expected) ── print("\n[1/2] Checking sensor_data.php reachability with curl (no signature → 403 auth failure is expected)...") try: result = subprocess.run( ["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "-A", "SHT30Sensor/2.0", "-X", "POST", API_URL, "-H", "Content-Type: application/json", "-d", "{}"], capture_output=True, text=True, timeout=10 ) code = result.stdout.strip() print(f" HTTP status code: {code}") if code in ("400", "403"): print(" → Endpoint reachable OK (rejected without signature/fields — expected)") elif code == "200": print(" → 200? Server accepted without a signature — check server configuration") elif code == "404": print(" → 404: check the API_URL path") else: print(f" → Response: {code} (check hosting/firewall/.htaccess)") except Exception as e: print(f" → curl failed: {e}") # ── Step 2: real measurement POST signed with wire.py (startup, dummy values) ── print("\n[2/2] Signed measurement POST (startup, dummy 24.00C/48.00%)...") try: ts = int(time.time()) body = wire.sht30_event_body( DEVICE_ID, DEVICE_LOCATION, SENSOR_ID, SENSOR_NAME, "startup", ts, 24.0, 48.0, "normal", APP_VERSION, ) sig = wire.sign_raw(API_KEY, body) print(f" Body: {body}") print(f" X-Signature: {sig[:16]}...") resp = requests.post( API_URL, data=body.encode("utf-8"), headers={ "Content-Type": "application/json", "X-Signature": sig, "X-Device-Id": DEVICE_ID, "User-Agent": "SHT30Sensor/2.0", }, timeout=10, ) print(f" HTTP status code: {resp.status_code}") print(f" Response body: {resp.text[:200]}") if resp.status_code == 200: signed_ok = True print(" → Success! Signature verified, measurement stored (check dashboard sensor_id=2)") elif resp.status_code == 403: print(" → 403 auth failure: API_KEY differs from the server's config.local.php, or signature mismatch") elif resp.status_code == 400: print(" → 400: check timestamp freshness (±600s) — verify Pi clock (NTP) sync") else: print(f" → Status code: {resp.status_code}") except ImportError: print(" → requests not installed. Run install.sh or sudo apt install python3-requests") except Exception as e: print(f" → Failed: {e}") print("\n" + "=" * 50) print(" Test complete" + ("" if signed_ok else " — signed POST failed (see log above)")) print("=" * 50) sys.exit(0 if signed_ok else 1)