Skip to content

Mill integration: Add support for air purifier devices Mill Compact Pro and Mill Silent Pro (GL-Air Purifier M/L) #114

@vonrobak

Description

@vonrobak

Description

The Mill integration currently filters out air purifier devices as "unsupported", despite the Mill cloud API providing complete sensor data for these devices. This feature request asks to add air purifier support to the existing Mill integration.

Problem Statement

Mill manufactures both heaters (currently supported) and air purifiers (currently unsupported) that use the same cloud API. The integration currently only creates entities for mill.Heater and mill.Socket device types, logging an error for air purifier devices:

ERROR (MainThread) [mill] Unsupported device, Air Purifiers {'deviceId': '...', 'customName': 'CompactPro', ...}

However, the Mill API already provides complete sensor data for air purifiers in the same format as other devices. The integration is filtering them out, not because data is unavailable, but because the device type isn't recognized.

Evidence: Complete Sensor Data Available

Real data from Home Assistant logs showing air purifier metrics:

CompactPro (GL-Air Purifier M)

{
  "deviceId": "b47d76d0-a044-4021-89f7-d848ad7b9e01",
  "macAddress": "EC:62:60:07:ED:48",
  "deviceType": {
    "childType": {
      "id": "021fee4b-39f0-4e2a-b3c4-f614c9673a1f",
      "name": "GL-Air Purifier M"
    },
    "parentType": {
      "id": "80c2105f-918c-410b-9046-3c08cba42b35",
      "name": "Air Purifiers"
    }
  },
  "isConnected": true,
  "customName": "CompactPro",
  "lastMetrics": {
    "deviceId": "b47d76d0-a044-4021-89f7-d848ad7b9e01",
    "receivedAt": "2026-01-31T12:33:27.380Z",
    "sentAt": "2026-01-31T12:33:27.000Z",
    "temperature": 19.74,
    "humidity": 35.12,
    "massPm_10": 4,
    "massPm_25": 4,
    "massPm_100": 4,
    "numberPm_05": 348,
    "numberPm_10": 464,
    "numberPm_25": 491,
    "numberPm_50": 502,
    "numberPm_100": 505,
    "eco2": 2147483647,
    "tvoc": 2147483647,
    "controlSignal": 24
  }
}

Note: eco2 and tvoc values of 2147483647 indicate these sensors are not present on the CompactPro model.

Silent Pro (GL-Air Purifier L)

{
  "deviceId": "d3d244dd-8cea-4875-b2ac-3c6925328a38",
  "macAddress": "EC:62:60:09:9F:08",
  "deviceType": {
    "childType": {
      "id": "b6f56a1b-24b5-4239-b800-64e553572204",
      "name": "GL-Air Purifier L"
    },
    "parentType": {
      "id": "80c2105f-918c-410b-9046-3c08cba42b35",
      "name": "Air Purifiers"
    }
  },
  "isConnected": true,
  "customName": "Mill Silent Pro",
  "lastMetrics": {
    "deviceId": "d3d244dd-8cea-4875-b2ac-3c6925328a38",
    "receivedAt": "2026-01-31T12:27:06.243Z",
    "sentAt": "2026-01-31T12:27:04.000Z",
    "temperature": 24.27,
    "humidity": 26.55,
    "massPm_10": 5,
    "massPm_25": 5,
    "massPm_100": 6,
    "numberPm_05": 408,
    "numberPm_10": 520,
    "numberPm_25": 550,
    "numberPm_50": 564,
    "numberPm_100": 566,
    "eco2": 606,
    "tvoc": 136,
    "airQualityIndex": 2,
    "controlSignal": 10
  }
}

Note: Silent Pro includes eCO2 and TVOC sensors with valid readings.

Proposed Solution

Add air purifier device support to the Mill integration by:

  1. Create new device class (or extend existing sensor logic):

    • Check for parentType.name == "Air Purifiers" in device type
    • Extract sensor data from lastMetrics field (same structure as existing devices)
  2. Add sensor entities based on device capabilities:

CompactPro (GL-Air Purifier M) - 6 sensors

Metric Key Entity Unit Device Class
temperature Temperature °C temperature
humidity Humidity % humidity
massPm_10 PM 1.0 µg/m³ pm10
massPm_25 PM 2.5 µg/m³ pm25
massPm_100 PM 10 µg/m³ None
numberPm_05 PM 0.5 Count count None

Silent Pro (GL-Air Purifier L) - 8 sensors

All CompactPro sensors PLUS:

Metric Key Entity Unit Device Class
eco2 Estimated CO₂ ppm co2
tvoc TVOC ppb None
airQualityIndex Air Quality Index - aqi

Sensor filtering: Skip eco2 and tvoc sensors if value equals 2147483647 (sentinel value indicating sensor not present).

  1. Device info already available:
    • MAC address: macAddress field
    • Model: deviceType.childType.name
    • Name: customName field
    • Connection status: isConnected field

Implementation Guidance

Location: homeassistant/components/mill/sensor.py

Current code (lines 157-170):

entities = [
    MillSensor(
        mill_data_coordinator,
        entity_description,
        mill_device,
    )
    for mill_device in mill_data_coordinator.data.values()
    for entity_description in (
        SOCKET_SENSOR_TYPES
        if isinstance(mill_device, mill.Socket)
        else HEATER_SENSOR_TYPES
        if isinstance(mill_device, mill.Heater)
        else SENSOR_TYPES
    )
]

Suggested approach:

  1. Option A: Create AirPurifier class in mill library (requires upstream change)
  2. Option B: Check device type in raw device data before mill library filtering (access mill_connection.request_controller.all_devices or equivalent)
  3. Option C: Add air purifier as new sensor type with attribute-based device type checking

Air purifier sensor types to add:

AIR_PURIFIER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
    SensorEntityDescription(
        key="temperature",
        device_class=SensorDeviceClass.TEMPERATURE,
        native_unit_of_measurement=UnitOfTemperature.CELSIUS,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    SensorEntityDescription(
        key="humidity",
        device_class=SensorDeviceClass.HUMIDITY,
        native_unit_of_measurement=PERCENTAGE,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    SensorEntityDescription(
        key="massPm_10",
        device_class=SensorDeviceClass.PM10,
        native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    SensorEntityDescription(
        key="massPm_25",
        device_class=SensorDeviceClass.PM25,
        native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    SensorEntityDescription(
        key="massPm_100",
        native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
        state_class=SensorStateClass.MEASUREMENT,
        translation_key="pm_100",
    ),
    SensorEntityDescription(
        key="numberPm_05",
        state_class=SensorStateClass.MEASUREMENT,
        translation_key="pm_05_count",
    ),
    SensorEntityDescription(
        key="eco2",
        device_class=SensorDeviceClass.CO2,
        native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
        state_class=SensorStateClass.MEASUREMENT,
    ),
    SensorEntityDescription(
        key="tvoc",
        native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
        state_class=SensorStateClass.MEASUREMENT,
        translation_key="tvoc",
    ),
    SensorEntityDescription(
        key="airQualityIndex",
        device_class=SensorDeviceClass.AQI,
        state_class=SensorStateClass.MEASUREMENT,
    ),
)

Use Cases

Air purifier sensor data enables valuable automations:

Air quality monitoring:

- trigger:
    - platform: numeric_state
      entity_id: sensor.silent_pro_eco2
      above: 1200
  action:
    - service: notify.mobile_app
      data:
        message: "High CO₂ detected ({{ states('sensor.silent_pro_eco2') }} ppm). Consider ventilation."

PM 2.5 alerts:

- trigger:
    - platform: numeric_state
      entity_id: sensor.compactpro_mass_pm_25
      above: 35  # WHO 24-hour guideline
  action:
    - service: notify.mobile_app
      data:
        message: "Poor air quality - PM 2.5: {{ states('sensor.compactpro_mass_pm_25') }} µg/m³"

Dashboard integration:

  • Real-time air quality monitoring across multiple rooms
  • Historical data tracking (PM 2.5 trends, CO₂ patterns)
  • Air quality index visualization

Affected Users

Mill sells air purifiers in Nordic markets (Norway, Sweden, Denmark) alongside their heaters. Users who have both Mill heaters and air purifiers expect both to be supported by the same integration.

Current workaround: None available without creating custom components or REST sensors with hardcoded credentials.

Additional Information

Mill Product Line:

  • Heaters: ✅ Supported (oil-filled, panel, convection heaters)
  • Smart Sockets: ✅ Supported
  • Air Purifiers: ❌ Not supported (this feature request)
    • GL-Air Purifier M (CompactPro)
    • GL-Air Purifier L (Silent Pro)

Mill API: Same cloud API (api.millheat.com) for all device types

Update frequency: 30 seconds (same as heaters, already implemented)

Dependencies:

  • Mill library: millheater==0.14.1 (may need update to add air purifier device class)
  • Alternative: Access raw device data before library filtering

Testing Availability

I can test this feature with two Mill air purifiers:

  • CompactPro (GL-Air Purifier M) - 6 sensors
  • Silent Pro (GL-Air Purifier L) - 8 sensors (includes eCO2/TVOC)

Both devices are connected to Mill cloud account and visible in Mill mobile app. Logs show complete sensor data being received by Home Assistant but filtered out.

References

Current Mill integration:

Relevant sensor device classes:

  • SensorDeviceClass.TEMPERATURE
  • SensorDeviceClass.HUMIDITY
  • SensorDeviceClass.PM10
  • SensorDeviceClass.PM25
  • SensorDeviceClass.CO2
  • SensorDeviceClass.AQI

Similar integrations with air purifier support:

  • Xiaomi Mi Air Purifier (xiaomi_miio)
  • Philips Air Purifier (philips_js)
  • Dyson (dyson)

Summary

The Mill API already provides complete air purifier sensor data in the same format as heaters and sockets. This feature request asks to stop filtering out air purifier devices and create sensor entities for the metrics already available in lastMetrics field.

Benefit: Users with Mill air purifiers gain native Home Assistant integration with no additional API calls or infrastructure changes required.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions