ZHA Quircks not loading due to "ImportError: attempted relative import with no known parent package"

Dear community,

I’m a bit of a newby here but getting along with my set-up. I’m trying out ZHA and Zigbee for my home and have selected the Aqara H1 EU No-neutral for one of my switches because I want to decouple the relay. The device shows up and works in ZHA but alas no decoupled mode is showing up.

I’ve done some searching and learned about ZHA quirks. I’ve done some google and found that maybe using the opple_switch quirk might solve my problem. I don’t know if I’m doing it right (as there doesn’t seem to be official installation documentation on the repo) but I’ve copied the file to my zha_quirks folder and nothing happens, even after rebooting/repairing/etc, the lot.

I’ve gone looking in the logs and there I find a traceback with the following error:

ImportError: attempted relative import with no known parent package

I’ve tried adding the opple_remote file as well that the quirk references but with no luck. I’ve tried setting permissions to 777 and no luck.

Any hints? Thanks

The quirks in the zha-device-handler repository are all included in ZHA - except those that are not in the currently release version yet.

In python code can import other packages.

While the information you provided does allow to track back the sources, it’s always good to think about those that you might want to answer - looking for oppo_switch on github does not return the path to the file as such.

You can see the relative import here -using a module/package outside the scope it was designed for can indeed give reference errors. Adding just a few referenced files may sometimes work, but you might end up hauling over a great deal of them.

However, as said, this probably already available and you can check the quirk that is used in the UI:
Example, the last line here shows the Quirk:

So if it show the one for your device, you’re using it.

In your particular case, you might be interested in this open issue:

Thanks for the quick reply.

I hadn’t realised that the quirks in the repo are already in home assistant, then the problem might be a different one.

The device is not using the quirk. Where do I start debugging this?

I’d still like to get the quirks system to work so that I can override when needed.

I’ve tried copying files over, however it still doesn’t work. It still shows the ImportError for every local file request. I’ve tried permissions, no dice. I just don’t know anymore.

The “signature” of the device you have is different from the “signature” available in your setup.
The quirk is found by matching the manufacturer and model name, and comparing the clusters reported by the device to the signature defined in the class (example below DanfossThermostat).

You can should check if the signature matches. If it does, then you maybe the latest quirk is not yet pushed to ZHA yet.

If it does not match, you can adapt.

Two methods:

  1. Copy the original code and adjust it - relative libraries need to become absolute of courase.
  2. Extend the original class and just update the signature (possibly keeping the “replacement”).

Below is an example where I extended.

  • It imports all modules, names that are referenced in the “wrapper” code.
    • The includes the quirk I am “upgrading”, and some constants (actually the constants come from the original code as the ‘… import *’ already imports all of it:
    from zhaquirks.lixee.zlinky import *
    from zhaquirks.lixee import LIXEE, ZLINKY_MANUFACTURER_CLUSTER_ID
  • It wraps the original code and updates the “signature”. In the code below that is class MyZLinkyTIC(ZLinkyTIC): signifies it extends on the original ZLinky TIC, but I updated the signature (I believe that the signature did not match exactly anymore due to a FW upgrade).
  • The example does nothing “fancy” - all definitions and added functionnality is still managed by the original code.
from zhaquirks.lixee.zlinky import *
from zigpy.profiles import zha
from zigpy.quirks import CustomCluster, CustomDevice
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, GreenPowerProxy, Identify, Ota, PowerConfiguration
from zigpy.zcl.clusters.homeautomation import ElectricalMeasurement, MeterIdentification
from zigpy.zcl.clusters.manufacturer_specific import ManufacturerSpecificCluster
from zigpy.zcl.clusters.smartenergy import Metering

from zhaquirks.const import (
    DEVICE_TYPE,
    ENDPOINTS,
    INPUT_CLUSTERS,
    MODELS_INFO,
    OUTPUT_CLUSTERS,
    PROFILE_ID,
)
from zhaquirks.lixee import LIXEE, ZLINKY_MANUFACTURER_CLUSTER_ID

class MyZLinkyTIC(ZLinkyTIC):
    """Modified ZLinky_TIC from LiXee."""

    signature = {
        MODELS_INFO: [(LIXEE, "ZLinky_TIC")],
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.METER_INTERFACE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    Metering.cluster_id,
                    MeterIdentification.cluster_id,
                    ElectricalMeasurement.cluster_id,
                    ZLinkyTICManufacturerCluster.cluster_id,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        },
    }
    replacement = {
        ENDPOINTS: {
            1: {
                PROFILE_ID: zha.PROFILE_ID,
                DEVICE_TYPE: zha.DeviceType.METER_INTERFACE,
                INPUT_CLUSTERS: [
                    Basic.cluster_id,
                    PowerConfiguration.cluster_id,
                    Identify.cluster_id,
                    ZLinkyTICMetering,
                    MeterIdentification.cluster_id,
                    ElectricalMeasurement.cluster_id,
                    ZLinkyTICManufacturerCluster,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id],
            },
            242: {
                PROFILE_ID: 41440,
                DEVICE_TYPE: 0x0061,
                INPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
                OUTPUT_CLUSTERS: [GreenPowerProxy.cluster_id],
            },
        },
    }

So that goes in the quirks directory that you defined (as you already know), and you can find out that it was matched by checking the information in the UI.

1 Like

I would love to do that, but my quirks don’t load due to an ImportError :confused:
I’m on Home Assistant OS, so I thought it’d be all fine.

I’ll keep trying!

Thanks for your great reply though.