Add Tuya Device Ventilation System (xfj)

I recently purchased a Pioneer wall mounted ERV ( Pioneer ECOasis 150). It utilizes a re-branded / re-skinned Tuya app, but I was able to successfully get it setup and working with the Tuya Smart Life app (by volcano technologies).

Using the Tuya integration, I am able to add the device to Home Assistant. The issue I am facing is that the Tuya device type (Ventilation System (xfj)-Tuya Developer Platform-Tuya Developer) is not supported by Home Assistant.

Scenes work, but I would prefer to control the device directly via HA. Please add support for the ā€œxfjā€ device type in the Tuya integration.

Hello mox1,

There are at lease 2 custom_integrations available from Github using the HACS loader that may have what you want. You would have to research them and see…
TuyaLocal and LocalTuya.

Hello,
This is hard to do without the device diagnostics :).

Could you please provide them?

I’ll see what I can do from there…

1 Like

I too have one of these ventilation systems, here are my diagnostics

{
  "home_assistant": {
    "installation_type": "Home Assistant OS",
    "version": "2024.9.2",
    "dev": false,
    "hassio": true,
    "virtualenv": false,
    "python_version": "3.12.4",
    "docker": true,
    "arch": "x86_64",
    "timezone": "America/New_York",
    "os_name": "Linux",
    "os_version": "6.6.46-haos",
    "supervisor": "2024.09.1",
    "host_os": "Home Assistant OS 13.1",
    "docker_version": "26.1.4",
    "chassis": "vm",
    "run_as_root": true
  },
  "custom_components": {},
  "integration_manifest": {
    "domain": "tuya",
    "name": "Tuya",
    "codeowners": [
      "Tuya",
      "zlinoliver",
      "frenck"
    ],
    "config_flow": true,
    "dependencies": [
      "ffmpeg"
    ],
    "dhcp": [
      {
        "macaddress": "105A17*"
      },
      {
        "macaddress": "10D561*"
      },
      {
        "macaddress": "1869D8*"
      },
      {
        "macaddress": "381F8D*"
      },
      {
        "macaddress": "508A06*"
      },
      {
        "macaddress": "68572D*"
      },
      {
        "macaddress": "708976*"
      },
      {
        "macaddress": "7CF666*"
      },
      {
        "macaddress": "84E342*"
      },
      {
        "macaddress": "D4A651*"
      },
      {
        "macaddress": "D81F12*"
      }
    ],
    "documentation": "https://www.home-assistant.io/integrations/tuya",
    "integration_type": "hub",
    "iot_class": "cloud_push",
    "loggers": [
      "tuya_iot"
    ],
    "requirements": [
      "tuya-device-sharing-sdk==0.1.9"
    ],
    "is_built_in": true
  },
  "setup_times": {},
  "data": {
    "endpoint": "https://apigw.tuyaus.com",
    "terminal_id": "1726850906678spsNUF",
    "mqtt_connected": true,
    "disabled_by": null,
    "disabled_polling": false,
    "id": "eb25edfdc9032d163d3d0m",
    "name": "ERVQ-H-F",
    "category": "xfj",
    "product_id": "gcaog2ut95yup99k",
    "product_name": "ERVQ-H-F",
    "online": true,
    "sub": false,
    "time_zone": "-04:00",
    "active_time": "2024-09-20T16:51:17+00:00",
    "create_time": "2024-09-20T16:51:17+00:00",
    "update_time": "2024-09-20T16:51:17+00:00",
    "function": {
      "switch": {
        "type": "Boolean",
        "value": {}
      }
    },
    "status_range": {
      "switch": {
        "type": "Boolean",
        "value": {}
      },
      "pm25": {
        "type": "Integer",
        "value": {
          "unit": "",
          "min": 0,
          "max": 1001,
          "scale": 0,
          "step": 1
        }
      },
      "eco2": {
        "type": "Integer",
        "value": {
          "unit": "",
          "min": 0,
          "max": 8001,
          "scale": 0,
          "step": 1
        }
      },
      "humidity_indoor": {
        "type": "Integer",
        "value": {
          "unit": "%",
          "min": 0,
          "max": 101,
          "scale": 0,
          "step": 1
        }
      },
      "temp_indoor": {
        "type": "Integer",
        "value": {
          "unit": "\u2109",
          "min": 0,
          "max": 200,
          "scale": 0,
          "step": 1
        }
      },
      "filter_life": {
        "type": "Integer",
        "value": {
          "unit": "\u5929",
          "min": 0,
          "max": 200,
          "scale": 0,
          "step": 1
        }
      },
      "fault": {
        "type": "Bitmap",
        "value": {
          "label": [
            "E1",
            "E2",
            "E3",
            "E4",
            "E5"
          ]
        }
      }
    },
    "status": {
      "switch": true,
      "pm25": 1,
      "eco2": 0,
      "humidity_indoor": 56,
      "temp_indoor": 73,
      "filter_life": 84,
      "fault": 0
    },
    "home_assistant": {
      "name": "ERVQ-H-F",
      "name_by_user": null,
      "disabled": false,
      "disabled_by": null,
      "entities": []
    },
    "set_up": false,
    "support_local": true
  }
}

