feat(iot): repackaged Odoo iot modules + Fusion Plating sensor wrapper

Phase A of the IoT initiative — gets the server-side infrastructure
in place before the Raspberry Pi hardware arrives, so the iot admin
UI + /fp/iot/ingest endpoint are ready to accept the first real
temperature reading as soon as the Pi is wired up.

New top-level folder: fusion_iot/

1. **iot_base/** — Odoo S.A. iot_base module, copied from
   RePackaged-Odoo verbatim. LGPL-3 upstream, no changes needed.

2. **iot/** — Odoo S.A. iot module, repackaged:
   - `models/update.py` neutralised (removed the publisher_warranty
     IoT-Box-counting report that phones home to odoo.com for
     enterprise licence enforcement)
   - `iot_handlers/lib/load_worldline_library.sh` deleted (proprietary
     Worldline payment lib fetch from download.odoo.com, not needed)
   - `wizard/add_iot_box.py._connect_iot_box_with_pairing_code` —
     upstream called odoo.com's iot-proxy to resolve pairing codes;
     replaced with a no-op. Pi-side iot_drivers proxy registers
     directly with this Odoo server instead.
   - Manifest rebranded with an explicit changelog preamble.

3. **fusion_plating_iot/** — new plating-specific wrapper:
   - `fp.tank.sensor` — maps an iot.device (or a direct-HTTP-ingest
     sensor) to a fusion.plating.tank + fusion.plating.bath.parameter.
     Supports DS18B20, PT100/1000, pH, conductivity, level. Per-sensor
     alert_min/max overrides.
   - `fp.tank.reading` — append-only time-series. On create, evaluates
     against sensor's alert range. On in-spec → out-of-spec TRANSITION,
     auto-raises a fusion.plating.quality.hold (once per excursion,
     no spam during sustained out-of-spec).
   - `POST /fp/iot/ingest` — shared-secret HTTP endpoint for sensors
     bypassing the Pi proxy. Token via X-FP-IOT-Token header OR body.
     Accepts single-reading or batch payloads.
   - Menu under Plating → Operations → Sensors & Readings.
   - Tank form inherits get a Sensors tab inline.

Deployed to entech. Verified end-to-end:
- Install: iot_base + iot + fusion_plating_iot all 'installed'
- Smoke test: in-spec → out-of-spec → hold raised (HOLD-0010);
  continued excursion → NO duplicate hold; back-in-spec → NEW
  excursion → NEW hold (HOLD-0011) ✓
- HTTP endpoint: correct token → 200 accepted; wrong token → 401;
  unknown device_serial → 404; batch payload → 200 accepted=N ✓

Phase B (when Raspberry Pi hardware arrives): DS18B20 iot_handler
driver for the Pi-side iot_drivers proxy + systemd service on
vanilla Raspberry Pi OS + first live reading from physical probe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-19 10:46:45 -04:00
parent c118b7c6b5
commit 6e964c230f
419 changed files with 76449 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
<svg width="128" height="128" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M46 48.6602L32 56.6602V40.6602L46 32.6602V48.6602Z" fill="white"/>
<path d="M22 13.2228V14.3745L4 24.6602V56.6602L32 40.6602V18.518L33 17.9346V40.6602C33 41.0191 32.8077 41.3504 32.4961 41.5285L4.49614 57.5285C4.18664 57.7053 3.80639 57.7041 3.49807 57.5252C3.18976 57.3462 3 57.0167 3 56.6602V24.6602C3 24.3014 3.19229 23.97 3.50386 23.792L22 13.2228Z" fill="#374874"/>
<path d="M46 32.6602L25 20.6602L11 28.6602L32 40.6602L46 32.6602Z" fill="white" stroke="#374874" stroke-linejoin="round"/>
<path d="M32 56.6602V40.6602L11 28.6602V44.6602L32 56.6602Z" fill="#C1DBF6" stroke="#374874" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.2348 56.526L46 32.8782V32.6602L32 40.6602V56.6602L32.2348 56.526Z" fill="#FBDBD0"/>
<path d="M46 48.6602L32 56.6602V40.6602L46 32.6602V48.6602Z" stroke="#374874" stroke-linejoin="round"/>
<circle cx="3.05662" cy="3.05662" r="3.55662" transform="matrix(-0.866025 0.5 0 1 30.3038 8.66986)" fill="white" stroke="#374874"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M27.6567 16.3114C26.1948 17.1555 25.0096 16.4712 25.0096 14.7831C25.0096 13.5978 25.5939 12.2327 26.4481 11.2324C28.1248 10.9129 29.4509 11.6785 30.0125 13.2903C29.5733 14.5302 28.6833 15.7187 27.6567 16.3114Z" fill="#FBDBD0"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.6567 8.43023C28.2242 7.52524 29.7275 7.37632 30.8359 8.01625C31.9443 8.65618 32.567 10.0325 32.567 11.8425C32.567 12.1187 32.7609 12.2306 33 12.0925C33.2391 11.9544 33.433 11.6187 33.433 11.3425C33.433 9.26731 32.7191 7.68928 31.4483 6.95559C30.1775 6.22189 28.4539 6.39263 26.6567 7.43023C26.4176 7.5683 26.2237 7.90409 26.2237 8.18023C26.2237 8.45637 26.4176 8.5683 26.6567 8.43023Z" fill="#FBDBD0"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.6567 5.58493C28.8778 4.30263 31.0078 4.09163 32.5783 4.99836C34.1488 5.90508 35.0311 7.85526 35.0311 10.4199C35.0311 10.696 35.225 10.8079 35.4641 10.6699C35.7033 10.5318 35.8971 10.196 35.8971 9.91987C35.8971 7.09004 34.9236 4.93819 33.1907 3.9377C31.4578 2.9372 29.1074 3.17002 26.6567 4.58493C26.4176 4.72301 26.2237 5.05879 26.2237 5.33493C26.2237 5.61108 26.4176 5.72301 26.6567 5.58493Z" fill="#FBDBD0"/>
<path d="M36 46.4502L37 43.9502L38.5 41.9502L40 40.9502H41.5C43 41.6169 46 43.0502 46 43.4502C46 43.8502 48.3333 44.9502 49.5 45.4502L52 46.9502L52.5 50.4502L48.5 54.9502H46.5L38 49.9502L36.5 48.9502L36 46.4502Z" fill="white"/>
<path d="M45.6754 52.3307C45.6754 50.2991 47.1105 47.8243 48.8808 46.8023C50.6506 45.7802 52.0857 46.5986 52.0857 48.6294C52.0857 50.6602 50.6506 53.1357 48.8808 54.1578C47.1106 55.1799 45.6754 54.3618 45.6754 52.3307Z" fill="#C1DBF6"/>
<path d="M42.3076 47.6844C41.8588 48.5764 41.5897 49.5392 41.5897 50.4188C41.5897 51.4176 41.9368 52.1231 42.5 52.4606" stroke="#374874" stroke-linecap="round"/>
<path d="M39.8076 46.4502C39.3588 47.3421 39.0897 48.3049 39.0897 49.1846C39.0897 50.1834 39.4368 50.8888 40 51.2264" stroke="#374874" stroke-linecap="round"/>
<path d="M44.7951 43.8904C45.6492 43.3971 46.4255 43.5969 47 43.8904" stroke="#374874" stroke-linecap="round"/>
<path d="M42.7951 42.7499C43.6492 42.2566 44.4255 42.4564 45 42.7499" stroke="#374874" stroke-linecap="round"/>
<path d="M41.0596 41.1822C40.6344 41.1822 40.1563 41.3078 39.6509 41.5995C37.8806 42.6215 36.4459 45.0967 36.4459 47.1279C36.4459 48.0927 36.7699 48.7831 37.2995 49.1331L37.3538 49.1671C37.368 49.1757 46.026 54.0325 46.4926 54.3144C46.6253 54.3946 46.7089 54.4389 46.7089 54.4389C46.9277 54.5441 47.1745 54.5985 47.4429 54.5985C47.8753 54.5985 48.3637 54.4572 48.8808 54.1587C50.6506 53.1366 52.0857 50.6618 52.0857 48.6302C52.0857 47.5628 51.6888 46.8309 51.0556 46.5247L42.0244 41.4352C41.7525 41.2752 41.4256 41.1822 41.0596 41.1822ZM41.0596 40.2679C41.5725 40.2679 42.0664 40.399 42.4881 40.6472L42.4941 40.6507L42.5 40.6543L51.4978 45.7234C52.4532 46.2091 53 47.2652 53 48.6302C53 50.9884 51.3915 53.7645 49.338 54.9504C48.6916 55.3236 48.0541 55.5128 47.443 55.5128C47.038 55.5128 46.6578 55.4288 46.3128 55.263L46.2963 55.255L46.28 55.2464C46.2692 55.2407 46.1699 55.1876 46.02 55.097C45.5552 54.8162 36.9036 49.9632 36.8819 49.9502L36.875 49.9461L36.868 49.9416L36.8137 49.9076L36.8045 49.9018L36.7954 49.8958C35.9805 49.3572 35.5316 48.3742 35.5316 47.1279C35.5316 44.7695 37.1402 41.9933 39.1937 40.8077C39.8143 40.4495 40.442 40.2679 41.0596 40.2679Z" fill="#374874"/>
<path d="M50.6716 48.2371L60.4262 53.6881L60.7131 54.2619V55.6964L60.1393 56.844L59.5655 57.7047L58.4179 58.5654H57.2703L48.6633 53.6881L47.8026 52.8274L47.5157 51.9667L47.8026 50.5323L48.6633 49.3847L49.524 48.524L50.6716 48.2371Z" fill="#374874"/>
<path d="M56.7972 57.0623C56.7972 55.8966 57.6206 54.4766 58.6364 53.8901C59.6519 53.3036 60.4754 53.7732 60.4754 54.9385C60.4754 56.1038 59.6519 57.5242 58.6364 58.1107C57.6207 58.6972 56.7972 58.2278 56.7972 57.0623Z" fill="#374874"/>
<path d="M50.4189 48.4748C50.1749 48.4748 49.9006 48.5468 49.6106 48.7142C48.5948 49.3007 47.7716 50.7209 47.7716 51.8864C47.7716 52.44 47.9575 52.8362 48.2614 53.037L48.2925 53.0565C48.3007 53.0615 56.9983 58.0386 57.266 58.2004C57.3422 58.2464 57.3902 58.2719 57.3902 58.2719C57.5157 58.3322 57.6573 58.3634 57.8114 58.3634C58.0595 58.3634 58.3397 58.2823 58.6364 58.111C59.6519 57.5246 60.4754 56.1045 60.4754 54.9388C60.4754 54.3263 60.2476 53.9064 59.8843 53.7307L50.9725 48.6199C50.8165 48.5281 50.629 48.4748 50.4189 48.4748ZM50.4189 47.9502C50.7132 47.9502 50.9967 48.0254 51.2386 48.1678L51.242 48.1698L51.2454 48.1719L60.138 53.2709C60.6862 53.5496 61 54.1556 61 54.9388C61 56.2919 60.077 57.8849 58.8988 58.5653C58.5278 58.7795 58.162 58.888 57.8114 58.888C57.579 58.888 57.3609 58.8398 57.1629 58.7447L57.1534 58.7401L57.1441 58.7352C57.1379 58.7319 57.0809 58.7014 56.9949 58.6494C56.7282 58.4883 48.0342 53.5133 48.0218 53.5059L48.0178 53.5035L48.0138 53.5009L47.9826 53.4814L47.9774 53.4781L47.9721 53.4746C47.5045 53.1656 47.247 52.6015 47.247 51.8864C47.247 50.5332 48.17 48.9402 49.3483 48.2599C49.7044 48.0544 50.0646 47.9502 50.4189 47.9502Z" fill="#374874"/>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB