import type { Models as ZHModels } from "zigbee-herdsman";
import type { ClusterCommandKeys, ClusterCommandResponseKeys, ClusterOrRawAttributeKeys, TCustomCluster, TCustomClusterPayload, ZigbeeOtaImageMeta } from "zigbee-herdsman/dist/controller/tstype";
import type { Header as ZHZclHeader } from "zigbee-herdsman/dist/zspec/zcl";
import type { TClusterAttributeKeys, TClusterPayload, TPartialClusterAttributes } from "zigbee-herdsman/dist/zspec/zcl/definition/clusters-types";
import type { FrameControl } from "zigbee-herdsman/dist/zspec/zcl/definition/tstype";
import type * as exposes from "./exposes";
export interface Logger {
    debug: (messageOrLambda: string | (() => string), namespace: string) => void;
    info: (messageOrLambda: string | (() => string), namespace: string) => void;
    warning: (messageOrLambda: string | (() => string), namespace: string) => void;
    error: (messageOrLambda: string | (() => string), namespace: string) => void;
}
export type Range = [number, number];
export interface KeyValue {
    [s: string]: unknown;
}
export interface KeyValueString {
    [s: string]: string;
}
export interface KeyValueNumberString {
    [s: number]: string;
}
export interface KeyValueAny {
    [s: string]: any;
}
export type Publish = (payload: KeyValue) => void;
export type Access = 0b001 | 0b010 | 0b100 | 0b011 | 0b101 | 0b111;
export type Expose = exposes.Numeric | exposes.Binary | exposes.Enum | exposes.Composite | exposes.List | exposes.Light | exposes.Switch | exposes.Lock | exposes.Cover | exposes.Climate | exposes.Fan | exposes.Text;
export type Option = exposes.Numeric | exposes.Binary | exposes.Composite | exposes.Enum | exposes.List | exposes.Text;
export interface Fingerprint {
    applicationVersion?: number;
    manufacturerID?: number;
    type?: "EndDevice" | "Router";
    dateCode?: string;
    hardwareVersion?: number;
    manufacturerName?: string;
    modelID?: string;
    powerSource?: "Battery" | "Mains (single phase)";
    softwareBuildID?: string;
    stackVersion?: number;
    zclVersion?: number;
    ieeeAddr?: RegExp;
    endpoints?: {
        ID?: number;
        profileID?: number;
        deviceID?: number;
        inputClusters?: number[];
        outputClusters?: number[];
    }[];
    priority?: number;
}
export type WhiteLabel = {
    vendor?: string;
    model: string;
    description?: string;
    fingerprint: Fingerprint[];
} | {
    vendor: string;
    model: string;
    description?: string;
};
export interface MockProperty {
    property: string;
    value: KeyValue | string;
}
export interface DiscoveryEntry {
    mockProperties: MockProperty[];
    type: string;
    object_id: string;
    discovery_payload: KeyValue;
}
export type BatteryLinearVoltage = {
    min: number;
    max: number;
    vOffset?: number;
};
export type BatteryNonLinearVoltage = "3V_2100" | "3V_1500_2800";
export interface DefinitionMeta {
    separateWhite?: boolean;
    /**
     * Enables the multi endpoint functionality in e.g. `fromZigbee.on_off`, example: normally this converter would return `{"state": "OFF"}`, when
     * multiEndpoint is enabled the `endpoint` method of the device definition will be called to determine the endpoint name which is then used as ke
     * y e.g. `{"state_left": "OFF"}`. Only needed when device sends the same attribute from multiple endpoints.
     *
     * @defaultValue false
     */
    multiEndpoint?: boolean;
    /**
     * enforce a certain endpoint for an attribute, e.g. `{"power": 4}` see `utils.enforceEndpoint()`
     */
    multiEndpointEnforce?: {
        [s: string]: number;
    };
    /**
     * Attributes to not suffix with the endpoint name
     */
    multiEndpointSkip?: string[];
    publishDuplicateTransaction?: boolean;
    tuyaDatapoints?: Tuya.MetaTuyaDataPoints;
    /**
     * used by toZigbee converters to disable the default response of some devices as they don't provide one.
     *
     * @defaultValue false
     */
    disableDefaultResponse?: boolean | ((entity: Zh.Endpoint) => boolean);
    /**
     *  Amount of pincodes the lock can handle
     */
    pinCodeCount?: number;
    /**
     * Set to true for cover controls that report position=100 as open.
     *
     * @defaultValue false
     */
    coverInverted?: boolean;
    /**
     * timeout for commands to this device used in toZigbee.
     *
     * @defaultValue 10000
     */
    timeout?: number;
    tuyaSendCommand?: "sendData" | "dataRequest";
    /**
     * Set cover state based on tilt
     */
    coverStateFromTilt?: boolean;
    /**
     * see e.g. HT-08 definition
     */
    thermostat?: {
        weeklyScheduleMaxTransitions?: number;
        weeklyScheduleSupportedModes?: number[];
        weeklyScheduleFirstDayDpId?: number;
        weeklyScheduleConversion?: string;
        /**
         * Do not map `pIHeatingDemand`/`pICoolingDemand` from 0-255 -\> 0-100, see `fromZigbee.thermostat`
         *
         * @defaultValue false
         */
        dontMapPIHeatingDemand?: boolean;
    };
    battery?: {
        /**
         * convert voltage to percentage using specified option. See `utils.batteryVoltageToPercentage()`
         *
         * @example '3V_2100'
         * @defaultValue null
         */
        voltageToPercentage?: BatteryNonLinearVoltage | BatteryLinearVoltage;
        /**
         * Prevents batteryPercentageRemaining from being divided (ZCL 200=100%, but some report 100=100%)
         *
         * @defaultValue false
         */
        dontDividePercentage?: boolean;
    };
    /**
     * see `toZigbee.light_color`
     *
     * @defaultValue false
     */
    applyRedFix?: boolean;
    /**
     * Indicates light turns off when brightness 1 is set
     *
     * @defaultValue false
     */
    turnsOffAtBrightness1?: boolean;
    moveToLevelWithOnOffDisable?: boolean | ((entity: Zh.Endpoint) => boolean);
    /**
     * Omit optional optionsMask/optionsOverride parameters for devices with strict ZCL v1 compliance
     *
     * @defaultValue false
     */
    omitOptionalLevelParams?: boolean;
    tuyaThermostatPreset?: {
        [s: number]: string;
    };
    /** Tuya specific thermostat options */
    tuyaThermostatSystemMode?: {
        [s: number]: string;
    };
    /** Tuya specific thermostat options */
    tuyaThermostatPresetToSystemMode?: {
        [s: number]: string;
    };
    /**
     * see `toZigbee.light_color`
     *
     * @defaultValue true
     */
    supportsEnhancedHue?: boolean | ((entity: Zh.Endpoint) => boolean);
    /**
     * Prevents some converters adding the `action_group` to the payload.
     *
     * @defaultValue false
     */
    disableActionGroup?: boolean;
    /**
     * see `toZigbee.light_color`, usually set by `light_*` extends via options.
     *
     * @defaultValue true
     */
    supportsHueAndSaturation?: boolean;
    /**
     * Do not set `position` or `tilt` to target value on /set. See `toZigbee.cover_position_tilt`
     *
     * @defaultValue false
     */
    coverPositionTiltDisableReport?: boolean;
    /**
     * Override the Home Assistant discovery payload using a custom function.
     */
    overrideHaDiscoveryPayload?(payload: KeyValueAny): void;
    /**
     * Never use a transition when transitioning to off (even when specified)
     */
    noOffTransitionWhenOff?: boolean | ((entity: Zh.Endpoint) => boolean);
    /**
     * Manufacturer specific
     */
    sinopeAlternateBacklightAutoDim?: boolean;
}
export type Configure = (device: Zh.Device, coordinatorEndpoint: Zh.Endpoint, definition: Definition) => Promise<void> | void;
export declare namespace OnEvent {
    type BaseData = {
        device: Zh.Device;
        deviceExposesChanged: () => void;
        state: KeyValue;
        options: KeyValue;
    };
    type Event = {
        type: "stop";
        data: {
            ieeeAddr: string;
        };
    } | {
        type: "deviceNetworkAddressChanged" | "deviceAnnounce" | "deviceJoined" | "start";
        data: BaseData;
    } | {
        type: "deviceOptionsChanged";
        data: BaseData & {
            from: KeyValue;
            to: KeyValue;
        };
    } | {
        type: "deviceInterview";
        data: BaseData & {
            status: "started" | "successful" | "failed";
        };
    };
    type Handler = (event: Event) => Promise<void> | void;
}
export interface ModernExtend {
    fromZigbee?: Definition["fromZigbee"];
    toZigbee?: Definition["toZigbee"];
    exposes?: (Expose | DefinitionExposesFunction)[];
    configure?: Definition["configure"][];
    meta?: Definition["meta"];
    ota?: Definition["ota"];
    options?: Option[];
    onEvent?: Definition["onEvent"][];
    endpoint?: Definition["endpoint"];
    isModernExtend: true;
}
export type DummyDevice = {
    manufacturerName?: string;
    isDummyDevice: true;
    applicationVersion?: number;
};
export type DefinitionExposesFunction = (device: Zh.Device | DummyDevice, options: KeyValue) => Expose[];
export type DefinitionExposes = Expose[] | DefinitionExposesFunction;
type DefinitionMatcher = {
    zigbeeModel: string[];
    fingerprint?: Fingerprint[];
} | {
    zigbeeModel?: string[];
    fingerprint: Fingerprint[];
};
type DefinitionBase = {
    model: string;
    vendor: string;
    description: string;
    whiteLabel?: WhiteLabel[];
    generated?: true;
    externalConverterName?: string;
};
type DefinitionConfig = {
    endpoint?: (device: Zh.Device) => {
        [s: string]: number;
    };
    /**
     * Semver version of the definition.
     * Changing this from one ZHC version to another, informs the application that it should trigger specific behavior (migration-like):
     * - major: reserved for future use
     * - minor: reserved for future use
     * - patch: the application should re-`configure` the device
     */
    version?: `0.0.${number}`;
    configure?: Configure;
    options?: Option[];
    meta?: DefinitionMeta;
    onEvent?: OnEvent.Handler;
    ota?: boolean | (Pick<ZigbeeOtaImageMeta, "modelId" | "otaHeaderString" | "hardwareVersionMin" | "hardwareVersionMax"> & {
        manufacturerName?: string;
    });
};
type DefinitionFeatures = {
    fromZigbee: Fz.Converter<any, any, any>[];
    toZigbee: Tz.Converter[];
    exposes: DefinitionExposes;
};
export type Definition = DefinitionMatcher & DefinitionBase & DefinitionConfig & DefinitionFeatures & Required<Pick<DefinitionConfig, "version">>;
export type DefinitionWithExtend = DefinitionMatcher & DefinitionBase & DefinitionConfig & (({
    extend: ModernExtend[];
} & Partial<DefinitionFeatures>) | DefinitionFeatures);
export type ExternalDefinitionWithExtend = DefinitionWithExtend & {
    externalConverterName: string;
};
export type ElementOf<T> = T extends readonly (infer U)[] ? U : T;
/** TFoundationRepetitive from ZSpec Zcl mapped to names used by ZHC (TODO: refactor names to match ZSpec Zcl directly / breaking ext. conv) */
export type TFoundationRepetitiveMapped = "read" | "readResponse" | "write" | "attributeReport";
export declare namespace Fz {
    export type ConverterTypeCmd<Cl extends number | string, Custom extends TCustomCluster | undefined = undefined> = `command${Capitalize<ClusterCommandKeys<Cl, Custom>[number] & string>}` | `command${Capitalize<ClusterCommandResponseKeys<Cl, Custom>[number] & string>}`;
    type ConverterType<Cl extends number | string, Custom extends TCustomCluster | undefined = undefined> = "raw" | TFoundationRepetitiveMapped | ClusterOrRawAttributeKeys<Cl, Custom>[number] | ConverterTypeCmd<Cl, Custom>;
    type ConverterTypeStringOrArray<Cl extends number | string, Custom extends TCustomCluster | undefined = undefined> = ConverterType<Cl, Custom> | readonly ConverterType<Cl, Custom>[];
    type MessageTypeDataMap<Cl extends string | number> = {
        raw: Buffer;
        read: (TClusterAttributeKeys<Cl>[number] | number)[];
        readResponse: TPartialClusterAttributes<Cl>;
        write: TPartialClusterAttributes<Cl>;
        attributeReport: TPartialClusterAttributes<Cl>;
    };
    type MessageTypeCustomDataMap<Custom extends TCustomCluster> = {
        raw: Buffer;
        read: (keyof Custom["attributes"] | number)[];
        readResponse: Partial<Custom["attributes"]>;
        write: Partial<Custom["attributes"]>;
        attributeReport: Partial<Custom["attributes"]>;
    };
    export interface Message<Cl extends number | string, Custom extends TCustomCluster | undefined = undefined, Ty extends ConverterTypeStringOrArray<Cl, Custom> = ConverterTypeStringOrArray<Cl, Custom>> {
        data: (ElementOf<Ty> extends infer Single ? Custom extends undefined ? Single extends keyof MessageTypeDataMap<Cl> ? MessageTypeDataMap<Cl>[Single] : Single extends string | number ? Single extends `command${infer Co}` ? TClusterPayload<Cl, Uncapitalize<Co>> : TClusterPayload<Cl, Single> : never : Custom extends TCustomCluster ? Single extends keyof MessageTypeCustomDataMap<Custom> ? MessageTypeDataMap<Cl>[Single] extends never ? MessageTypeCustomDataMap<Custom>[Single] extends never ? Record<number, unknown> : MessageTypeCustomDataMap<Custom>[Single] : MessageTypeDataMap<Cl>[Single] & MessageTypeCustomDataMap<Custom>[Single] : Single extends string | number ? Single extends `command${infer Co}` ? TClusterPayload<Cl, Uncapitalize<Co>> extends never ? TCustomClusterPayload<Custom, Uncapitalize<Co>> : TClusterPayload<Cl, Uncapitalize<Co>> & TCustomClusterPayload<Custom, Uncapitalize<Co>> : TClusterPayload<Cl, Single> extends never ? TCustomClusterPayload<Custom, Single> : TClusterPayload<Cl, Single> & TCustomClusterPayload<Custom, Single> : never : never : never) & Record<number, unknown>;
        endpoint: Zh.Endpoint;
        device: Zh.Device;
        meta: {
            zclTransactionSequenceNumber?: number;
            manufacturerCode?: number;
            frameControl?: FrameControl;
            rawData: Buffer;
        };
        groupID: number;
        type: ElementOf<Ty>;
        cluster: string | number;
        linkquality: number;
    }
    export interface Meta {
        state: KeyValue;
        device: Zh.Device;
        deviceExposesChanged: () => void;
    }
    export interface Converter<Cl extends number | string, Custom extends TCustomCluster | undefined = undefined, Ty extends ConverterTypeStringOrArray<Cl, Custom> = ConverterTypeStringOrArray<Cl, Custom>> {
        cluster: Cl;
        type: Ty;
        options?: Option[] | ((definition: Definition) => Option[]);
        convert: (model: Definition, msg: Message<Cl, Custom, Ty>, publish: Publish, options: KeyValue, meta: Fz.Meta) => KeyValueAny | void | Promise<void>;
    }
    export {};
}
export declare namespace Tz {
    interface Meta {
        message: KeyValue;
        device: Zh.Device | undefined;
        mapped: Definition | Definition[];
        options: KeyValue;
        state: KeyValue;
        endpoint_name: string | undefined;
        membersState?: {
            [s: string]: KeyValue;
        };
        publish: Publish;
        converterOptions?: KeyValue;
    }
    type ConvertSetResult = {
        state?: KeyValue;
        membersState?: {
            [s: string]: KeyValue;
        };
    } | void;
    interface Converter {
        key?: string[];
        options?: Option[] | ((definition: Definition) => Option[]);
        endpoints?: string[];
        convertSet?: (entity: Zh.Endpoint | Zh.Group, key: string, value: unknown, meta: Tz.Meta) => Promise<ConvertSetResult> | ConvertSetResult;
        convertGet?: (entity: Zh.Endpoint | Zh.Group, key: string, meta: Tz.Meta) => Promise<void>;
    }
}
export declare namespace Zh {
    type Endpoint = ZHModels.Endpoint;
    type Device = ZHModels.Device;
    type Group = ZHModels.Group;
    type ZclHeader = ZHZclHeader;
}
export declare namespace Tuya {
    interface DpValue {
        dp: number;
        datatype: number;
        data: Buffer;
    }
    interface ValueConverterSingle {
        to?: (value: any, meta?: Tz.Meta) => unknown;
        from?: (value: any, meta?: Fz.Meta, options?: KeyValue, publish?: Publish, msg?: Fz.Message<any>) => number | string | boolean | KeyValue | KeyValue[] | null;
    }
    interface MetaTuyaDataPointsMeta {
        skip?: (meta: Tz.Meta) => boolean;
        optimistic?: boolean;
    }
    type MetaTuyaDataPointsSingle = [number, string, ValueConverterSingle, MetaTuyaDataPointsMeta?];
    type MetaTuyaDataPoints = MetaTuyaDataPointsSingle[];
}
export declare namespace Reporting {
    interface Override {
        min?: number;
        max?: number;
        change?: number;
    }
}
export type LevelConfigFeatures = ("on_off_transition_time" | "on_transition_time" | "off_transition_time" | "execute_if_off" | "on_level" | "current_level_startup")[];
export {};
//# sourceMappingURL=types.d.ts.map