Hello,
This should now be fully supported by my custom integration:

Please download the latest BETA version as this support has not made it yet in the stable release :).

Have a nice day,
Azerty

1 Like

Wow, it works! fantastic. Thank you so much for doing this, I really appreciate it.

Hello, I have a similar system , but with far more entities which are not fully recognized
Here are my diagnostic for an energy recovery ventilator ERV


{
  "home_assistant": {
    "installation_type": "Home Assistant OS",
    "version": "2025.1.4",
    "dev": false,
    "hassio": true,
    "virtualenv": false,
    "python_version": "3.13.1",
    "docker": true,
    "arch": "aarch64",
    "timezone": "Europe/Rome",
    "os_name": "Linux",
    "os_version": "6.6.62-haos-raspi",
    "supervisor": "2024.12.3",
    "host_os": "Home Assistant OS 14.2",
    "docker_version": "27.2.0",
    "chassis": "embedded",
    "run_as_root": true
  },
  "custom_components": {
    "xtend_tuya": {
      "documentation": "https://github.com/azerty9971/xtend_tuya",
      "version": "3.0.8",
      "requirements": [
        "tuya-device-sharing-sdk==0.2.1",
        "tuya-iot-py-sdk==0.6.6"
      ]
    },
    "thermal_comfort": {
      "documentation": "https://github.com/dolezsa/thermal_comfort/blob/6af848f73d658eb7344f613dbcd097ea97573d18/README.md",
      "version": "2.2.2",
      "requirements": []
    },
    "hacs": {
      "documentation": "https://hacs.xyz/docs/use/",
      "version": "2.0.5",
      "requirements": [
        "aiogithubapi>=22.10.1"
      ]
    },
    "tuya_local": {
      "documentation": "https://github.com/make-all/tuya-local",
      "version": "2025.1.1",
      "requirements": [
        "tinytuya==1.15.1",
        "tuya-device-sharing-sdk~=0.2.1"
      ]
    },
    "alarmo": {
      "documentation": "https://github.com/nielsfaber/alarmo",
      "version": "v1.10.7",
      "requirements": []
    },
    "localtuya": {
      "documentation": "https://github.com/rospogrigio/localtuya/",
      "version": "5.2.3",
      "requirements": []
    },
    "dreame_vacuum": {
      "documentation": "https://github.com/Tasshack/dreame-vacuum",
      "version": "v1.0.4",
      "requirements": [
        "pillow",
        "numpy",
        "pybase64",
        "requests",
        "pycryptodome",
        "python-miio",
        "py-mini-racer",
        "tzlocal",
        "paho-mqtt"
      ]
    },
    "connectlife": {
      "documentation": "https://github.com/oyvindwe/connectlife-ha",
      "version": "0.22.1",
      "requirements": [
        "connectlife==0.5.3"
      ]
    },
    "adaptive_lighting": {
      "documentation": "https://github.com/basnijholt/adaptive-lighting#readme",
      "version": "1.25.0",
      "requirements": [
        "ulid-transform"
      ]
    }
  },
  "integration_manifest": {
    "domain": "xtend_tuya",
    "name": "Xtend Tuya",
    "after_dependencies": [
      "tuya"
    ],
    "codeowners": [
      "azerty9971"
    ],
    "config_flow": true,
    "dependencies": [
      "ffmpeg",
      "http"
    ],
    "dhcp": [
      {
        "macaddress": "105A17*"
      },
      {
        "macaddress": "10D561*"
      },
      {
        "macaddress": "1869D8*"
      },
      {
        "macaddress": "381F8D*"
      },
      {
        "macaddress": "508A06*"
      },
      {
        "macaddress": "68572D*"
      },
      {
        "macaddress": "708976*"
      },
      {
        "macaddress": "7CF666*"
      },
      {
        "macaddress": "84E342*"
      },
      {
        "macaddress": "D4A651*"
      },
      {
        "macaddress": "D81F12*"
      }
    ],
    "documentation": "https://github.com/azerty9971/xtend_tuya",
    "integration_type": "hub",
    "iot_class": "cloud_push",
    "issue_tracker": "https://github.com/azerty9971/xtend_tuya/issues",
    "loggers": [
      "tuya_iot",
      "tuya_sharing"
    ],
    "requirements": [
      "tuya-device-sharing-sdk==0.2.1",
      "tuya-iot-py-sdk==0.6.6"
    ],
    "version": "3.0.8",
    "is_built_in": false,
    "overwrites_built_in": false
  },
  "setup_times": {},
  "data": {
    "mqtt_connected": null,
    "disabled_by": null,
    "disabled_polling": false,
    "id": "bf2e905eea20e98690croh",
    "name": "Energy Recovery Ventilator ",
    "category": "xfj",
    "local_key": "BHZEHK<|3j{F+5l-",
    "product_id": "ics2husbxx7n6wz5",
    "product_name": "Energy Recovery Ventilator ",
    "online": true,
    "sub": false,
    "time_zone": "+01:00",
    "active_time": "2024-11-25T16:45:34+00:00",
    "create_time": "2024-11-25T16:45:34+00:00",
    "update_time": "2024-11-25T16:45:34+00:00",
    "function": {
      "switch": {
        "type": "Boolean",
        "value": {},
        "property_update": false,
        "accessMode": null,
        "dpId": 1
      },
      "child_lock": {
        "type": "Boolean",
        "value": {},
        "property_update": false,
        "accessMode": null,
        "dpId": 14
      }
    },
    "status_range": {
      "switch": {
        "type": "Boolean",
        "value": {},
        "property_update": false,
        "access_mode": null,
        "dpId": 1
      },
      "eco2": {
        "type": "Integer",
        "value": {
          "unit": "",
          "min": 0,
          "max": 8001,
          "scale": 0,
          "step": 1
        },
        "property_update": false,
        "access_mode": null,
        "dpId": 6
      },
      "humidity_indoor": {
        "type": "Integer",
        "value": {
          "unit": "%",
          "min": 0,
          "max": 101,
          "scale": 0,
          "step": 1
        },
        "property_update": false,
        "access_mode": null,
        "dpId": 8
      },
      "temp_indoor": {
        "type": "Integer",
        "value": {
          "unit": "\u2103",
          "min": -20,
          "max": 100,
          "scale": 0,
          "step": 1
        },
        "property_update": false,
        "access_mode": null,
        "dpId": 9
      },
      "filter_life": {
        "type": "Integer",
        "value": {
          "unit": "\u5929",
          "min": 0,
          "max": 200,
          "scale": 0,
          "step": 1
        },
        "property_update": false,
        "access_mode": null,
        "dpId": 11
      },
      "child_lock": {
        "type": "Boolean",
        "value": {},
        "property_update": false,
        "access_mode": null,
        "dpId": 14
      },
      "fault": {
        "type": "Raw",
        "value": {
          "label": [
            "e1"
          ],
          "type": "bitmap",
          "maxlen": 1
        },
        "property_update": false,
        "access_mode": null,
        "dpId": 18
      },
      "temp_outdoor": {
        "type": "Integer",
        "value": {
          "unit": "\u2103",
          "min": -20,
          "max": 100,
          "scale": 0,
          "step": 1
        },
        "property_update": false,
        "access_mode": null,
        "dpId": 22
      }
    },
    "status": {
      "switch": true,
      "eco2": 440,
      "humidity_indoor": 55,
      "temp_indoor": 17,
      "filter_life": 35,
      "child_lock": false,
      "fault": 0,
      "temp_outdoor": 9
    },
    "local_strategy": {
      "1": {
        "value_convert": "default",
        "status_code": "switch",
        "config_item": {
          "statusFormat": "{\"switch\": \"$\"}",
          "valueDesc": "{}",
          "valueType": "Boolean",
          "enumMappingMap": {},
          "pid": "ics2husbxx7n6wz5"
        },
        "status_code_alias": [],
        "property_update": false,
        "use_open_api": false
      },
      "6": {
        "value_convert": "default",
        "status_code": "eco2",
        "config_item": {
          "statusFormat": "{\"eco2\": \"$\"}",
          "valueDesc": "{\"unit\": \"\", \"min\": 0, \"max\": 8001, \"scale\": 0, \"step\": 1}",
          "valueType": "Integer",
          "enumMappingMap": {},
          "pid": "ics2husbxx7n6wz5"
        },
        "status_code_alias": [],
        "property_update": false,
        "use_open_api": false
      },
      "8": {
        "value_convert": "default",
        "status_code": "humidity_indoor",
        "config_item": {
          "statusFormat": "{\"humidity_indoor\": \"$\"}",
          "valueDesc": "{\"unit\": \"%\", \"min\": 0, \"max\": 101, \"scale\": 0, \"step\": 1}",
          "valueType": "Integer",
          "enumMappingMap": {},
          "pid": "ics2husbxx7n6wz5"
        },
        "status_code_alias": [],
        "property_update": false,
        "use_open_api": false
      },
      "9": {
        "value_convert": "default",
        "status_code": "temp_indoor",
        "config_item": {
          "statusFormat": "{\"temp_indoor\": \"$\"}",
          "valueDesc": "{\"unit\": \"\\u2103\", \"min\": -20, \"max\": 100, \"scale\": 0, \"step\": 1}",
          "valueType": "Integer",
          "enumMappingMap": {},
          "pid": "ics2husbxx7n6wz5"
        },
        "status_code_alias": [],
        "property_update": false,
        "use_open_api": false
      },
      "11": {
        "value_convert": "default",
        "status_code": "filter_life",
        "config_item": {
          "statusFormat": "{\"filter_life\": \"$\"}",
          "valueDesc": "{\"unit\": \"\\u5929\", \"min\": 0, \"max\": 200, \"scale\": 0, \"step\": 1}",
          "valueType": "Integer",
          "enumMappingMap": {},
          "pid": "ics2husbxx7n6wz5"
        },
        "status_code_alias": [],
        "property_update": false,
        "use_open_api": false
      },
      "14": {
        "value_convert": "default",
        "status_code": "child_lock",
        "config_item": {
          "statusFormat": "{\"child_lock\": \"$\"}",
          "valueDesc": "{}",
          "valueType": "Boolean",
          "enumMappingMap": {},
          "pid": "ics2husbxx7n6wz5"
        },
        "status_code_alias": [],
        "property_update": false,
        "use_open_api": false
      },
      "18": {
        "value_convert": "default",
        "status_code": "fault",
        "config_item": {
          "statusFormat": "{\"fault\": \"$\"}",
          "valueDesc": "{\"label\": [\"e1\"], \"type\": \"bitmap\", \"maxlen\": 1}",
          "valueType": "Raw",
          "enumMappingMap": {},
          "pid": "ics2husbxx7n6wz5"
        },
        "status_code_alias": [],
        "property_update": false,
        "use_open_api": false
      },
      "22": {
        "value_convert": "default",
        "status_code": "temp_outdoor",
        "config_item": {
          "statusFormat": "{\"temp_outdoor\": \"$\"}",
          "valueDesc": "{\"unit\": \"\\u2103\", \"min\": -20, \"max\": 100, \"scale\": 0, \"step\": 1}",
          "valueType": "Integer",
          "enumMappingMap": {},
          "pid": "ics2husbxx7n6wz5"
        },
        "status_code_alias": [],
        "property_update": false,
        "use_open_api": false
      }
    },
    "home_assistant": {
      "name": "Energy Recovery Ventilator ",
      "name_by_user": null,
      "disabled": false,
      "disabled_by": null,
      "entities": [
        {
          "disabled": false,
          "disabled_by": null,
          "entity_category": null,
          "device_class": null,
          "original_device_class": null,
          "icon": null,
          "original_icon": null,
          "unit_of_measurement": "",
          "state": {
            "entity_id": "sensor.energy_recovery_ventilator_concentrazione_di_anidride_carbonica",
            "state": "440.0",
            "attributes": {
              "state_class": "measurement",
              "unit_of_measurement": "",
              "friendly_name": "Energy Recovery Ventilator  Concentrazione di anidride carbonica"
            },
            "last_changed": "2025-01-29T22:24:42.279029+00:00",
            "last_reported": "2025-01-29T22:24:53.779885+00:00",
            "last_updated": "2025-01-29T22:24:42.279029+00:00"
          }
        },
        {
          "disabled": false,
          "disabled_by": null,
          "entity_category": null,
          "device_class": null,
          "original_device_class": "temperature",
          "icon": null,
          "original_icon": null,
          "unit_of_measurement": "\u00b0C",
          "state": {
            "entity_id": "sensor.energy_recovery_ventilator_temperatura",
            "state": "17.0",
            "attributes": {
              "state_class": "measurement",
              "unit_of_measurement": "\u00b0C",
              "device_class": "temperature",
              "friendly_name": "Energy Recovery Ventilator  Temperatura"
            },
            "last_changed": "2025-01-29T22:24:27.962973+00:00",
            "last_reported": "2025-01-29T22:24:53.780119+00:00",
            "last_updated": "2025-01-29T22:24:27.962973+00:00"
          }
        },
        {
          "disabled": false,
          "disabled_by": null,
          "entity_category": null,
          "device_class": null,
          "original_device_class": "humidity",
          "icon": null,
          "original_icon": null,
          "unit_of_measurement": "%",
          "state": {
            "entity_id": "sensor.energy_recovery_ventilator_umidita",
            "state": "55.0",
            "attributes": {
              "state_class": "measurement",
              "unit_of_measurement": "%",
              "device_class": "humidity",
              "friendly_name": "Energy Recovery Ventilator  Umidit\u00e0"
            },
            "last_changed": "2025-01-29T22:24:27.966722+00:00",
            "last_reported": "2025-01-29T22:24:53.780297+00:00",
            "last_updated": "2025-01-29T22:24:27.966722+00:00"
          }
        },
        {
          "disabled": false,
          "disabled_by": null,
          "entity_category": "config",
          "device_class": null,
          "original_device_class": null,
          "icon": null,
          "original_icon": null,
          "unit_of_measurement": null,
          "state": {
            "entity_id": "switch.energy_recovery_ventilator_interruttore",
            "state": "on",
            "attributes": {
              "friendly_name": "Energy Recovery Ventilator  Interruttore"
            },
            "last_changed": "2025-01-29T22:24:27.995419+00:00",
            "last_reported": "2025-01-29T22:24:53.780426+00:00",
            "last_updated": "2025-01-29T22:24:27.995419+00:00"
          }
        }
      ]
    },
    "set_up": true,
    "support_local": true,
    "data_model": {}
  }
}

for anyone else looking for this, i have a apollo ERV (Holtop Rebrand AKA Pioneer ecoasis 150). I was able to get it working fully with modes and fan speed using local tuya with the following template. I did not configure pm2.5 as my version doesnt appear to have the sensor as it always reports 0 but its easy to add it to the template if you need it.

- switch:
    friendly_name: 'Apollo ERV '
    entity_category: None
    restore_on_reconnect: false
    is_passive_entity: false
    device_class: switch
    id: '1'
    platform: switch
    icon: ''
- sensor:
    friendly_name: co2
    entity_category: diagnostic
    unit_of_measurement: ppm
    device_class: carbon_dioxide
    state_class: measurement
    id: '6'
    platform: sensor
    icon: ''
- sensor:
    friendly_name: Humidity
    entity_category: diagnostic
    unit_of_measurement: '%'
    device_class: humidity
    state_class: measurement
    id: '8'
    platform: sensor
    icon: ''
- select:
    friendly_name: Fan Speed
    entity_category: config
    select_options:
      '0': Manual
      '1': Auto
      '2': Sleep
      '3': Pure Low
      '4': Pure Medium
      '5': Pure High
    restore_on_reconnect: true
    is_passive_entity: false
    id: '2'
    platform: select
    icon: ''
- sensor:
    friendly_name: Indoor Temperature
    entity_category: diagnostic
    unit_of_measurement: Fahrenheit
    device_class: temperature
    state_class: measurement
    id: '9'
    platform: sensor
    icon: ''
- sensor:
    friendly_name: Filter days left before cleaning
    entity_category: diagnostic
    unit_of_measurement: Days
    state_class: measurement
    id: '11'
    platform: sensor
    icon: ''
- sensor:
    friendly_name: Filter status
    entity_category: diagnostic
    state_class: measurement
    id: '105'
    platform: sensor
    icon: ''
- button:
    friendly_name: Filter Reset
    entity_category: config
    id: '108'
    platform: button
    icon: ''
- sensor:
    friendly_name: Fault Code
    entity_category: diagnostic
    id: '18'
    platform: sensor
    icon: ''
- number:
    id: '103'
    friendly_name: Intake Fan Speed
    entity_category: config
    min_value: 0.0
    max_value: 8.0
    step_size: 1.0
    restore_on_reconnect: true
    is_passive_entity: false
    device_class: speed
    platform: number
- number:
    id: '104'
    friendly_name: Exhaust Fan Speed
    entity_category: config
    min_value: 0.0
    max_value: 8.0
    step_size: 1.0
    restore_on_reconnect: true
    is_passive_entity: false
    dps_default_value: '3'
    device_class: speed
    platform: number

How did you get your ERV into Home Assistant? I have the Pioneer Airlink app, which has a user code and when I scan it with the home assistant area to scan, it says to use the correct app.

What app did you use to get your Pioneer ERV into and scan the Home Assistant QR code?

Thanks for the help

Check my esphome config for holtop erv.

Thanks for the template, I mistakenly blew away all my local Tuya settings when I got a new mini-split. One simple question though, I’ve been spinning my wheels for an hour trying to load up a template when adding this device but can’t figure it out.

I’ve went so far as adding a /templates directory in LocalTuya and adding an ERV.yaml template based on the one you shared, but I can not figure out how to select it anywhere.

Any help would be appreciated!

So for anyone else whos looking at this, after using my above code for a while, It kept disconnecting every few minutes unless i rbooted the integration. I ended up opening it up ( take unit off wall, unscrew 6 long bronze colored screws from back lift off front cover) and found that the module for tuya is super simple, in its own seperate enclosure and just sticked on with a JST connection with clearly labeled pins on the PCB. So i unsoldered and soldered the wires TRGV board label for Tx RX Gnd and VCC to a esp32. I used the data points i already had setup up above had gemini help me setup the ESPHOME YAML and it just worked. instantly. I love cloud cutting.

Id recommend anyone else with a holtop/apollo erv unit just go this route. Another bonus is you can leave the unit on, but turn fans to 0 speed now (which the tuya module would not allow). This lets me have a continous CO2 reading + humidity.

