refactor(fusion_iot): port sensor taxonomy + dashboards, retire fusion_plating_sensors

fusion_plating_sensors had broader scope (sensor_type taxonomy,
dashboards, location flexibility) but its core logic was ALL
scaffolding — alert rules stored thresholds with zero side effects,
measurement create just filled a name sequence, the HTTP endpoint
required user-auth session cookies. Meanwhile fusion_plating_iot had
the actual working alerting: in-spec checks, quality-hold auto-raise
with excursion dedupe, setpoint + deviation, token-auth ingest for
headless hardware. Plus 563 real readings from the pilot Pi.

Right unification: keep fusion_plating_iot (working) as the base,
port the valuable structural bits from fusion_plating_sensors, demolish
the latter entirely.

**Ported to fusion_plating_iot:**

- `fp.sensor.type` — taxonomy model with 8 seeded types (Temperature,
  pH, Conductivity, Level, Pressure, Flow, Concentration, Switch).
  Richer than the device_kind Selection; hardware-independent (one
  "Temperature" type covers DS18B20 / PT100 / thermocouple).
- `fp.sensor.dashboard` — named grouping of sensors with
  out-of-spec count. Simple but useful ("ENP Line 1 — all tanks")
  without the broken alert-rule complexity.
- Extended `fp.tank.sensor`:
  * `uuid` (stable logical ID, survives hardware swaps)
  * `sensor_type_id` (link to the taxonomy above)
  * `work_center_id`, `facility_id`, `location_name` — alternatives to
    tank_id so probes can live on ovens, ambient air, effluent pipes
    without faking a "tank"
  * `effective_location` computed — picks the first non-empty of the
    four location fields for display

**Post-install hook** backfills UUID + default sensor_type on existing
live sensors. Verified on the 2 pilot sensors: both got UUIDs, both
auto-assigned the Temperature type via device_kind=ds18b20 mapping.

**Deleted** (all of fusion_plating_sensors, 1205 LOC):
- fp.sensor (replaced by fp.tank.sensor with added fields)
- fp.sensor.measurement (replaced by fp.tank.reading)
- fp.sensor.alert.rule (replaced by inline alert_min/max + working hold)
- /fp/sensor/measure controller (replaced by /fp/iot/ingest)
- fp.sensor.measure.wizard (not needed — Odoo's normal create form works)
- The "Sensors" submenu hierarchy (Dashboards/All Sensors/Measurements/
  Sensor Types) that created the dup menus the user reported

**Menu now**: Plating → Operations → Sensors
  - Dashboards    (fp.sensor.dashboard)
  - Sensors       (fp.tank.sensor — renamed from "Tank Sensors" since
                   it supports non-tank locations now)
  - Readings      (fp.tank.reading)
  - Sensor Types  (fp.sensor.type)

No data loss: all 591 Pi readings preserved (up from 563 earlier as
the live poller kept running throughout the refactor). Brief 503 on
the Pi during the Odoo module-update restart; poller auto-retried on
the next 30s tick.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-20 19:58:57 -04:00
parent 118f96dad4
commit cf205cfd11
34 changed files with 573 additions and 1224 deletions

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1
Default sensor types — the common ones every plating shop needs.
noupdate="1" so admins can tweak without losing edits on module upgrade.
-->
<odoo noupdate="1">
<record id="fp_sensor_type_temperature" model="fp.sensor.type">
<field name="name">Temperature</field>
<field name="code">temperature</field>
<field name="sequence">10</field>
<field name="measurement_type">number</field>
<field name="default_uom">°C</field>
<field name="icon">fa-thermometer-half</field>
</record>
<record id="fp_sensor_type_ph" model="fp.sensor.type">
<field name="name">pH</field>
<field name="code">ph</field>
<field name="sequence">20</field>
<field name="measurement_type">number</field>
<field name="default_uom">pH</field>
<field name="icon">fa-flask</field>
</record>
<record id="fp_sensor_type_conductivity" model="fp.sensor.type">
<field name="name">Conductivity</field>
<field name="code">conductivity</field>
<field name="sequence">30</field>
<field name="measurement_type">number</field>
<field name="default_uom">µS/cm</field>
<field name="icon">fa-bolt</field>
</record>
<record id="fp_sensor_type_level" model="fp.sensor.type">
<field name="name">Tank Level</field>
<field name="code">level</field>
<field name="sequence">40</field>
<field name="measurement_type">number</field>
<field name="default_uom">cm</field>
<field name="icon">fa-tint</field>
</record>
<record id="fp_sensor_type_pressure" model="fp.sensor.type">
<field name="name">Pressure</field>
<field name="code">pressure</field>
<field name="sequence">50</field>
<field name="measurement_type">number</field>
<field name="default_uom">kPa</field>
<field name="icon">fa-tachometer</field>
</record>
<record id="fp_sensor_type_flow" model="fp.sensor.type">
<field name="name">Flow Rate</field>
<field name="code">flow</field>
<field name="sequence">60</field>
<field name="measurement_type">number</field>
<field name="default_uom">L/min</field>
<field name="icon">fa-cogs</field>
</record>
<record id="fp_sensor_type_concentration" model="fp.sensor.type">
<field name="name">Concentration</field>
<field name="code">concentration</field>
<field name="sequence">70</field>
<field name="measurement_type">number</field>
<field name="default_uom">g/L</field>
<field name="icon">fa-vial</field>
</record>
<record id="fp_sensor_type_switch" model="fp.sensor.type">
<field name="name">Limit / Float Switch</field>
<field name="code">switch</field>
<field name="sequence">100</field>
<field name="measurement_type">boolean</field>
<field name="icon">fa-toggle-on</field>
</record>
</odoo>