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": {}
  }
}