(yes i should have used different TX RX pins but im lazy)

esphome:
name: apollo-erv
friendly_name: Apollo ERV

esp32:
  board: esp32dev
  framework:
    type: arduino


api:
  encryption:
    key: "nope"


ota:
  - platform: esphome
    password: "nope"


# Using the Silkscreen TXD (GPIO1) and RXD (GPIO3)
uart:
  id: tuya_uart
  rx_pin: GPIO3
  tx_pin: GPIO1
  baud_rate: 9600


tuya:
  id: tuya_bus


logger:
  level: DEBUG
  baud_rate: 0 # VERY IMPORTANT when using GPIO1/3 to avoid logger interference


# --- DATA POINT MAPPING ---


switch:
  - platform: tuya
    name: "Power"
    switch_datapoint: 1
    device_class: switch
    
  - platform: tuya
    name: "Filter Reset"
    switch_datapoint: 108
    id: filter_reset_sw
    on_turn_on:
      - delay: 500ms
      - switch.turn_off: filter_reset_sw


select:
  - platform: tuya
    name: "Fan Mode"
    enum_datapoint: 2
    options:
      0: "Manual"
      1: "Auto"
      2: "Sleep"
      3: "Pure Low"
      4: "Pure Medium"
      5: "Pure High"


sensor:
  - platform: tuya
    name: "CO2"
    sensor_datapoint: 6
    unit_of_measurement: "ppm"
    device_class: carbon_dioxide
    state_class: measurement


  - platform: tuya
    name: "Humidity"
    sensor_datapoint: 8
    unit_of_measurement: "%"
    device_class: humidity
    state_class: measurement


  - platform: tuya
    name: "Indoor Temperature"
    sensor_datapoint: 9
    unit_of_measurement: "°F"
    device_class: temperature
    state_class: measurement


  - platform: tuya
    name: "Filter Days Left"
    sensor_datapoint: 11
    unit_of_measurement: "days"
    icon: "mdi:filter-outline"
    state_class: measurement


  - platform: tuya
    name: "Filter Status"
    sensor_datapoint: 105
    icon: "mdi:alert-circle-outline"


  - platform: tuya
    name: "Fault Code"
    sensor_datapoint: 18
    icon: "mdi:alert-octagon"


number:
  - platform: tuya
    name: "Intake Fan Speed"
    number_datapoint: 103
    min_value: 0
    max_value: 8
    step: 1
    mode: slider


  - platform: tuya
    name: "Exhaust Fan Speed"
    number_datapoint: 104
    min_value: 0
    max_value: 8
    step: 1
    mode: slider