Add MHI aircon manual control (Phase 2, Modbus only)
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>
This commit is contained in:
parent
a9b5703c57
commit
e5c40bbb8c
14 changed files with 935 additions and 20 deletions
|
|
@ -73,8 +73,71 @@ export interface Device extends DeviceSummary {
|
|||
photo_count: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
mhi_gateway_id?: number | null
|
||||
mhi_unit_index?: number | null
|
||||
mhi_iu_address?: number | null
|
||||
mhi_register_map?: Record<string, MhiRegisterField> | null
|
||||
}
|
||||
|
||||
// ── MHI Modbus gateways (manual aircon control) ──────────────────────────
|
||||
export interface MhiRegisterField {
|
||||
address: number
|
||||
active: boolean
|
||||
readWrite: string | null
|
||||
}
|
||||
|
||||
export interface MhiImportedUnit {
|
||||
unitIndex: number
|
||||
iu: number | null
|
||||
ou: number | null
|
||||
fields: Record<string, MhiRegisterField>
|
||||
}
|
||||
|
||||
export interface MhiImportResult {
|
||||
meta: {
|
||||
projectName: string | null
|
||||
mapsVersion: string | null
|
||||
internalProtocol: string | null
|
||||
externalProtocol: string | null
|
||||
timestamp: string | null
|
||||
}
|
||||
global: Record<string, MhiRegisterField>
|
||||
units: MhiImportedUnit[]
|
||||
unmatchedRows: { row: number; description: string }[]
|
||||
}
|
||||
|
||||
export interface MhiGateway {
|
||||
id: number
|
||||
name: string
|
||||
host: string
|
||||
port: number
|
||||
slave_id: number
|
||||
address_base: number
|
||||
imported_filename: string | null
|
||||
imported_units: MhiImportResult | null
|
||||
imported_at: string | null
|
||||
created_at: string
|
||||
updated_at: string
|
||||
assigned_count: number
|
||||
}
|
||||
|
||||
export interface MhiStatus {
|
||||
external_ref: string
|
||||
onOff?: string
|
||||
mode?: string
|
||||
setpoint?: number
|
||||
fanSpeed?: string
|
||||
roomTemp?: number
|
||||
errorCode?: number
|
||||
compressor?: string
|
||||
commStatus?: string
|
||||
filterSign?: string
|
||||
error?: string
|
||||
}
|
||||
|
||||
export const MHI_MODES = ['cool', 'heat', 'fan', 'auto', 'dry'] as const
|
||||
export const MHI_FAN_SPEEDS = ['low', 'medium', 'high', 'powerful'] as const
|
||||
|
||||
export interface DevicePhoto {
|
||||
id: number
|
||||
device_id: number
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue