There was no way to remove an mhi_gateways row either, alongside the
already-fixed device-delete gap — exposed by the same Modbus->MQTT
switchover. Adds DELETE /api/mhi-gateways/:id (manage_devices cap) and a
'Delete gateway' button. Devices referencing the gateway are NOT deleted
(mhi_gateway_id just goes NULL per the existing ON DELETE SET NULL FK) —
the confirm dialog says so and points at the separate device-delete flow
for retiring the stale mhi_modbus rows too.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Manual on/off/mode/setpoint/fan control for MHI indoor units via the
already-verified Intesis Modbus TCP gateway, deliberately NOT wired into
the NewBook-driven scheduler yet — that stays deferred. Modbus doesn't
depend on the MQTT broker (separate infra, still unbuilt), so this can be
deployed and tested standalone.
- mhi_gateways table (connection config: host/port/slave id/address base)
+ zone_devices columns for MHI devices (gateway id, unit index, IU hint,
and the per-device register map staged from a MAPS import — ground
truth, never re-derived from room/IU at runtime)
- drivers/mhi-modbus.js: discover/getStatus/setTarget over modbus-serial,
same interface as trv.js/homeassistant.js; per-gateway request queue
since Modbus TCP requires serialised requests; falls back to the
profile's stride formula (with a loud warning) only if a unit has never
been through an import
- routes/mhi-gateways.js: gateway CRUD, live test-connection, xlsx import
(stages the parsed result for review — never auto-creates devices),
per-unit 'assign to zone' as the explicit commit step
- routes/override.js: GET .../mhi-status, POST .../mhi-control (control cap)
- frontend: GatewaysPanel (add gateway, test connection, import + preview,
assign units) and MhiControlPanel (on/off, mode, setpoint, fan) wired
into Devices.tsx / ZoneDetailModal.tsx
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>