mirror of
https://github.com/adrianjagielak/home-assistant-futurehome.git
synced 2026-05-28 05:55:40 +00:00
HA 2026.5 enforces strict validation of device_class/unit_of_measurement pairs in MQTT discovery payloads. Four categories were broken: - power_factor: unit was sent as "power_factor" (the FIMP field name); HA requires the field to be omitted or empty for this device class. Fixed by normalising the display unit separately from the FIMP data-path key. - illuminance: unit "Lux" is rejected; normalise to "lx". When a sensor reports luminance as "%" (some Z-Wave devices), the illuminance device class is dropped so the entity becomes a generic sensor rather than triggering a validation error. - reactive_power (regular/export meter): unit "VAr" is rejected; HA requires lowercase "var". - reactive_power (extended meter values, e.g. p_import_react): the unit determination logic fell through to the generic power branch and sent "W"; reactive power extended values now emit "var", apparent power values emit "VA", and reactive energy values emit "kvarh". Fixes #31 Co-authored-by: Claude <noreply@anthropic.com>
100 lines
3.7 KiB
TypeScript
100 lines
3.7 KiB
TypeScript
import {
|
|
VinculumPd7Device,
|
|
VinculumPd7Service,
|
|
} from '../fimp/vinculum_pd7_device';
|
|
import {
|
|
SensorDeviceClass,
|
|
SensorStateClass,
|
|
} from '../ha/mqtt_components/_enums';
|
|
import { ServiceComponentsCreationResult } from '../ha/publish_device';
|
|
|
|
export function _sensor_numeric__components(
|
|
topicPrefix: string,
|
|
device: VinculumPd7Device,
|
|
svc: VinculumPd7Service,
|
|
svcName: string,
|
|
): ServiceComponentsCreationResult | undefined {
|
|
type SensorNumericDataTuple = [
|
|
device_class: SensorDeviceClass | undefined,
|
|
name: string | undefined,
|
|
unit: string,
|
|
state_class?: SensorStateClass,
|
|
];
|
|
|
|
const data = (
|
|
{
|
|
sensor_accelx: [undefined, 'Acceleration, X-axis', 'm/s2'],
|
|
sensor_accely: [undefined, 'Acceleration, Y-axis', 'm/s2'],
|
|
sensor_accelz: [undefined, 'Acceleration, Z-axis', 'm/s2'],
|
|
sensor_airflow: [undefined, 'Air flow', 'm3/h'],
|
|
sensor_airq: ['aqi', undefined, 'pm25'],
|
|
sensor_anglepos: [
|
|
undefined,
|
|
'Angle Position',
|
|
'%',
|
|
svc.props?.sup_units?.[0] === '%' ? 'measurement' : 'measurement_angle',
|
|
],
|
|
sensor_atmo: ['atmospheric_pressure', undefined, 'kPa'],
|
|
sensor_baro: ['atmospheric_pressure', undefined, 'kPa'],
|
|
sensor_co: ['carbon_monoxide', undefined, 'mol/m3'],
|
|
sensor_co2: ['carbon_dioxide', undefined, 'ppm'],
|
|
sensor_current: ['current', undefined, 'A'],
|
|
sensor_dew: ['temperature', 'Dew', '°C'],
|
|
sensor_direct: ['wind_direction', 'Direction', '°'],
|
|
sensor_distance: ['distance', undefined, 'm'],
|
|
sensor_elresist: [undefined, 'Electrical resistivity', 'ohm/m'],
|
|
sensor_freq: ['frequency', undefined, 'Hz'],
|
|
sensor_gp: [undefined, 'Sensor', '%'],
|
|
sensor_gust: [undefined, 'Gust', 'km/h'],
|
|
sensor_humid: ['humidity', undefined, '%'],
|
|
sensor_lumin: ['illuminance', undefined, 'lx'],
|
|
sensor_moist: ['moisture', undefined, '%'],
|
|
sensor_noise: ['sound_pressure', undefined, 'dB'],
|
|
sensor_power: ['power', undefined, 'W'],
|
|
sensor_rain: ['precipitation_intensity', undefined, 'mm/h'],
|
|
sensor_rotation: [undefined, 'Rotation', 'rpm'],
|
|
sensor_seismicint: [undefined, 'Seismic intensity', 'EMCRO'],
|
|
sensor_seismicmag: [undefined, 'Seismic magnitude', 'MB'],
|
|
sensor_solarrad: [undefined, 'Solar radiation', 'W/m2'],
|
|
sensor_tank: ['volume_storage', undefined, 'l'],
|
|
sensor_temp: ['temperature', undefined, '°C'],
|
|
sensor_tidelvl: [undefined, 'Tide level', 'm'],
|
|
sensor_uv: [undefined, 'Ultraviolet', 'index'],
|
|
sensor_veloc: [undefined, 'Velocity', 'm/2'],
|
|
sensor_voltage: ['voltage', undefined, 'V'],
|
|
sensor_watflow: ['volume_flow_rate', 'Water flow', 'l/h'],
|
|
sensor_watpressure: ['pressure', 'Water pressure', 'kPa'],
|
|
sensor_wattemp: ['temperature', 'Water temperature', '°C'],
|
|
sensor_weight: ['weight', undefined, 'kg'],
|
|
sensor_wind: ['wind_speed', undefined, 'km/h'],
|
|
} as Record<string, SensorNumericDataTuple>
|
|
)[svcName];
|
|
|
|
if (!data) return undefined;
|
|
|
|
let device_class = data[0];
|
|
const name = data[1];
|
|
let unit = svc.props?.sup_units?.[0] ?? data[2];
|
|
if (unit === 'C') unit = '°C';
|
|
if (unit === 'F') unit = '°F';
|
|
if (unit === 'kph') unit = 'km/h';
|
|
if (unit === 'Lux') unit = 'lx';
|
|
// HA rejects illuminance + %; drop device_class for percentage-reporting sensors
|
|
if (device_class === 'illuminance' && unit === '%') device_class = undefined;
|
|
const state_class = data[3];
|
|
|
|
return {
|
|
components: {
|
|
[svc.addr]: {
|
|
unique_id: svc.addr,
|
|
platform: 'sensor',
|
|
name: name,
|
|
device_class: device_class,
|
|
state_class: state_class,
|
|
unit_of_measurement: unit,
|
|
value_template: `{{ value_json['${svc.addr}'].sensor }}`,
|
|
},
|
|
},
|
|
};
|
|
}
|