zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
4,664 lines • 210 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.definitions = void 0;
const zigbee_herdsman_1 = require("zigbee-herdsman");
const fz = __importStar(require("../converters/fromZigbee"));
const tz = __importStar(require("../converters/toZigbee"));
const exposes = __importStar(require("../lib/exposes"));
const logger_1 = require("../lib/logger");
const lumi = __importStar(require("../lib/lumi"));
const m = __importStar(require("../lib/modernExtend"));
const reporting = __importStar(require("../lib/reporting"));
const globalStore = __importStar(require("../lib/store"));
const e = exposes.presets;
const ea = exposes.access;
const { lumiAction, lumiOperationMode, lumiPowerOnBehavior, lumiZigbeeOTA, lumiSwitchType, lumiAirQuality, lumiVoc, lumiDisplayUnit, lumiLight, lumiOutageCountRestoreBindReporting, lumiElectricityMeter, lumiPower, lumiOverloadProtection, lumiLedIndicator, lumiButtonLock, lumiMotorSpeed, lumiCurtainSpeed, lumiCurtainManualOpenClose, lumiCurtainAdaptivePullingSpeed, lumiCurtainManualStop, lumiCurtainReverse, lumiCurtainStatus, lumiCurtainLastManualOperation, lumiCurtainPosition, lumiCurtainTraverseTime, lumiCurtainCalibrationStatus, lumiCurtainCalibrated, lumiCurtainIdentifyBeep, lumiOnOff, lumiLedDisabledNight, lumiFlipIndicatorLight, lumiPreventReset, lumiClickMode, lumiSlider, lumiSetEventMode, lumiSwitchMode, lumiVibration, lumiReportInterval, lumiSensitivityAdjustment, lumiKnobRotation, lumiCommandMode, lumiBattery, lumiLockRelay, lumiMultiClick, lumiPreventLeave, lumiExternalSensor, } = lumi.modernExtend;
const NS = "zhc:lumi";
const { manufacturerCode } = lumi;
exports.definitions = [
{
zigbeeModel: ["lumi.flood.acn001"],
model: "SJCGQ13LM",
vendor: "Aqara",
description: "Water leak sensor E1",
fromZigbee: [fz.ias_water_leak_alarm_1, lumi.fromZigbee.lumi_specific, fz.battery],
toZigbee: [],
exposes: [e.water_leak(), e.battery(), e.battery_low(), e.battery_voltage(), e.device_temperature(), e.power_outage_count(false)],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.airm.fhac01"],
model: "KQJCMB11LM",
vendor: "Aqara",
description: "Air monitoring panel S1",
fromZigbee: [fz.temperature, fz.humidity, lumi.fromZigbee.lumi_pm25, lumi.fromZigbee.lumi_co2],
toZigbee: [],
exposes: [e.temperature(), e.humidity(), e.pm25(), e.co2()],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.magnet.acn001"],
model: "MCCGQ14LM",
vendor: "Aqara",
description: "Door and window sensor E1",
fromZigbee: [fz.ias_contact_alarm_1, lumi.fromZigbee.lumi_specific, fz.battery],
toZigbee: [],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [e.contact(), e.battery(), e.battery_low(), e.battery_voltage()],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
},
extend: [
m.quirkCheckinInterval("1_HOUR"),
// OTA request: "fieldControl":0, "manufacturerCode":4447, "imageType":10635, no available for now
// https://github.com/Koenkk/zigbee-OTA/pull/138
// lumiZigbeeOTA(),
],
},
{
zigbeeModel: ["lumi.magnet.ac01"],
model: "MCCGQ13LM",
vendor: "Aqara",
description: "Door and window sensor P1",
fromZigbee: [lumi.fromZigbee.lumi_contact, fz.ias_contact_alarm_1, lumi.fromZigbee.lumi_specific],
toZigbee: [lumi.toZigbee.lumi_detection_distance],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [
e.contact(),
e.battery(),
e.battery_voltage(),
e.tamper(),
e
.enum("detection_distance", ea.ALL, ["10mm", "20mm", "30mm"])
.withDescription('The sensor will be considered "off" within the set distance. Please press the device button before setting'),
],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.dimmer.rcbac1"],
model: "ZNDDMK11LM",
vendor: "Aqara",
description: "Smart lightstrip driver",
fromZigbee: [lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, ...m.light({ colorTemp: { range: undefined }, color: true }).fromZigbee],
toZigbee: [
lumi.toZigbee.lumi_dimmer_mode,
lumi.toZigbee.lumi_switch_power_outage_memory,
...m.light({ colorTemp: { range: undefined }, color: true }).toZigbee,
],
exposes: [
e.power(),
e.energy(),
e.voltage(),
e.device_temperature(),
e.power_outage_memory(),
// When in rgbw mode, only one of color and colortemp will be valid, and l2 will be invalid
// Do not control l2 in rgbw mode
e
.light_brightness_colortemp_colorxy([153, 370])
.removeFeature("color_temp_startup")
.withEndpoint("l1"),
e.light_brightness_colortemp([153, 370]).removeFeature("color_temp_startup").withEndpoint("l2"),
e.enum("dimmer_mode", ea.ALL, ["rgbw", "dual_ct"]).withDescription("Switch between rgbw mode or dual color temperature mode"),
],
extend: [m.deviceEndpoints({ endpoints: { l1: 1, l2: 2 } }), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.light.aqcn02"],
model: "ZNLDP12LM",
vendor: "Aqara",
description: "Light bulb",
extend: [lumiLight({ colorTemp: true, powerOutageMemory: "light" }), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.light.acn003"],
model: "ZNXDD01LM",
vendor: "Aqara",
description: "Ceiling light L1-350",
extend: [lumiLight({ colorTemp: true, powerOutageMemory: "switch", levelConfig: { features: ["on_level"] } }), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.light.cwac02", "lumi.light.acn014"],
model: "ZNLDP13LM",
vendor: "Aqara",
description: "Light bulb T1",
whiteLabel: [{ vendor: "Aqara", model: "LEDLBT1-L01" }],
extend: [
lumiZigbeeOTA(),
lumiLight({ colorTemp: true, powerOutageMemory: "switch" }),
m.forceDeviceType({ type: "Router" }),
m.forcePowerSource({ powerSource: "Mains (single phase)" }),
],
},
{
zigbeeModel: ["lumi.light.cwopcn01"],
model: "XDD11LM",
vendor: "Aqara",
description: "Opple MX960",
meta: { turnsOffAtBrightness1: true },
extend: [lumiLight({ colorTemp: true, powerOutageMemory: "switch" }), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.light.cwopcn02"],
model: "XDD12LM",
vendor: "Aqara",
description: "Opple MX650",
meta: { turnsOffAtBrightness1: true },
extend: [lumiZigbeeOTA(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
},
{
zigbeeModel: ["lumi.light.cwopcn03"],
model: "XDD13LM",
vendor: "Aqara",
description: "Opple MX480",
meta: { turnsOffAtBrightness1: true },
extend: [lumiLight({ colorTemp: true, powerOutageMemory: "switch", colorTempRange: [175, 370] }), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.light.cwjwcn01"],
model: "JWSP001A",
vendor: "Aqara",
description: "Jiawen LED Driver & Dimmer",
extend: [lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
},
{
zigbeeModel: ["lumi.light.cwjwcn02"],
model: "JWDL001A",
vendor: "Aqara",
description: "Embedded spot led light",
extend: [lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
},
{
zigbeeModel: ["lumi.sensor_switch"],
model: "WXKG01LM",
vendor: "Xiaomi",
whiteLabel: [
{ vendor: "Xiaomi", model: "YTC4040GL" },
{ vendor: "Xiaomi", model: "YTC4006CN" },
{ vendor: "Xiaomi", model: "YTC4017CN" },
{ vendor: "Xiaomi", model: "ZHTZ02LM" },
],
description: "Mi wireless switch",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_WXKG01LM],
exposes: [
e.battery(),
e.action(["single", "double", "triple", "quadruple", "hold", "release", "many"]),
e.battery_voltage(),
e.power_outage_count(false),
],
toZigbee: [],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.sensor_switch.aq2", "lumi.remote.b1acn01"],
model: "WXKG11LM",
vendor: "Aqara",
description: "Wireless mini switch",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [
e.battery(),
e.battery_voltage(),
e.action(["single", "double", "triple", "quadruple", "hold", "release"]),
e.device_temperature(),
e.power_outage_count(),
],
fromZigbee: [lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_basic],
toZigbee: [],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.sensor_switch.aq3", "lumi.sensor_swit"],
model: "WXKG12LM",
vendor: "Aqara",
description: "Wireless mini switch (with gyroscope)",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [e.battery(), e.action(["single", "double", "hold", "release", "shake"]), e.battery_voltage()],
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.sensor_86sw1"],
model: "WXKG03LM_rev1",
vendor: "Aqara",
description: "Wireless remote switch (single rocker), 2016 model",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [e.battery(), e.action(["single"]), e.battery_voltage()],
fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_basic],
toZigbee: [],
extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.remote.b186acn01"],
model: "WXKG03LM_rev2",
vendor: "Aqara",
description: "Wireless remote switch (single rocker), 2018 model",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [e.battery(), e.action(["single", "double", "hold"]), e.battery_voltage()],
fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_basic],
toZigbee: [],
extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.remote.b186acn02"],
model: "WXKG06LM",
vendor: "Aqara",
description: "Wireless remote switch D1 (single rocker)",
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [],
exposes: [e.battery(), e.action(["single", "double", "hold"]), e.battery_voltage()],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
configure: async (device, coordinatorEndpoint) => {
try {
const endpoint = device.endpoints[1];
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
}
catch {
// fails for some but device works as expected: https://github.com/Koenkk/zigbee2mqtt/issues/9136
}
},
},
{
zigbeeModel: ["lumi.light.acn132"],
model: "LGYCDD01LM",
vendor: "Aqara",
whiteLabel: [{ vendor: "Aqara", model: "RLS-K01D" }],
description: "Light strip T1",
extend: [
m.light({ effect: false, powerOnBehavior: false, colorTemp: { startup: false, range: [153, 370] }, color: true }),
lumiPowerOnBehavior(),
m.numeric({
name: "length",
valueMin: 1,
valueMax: 10,
valueStep: 0.2,
scale: 5,
unit: "m",
cluster: "manuSpecificLumi",
attribute: { ID: 0x051b, type: 0x20 },
description: "LED strip length",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "min_brightness",
valueMin: 0,
valueMax: 99,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0515, type: 0x20 },
description: "Minimum brightness level",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "max_brightness",
valueMin: 1,
valueMax: 100,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0516, type: 0x20 },
description: "Maximum brightness level",
zigbeeCommandOptions: { manufacturerCode },
}),
m.binary({
name: "audio",
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
cluster: "manuSpecificLumi",
attribute: { ID: 0x051c, type: 0x20 },
description: "Enabling audio",
zigbeeCommandOptions: { manufacturerCode },
}),
m.enumLookup({
name: "audio_sensitivity",
lookup: { low: 0, medium: 1, high: 2 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x051e, type: 0x20 },
description: "Audio sensitivity",
zigbeeCommandOptions: { manufacturerCode },
}),
m.enumLookup({
name: "audio_effect",
lookup: { random: 0, blink: 1, rainbow: 2, wave: 3 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x051d, type: 0x23 },
description: "Audio effect",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "preset",
valueMin: 1,
valueMax: 32,
cluster: "manuSpecificLumi",
attribute: { ID: 0x051f, type: 0x23 },
description: "Preset index (0-6 default presets)",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "speed",
valueMin: 1,
valueMax: 100,
cluster: "manuSpecificLumi",
attribute: { ID: 0x0520, type: 0x20 },
description: "Effect speed",
zigbeeCommandOptions: { manufacturerCode },
}),
lumiZigbeeOTA(),
],
},
{
zigbeeModel: ["lumi.sensor_86sw2", "lumi.sensor_86sw2.es1"],
model: "WXKG02LM_rev1",
vendor: "Aqara",
description: "Wireless remote switch (double rocker), 2016 model",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [e.battery(), e.action(["single_left", "single_right", "single_both"]), e.battery_voltage(), e.power_outage_count(false)],
fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_basic],
toZigbee: [],
extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.remote.b286acn01"],
model: "WXKG02LM_rev2",
vendor: "Aqara",
description: "Wireless remote switch (double rocker), 2018 model",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [
e.battery(),
e.action([
"single_left",
"single_right",
"single_both",
"double_left",
"double_right",
"double_both",
"hold_left",
"hold_right",
"hold_both",
]),
e.battery_voltage(),
],
fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_basic],
toZigbee: [],
extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.b1laus01"],
model: "WS-USC01",
vendor: "Aqara",
description: "Smart wall switch (no neutral, single rocker), US",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_switch_mode_switch,
lumi.toZigbee.lumi_switch_power_outage_memory,
],
exposes: [
e.switch(),
e.action(["single", "double"]),
e.flip_indicator_light(),
e.power_outage_memory(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
e.power_outage_count(),
e.device_temperature().withAccess(ea.STATE),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
// set "event" mode
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.switch.b2laus01"],
model: "WS-USC02",
vendor: "Aqara",
description: "Smart wall switch (no neutral, double rocker), US",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_switch_mode_switch,
],
exposes: [
e.switch().withEndpoint("top"),
e.switch().withEndpoint("bottom"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for top button").withEndpoint("top"),
e
.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
.withDescription("Decoupled mode for bottom button")
.withEndpoint("bottom"),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
e.power_outage_count(),
e.device_temperature().withAccess(ea.STATE),
e.flip_indicator_light(),
e.power_outage_memory(),
e.action(["single_top", "single_bottom", "single_both", "double_top", "double_bottom", "double_both"]),
],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { top: 1, bottom: 2 };
},
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.b1naus01"],
model: "WS-USC03",
vendor: "Aqara",
description: "Smart wall switch (with neutral, single rocker), US",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_power,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
],
exposes: [
e.switch(),
e.action(["single", "double"]),
e.flip_indicator_light(),
e.power_outage_count(),
e.device_temperature().withAccess(ea.STATE),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.voltage(),
e.power_outage_memory(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
// set "event" mode
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.b2naus01"],
model: "WS-USC04",
vendor: "Aqara",
description: "Smart wall switch (with neutral, double rocker), US",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_power,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
],
exposes: [
e.switch().withEndpoint("top"),
e.switch().withEndpoint("bottom"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for top button").withEndpoint("top"),
e
.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
.withDescription("Decoupled mode for bottom button")
.withEndpoint("bottom"),
e.power_outage_count(),
e.device_temperature().withAccess(ea.STATE),
e.flip_indicator_light(),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.voltage(),
e.power_outage_memory(),
e.action(["single_top", "single_bottom", "single_both", "double_top", "double_bottom", "double_both"]),
],
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
endpoint: (device) => {
return { top: 1, bottom: 2 };
},
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.l1acn1"],
model: "QBKG27LM",
vendor: "Aqara",
description: "Smart wall switch H1 (no neutral, single rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_switch_mode_switch,
],
exposes: [
e.switch(),
e.device_temperature(),
e.power_outage_memory(),
e.led_disabled_night(),
e.flip_indicator_light(),
e.action(["single", "double"]),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
e.power_outage_count(),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.l2acn1"],
model: "QBKG28LM",
vendor: "Aqara",
description: "Smart wall switch H1 (no neutral, double rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_switch_mode_switch,
],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { left: 1, right: 2 };
},
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.device_temperature(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
e.power_outage_memory(),
e.flip_indicator_light(),
e.led_disabled_night(),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.l3acn1"],
model: "QBKG29LM",
vendor: "Aqara",
description: "Smart wall switch H1 (no neutral, triple rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_switch_mode_switch,
],
meta: { multiEndpoint: true },
endpoint: (device) => ({ left: 1, center: 2, right: 3 }),
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("center"),
e.switch().withEndpoint("right"),
e.power_outage_memory(),
e.flip_indicator_light(),
e.led_disabled_night(),
e.power_outage_count(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e
.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
.withDescription("Decoupled mode for center button")
.withEndpoint("center"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
e.device_temperature().withAccess(ea.STATE),
e.action([
"single_left",
"double_left",
"single_center",
"double_center",
"single_right",
"double_right",
"single_left_center",
"double_left_center",
"single_left_right",
"double_left_right",
"single_center_right",
"double_center_right",
"single_all",
"double_all",
]),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.n1acn1"],
model: "QBKG30LM",
vendor: "Aqara",
description: "Smart wall switch H1 Pro (with neutral, single rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_flip_indicator_light,
],
exposes: [
e.switch(),
e.power(),
e.energy(),
e.voltage(),
e.device_temperature(),
e.power_outage_memory(),
e.led_disabled_night(),
e.flip_indicator_light(),
e.action(["single", "double"]),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
e.power_outage_count(),
],
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.n2acn1"],
model: "QBKG31LM",
vendor: "Aqara",
description: "Smart wall switch H1 Pro (with neutral, double rocker)",
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
endpoint: (device) => {
return { left: 1, right: 2 };
},
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_flip_indicator_light,
],
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.power(),
e.energy(),
e.voltage(),
e.device_temperature(),
e.power_outage_memory(),
e.led_disabled_night(),
e.flip_indicator_light(),
e.action(["single_left", "single_right", "single_both", "double_left", "double_right", "double_both"]),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e.power_outage_count(),
],
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.n3acn1"],
model: "QBKG32LM",
vendor: "Aqara",
description: "Smart wall switch H1 Pro (with neutral, triple rocker)",
meta: { multiEndpoint: true },
endpoint: (device) => {
return { left: 1, center: 2, right: 3 };
},
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_flip_indicator_light,
],
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.switch().withEndpoint("center"),
e.power(),
e.energy(),
e.voltage(),
e.device_temperature(),
e.power_outage_memory(),
e.led_disabled_night(),
e.flip_indicator_light(),
e.action([
"single_left",
"double_left",
"single_center",
"double_center",
"single_right",
"double_right",
"single_left_center",
"double_left_center",
"single_left_right",
"double_left_right",
"single_center_right",
"double_center_right",
"single_all",
"double_all",
]),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e
.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
.withDescription("Decoupled mode for center button")
.withEndpoint("center"),
e.power_outage_count(),
],
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.l1aeu1"],
model: "WS-EUK01",
vendor: "Aqara",
description: "Smart wall switch H1 EU (no neutral, single rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_switch_mode_switch,
],
exposes: [
e.switch(),
e.action(["single", "double"]),
e.power_outage_memory(),
e.flip_indicator_light(),
e.led_disabled_night(),
e.power_outage_count(),
e.device_temperature().withAccess(ea.STATE),
e.operation_mode_select(["control_relay", "decoupled"]).withDescription("Switches between direct relay control and action sending only"),
e
.mode_switch_select(["anti_flicker_mode", "quick_mode"])
.withDescription("Features. Anti flicker mode can be used to solve blinking issues of some lights." +
"Quick mode makes the device respond faster."),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
// set "event" mode
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.l2aeu1"],
model: "WS-EUK02",
vendor: "Aqara",
description: "Smart wall switch H1 EU (no neutral, double rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_switch_mode_switch,
],
meta: { multiEndpoint: true },
endpoint: (_device) => {
return { left: 1, right: 2 };
},
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.power_outage_memory(),
e.flip_indicator_light(),
e.led_disabled_night(),
e.power_outage_count(),
e.device_temperature().withAccess(ea.STATE),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.n1aeu1"],
model: "WS-EUK03",
vendor: "Aqara",
description: "Smart wall switch H1 EU (with neutral, single rocker)",
fromZigbee: [fz.on_off, fz.electrical_measurement, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
tz.electrical_measurement_power,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_led_disabled_night,
],
exposes: [
e.switch(),
e.action(["single", "double"]),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.flip_indicator_light(),
e.power_outage_memory(),
e.device_temperature().withAccess(ea.STATE),
e.led_disabled_night(),
e.power_outage_count(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
// set "event" mode
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.n2aeu1"],
model: "WS-EUK04",
vendor: "Aqara",
description: "Smart wall switch H1 EU (with neutral, double rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_power,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
lumi.toZigbee.lumi_led_disabled_night,
],
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
endpoint: (device) => {
return { left: 1, right: 2 };
},
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
e.device_temperature().withAccess(ea.STATE),
e.power_outage_memory(),
e.flip_indicator_light(),
e.led_disabled_night(),
e.power_outage_count(),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
// set "event" mode
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiPreventReset()],
},
{
zigbeeModel: ["lumi.ctrl_neutral1"],
model: "QBKG04LM",
vendor: "Aqara",
description: "Smart wall switch (no neutral, single rocker)",
fromZigbee: [lumi.fromZigbee.lumi_on_off, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_operation_mode_basic],
exposes: [
e.switch(),
e.action(["release", "hold", "double", "single", "hold_release"]),
e.enum("operation_mode", ea.STATE_SET, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
],
toZigbee: [tz.on_off, { ...lumi.toZigbee.lumi_switch_operation_mode_basic, convertGet: null }],
endpoint: (device) => {
return { system: 1, default: 2 };
},
extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forceDeviceType({ type: "EndDevice" })],
},
{
zigbeeModel: ["lumi.ctrl_ln1.aq1", "lumi.ctrl_ln1"],
model: "QBKG11LM",
vendor: "Aqara",
description: "Smart wall switch (with neutral, single rocker)",
fromZigbee: [
lumi.fromZigbee.lumi_action,
lumi.fromZigbee.lumi_action_multistate,
lumi.fromZigbee.lumi_on_off,
lumi.fromZigbee.lumi_basic,
lumi.fromZigbee.lumi_operation_mode_basic,
fz.ignore_multistate_report,
lumi.fromZigbee.lumi_power,
],
exposes: [
e.switch(),
e.power().withAccess(ea.STATE_GET),
e.device_temperature(),
e.energy(),
e.action(["single", "double", "release", "hold"]),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_operation_mode_basic, lumi.toZigbee.lumi_power],
endpoint: (device) => {
return { system: 1 };
},
extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.ctrl_neutral2"],
model: "QBKG03LM",
vendor: "Aqara",
description: "Smart wall switch (no neutral, double rocker)",
fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_on_off, lumi.fromZigbee.lumi_operation_mode_basic, lumi.fromZigbee.lumi_basic],
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.device_temperature(),
e.action([
"release_left",
"release_right",
"release_both",
"double_left",
"double_right",
"single_left",
"single_right",
"hold_release_left",
"hold_release_left",
]),
e
.enum("operation_mode", ea.STATE_SET, ["control_left_relay", "control_right_relay", "decoupled"])
.withDescription("Operation mode for left button")
.withEndpoint("left")
.withCategory("config"),
e
.enum("operation_mode", ea.STATE_SET, ["control_left_relay", "control_right_relay", "decoupled"])
.withDescription("Operation mode for right button")
.withEndpoint("right")
.withCategory("config"),
],
toZigbee: [tz.on_off, { ...lumi.toZigbee.lumi_switch_operation_mode_basic, convertGet: null }, lumi.toZigbee.lumi_power],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { system: 1, left: 2, right: 3 };
},
extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forceDeviceType({ type: "EndDevice" })],
},
{
zigbeeModel: ["lumi.ctrl_ln2.aq1", "lumi.ctrl_ln2"],
model: "QBKG12LM",
vendor: "Aqara",
description: "Smart wall switch (with neutral, double rocker)",
fromZigbee: [
lumi.fromZigbee.lumi_action,
lumi.fromZigbee.lumi_action_multistate,
lumi.fromZigbee.lumi_on_off,
lumi.fromZigbee.lumi_basic,
lumi.fromZigbee.lumi_operation_mode_basic,
lumi.fromZigbee.lumi_power,
],
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.device_temperature(),
e.energy(),
e.power().withAccess(ea.STATE_GET),
e.action([
"single_left",
"single_right",
"single_both",
"double_left",
"double_right",
"double_both",
"hold_left",
"hold_right",
"hold_both",
"release_left",
"release_right",
"release_both",
]),
e
.enum("operation_mode", ea.ALL, ["control_left_relay", "control_right_relay", "decoupled"])
.withDescription("Operation mode for left button")
.withEndpoint("left"),
e
.enum("operation_mode", ea.ALL, ["control_left_relay", "control_right_relay", "decoupled"])
.withDescription("Operation mode for right button")
.withEndpoint("right"),
],
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_operation_mode_basic, lumi.toZigbee.lumi_power],
endpoint: (device) => {
return { left: 1, right: 2, system: 1 };
},
extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.remote.b286acn02"],
model: "WXKG07LM",
vendor: "Aqara",
description: "Wireless remote switch D1 (double rocker)",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [],
endpoint: (device) => {
return { left: 1, right: 2, both: 3 };
},
exposes: [
e.battery(),
e.battery_voltage(),
e.action([
"single_left",
"single_right",
"single_both",
"double_left",
"double_right",
"double_both",
"hold_left",
"hold_right",
"hold_both",
]),
],
extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.b1lacn02"],
model: "QBKG21LM",
vendor: "Aqara",
description: "Smart wall switch D1 (no neutral, single rocker)",
fromZigbee: [lumi.fromZigbee.lumi_on_off, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_operation_mode_basic],
exposes: [
e.switch(),
e.action(["release", "hold", "double", "single", "hold_release"]),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_operation_mode_basic],
endpoint: (device) => {
return { system: 1, default: 2 };
},
extend: [lumiPreventReset(), m.forceDeviceType({ type: "EndDevice" }), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.switch.b2lacn02"],
model: "QBKG22LM",
vendor: "Aqara",
description: "Smart wall switch D1 (no neutral, double rocker)",
fromZigbee: [lumi.fromZigbee.lumi_on_off, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_operation_mode_basic],
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.action([
"release_left",
"release_right",
"release_both",
"double_left",
"double_right",
"single_left",
"single_right",
"hold_release_left",
"hold_release_left",
]),
e
.enum("operation_mode", ea.ALL, ["control_left_relay", "control_right_relay", "decoupled"])
.withDescription("Operation mode for left button")
.withEndpoint("left"),
e
.enum("operation_mode", ea.ALL, ["control_left_relay", "control_right_relay", "decoupled"])
.withDescription("Operation mode for right button")
.withEndpoint("right"),
],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_operation_mode_basic],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { system: 1, left: 2, right: 3 };
},
extend: [lumiPreventReset(), m.forceDeviceType({ type: "EndDevice" })],
},
{
zigbeeModel: ["lumi.switch.l3acn3"],
model: "QBKG25LM",
vendor: "Aqara",
description: "Smart wall switch D1 (no neutral, triple rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_switch_mode_switch,
lumi.toZigbee.lumi_flip_indicator_light,
],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { left: 1, center: 2, right: 3 };
},
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("center"),
e.switch().withEndpoint("right"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e
.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
.withDescription("Decoupled mode for center button")
.withEndpoint("center"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
e.power_outage_memory(),
e.led_disabled_night(),
e.device_temperature().withAccess(ea.STATE),
e.flip_indicator_light(),
e.action([
"left_single",
"left_double",
"center_single",
"center_double",
"right_single",
"right_double",
"single_left_center",
"double_left_center",
"single_left_right",
"double_left_right",
"single_center_right",
"double_center_right",
"single_all",
"double_all",
]),
e.power_outage_count(),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.n3acn3"],
model: "QBKG26LM",
vendor: "Aqara",
description: "Smart wall switch D1 (with neutral, triple rocker)",
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("center"),
e.switch().withEndpoint("right"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e
.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
.withDescription("Decoupled mode for center button")
.withEndpoint("center"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e.power().withAccess(ea.STATE),
e.power_outage_memory(),
e.led_disabled_night(),
e.voltage(),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.flip_indicator_light(),
e.action([
"single_left",
"double_left",
"single_center",
"double_center",
"single_right",
"double_right",
"single_left_center",
"double_left_center",
"single_left_right",
"double_left_right",
"single_center_right",
"double_center_right",
"single_all",
"double_all",
]),
],
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_flip_indicator_light,
],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { left: 1, center: 2, right: 3 };
},
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.b1nacn02"],
model: "QBKG23LM",
vendor: "Aqara",
description: "Smart wall switch D1 (with neutral, single rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_multistate],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_power, lumi.toZigbee.lumi_switch_operation_mode_basic],
endpoint: (device) => {
return { system: 1 };
},
exposes: [
e.switch(),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.voltage(),
e.action(["single", "release"]),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
],
extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forceDeviceType({ type: "Router" }), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.switch.b2nacn02"],
model: "QBKG24LM",
vendor: "Aqara",
description: "Smart wall switch D1 (with neutral, double rocker)",
fromZigbee: [
fz.on_off,
lumi.fromZigbee.lumi_power,
lumi.fromZigbee.lumi_action_multistate,
lumi.fromZigbee.lumi_operation_mode_basic,
lumi.fromZigbee.lumi_specific,
lumi.fromZigbee.lumi_basic,
],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_power, lumi.toZigbee.lumi_switch_operation_mode_basic],
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
endpoint: (device) => {
return { left: 1, right: 2, system: 1 };
},
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.energy(),
e.power().withAccess(ea.STATE_GET),
e.action(["hold_left", "single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
e
.enum("operation_mode", ea.ALL, ["control_left_relay", "decoupled"])
.withDescription("Decoupled mode for left button")
.withEndpoint("left"),
e
.enum("operation_mode", ea.ALL, ["control_right_relay", "decoupled"])
.withDescription("Decoupled mode for right button")
.withEndpoint("right"),
],
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.b1lacn01"],
model: "QBKG17LM",
vendor: "Aqara",
description: "Smart wall switch T1 (no neutral, single rocker)",
extend: [
lumiZigbeeOTA(),
lumiOnOff({ powerOutageMemory: "binary", operationMode: true }),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiAction({ actionLookup: { single: 1, double: 2 } }),
lumiPreventReset(),
],
},
{
zigbeeModel: ["lumi.switch.b2lacn01"],
model: "QBKG18LM",
vendor: "Aqara",
description: "Smart wall switch T1 (no neutral, double rocker)",
extend: [
lumiZigbeeOTA(),
m.deviceEndpoints({ endpoints: { left: 1, right: 2 } }),
lumiOnOff({ powerOutageMemory: "binary", operationMode: true, endpointNames: ["left", "right"] }),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiAction({ actionLookup: { single: 1, double: 2 }, buttonLookup: { left: 41, right: 42, both: 51 } }),
lumiPreventReset(),
],
},
{
zigbeeModel: ["lumi.switch.b1nacn01"],
model: "QBKG19LM",
vendor: "Aqara",
description: "Smart wall switch T1 (with neutral, single rocker)",
extend: [
lumiZigbeeOTA(),
lumiOnOff({ powerOutageMemory: "binary", operationMode: true }),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiAction({ actionLookup: { single: 1, double: 2 } }),
lumiElectricityMeter(),
lumiPower(),
lumiPreventReset(),
],
},
{
zigbeeModel: ["lumi.switch.b2nacn01"],
model: "QBKG20LM",
vendor: "Aqara",
description: "Smart wall switch T1 (with neutral, double rocker)",
extend: [
m.forceDeviceType({ type: "Router" }),
m.forcePowerSource({ powerSource: "Mains (single phase)" }),
lumiZigbeeOTA(),
m.deviceEndpoints({ endpoints: { left: 1, right: 2 } }),
lumiOnOff({ powerOutageMemory: "binary", operationMode: true, endpointNames: ["left", "right"] }),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiAction({ actionLookup: { single: 1, double: 2 }, buttonLookup: { left: 41, right: 42, both: 51 } }),
lumiElectricityMeter(),
lumiPower(),
lumiPreventReset(),
],
},
{
zigbeeModel: ["lumi.switch.b3l01"],
model: "QBKG33LM",
vendor: "Aqara",
description: "Smart wall switch T1 (no neutral, triple rocker)",
extend: [
lumiZigbeeOTA(),
m.deviceEndpoints({ endpoints: { left: 1, center: 2, right: 3 } }),
lumiOnOff({ powerOutageMemory: "binary", operationMode: true, endpointNames: ["left", "center", "right"] }),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiAction({
actionLookup: { single: 1, double: 2 },
buttonLookup: {
left: 41,
center: 42,
right: 43,
left_center: 51,
left_right: 52,
center_right: 53,
all: 61,
},
}),
lumiPreventReset(),
],
},
{
zigbeeModel: ["lumi.switch.b3n01"],
model: "QBKG34LM",
vendor: "Aqara",
description: "Smart wall switch T1 (with neutral, triple rocker)",
extend: [
lumiZigbeeOTA(),
m.deviceEndpoints({ endpoints: { left: 1, center: 2, right: 3 } }),
lumiOnOff({ powerOutageMemory: "binary", operationMode: true, endpointNames: ["left", "center", "right"] }),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiAction({
actionLookup: { single: 1, double: 2 },
buttonLookup: {
left: 41,
center: 42,
right: 43,
left_center: 51,
left_right: 52,
center_right: 53,
all: 61,
},
}),
lumiElectricityMeter(),
lumiPower(),
lumiPreventReset(),
],
},
{
zigbeeModel: ["lumi.sens", "lumi.sensor_ht"],
model: "WSDCGQ01LM",
vendor: "Xiaomi",
whiteLabel: [
{ vendor: "Xiaomi", model: "YTC4042GL" },
{ vendor: "Xiaomi", model: "YTC4007CN" },
{ vendor: "Xiaomi", model: "YTC4018CN" },
],
description: "Mi temperature and humidity sensor",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_temperature, fz.humidity],
toZigbee: [],
exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.weather"],
model: "WSDCGQ11LM",
vendor: "Aqara",
description: "Temperature and humidity sensor",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_temperature, fz.humidity, fz.pressure],
toZigbee: [],
exposes: [e.battery(), e.temperature(), e.humidity(), e.pressure(), e.battery_voltage()],
extend: [m.quirkCheckinInterval("1_HOUR"), m.forcePowerSource({ powerSource: "Battery" })],
},
{
zigbeeModel: ["lumi.sensor_ht.agl02"],
model: "WSDCGQ12LM",
vendor: "Aqara",
description: "Temperature and humidity sensor T1",
whiteLabel: [
{ vendor: "Aqara", model: "TH-S02D" },
{ vendor: "Yandex", model: "YNDX-00523" },
],
fromZigbee: [lumi.fromZigbee.lumi_specific, fz.temperature, fz.humidity, lumi.fromZigbee.lumi_pressure, fz.battery],
toZigbee: [],
exposes: [e.temperature(), e.humidity(), e.pressure(), e.device_temperature(), e.battery(), e.battery_voltage(), e.power_outage_count(false)],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
const binds = ["msTemperatureMeasurement", "msRelativeHumidity", "msPressureMeasurement"];
await reporting.bind(endpoint, coordinatorEndpoint, binds);
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.sensor_motion"],
model: "RTCGQ01LM",
vendor: "Xiaomi",
whiteLabel: [
{ vendor: "Xiaomi", model: "YTC4041GL" },
{ vendor: "Xiaomi", model: "YTC4004CN" },
{ vendor: "Xiaomi", model: "YTC4016CN" },
{ vendor: "Xiaomi", model: "ZHTZ02LM" },
],
description: "Mi motion sensor",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, fz.occupancy_with_timeout],
toZigbee: [],
exposes: [e.battery(), e.occupancy(), e.battery_voltage(), e.power_outage_count(false)],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.sensor_motion.aq2"],
model: "RTCGQ11LM",
vendor: "Aqara",
description: "Motion sensor",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, fz.occupancy_with_timeout, lumi.fromZigbee.lumi_illuminance],
toZigbee: [],
exposes: [e.battery(), e.occupancy(), e.device_temperature(), e.battery_voltage(), e.illuminance(), e.power_outage_count(false)],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.motion.agl02"],
model: "RTCGQ12LM",
vendor: "Aqara",
description: "Motion sensor T1",
whiteLabel: [{ vendor: "Yandex", model: "YNDX-00522" }],
fromZigbee: [lumi.fromZigbee.lumi_occupancy_illuminance, lumi.fromZigbee.lumi_specific, fz.battery],
toZigbee: [lumi.toZigbee.lumi_detection_interval],
exposes: [
e.occupancy(),
e.illuminance(),
e
.numeric("detection_interval", ea.ALL)
.withValueMin(2)
.withValueMax(65535)
.withUnit("s")
.withDescription("Time interval for detecting actions"),
e.device_temperature(),
e.battery(),
e.battery_voltage(),
e.power_outage_count(false),
],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
await endpoint.read("manuSpecificLumi", [0x0102], { manufacturerCode: manufacturerCode });
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.motion.agl04"],
model: "RTCGQ13LM",
vendor: "Aqara",
description: "High precision motion sensor",
fromZigbee: [lumi.fromZigbee.lumi_occupancy, lumi.fromZigbee.lumi_specific, fz.battery],
toZigbee: [lumi.toZigbee.lumi_detection_interval, lumi.toZigbee.lumi_motion_sensitivity],
exposes: [
e.occupancy(),
e.enum("motion_sensitivity", ea.ALL, ["low", "medium", "high"]),
e
.numeric("detection_interval", ea.ALL)
.withValueMin(2)
.withValueMax(65535)
.withUnit("s")
.withDescription("Time interval for detecting actions"),
e.device_temperature(),
e.battery(),
e.battery_voltage(),
e.power_outage_count(false),
],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
await endpoint.read("manuSpecificLumi", [0x0102], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.motion.ac02"],
model: "RTCGQ14LM",
vendor: "Aqara",
whiteLabel: [{ vendor: "Aqara", model: "MS-S02" }],
description: "Motion sensor P1",
fromZigbee: [lumi.fromZigbee.lumi_occupancy_illuminance, lumi.fromZigbee.lumi_specific, fz.battery],
toZigbee: [lumi.toZigbee.lumi_detection_interval, lumi.toZigbee.lumi_motion_sensitivity, lumi.toZigbee.lumi_trigger_indicator],
exposes: [
e.occupancy(),
e.illuminance(),
e
.motion_sensitivity_select(["low", "medium", "high"])
.withDescription("Select motion sensitivity to use. Press pairing button right before changing this otherwise it will fail."),
e
.detection_interval()
.withDescription("Time interval between action detection. Press pairing button right before changing this otherwise it will fail."),
e
.trigger_indicator()
.withDescription("When this option is enabled then " +
"blue LED will blink once when motion is detected. " +
"Press pairing button right before changing this otherwise it will fail."),
e.device_temperature(),
e.battery(),
e.battery_voltage(),
],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
await endpoint.read("manuSpecificLumi", [0x0102], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0152], { manufacturerCode: manufacturerCode });
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.motion.acn001"],
model: "RTCGQ15LM",
vendor: "Aqara",
description: "Motion sensor E1",
fromZigbee: [lumi.fromZigbee.lumi_occupancy_illuminance, lumi.fromZigbee.lumi_specific, fz.battery],
toZigbee: [lumi.toZigbee.lumi_detection_interval],
exposes: [
e.occupancy(),
e.illuminance(),
e
.numeric("detection_interval", ea.ALL)
.withValueMin(2)
.withValueMax(65535)
.withUnit("s")
.withDescription("Time interval for detecting actions"),
e.device_temperature(),
e.battery(),
e.battery_voltage(),
e.power_outage_count(false),
],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
await endpoint.read("manuSpecificLumi", [0x0102], { manufacturerCode: manufacturerCode });
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.motion.ac01"],
model: "RTCZCGQ11LM",
vendor: "Aqara",
description: "Presence sensor FP1",
fromZigbee: [lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_presence_region_events],
toZigbee: [
lumi.toZigbee.lumi_presence,
lumi.toZigbee.lumi_monitoring_mode,
lumi.toZigbee.lumi_approach_distance,
lumi.toZigbee.lumi_motion_sensitivity,
lumi.toZigbee.lumi_reset_nopresence_status,
lumi.toZigbee.lumi_presence_region_upsert,
lumi.toZigbee.lumi_presence_region_delete,
],
exposes: [
e.presence().withAccess(ea.STATE_GET),
e.device_temperature(),
e.power_outage_count(),
e
.enum("presence_event", ea.STATE, ["enter", "leave", "left_enter", "right_leave", "right_enter", "left_leave", "approach", "away"])
.withDescription('Presence events: "enter", "leave", "left_enter", "right_leave", "right_enter", "left_leave", "approach", "away"'),
e
.enum("monitoring_mode", ea.ALL, ["undirected", "left_right"])
.withDescription("Monitoring mode with or without considering right and left sides"),
e.enum("approach_distance", ea.ALL, ["far", "medium", "near"]).withDescription("The distance at which the sensor detects approaching"),
e
.enum("motion_sensitivity", ea.ALL, ["low", "medium", "high"])
.withDescription("Different sensitivities means different static human body recognition rate and response speed of occupied"),
e.enum("reset_nopresence_status", ea.SET, [""]).withDescription("Reset the status of no presence"),
e
.enum("action", ea.STATE, ["region_*_enter", "region_*_leave", "region_*_occupied", "region_*_unoccupied"])
.withDescription('Most recent region event. Event template is "region_<REGION_ID>_<EVENT_TYPE>", ' +
'where <REGION_ID> is region number (1-10), <EVENT_TYPE> is one of "enter", "leave", "occupied", "unoccupied". ' +
'"enter" / "leave" events are usually triggered first, followed by "occupied" / "unoccupied" after a couple of seconds.'),
e
.composite("region_upsert", "region_upsert", ea.SET)
.withDescription("Definition of a new region to be added (or replace existing one). " +
"Creating or modifying a region requires you to define which zones of a 7x4 detection grid " +
"should be active for that zone. Regions can overlap, meaning that a zone can be defined " +
'in more than one region (eg. "zone x = 1 & y = 1" can be added to region 1 & 2). ' +
'"Zone x = 1 & y = 1" is the nearest zone on the right (from sensor\'s perspective, along the detection path).')
.withFeature(e
.numeric("region_id", ea.SET)
.withValueMin(lumi.presence.constants.region_config_regionId_min)
.withValueMax(lumi.presence.constants.region_config_regionId_max))
.withFeature(e
.list("zones", ea.SET, e
.composite("Zone position", "zone_position", ea.SET)
.withFeature(e
.numeric("x", ea.SET)
.withValueMin(lumi.presence.constants.region_config_zoneX_min)
.withValueMax(lumi.presence.constants.region_config_zoneX_max))
.withFeature(e
.numeric("y", ea.SET)
.withValueMin(lumi.presence.constants.region_config_zoneY_min)
.withValueMax(lumi.presence.constants.region_config_zoneY_max)))
.withDescription('list of dictionaries in the format {"x": 1, "y": 1}, {"x": 2, "y": 1}')),
e
.composite("region_delete", "region_delete", ea.SET)
.withDescription("Region definition to be deleted from the device.")
.withFeature(e
.numeric("region_id", ea.SET)
.withValueMin(lumi.presence.constants.region_config_regionId_min)
.withValueMax(lumi.presence.constants.region_config_regionId_max)),
],
configure: async (device, coordinatorEndpoint) => {
device.softwareBuildID = `${device.applicationVersion}`;
device.save();
const endpoint = device.getEndpoint(1);
await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0142], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0144], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0146], { manufacturerCode: manufacturerCode });
},
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.sensor_occupy.agl1"],
model: "FP1E",
vendor: "Aqara",
description: "Presence sensor",
fromZigbee: [lumi.fromZigbee.lumi_specific],
toZigbee: [lumi.toZigbee.lumi_motion_sensitivity],
exposes: [
e.device_temperature(),
e.power_outage_count(),
e.motion_sensitivity_select(["low", "medium", "high"]).withDescription("Select motion sensitivity to use."),
],
ota: true,
configure: async (device, coordinatorEndpoint) => {
// Retrieve motion sensitivity value
const endpoint = device.getEndpoint(1);
await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
},
extend: [
lumiZigbeeOTA(),
lumi.lumiModernExtend.fp1ePresence(),
lumi.lumiModernExtend.fp1eMovement(),
lumi.lumiModernExtend.fp1eTargetDistance(),
lumi.lumiModernExtend.fp1eDetectionRange(),
lumi.lumiModernExtend.fp1eSpatialLearning(),
lumi.lumiModernExtend.fp1eRestartDevice(),
m.identify(),
],
},
{
zigbeeModel: ["lumi.sensor_magnet"],
model: "MCCGQ01LM",
vendor: "Xiaomi",
whiteLabel: [
{ vendor: "Xiaomi", model: "YTC4039GL" },
{ vendor: "Xiaomi", model: "YTC4005CN" },
{ vendor: "Xiaomi", model: "YTC4015CN" },
{ vendor: "Xiaomi", model: "ZHTZ02LM" },
],
description: "Mi door and window sensor",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_contact],
toZigbee: [],
exposes: [e.battery(), e.contact(), e.battery_voltage(), e.power_outage_count(false)],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.sensor_magnet.aq2"],
model: "MCCGQ11LM",
vendor: "Aqara",
description: "Door and window sensor",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_contact],
toZigbee: [],
exposes: [e.battery(), e.contact(), e.device_temperature(), e.battery_voltage(), e.power_outage_count(false), e.trigger_count()],
extend: [m.quirkCheckinInterval("1_HOUR"), m.forcePowerSource({ powerSource: "Battery" })],
},
{
zigbeeModel: ["lumi.sensor_wleak.aq1"],
model: "SJCGQ11LM",
vendor: "Aqara",
description: "Water leak sensor",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic],
toZigbee: [],
exposes: [e.battery(), e.battery_voltage(), e.device_temperature(), e.power_outage_count(false), e.trigger_count()],
extend: [m.quirkCheckinInterval("1_HOUR"), m.iasZoneAlarm({ zoneType: "water_leak", zoneAttributes: ["alarm_1", "battery_low"] })],
},
{
zigbeeModel: ["lumi.flood.agl02"],
model: "SJCGQ12LM",
vendor: "Aqara",
description: "Water leak sensor T1",
whiteLabel: [
{ vendor: "Aqara", model: "WL-S02D" },
{ vendor: "Yandex", model: "YNDX-00521" },
],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, fz.ias_water_leak_alarm_1, lumi.fromZigbee.lumi_specific],
toZigbee: [],
exposes: [e.battery(), e.water_leak(), e.battery_low(), e.tamper(), e.battery_voltage()],
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.sensor_cube", "lumi.sensor_cube.aqgl01"],
model: "MFKZQ01LM",
vendor: "Aqara",
description: "Cube",
whiteLabel: [{ vendor: "Xiaomi", model: "MFKZQ01LM" }],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_action_analog],
exposes: [
e.battery(),
e.battery_voltage(),
e.angle("action_angle"),
e.device_temperature(),
e.power_outage_count(false),
e.cube_side("action_from_side"),
e.cube_side("action_side"),
e.cube_side("action_to_side"),
e.cube_side("side"),
e.action(["shake", "throw", "wakeup", "fall", "tap", "slide", "flip180", "flip90", "rotate_left", "rotate_right"]),
],
toZigbee: [],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.plug"],
model: "ZNCZ02LM",
description: "Mi smart plug",
vendor: "Xiaomi",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_basic, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory, lumi.toZigbee.lumi_power],
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature(), e.power_outage_memory()],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.plug.mitw01"],
model: "ZNCZ03LM",
description: "Mi smart plug TW",
vendor: "Xiaomi",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_basic, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_power],
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE), e.voltage()],
},
{
zigbeeModel: ["lumi.plug.mmeu01"],
model: "ZNCZ04LM",
description: "Mi smart plug EU",
vendor: "Xiaomi",
fromZigbee: [
fz.on_off,
lumi.fromZigbee.lumi_power,
lumi.fromZigbee.lumi_specific,
fz.ignore_occupancy_report,
fz.ignore_illuminance_report,
fz.ignore_time_read,
],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_power,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_auto_off,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_overload_protection,
],
exposes: [
e.switch(),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.voltage(),
e.current(),
e.consumer_connected(),
e.led_disabled_night(),
e.power_outage_memory(),
e.auto_off(20),
e.overload_protection(100, 2300),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.plug.maus01"],
model: "ZNCZ12LM",
description: "Smart plug US",
vendor: "Aqara",
fromZigbee: [
fz.on_off,
lumi.fromZigbee.lumi_power,
lumi.fromZigbee.lumi_specific,
lumi.fromZigbee.lumi_basic,
fz.ignore_occupancy_report,
fz.ignore_illuminance_report,
],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_power,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_auto_off,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_overload_protection,
],
exposes: [
e.switch(),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.voltage(),
e.current(),
e.consumer_connected(),
e.led_disabled_night(),
e.power_outage_memory(),
e.auto_off(20),
e.overload_protection(100, 2300),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.plug.maeu01"],
model: "SP-EUC01",
description: "Smart plug EU",
vendor: "Aqara",
extend: [m.forceDeviceType({ type: "Router" }), lumiZigbeeOTA()],
fromZigbee: [
fz.on_off,
lumi.fromZigbee.lumi_basic,
fz.electrical_measurement,
fz.metering,
lumi.fromZigbee.lumi_specific,
lumi.fromZigbee.lumi_power,
fz.device_temperature,
],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_overload_protection,
lumi.toZigbee.lumi_auto_off,
lumi.toZigbee.lumi_socket_button_lock,
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
await reporting.onOff(endpoint);
// Not all plugs support electricity measurements:
// - https://github.com/Koenkk/zigbee2mqtt/issues/6861
// - https://github.com/Koenkk/zigbee-herdsman-converters/issues/1050#issuecomment-673111969
// Voltage and current are not supported:
// - https://github.com/Koenkk/zigbee-herdsman-converters/issues/1050
try {
await reporting.bind(endpoint, coordinatorEndpoint, ["haElectricalMeasurement"]);
await endpoint.read("haElectricalMeasurement", ["acPowerMultiplier", "acPowerDivisor"]);
}
catch (e) {
logger_1.logger.warning(`SP-EUC01 failed to setup electricity measurements (${e.message})`, NS);
logger_1.logger.debug(`${e.stack}`, NS);
}
try {
await reporting.bind(endpoint, coordinatorEndpoint, ["seMetering"]);
await reporting.readMeteringMultiplierDivisor(endpoint);
await reporting.currentSummDelivered(endpoint, { change: 0 });
}
catch (e) {
logger_1.logger.warning(`SP-EUC01 failed to setup metering (${e.message})`, NS);
logger_1.logger.debug(`${e.stack}`, NS);
}
},
onEvent: (type, data, device) => {
const switchEndpoint = device.getEndpoint(1);
if (switchEndpoint == null) {
return;
}
// This device doesn't support temperature reporting.
// Therefore we read the temperature every 30 min.
if (type === "stop") {
clearInterval(globalStore.getValue(device, "interval"));
globalStore.clearValue(device, "interval");
}
else if (!globalStore.hasValue(device, "interval")) {
const interval = setInterval(async () => {
try {
await switchEndpoint.read("genDeviceTempCfg", ["currentTemperature"]);
}
catch {
// Do nothing
}
}, 1800000);
globalStore.putValue(device, "interval", interval);
}
},
exposes: [
e.switch(),
e.power(),
e.energy(),
e.power_outage_memory(),
e.voltage(),
e.current(),
e.device_temperature().withDescription("Device temperature (polled every 30 min)"),
e.consumer_connected(),
e.led_disabled_night(),
e.overload_protection(100, 2300),
e.auto_off(20),
e.button_lock(),
],
},
{
zigbeeModel: ["lumi.plug.aq1"],
model: "ZNCZ11LM",
vendor: "Aqara",
description: "Smart plug",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, fz.ignore_occupancy_report, lumi.fromZigbee.lumi_basic],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_power,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_auto_off,
],
exposes: [
e.switch(),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.device_temperature(),
e.voltage(),
e.power_outage_memory(),
e.led_disabled_night(),
e.auto_off(30),
],
extend: [m.customTimeResponse("2000_LOCAL")],
},
{
zigbeeModel: ["lumi.ctrl_86plug", "lumi.ctrl_86plug.aq1"],
model: "QBCZ11LM",
description: "Smart wall outlet",
vendor: "Aqara",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_basic],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory, lumi.toZigbee.lumi_power],
exposes: [
e.switch(),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.voltage(),
e.power_outage_memory(),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.sensor_smoke"],
model: "JTYJ-GD-01LM/BW",
description: "Mijia Honeywell smoke detector",
vendor: "Xiaomi",
whiteLabel: [{ vendor: "Xiaomi", model: "YTC4020RT" }],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_smoke],
toZigbee: [lumi.toZigbee.lumi_sensitivity, lumi.toZigbee.lumi_selftest],
exposes: [
e.smoke(),
e.battery_low(),
e.tamper(),
e.battery(),
e.enum("sensitivity", ea.STATE_SET, ["low", "medium", "high"]),
e.numeric("smoke_density", ea.STATE),
e.enum("selftest", ea.SET, [""]),
e.battery_voltage(),
e.binary("test", ea.STATE, true, false).withDescription("Test mode activated"),
e.device_temperature(),
e.power_outage_count(false),
],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.sensor_natgas"],
model: "JTQJ-BF-01LM/BW",
vendor: "Xiaomi",
whiteLabel: [{ vendor: "Xiaomi", model: "YTC4019RT" }],
description: "Mijia Honeywell gas leak detector",
fromZigbee: [fz.ias_gas_alarm_1, lumi.fromZigbee.lumi_gas_sensitivity, lumi.fromZigbee.lumi_gas_density],
toZigbee: [lumi.toZigbee.lumi_sensitivity, lumi.toZigbee.lumi_selftest],
exposes: [
e.gas(),
e.tamper(),
e.enum("sensitivity", ea.STATE_SET, ["low", "medium", "high"]),
e.numeric("gas_density", ea.STATE),
e.enum("selftest", ea.SET, [""]),
],
extend: [m.forceDeviceType({ type: "Router" }), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.sensor_gas.acn02"],
model: "JT-BZ-01AQ/A",
vendor: "Aqara",
description: "Smart natural gas detector",
whiteLabel: [{ vendor: "Aqara", model: "JT-BZ-03AQ/A" }],
fromZigbee: [lumi.fromZigbee.lumi_specific],
toZigbee: [
lumi.toZigbee.lumi_alarm,
lumi.toZigbee.lumi_density,
lumi.toZigbee.lumi_gas_sensitivity,
lumi.toZigbee.lumi_selftest,
lumi.toZigbee.lumi_buzzer,
lumi.toZigbee.lumi_buzzer_manual,
lumi.toZigbee.lumi_linkage_alarm,
lumi.toZigbee.lumi_state,
lumi.toZigbee.lumi_power_outage_count,
],
exposes: [
e.gas().withAccess(ea.STATE_GET),
e.numeric("gas_density", ea.STATE_GET).withUnit("%LEL").withDescription("Value of gas concentration"),
e
.enum("gas_sensitivity", ea.ALL, ["10%LEL", "15%LEL"])
.withDescription('Gas concentration value at which an alarm is triggered ("10%LEL" is more sensitive than "15%LEL")'),
e
.enum("selftest", ea.SET, ["selftest"])
.withDescription("Starts the self-test process (checking the indicator light and buzzer work properly)"),
e.binary("test", ea.STATE, true, false).withDescription("Self-test in progress"),
e
.enum("buzzer", ea.SET, ["mute", "alarm"])
.withDescription("The buzzer can be muted and alarmed manually. " +
'During a gas alarm, the buzzer can be manually muted for 10 minutes ("mute"), but cannot be unmuted manually ' +
"before this timeout expires. The buzzer cannot be pre-muted, as this function only works during a gas alarm. " +
'During the absence of a gas alarm, the buzzer can be manually alarmed ("alarm") and disalarmed ("mute"), ' +
'but for this "linkage_alarm" option must be enabled'),
e.binary("buzzer_manual_alarm", ea.STATE_GET, true, false).withDescription("Buzzer alarmed (manually)"),
e.binary("buzzer_manual_mute", ea.STATE_GET, true, false).withDescription("Buzzer muted (manually)"),
e
.binary("linkage_alarm", ea.ALL, true, false)
.withDescription("When this option is enabled and a gas " +
'alarm has occurred, then "linkage_alarm_state"=true, and when the gas alarm has ended or the buzzer has ' +
'been manually muted, then "linkage_alarm_state"=false'),
e.binary("linkage_alarm_state", ea.STATE, true, false).withDescription('"linkage_alarm" is triggered'),
e
.binary("state", ea.STATE_GET, "preparation", "work")
.withDescription('"Preparation" or "work" ' +
'(measurement of the gas concentration value and triggering of an alarm are only performed in the "work" state)'),
e.power_outage_count().withAccess(ea.STATE_GET),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.write("manuSpecificLumi", { 331: { value: 1, type: 0x20 } }, { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x013a], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x013b], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x013d], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0126], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0139], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x014b], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0002], { manufacturerCode: manufacturerCode });
},
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.sensor_smoke.acn03"],
model: "JY-GZ-01AQ",
vendor: "Aqara",
description: "Smart smoke detector",
whiteLabel: [{ vendor: "Aqara", model: "JY-GZ-03AQ" }],
fromZigbee: [lumi.fromZigbee.lumi_specific, fz.battery],
toZigbee: [
lumi.toZigbee.lumi_alarm,
lumi.toZigbee.lumi_density,
lumi.toZigbee.lumi_selftest,
lumi.toZigbee.lumi_buzzer,
lumi.toZigbee.lumi_buzzer_manual,
lumi.toZigbee.lumi_heartbeat_indicator,
lumi.toZigbee.lumi_linkage_alarm,
],
exposes: [
e.smoke().withAccess(ea.STATE_GET),
e.numeric("smoke_density", ea.STATE_GET).withDescription("Value of smoke concentration"),
e.numeric("smoke_density_dbm", ea.STATE_GET).withUnit("dB/m").withDescription("Value of smoke concentration in dB/m"),
e
.enum("selftest", ea.SET, ["selftest"])
.withDescription("Starts the self-test process (checking the indicator light and buzzer work properly)"),
e.binary("test", ea.STATE, true, false).withDescription("Self-test in progress"),
e
.enum("buzzer", ea.SET, ["mute", "alarm"])
.withDescription("The buzzer can be muted and alarmed manually. " +
'During a smoke alarm, the buzzer can be manually muted for 80 seconds ("mute") and unmuted ("alarm"). ' +
"The buzzer cannot be pre-muted, as this function only works during a smoke alarm. " +
'During the absence of a smoke alarm, the buzzer can be manually alarmed ("alarm") and disalarmed ("mute"), ' +
'but for this "linkage_alarm" option must be enabled'),
e.binary("buzzer_manual_alarm", ea.STATE_GET, true, false).withDescription("Buzzer alarmed (manually)"),
e.binary("buzzer_manual_mute", ea.STATE_GET, true, false).withDescription("Buzzer muted (manually)"),
e
.binary("heartbeat_indicator", ea.ALL, true, false)
.withDescription("When this option is enabled then in the normal monitoring state, the green indicator light flashes every 60 seconds"),
e
.binary("linkage_alarm", ea.ALL, true, false)
.withDescription("When this option is enabled and a smoke " +
'alarm has occurred, then "linkage_alarm_state"=true, and when the smoke alarm has ended or the buzzer has ' +
'been manually muted, then "linkage_alarm_state"=false'),
e.binary("linkage_alarm_state", ea.STATE, true, false).withDescription('"linkage_alarm" is triggered'),
e.battery(),
e.battery_voltage(),
e.power_outage_count(false),
],
meta: { battery: { voltageToPercentage: { min: 2475, max: 3000 } } },
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.write("manuSpecificLumi", { 331: { value: 1, type: 0x20 } }, { manufacturerCode: manufacturerCode });
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
await endpoint.read("manuSpecificLumi", [0x013a], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x013b], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x013c], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x013d], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0126], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x014b], { manufacturerCode: manufacturerCode });
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.lock.v1"],
model: "A6121",
vendor: "Xiaomi",
description: "Vima Smart Lock",
fromZigbee: [lumi.fromZigbee.lumi_lock_report],
exposes: [e.text("inserted", ea.STATE)],
toZigbee: [],
},
{
zigbeeModel: ["lumi.vibration.aq1"],
model: "DJT11LM",
vendor: "Aqara",
description: "Vibration sensor",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_vibration_analog],
toZigbee: [lumi.toZigbee.lumi_vibration_sensitivity],
exposes: [
e.battery(),
e.device_temperature(),
e.vibration(),
e.action(["vibration", "tilt", "drop"]),
e.numeric("strength", ea.STATE),
e.numeric("sensitivity", ea.STATE_SET).withDescription("Sensitivity, 1 = highest, 21 = lowest").withValueMin(1).withValueMax(21),
e.angle_axis("angle_x"),
e.angle_axis("angle_y"),
e.angle_axis("angle_z"),
e.x_axis(),
e.y_axis(),
e.z_axis(),
e.battery_voltage(),
e.power_outage_count(false),
],
extend: [m.quirkCheckinInterval("1_HOUR")],
},
{
zigbeeModel: ["lumi.vibration.agl01"],
model: "DJT12LM",
vendor: "Aqara",
description: "Vibration sensor T1",
extend: [
lumiVibration(),
// lumiMiscellaneous(),
lumiReportInterval(),
lumiSensitivityAdjustment(),
lumiBattery({ voltageToPercentage: { min: 2850, max: 3000 } }),
lumiZigbeeOTA(),
m.quirkCheckinInterval("1_HOUR"),
],
},
{
zigbeeModel: ["lumi.curtain"],
model: "ZNCLDJ11LM",
description: "Curtain controller",
vendor: "Aqara",
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_curtain_position, lumi.fromZigbee.lumi_curtain_position_tilt],
toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_options],
onEvent: async (type, data, device) => {
if (type === "message" &&
data.type === "attributeReport" &&
data.cluster === "genBasic" &&
data.data["1028"] !== undefined &&
data.data["1028"] === 0) {
// Try to read the position after the motor stops, the device occasionally report wrong data right after stopping
// Might need to add delay, seems to be working without one but needs more tests.
await device.getEndpoint(1).read("genAnalogOutput", ["presentValue"]);
}
},
exposes: [
e.cover_position().setAccess("state", ea.ALL),
e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
e.enum("motor_state", ea.STATE, ["stopped", "opening", "closing"]).withDescription("Motor state"),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.curtain.aq2"],
model: "ZNGZDJ11LM",
description: "Roller shade controller",
vendor: "Aqara",
whiteLabel: [{ vendor: "Aqara", model: "SRSC-M01" }],
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_curtain_position, lumi.fromZigbee.lumi_curtain_position_tilt],
toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_options],
exposes: [
e.cover_position().setAccess("state", ea.ALL),
e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.curtain.vagl02"],
model: "ZNGZDJ16LM",
description: "Roller shade controller T1C",
vendor: "Aqara",
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_curtain_position, lumi.fromZigbee.lumi_curtain_position_tilt],
toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_options],
exposes: [
e.cover_position().setAccess("state", ea.ALL),
e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.curtain.hagl04"],
model: "ZNCLDJ12LM",
vendor: "Aqara",
description: "Curtain controller B1",
fromZigbee: [
lumi.fromZigbee.lumi_basic,
lumi.fromZigbee.lumi_curtain_position,
lumi.fromZigbee.lumi_curtain_position_tilt,
lumi.fromZigbee.lumi_curtain_status,
],
toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_options],
onEvent: async (type, data, device) => {
// The position (genAnalogOutput.presentValue) reported via an attribute contains an invalid value
// however when reading it will provide the correct value.
if (data.type === "attributeReport" && data.cluster === "genAnalogOutput") {
await device.endpoints[0].read("genAnalogOutput", ["presentValue"]);
}
},
exposes: [
e.cover_position().setAccess("state", ea.ALL),
e.battery(),
e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
e.enum("motor_state", ea.STATE, ["closing", "opening", "stopped"]).withDescription("The current state of the motor."),
e.power_outage_count(),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.curtain.hagl07"],
model: "ZNCLDJ14LM",
vendor: "Aqara",
description: "Curtain controller C2",
fromZigbee: [
lumi.fromZigbee.lumi_basic,
lumi.fromZigbee.lumi_curtain_position,
lumi.fromZigbee.lumi_curtain_status,
lumi.fromZigbee.lumi_curtain_options,
],
toZigbee: [
lumi.toZigbee.lumi_curtain_position_state,
lumi.toZigbee.lumi_curtain_hand_open,
lumi.toZigbee.lumi_curtain_reverse,
lumi.toZigbee.lumi_curtain_limits_calibration_ZNCLDJ14LM,
],
exposes: [
e.cover_position().setAccess("state", ea.ALL),
e.binary("reverse_direction", ea.ALL, true, false).withDescription("Whether the curtain direction is inverted"),
e.binary("hand_open", ea.ALL, true, false).withDescription("Pulling curtains by hand starts the motor"),
e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
e.enum("motor_state", ea.STATE, ["closing", "opening", "stopped"]).withDescription("The current state of the motor."),
e.power_outage_count(),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.curtain.acn04"],
model: "ZNCLDJ01LM",
vendor: "Aqara",
description: "Curtain controller C3",
toZigbee: [lumi.toZigbee.lumi_curtain_limits_calibration, lumi.toZigbee.lumi_curtain_automatic_calibration_ZNCLDJ01LM],
exposes: [
e.enum("limits_calibration", ea.SET, ["start", "end", "reset"]).withDescription("Calibrate the position limits"),
e
.enum("automatic_calibration", ea.SET, ["calibrate"])
.withDescription("Performs an automatic calibration process similar to Aqara’s method to set curtain limits."),
],
extend: [
m.windowCovering({ controls: ["lift"], coverInverted: true, configureReporting: true }),
lumiCurtainSpeed(),
lumiCurtainManualOpenClose(),
lumiCurtainAdaptivePullingSpeed(),
lumiCurtainManualStop(),
lumiCurtainReverse(),
lumiCurtainStatus(),
lumiCurtainLastManualOperation(),
lumiCurtainPosition(),
lumiCurtainTraverseTime(),
lumiCurtainCalibrationStatus(),
lumiCurtainCalibrated(),
lumiCurtainIdentifyBeep(),
m.identify(),
lumiZigbeeOTA(),
],
},
{
zigbeeModel: ["lumi.curtain.acn002"],
model: "ZNJLBL01LM",
description: "Roller shade driver E1",
vendor: "Aqara",
whiteLabel: [{ vendor: "Aqara", model: "RSD-M01" }],
fromZigbee: [
lumi.fromZigbee.lumi_curtain_position,
lumi.fromZigbee.lumi_curtain_status,
fz.ignore_basic_report,
lumi.fromZigbee.lumi_specific,
],
ota: true,
toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_battery, lumi.toZigbee.lumi_curtain_charging_status],
onEvent: async (type, data, device) => {
if (type === "message" &&
data.type === "attributeReport" &&
data.cluster === "genMultistateOutput" &&
data.data.presentValue !== undefined &&
data.data.presentValue > 1) {
// Try to read the position after the motor stops, the device occasionally report wrong data right after stopping
// Might need to add delay, seems to be working without one but needs more tests.
await device.getEndpoint(1).read("genAnalogOutput", ["presentValue"]);
}
},
exposes: [
e.cover_position().setAccess("state", ea.ALL),
e.battery().withAccess(ea.STATE_GET),
e.device_temperature(),
e.binary("charging_status", ea.STATE_GET, true, false).withDescription("The current charging status."),
e.enum("motor_state", ea.STATE, ["closing", "opening", "stopped", "blocked"]).withDescription("The current state of the motor."),
e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
],
configure: async (device, coordinatorEndpoint) => {
device.powerSource = "Battery";
device.save();
const endpoint = device.getEndpoint(1);
await endpoint.read("manuSpecificLumi", [0x040a], { manufacturerCode: manufacturerCode });
},
extend: [
m.quirkAddEndpointCluster({
endpointID: 1,
inputClusters: ["manuSpecificLumi"],
}),
lumiZigbeeOTA(),
lumiMotorSpeed(),
],
},
{
// 'lumi.curtain.acn003' - CN version (ZNCLBL01LM), 'lumi.curtain.agl001' - global version (CM-M01)
zigbeeModel: ["lumi.curtain.acn003", "lumi.curtain.agl001"],
model: "ZNCLBL01LM",
vendor: "Aqara",
whiteLabel: [
{ vendor: "Aqara", model: "CM-M01" },
{ vendor: "Aqara", model: "CM-M01R" },
],
description: "Curtain driver E1",
fromZigbee: [fz.battery, lumi.fromZigbee.lumi_curtain_position_tilt, lumi.fromZigbee.lumi_specific, fz.power_source],
toZigbee: [
lumi.toZigbee.lumi_curtain_position_state,
lumi.toZigbee.lumi_curtain_battery_voltage,
lumi.toZigbee.lumi_curtain_hooks_lock,
lumi.toZigbee.lumi_curtain_hooks_state,
lumi.toZigbee.lumi_curtain_hand_open,
lumi.toZigbee.lumi_curtain_limits_calibration,
tz.power_source,
tz.battery_percentage_remaining,
],
exposes: [
e.cover_position().setAccess("state", ea.ALL),
e.binary("hand_open", ea.ALL, true, false).withDescription("Pulling curtains by hand starts the motor"),
e.enum("limits_calibration", ea.SET, ["start", "end", "reset"]).withDescription("Calibrate the position limits"),
e.battery().withAccess(ea.STATE_GET),
e.battery_voltage().withAccess(ea.STATE_GET),
e.device_temperature(),
e.illuminance(),
e.action(["manual_open", "manual_close"]),
e.enum("motor_state", ea.STATE, ["stopped", "opening", "closing", "pause"]).withDescription("Motor state"),
e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
e.enum("hooks_lock", ea.STATE_SET, ["LOCK", "UNLOCK"]).withDescription("Lock the curtain driver hooks"),
e.enum("hooks_state", ea.STATE_GET, ["unlocked", "locked", "locking", "unlocking"]).withDescription("Hooks state"),
e.numeric("target_position", ea.STATE).withUnit("%").withDescription("Target position"),
e.enum("power_source", ea.STATE_GET, ["battery", "dc_source"]).withDescription("The current power source"),
e.binary("charging", ea.STATE_GET, true, false).withDescription("The current charging state"),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
// Read correct version to replace version advertised by `genBasic` and `genOta`:
// https://github.com/Koenkk/zigbee2mqtt/issues/15745
await endpoint.read("manuSpecificLumi", [0x00ee], { manufacturerCode: manufacturerCode });
await endpoint.read("genPowerCfg", ["batteryPercentageRemaining"]);
await endpoint.read("manuSpecificLumi", [0x040b], { manufacturerCode: manufacturerCode });
await endpoint.read("manuSpecificLumi", [0x0428], { manufacturerCode: manufacturerCode });
await endpoint.read("genBasic", ["powerSource"]);
await endpoint.read("closuresWindowCovering", ["currentPositionLiftPercentage"]);
},
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.relay.c2acn01"],
model: "LLKZMK11LM",
vendor: "Aqara",
description: "Dual relay module",
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_power, fz.ignore_multistate_report, fz.on_off, lumi.fromZigbee.lumi_basic_raw],
meta: { multiEndpoint: true },
toZigbee: [tz.on_off, lumi.toZigbee.lumi_interlock, lumi.toZigbee.lumi_power, lumi.toZigbee.lumi_switch_power_outage_memory],
endpoint: (device) => {
return { l1: 1, l2: 2 };
},
exposes: [
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.device_temperature(),
e.voltage(),
e.current(),
e.switch().withEndpoint("l1"),
e.switch().withEndpoint("l2"),
e.power_outage_count(false),
e.power_outage_memory(),
e.binary("interlock", ea.STATE_SET, true, false).withDescription("Enabling prevents both relais being on at the same time"),
],
extend: [lumiZigbeeOTA(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.switch.acn047"],
model: "LLKZMK12LM",
vendor: "Aqara",
whiteLabel: [{ vendor: "Aqara", model: "DCM-K01" }],
description: "Dual relay module T2",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_power],
toZigbee: [tz.on_off],
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
endpoint: (device) => {
return { l1: 1, l2: 2 };
},
exposes: [
e.switch().withEndpoint("l1"),
e.switch().withEndpoint("l2"),
e.power(),
e.current(),
e.energy(),
e.voltage(),
e.device_temperature(),
],
extend: [
lumiSwitchType(),
lumiPowerOnBehavior({ lookup: { on: 0, previous: 1, off: 2, toggle: 3 } }),
lumiOperationMode({ description: "Decoupled mode for 1st relay", endpointName: "l1" }),
lumiOperationMode({ description: "Decoupled mode for 2nd relay", endpointName: "l2" }),
lumiAction({ endpointNames: ["l1", "l2"] }),
m.binary({
name: "interlock",
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
cluster: "manuSpecificLumi",
attribute: { ID: 0x02d0, type: 0x10 },
description: "Enabling prevents both relays being on at the same time (Interlock)",
zigbeeCommandOptions: { manufacturerCode },
}),
m.enumLookup({
name: "mode",
lookup: { power: 0, pulse: 1, dry: 3 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x0289, type: 0x20 },
description: "Work mode: Power mode, Dry mode with impulse, Dry mode",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "pulse_length",
valueMin: 200,
valueMax: 2000,
unit: "ms",
cluster: "manuSpecificLumi",
attribute: { ID: 0x00eb, type: 0x21 },
description: "Impulse length in Dry mode with impulse",
zigbeeCommandOptions: { manufacturerCode },
}),
lumiZigbeeOTA(),
],
},
{
zigbeeModel: ["lumi.lock.acn02"],
model: "ZNMS12LM",
description: "Smart door lock S2",
vendor: "Aqara",
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_door_lock_report, lumi.fromZigbee.lumi_door_lock_low_battery],
toZigbee: [],
exposes: [
e.battery(),
e.battery_voltage(),
e.battery_low(),
e.binary("state", ea.STATE, "UNLOCK", "LOCK"),
e.binary("reverse", ea.STATE, "UNLOCK", "LOCK"),
e.enum("action", ea.STATE, [
"finger_not_match",
"password_not_match",
"reverse_lock",
"reverse_lock_cancel",
"locked",
"lock_opened",
"finger_add",
"finger_delete",
"password_add",
"password_delete",
"lock_opened_inside",
"lock_opened_outside",
"ring_bell",
"change_language_to",
"finger_open",
"password_open",
"door_closed",
]),
],
meta: { battery: { voltageToPercentage: { min: 3000, max: 4200 } } },
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA(), m.forceDeviceType({ type: "EndDevice" })],
},
{
zigbeeModel: ["lumi.lock.acn03"],
model: "ZNMS13LM",
description: "Smart door lock S2 Pro",
vendor: "Aqara",
fromZigbee: [lumi.fromZigbee.lumi_door_lock_report, fz.ignore_basic_report],
toZigbee: [],
exposes: [
e.binary("state", ea.STATE, "UNLOCK", "LOCK"),
e.binary("reverse", ea.STATE, "UNLOCK", "LOCK"),
e.enum("action", ea.STATE, [
"finger_not_match",
"password_not_match",
"reverse_lock",
"reverse_lock_cancel",
"locked",
"lock_opened",
"finger_add",
"finger_delete",
"password_add",
"password_delete",
"lock_opened_inside",
"lock_opened_outside",
"ring_bell",
"change_language_to",
"finger_open",
"password_open",
"door_closed",
]),
],
extend: [m.quirkCheckinInterval("1_HOUR"), m.forceDeviceType({ type: "EndDevice" })],
},
{
zigbeeModel: ["lumi.lock.aq1"],
model: "ZNMS11LM",
description: "Smart door lock",
vendor: "Aqara",
fromZigbee: [lumi.fromZigbee.lumi_door_lock_report, fz.ignore_basic_report],
toZigbee: [],
exposes: [
e.binary("state", ea.STATE, "UNLOCK", "LOCK"),
e.binary("reverse", ea.STATE, "UNLOCK", "LOCK"),
e.enum("action", ea.STATE, [
"finger_not_match",
"password_not_match",
"reverse_lock",
"reverse_lock_cancel",
"locked",
"lock_opened",
"finger_add",
"finger_delete",
"password_add",
"password_delete",
"lock_opened_inside",
"lock_opened_outside",
"ring_bell",
"change_language_to",
"finger_open",
"password_open",
"door_closed",
]),
],
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.remote.b286opcn01"],
model: "WXCJKG11LM",
vendor: "Aqara",
description: "Opple wireless switch (single band)",
fromZigbee: [
lumi.fromZigbee.lumi_action_on,
lumi.fromZigbee.lumi_action_off,
fz.battery,
lumi.fromZigbee.lumi_action_multistate,
lumi.fromZigbee.lumi_specific,
],
exposes: [
e.battery(),
e.battery_voltage(),
e.action([
"button_1_hold",
"button_1_release",
"button_1_single",
"button_1_double",
"button_1_triple",
"button_2_hold",
"button_2_release",
"button_2_single",
"button_2_double",
"button_2_triple",
]),
e
.enum("operation_mode", ea.ALL, ["command", "event"])
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
],
toZigbee: [lumi.toZigbee.lumi_operation_mode_opple],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR")],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
},
},
{
zigbeeModel: ["lumi.remote.b486opcn01"],
model: "WXCJKG12LM",
vendor: "Aqara",
description: "Opple wireless switch (double band)",
fromZigbee: [
lumi.fromZigbee.lumi_action_on,
lumi.fromZigbee.lumi_action_off,
lumi.fromZigbee.lumi_action_step,
lumi.fromZigbee.lumi_action_step_color_temp,
fz.battery,
lumi.fromZigbee.lumi_action_multistate,
lumi.fromZigbee.lumi_specific,
],
exposes: [
e.battery(),
e.battery_voltage(),
e.action([
"button_1_hold",
"button_1_release",
"button_1_single",
"button_1_double",
"button_1_triple",
"button_2_hold",
"button_2_release",
"button_2_single",
"button_2_double",
"button_2_triple",
"button_3_hold",
"button_3_release",
"button_3_single",
"button_3_double",
"button_3_triple",
"button_4_hold",
"button_4_release",
"button_4_single",
"button_4_double",
"button_4_triple",
]),
e
.enum("operation_mode", ea.ALL, ["command", "event"])
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
],
toZigbee: [lumi.toZigbee.lumi_operation_mode_opple],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR")],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingColorCtrl", "genPowerCfg"]);
},
},
{
zigbeeModel: ["lumi.remote.b686opcn01"],
model: "WXCJKG13LM",
vendor: "Aqara",
description: "Opple wireless switch (triple band)",
fromZigbee: [
lumi.fromZigbee.lumi_action_on,
lumi.fromZigbee.lumi_action_off,
lumi.fromZigbee.lumi_action_step,
lumi.fromZigbee.lumi_action_move,
lumi.fromZigbee.lumi_action_stop,
lumi.fromZigbee.lumi_action_step_color_temp,
lumi.fromZigbee.lumi_action_move_color_temp,
fz.battery,
lumi.fromZigbee.lumi_action_multistate,
lumi.fromZigbee.lumi_specific,
],
exposes: [
e.battery(),
e.battery_voltage(),
e.action([
"button_1_hold",
"button_1_release",
"button_1_single",
"button_1_double",
"button_1_triple",
"button_2_hold",
"button_2_release",
"button_2_single",
"button_2_double",
"button_2_triple",
"button_3_hold",
"button_3_release",
"button_3_single",
"button_3_double",
"button_3_triple",
"button_4_hold",
"button_4_release",
"button_4_single",
"button_4_double",
"button_4_triple",
"button_5_hold",
"button_5_release",
"button_5_single",
"button_5_double",
"button_5_triple",
"button_6_hold",
"button_6_release",
"button_6_single",
"button_6_double",
"button_6_triple",
]),
e
.enum("operation_mode", ea.ALL, ["command", "event"])
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
e.power_outage_count(false),
],
toZigbee: [lumi.toZigbee.lumi_operation_mode_opple],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR")],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingColorCtrl", "genPowerCfg"]);
},
},
{
zigbeeModel: ["lumi.sen_ill.mgl01"],
model: "GZCGQ01LM",
vendor: "Xiaomi",
whiteLabel: [{ vendor: "Xiaomi", model: "YTC4043GL" }],
description: "Mi light sensor",
fromZigbee: [fz.battery, lumi.fromZigbee.lumi_specific],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR"), m.illuminance()],
exposes: [e.battery(), e.battery_voltage()],
},
{
zigbeeModel: ["lumi.light.acn128"],
model: "TDL01LM",
vendor: "Aqara",
description: "Spotlight T3",
whiteLabel: [
{ vendor: "Aqara", model: "MZSD11LM" },
{ vendor: "Aqara", model: "MZSD12LM" },
{ vendor: "Aqara", model: "MZTD11LM" },
],
extend: [
lumiZigbeeOTA(),
lumiLight({
colorTemp: true,
color: false,
powerOutageMemory: "enum",
levelConfig: { features: ["on_off_transition_time", "on_transition_time", "off_transition_time", "execute_if_off", "on_level"] },
}),
m.numeric({
name: "min_brightness",
valueMin: 0,
valueMax: 99,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0515, type: 0x20 },
description: "Minimum brightness level",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "max_brightness",
valueMin: 1,
valueMax: 100,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0516, type: 0x20 },
description: "Maximum brightness level",
zigbeeCommandOptions: { manufacturerCode },
}),
],
},
{
zigbeeModel: ["lumi.light.rgbac1"],
model: "ZNTGMK11LM",
vendor: "Aqara",
description: "Smart RGBW light controller",
extend: [m.light({ colorTemp: { range: undefined }, color: { modes: ["xy", "hs"] } }), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.light.cwacn1"],
model: "ZNTGMK12LM",
vendor: "Aqara",
description: "Smart color temperature light controller",
extend: [lumiLight({ colorTemp: true, powerOutageCount: true, deviceTemperature: true }), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.light.cbacn1"],
model: "HLQDQ01LM",
vendor: "Aqara",
description: "Smart LED controller",
extend: [m.light(), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.light.acn004"],
model: "SSWQD02LM",
vendor: "Aqara",
description: "Smart dimmer controller T1 Pro",
extend: [lumiZigbeeOTA(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
},
{
zigbeeModel: ["lumi.dimmer.acn003"],
model: "ZNDDQDQ11LM",
vendor: "Aqara",
description: "T1 light strip controller",
extend: [lumiZigbeeOTA(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
},
{
zigbeeModel: ["lumi.dimmer.acn004"],
model: "ZNDDQDQ12LM",
vendor: "Aqara",
description: "T1 light strip controller",
extend: [lumiZigbeeOTA(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
},
{
zigbeeModel: ["lumi.light.acn026", "lumi.light.acn024", "lumi.light.acn025"],
model: "SSWQD03LM",
vendor: "Aqara",
description: "Spotlight T2",
extend: [lumiZigbeeOTA(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
},
{
zigbeeModel: ["lumi.switch.n0agl1"],
model: "SSM-U01",
vendor: "Aqara",
description: "Single switch module T1 (with neutral)",
// Ignore energy metering reports, rely on aqara_opple: https://github.com/Koenkk/zigbee2mqtt/issues/10709
fromZigbee: [
fz.on_off,
fz.device_temperature,
lumi.fromZigbee.lumi_specific,
fz.ignore_metering,
fz.ignore_electrical_measurement,
lumi.fromZigbee.lumi_power,
],
exposes: [
e.switch(),
e.energy(),
e.power(),
e.device_temperature(),
e.power_outage_memory(),
e.power_outage_count(),
e.switch_type(),
e.voltage(),
e.current(),
],
toZigbee: [lumi.toZigbee.lumi_switch_type, tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory, lumi.toZigbee.lumi_led_disabled_night],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genDeviceTempCfg"]);
await reporting.onOff(endpoint);
await reporting.deviceTemperature(endpoint);
},
extend: [lumiZigbeeOTA(), m.forceDeviceType({ type: "Router" }), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.switch.n0acn2"],
model: "DLKZMK11LM",
vendor: "Aqara",
description: "Single switch module T1 (with neutral), CN",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_power,
lumi.toZigbee.lumi_switch_type,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
],
exposes: [
e.switch(),
e.power().withAccess(ea.STATE_GET),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.voltage(),
e.current(),
e.power_outage_memory(),
e.led_disabled_night(),
e.switch_type(),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
},
{
zigbeeModel: ["lumi.switch.l0agl1"],
model: "SSM-U02",
vendor: "Aqara",
description: "Single switch module T1 (no neutral)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_specific],
exposes: [e.switch(), e.power_outage_memory(), e.switch_type(), e.power_outage_count(), e.device_temperature()],
toZigbee: [lumi.toZigbee.lumi_switch_type, tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory],
extend: [m.forcePowerSource({ powerSource: "Mains (single phase)" })],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
await reporting.onOff(endpoint);
},
},
{
zigbeeModel: ["lumi.switch.l0acn1"],
model: "DLKZMK12LM",
vendor: "Aqara",
description: "Single switch module T1 (no neutral), CN",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_specific],
exposes: [e.switch(), e.power_outage_memory(), e.switch_type()],
toZigbee: [lumi.toZigbee.lumi_switch_type, tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory],
extend: [m.forcePowerSource({ powerSource: "Mains (single phase)" })],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
await reporting.onOff(endpoint);
},
},
{
zigbeeModel: ["lumi.switch.n4acn4"],
model: "ZNCJMB14LM",
vendor: "Aqara",
description: "Smart touch panel S1",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_smart_panel_ZNCJMB14LM],
toZigbee: [tz.on_off, lumi.toZigbee.lumi_smart_panel_ZNCJMB14LM],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { left: 1, center: 2, right: 3 };
},
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("center"),
e.switch().withEndpoint("right"),
e.binary("standby_enabled", ea.STATE_SET, true, false).withDescription("Enable standby"),
e.enum("theme", ea.STATE_SET, ["classic", "concise"]).withDescription("Display theme"),
e.enum("beep_volume", ea.STATE_SET, ["mute", "low", "medium", "high"]).withDescription("Beep volume"),
e
.numeric("lcd_brightness", ea.STATE_SET)
.withValueMin(1)
.withValueMax(100)
.withUnit("%")
.withDescription("LCD brightness (will not persist if auto-brightness is enabled)"),
e.enum("language", ea.STATE_SET, ["chinese", "english"]).withDescription("Interface language"),
e.enum("screen_saver_style", ea.STATE_SET, ["classic", "analog clock"]).withDescription("Screen saver style"),
e.numeric("standby_time", ea.STATE_SET).withValueMin(0).withValueMax(65534).withUnit("s").withDescription("Display standby time"),
e.enum("font_size", ea.STATE_SET, ["small", "medium", "large"]).withDescription("Display font size"),
e.binary("lcd_auto_brightness_enabled", ea.STATE_SET, true, false).withDescription("Enable LCD auto brightness"),
e.enum("homepage", ea.STATE_SET, ["scene", "feel", "thermostat", "switch"]).withDescription("Default display homepage"),
e.binary("screen_saver_enabled", ea.STATE_SET, true, false).withDescription("Enable screen saver"),
e
.numeric("standby_lcd_brightness", ea.STATE_SET)
.withValueMin(1)
.withValueMax(100)
.withUnit("%")
.withDescription("Standby LCD brightness"),
e
.enum("available_switches", ea.STATE_SET, ["none", "1", "2", "3", "1 and 2", "1 and 3", "2 and 3", "all"])
.withDescription("Control which switches are available in the switches screen (none disables switches screen)"),
e
.composite("switch_1_text_icon", "switch_1_text_icon", ea.STATE_SET)
.withDescription("Switch 1 text and icon")
.withFeature(e.enum("switch_1_icon", ea.STATE_SET, ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]).withDescription("Icon"))
.withFeature(e.text("switch_1_text", ea.STATE_SET).withDescription("Text")),
e
.composite("switch_2_text_icon", "switch_2_text_icon", ea.STATE_SET)
.withDescription("Switch 2 text and icon")
.withFeature(e.enum("switch_2_icon", ea.STATE_SET, ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]).withDescription("Icon"))
.withFeature(e.text("switch_2_text", ea.STATE_SET).withDescription("Text")),
e
.composite("switch_3_text_icon", "switch_3_text_icon", ea.STATE_SET)
.withDescription("Switch 3 text and icon")
.withFeature(e.enum("switch_3_icon", ea.STATE_SET, ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]).withDescription("Icon"))
.withFeature(e.text("switch_3_text", ea.STATE_SET).withDescription("Text")),
],
configure: async (device, coordinatorEndpoint) => {
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ["genOnOff"]);
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ["genOnOff"]);
await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ["genOnOff"]);
await reporting.onOff(device.getEndpoint(1));
// await reporting.onOff(device.getEndpoint(2)); ToDo: Currently fails
// await reporting.onOff(device.getEndpoint(3)); ToDo: Currently fails
},
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.remote.b186acn03"],
model: "WXKG05LM",
vendor: "Aqara",
description: "Wireless remote switch T1 (single rocker)",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR")],
fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate, fz.battery, lumi.fromZigbee.lumi_specific],
toZigbee: [],
exposes: [e.action(["single", "double", "hold"]), e.battery()],
},
{
zigbeeModel: ["lumi.remote.b28ac1"],
model: "WXKG15LM",
vendor: "Aqara",
whiteLabel: [{ vendor: "Aqara", model: "WRS-R02" }],
description: "Wireless remote switch H1 (double rocker)",
fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, fz.command_toggle],
toZigbee: [lumi.toZigbee.lumi_switch_click_mode, lumi.toZigbee.lumi_operation_mode_opple],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } }, multiEndpoint: true },
extend: [m.quirkCheckinInterval("1_HOUR")],
exposes: [
e.battery(),
e.battery_voltage(),
e.action([
"single_left",
"single_right",
"single_both",
"double_left",
"double_right",
"double_both",
"triple_left",
"triple_right",
"triple_both",
"hold_left",
"hold_right",
"hold_both",
]),
e
.enum("click_mode", ea.ALL, ["fast", "multi"])
.withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
"multi: supports more events like double and hold"),
e
.enum("operation_mode", ea.ALL, ["command", "event"])
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
const endpoint2 = device.getEndpoint(3);
// set "event" mode
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
// turn on the "multiple clicks" mode, otherwise the only "single click" events.
// if value is 1 - there will be single clicks, 2 - multiple.
await endpoint1.write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: manufacturerCode });
await reporting.bind(endpoint1, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
await reporting.bind(endpoint2, coordinatorEndpoint, ["genOnOff"]);
// TODO/BUG:
// Did not understand how to separate the left and right keys in command mode -
// the "toggleCommand" always arrives from the first endpoint
},
},
{
zigbeeModel: ["lumi.switch.b1lc04"],
model: "QBKG38LM",
vendor: "Aqara",
description: "Smart wall switch E1 (no neutral, single rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_switch_mode_switch,
lumi.toZigbee.lumi_flip_indicator_light,
],
exposes: [
e.switch(),
e.power_outage_memory(),
e.action(["single", "double"]),
e.device_temperature(),
e.flip_indicator_light(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for button"),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.b2lc04"],
model: "QBKG39LM",
vendor: "Aqara",
description: "Smart wall switch E1 (no neutral, double rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_switch_mode_switch,
lumi.toZigbee.lumi_flip_indicator_light,
],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { left: 1, right: 2 };
},
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.device_temperature(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e
.enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
.withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
e.power_outage_memory(),
e.flip_indicator_light(),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.airmonitor.acn01"],
model: "VOCKQJK11LM",
vendor: "Aqara",
whiteLabel: [{ vendor: "Aqara", model: "AAQS-S01" }],
description: "TVOC air quality monitor",
fromZigbee: [fz.battery, lumi.fromZigbee.lumi_specific],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [e.device_temperature(), e.battery(), e.battery_voltage()],
extend: [
m.quirkCheckinInterval("1_HOUR"),
m.quirkAddEndpointCluster({
endpointID: 1,
inputClusters: ["msTemperatureMeasurement", "msRelativeHumidity", "genAnalogInput", "manuSpecificLumi"],
}),
lumiAirQuality(),
lumiVoc(),
m.temperature(),
m.humidity(),
lumiDisplayUnit(),
lumiOutageCountRestoreBindReporting(),
lumiZigbeeOTA(),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
const binds = ["genPowerCfg"];
await reporting.bind(endpoint, coordinatorEndpoint, binds);
await reporting.batteryVoltage(endpoint);
},
},
{
zigbeeModel: ["lumi.switch.b2nc01"],
model: "QBKG41LM",
vendor: "Aqara",
description: "Smart wall switch E1 (with neutral, double rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { left: 1, right: 2 };
},
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
e.power_outage_memory(),
e.device_temperature(),
e.flip_indicator_light(),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.plug.macn01"],
model: "ZNCZ15LM",
vendor: "Aqara",
description: "Smart plug T1, CN",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_overload_protection,
lumi.toZigbee.lumi_socket_button_lock,
],
exposes: [
e.switch(),
e.power().withAccess(ea.STATE),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.voltage(),
e.current(),
e.consumer_connected().withAccess(ea.STATE),
e.power_outage_memory(),
e.led_disabled_night(),
e.button_lock(),
e.overload_protection(100, 2500),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.switch.b1nc01"],
model: "QBKG40LM",
vendor: "Aqara",
description: "Smart wall switch E1 (with neutral, single rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_flip_indicator_light,
],
exposes: [
e.switch(),
e.action(["single", "double"]),
e.power_outage_memory(),
e.device_temperature(),
e.flip_indicator_light(),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.remote.b1acn02"],
model: "WXKG13LM",
vendor: "Aqara",
description: "Wireless mini switch T1",
whiteLabel: [
{ vendor: "Aqara", model: "WB-R02D" },
{ vendor: "Yandex", model: "YNDX-00524" },
],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [],
exposes: [e.battery(), e.battery_voltage(), e.action(["single", "double", "triple", "quadruple", "quintuple", "hold", "release", "many"])],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.sen_ill.agl01"],
model: "GZCGQ11LM",
vendor: "Aqara",
description: "Light sensor T1",
fromZigbee: [fz.battery, lumi.fromZigbee.lumi_specific],
toZigbee: [lumi.toZigbee.lumi_detection_period],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
exposes: [
e.battery(),
e.battery_voltage(),
e
.numeric("detection_period", exposes.access.ALL)
.withValueMin(1)
.withValueMax(59)
.withUnit("s")
.withDescription("Time interval in seconds to report after light changes"),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
await endpoint.read("manuSpecificLumi", [0x0000], { manufacturerCode: manufacturerCode });
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA(), m.illuminance({ reporting: false })],
},
{
zigbeeModel: ["lumi.plug.sacn03"],
model: "QBCZ15LM",
vendor: "Aqara",
description: "Smart wall outlet H1 (USB)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_button_switch_mode,
lumi.toZigbee.lumi_overload_protection,
lumi.toZigbee.lumi_socket_button_lock,
],
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
endpoint: () => {
return { relay: 1, usb: 2 };
},
exposes: [
e.switch().withEndpoint("relay"),
e.switch().withEndpoint("usb"),
e.power().withAccess(ea.STATE),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.voltage(),
e.current(),
e.power_outage_memory(),
e.led_disabled_night(),
e.button_lock(),
e
.enum("button_switch_mode", exposes.access.ALL, ["relay", "relay_and_usb"])
.withDescription("Control both relay and usb or only the relay with the physical switch button"),
e.overload_protection(100, 2500),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.magnet.agl02"],
model: "MCCGQ12LM",
vendor: "Aqara",
description: "Door and window sensor T1",
whiteLabel: [
{ vendor: "Aqara", model: "DW-S03D" },
{ vendor: "Yandex", model: "YNDX-00520" },
],
fromZigbee: [lumi.fromZigbee.lumi_contact, lumi.fromZigbee.lumi_specific, fz.ias_contact_alarm_1],
toZigbee: [],
exposes: [e.contact(), e.battery(), e.battery_voltage()],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.plug.sacn02"],
model: "QBCZ14LM",
vendor: "Aqara",
description: "Smart wall outlet T1",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_overload_protection,
lumi.toZigbee.lumi_socket_button_lock,
],
exposes: [
e.switch(),
e.power().withAccess(ea.STATE),
e.energy(),
e.device_temperature().withAccess(ea.STATE),
e.voltage(),
e.current(),
e.power_outage_memory(),
e.led_disabled_night(),
e.button_lock(),
e.overload_protection(100, 2500),
],
extend: [lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.remote.rkba01"],
model: "ZNXNKG02LM",
vendor: "Aqara",
description: "Smart rotary knob H1 (wireless)",
extend: [
m.quirkCheckinInterval("1_HOUR"),
lumiPreventReset(),
lumiCommandMode(),
lumiAction({ actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
lumiBattery({ voltageToPercentage: { min: 2850, max: 3000 } }),
lumiKnobRotation(),
m.enumLookup({
name: "sensitivity",
lookup: { low: 720, medium: 360, high: 180 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x0234, type: 0x21 },
description: "Rotation sensitivity",
zigbeeCommandOptions: { manufacturerCode },
}),
],
},
{
zigbeeModel: ["lumi.remote.acn003"],
model: "WXKG16LM",
vendor: "Aqara",
description: "Wireless remote switch E1 (single rocker)",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR")],
fromZigbee: [lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [lumi.toZigbee.lumi_switch_click_mode],
exposes: [
e.battery(),
e.battery_voltage(),
e.action(["single", "double", "hold"]),
e
.enum("click_mode", ea.ALL, ["fast", "multi"])
.withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
"multi: supports more events like double and hold"),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: manufacturerCode });
},
},
{
zigbeeModel: ["lumi.remote.acn004"],
model: "WXKG17LM",
vendor: "Aqara",
description: "Wireless remote switch E1 (double rocker)",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
exposes: [
e.battery(),
e.battery_voltage(),
e.action(["single_left", "single_right", "single_both", "double_left", "double_right", "hold_left", "hold_right"]),
e
.enum("click_mode", ea.ALL, ["fast", "multi"])
.withDescription("Click mode, fast: only supports single click which will be send immediately after clicking, multi: supports more events like double and hold"),
],
fromZigbee: [lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [lumi.toZigbee.lumi_switch_click_mode],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
// set multiclick mode
await endpoint1.write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: manufacturerCode });
},
},
{
zigbeeModel: ["lumi.remote.b18ac1"],
model: "WXKG14LM",
vendor: "Aqara",
description: "Wireless remote switch H1 (single rocker)",
fromZigbee: [lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, fz.command_toggle],
toZigbee: [lumi.toZigbee.lumi_switch_click_mode, lumi.toZigbee.lumi_operation_mode_opple],
exposes: [
e.battery(),
e.battery_voltage(),
e.action(["single", "double", "triple", "hold"]),
e
.enum("click_mode", ea.ALL, ["fast", "multi"])
.withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
"multi: supports more events like double and hold"),
e
.enum("operation_mode", ea.ALL, ["command", "event"])
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR")],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
await endpoint1.read("manuSpecificLumi", [0x0125], { manufacturerCode: manufacturerCode });
},
},
{
zigbeeModel: ["lumi.airrtc.agl001"],
model: "SRTS-A01",
vendor: "Aqara",
description: "Smart radiator thermostat E1",
fromZigbee: [lumi.fromZigbee.lumi_trv, fz.thermostat, fz.battery],
toZigbee: [lumi.toZigbee.lumi_trv, tz.thermostat_occupied_heating_setpoint],
exposes: [
e.setup().withDescription("Indicates if the device is in setup mode (E11)"),
e
.climate()
.withSetpoint("occupied_heating_setpoint", 5, 30, 0.5)
.withLocalTemperature(ea.STATE, "Current temperature measured by the internal or external sensor")
.withSystemMode(["off", "heat"], ea.ALL)
.withPreset(["manual", "away", "auto"])
.setAccess("preset", ea.ALL),
e.temperature_sensor_select(["internal", "external"]).withAccess(ea.ALL),
e.external_temperature_input().withDescription("Input for remote temperature sensor (when sensor is set to external)"),
e.calibrated().withDescription("Indicates if this valve is calibrated, use the calibrate option to calibrate"),
e.enum("calibrate", ea.ALL, ["calibrate"]).withDescription("Calibrates the valve").withCategory("config"),
e.child_lock().withAccess(ea.ALL),
e.window_detection_bool(),
e.window_open(),
e.valve_detection_bool(),
e
.valve_alarm()
.withDescription("Notifies of a temperature control abnormality if valve detection is enabled " +
"(e.g., thermostat not installed correctly, valve failure or incorrect calibration, " +
"incorrect link to external temperature sensor)"),
e.away_preset_temperature().withAccess(ea.ALL),
e.battery_voltage(),
e.battery(),
e.power_outage_count(),
e.device_temperature(),
e.schedule(),
e
.schedule_settings()
.withDescription("Smart schedule configuration (default: mon,tue,wed,thu,fri|8:00,24.0|18:00,17.0|23:00,22.0|8:00,22.0)"),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
// Initialize battery percentage and voltage
await endpoint.read("manuSpecificLumi", [0x040a], { manufacturerCode: manufacturerCode });
await endpoint.read("genPowerCfg", ["batteryVoltage"]);
},
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["aqara.feeder.acn001"],
model: "ZNCWWSQ01LM",
vendor: "Aqara",
description: "Smart pet feeder C1",
whiteLabel: [{ vendor: "Aqara", model: "PETC1-M01" }],
fromZigbee: [lumi.fromZigbee.lumi_feeder],
toZigbee: [lumi.toZigbee.lumi_feeder],
exposes: [
e.enum("feed", ea.STATE_SET, ["", "START"]).withDescription("Start feeding"),
e.enum("feeding_source", ea.STATE, ["schedule", "manual", "remote"]).withDescription("Feeding source"),
e.numeric("feeding_size", ea.STATE).withDescription("Feeding size").withUnit("portion"),
e.numeric("portions_per_day", ea.STATE).withDescription("Portions per day"),
e.numeric("weight_per_day", ea.STATE).withDescription("Weight per day").withUnit("g"),
e.binary("error", ea.STATE, true, false).withDescription("Indicates whether there is an error with the feeder"),
e
.list("schedule", ea.STATE_SET, e
.composite("dayTime", "dayTime", exposes.access.STATE_SET)
.withFeature(e.enum("days", exposes.access.STATE_SET, [
"everyday",
"workdays",
"weekend",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
"sun",
"mon-wed-fri-sun",
"tue-thu-sat",
]))
.withFeature(e.numeric("hour", exposes.access.STATE_SET))
.withFeature(e.numeric("minute", exposes.access.STATE_SET))
.withFeature(e.numeric("size", exposes.access.STATE_SET)))
.withDescription("Feeding schedule"),
e
.binary("led_indicator", ea.STATE_SET, "ON", "OFF")
.withLabel("Disable LED at night")
.withDescription("LED indicator will be disabled every day from 21:00 to 09:00")
.withCategory("config"),
e.child_lock(),
e.enum("mode", ea.STATE_SET, ["schedule", "manual"]).withDescription("Feeding mode"),
e
.numeric("serving_size", ea.STATE_SET)
.withValueMin(1)
.withValueMax(10)
.withDescription("One serving size")
.withUnit("portion")
.withCategory("config"),
e
.numeric("portion_weight", ea.STATE_SET)
.withValueMin(1)
.withValueMax(20)
.withDescription("Portion weight")
.withUnit("g")
.withCategory("config"),
],
extend: [lumiZigbeeOTA(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("manuSpecificLumi", [0xfff1], { manufacturerCode: manufacturerCode });
},
},
{
zigbeeModel: ["lumi.remote.acn007"],
model: "WXKG20LM",
vendor: "Aqara",
description: "Wireless mini switch E1",
fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR")],
exposes: [
e.battery(),
e.battery_voltage(),
e.action(["single", "double", "hold", "release"]),
e.device_temperature(),
e.power_outage_count(),
],
},
{
zigbeeModel: ["lumi.remote.acn009"],
model: "WXKG22LM",
vendor: "Aqara",
description: "Wireless remote switch H1M (double rocker)",
fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, fz.command_toggle],
toZigbee: [lumi.toZigbee.lumi_switch_click_mode, lumi.toZigbee.lumi_operation_mode_opple],
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } }, multiEndpoint: true },
extend: [m.quirkCheckinInterval("1_HOUR")],
exposes: [
e.battery(),
e.battery_voltage(),
e.action([
"single_left",
"single_right",
"single_both",
"double_left",
"double_right",
"double_both",
"triple_left",
"triple_right",
"triple_both",
"hold_left",
"hold_right",
"hold_both",
]),
e
.enum("click_mode", ea.ALL, ["fast", "multi"])
.withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
"multi: supports more events like double and hold"),
e
.enum("operation_mode", ea.ALL, ["command", "event"])
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
const endpoint2 = device.getEndpoint(3);
// set "event" mode
await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
// turn on the "multiple clicks" mode, otherwise the only "single click" events.
// if value is 1 - there will be single clicks, 2 - multiple.
await endpoint1.write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: manufacturerCode });
await reporting.bind(endpoint1, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
await reporting.bind(endpoint2, coordinatorEndpoint, ["genOnOff"]);
// TODO/BUG:
// Did not understand how to separate the left and right keys in command mode -
// the "toggleCommand" always arrives from the first endpoint
},
},
{
zigbeeModel: ["lumi.remote.b286acn03"],
model: "WXKG04LM",
vendor: "Aqara",
description: "Wireless remote switch T1 (double rocker)",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [],
endpoint: (device) => {
return { left: 1, right: 2, both: 3 };
},
exposes: [
e.battery(),
e.battery_voltage(),
e.action([
"button_1_hold",
"button_1_release",
"button_1_single",
"button_1_double",
"button_1_triple",
"button_2_hold",
"button_2_release",
"button_2_single",
"button_2_double",
"button_2_triple",
"button_3_hold",
"button_3_release",
"button_3_single",
"button_3_double",
"button_3_triple",
]),
],
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
},
{
zigbeeModel: ["lumi.switch.acn048"],
model: "ZNQBKG38LM",
vendor: "Aqara",
description: "Smart wall switch Z1 (single rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
lumiOnOff({ operationMode: true, powerOutageMemory: "enum", lockRelay: true }),
lumiAction(),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
lumiSetEventMode(),
],
},
{
zigbeeModel: ["lumi.switch.acn049"],
model: "ZNQBKG39LM",
vendor: "Aqara",
description: "Smart wall switch Z1 (double rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { top: 1, bottom: 2 } }),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["top", "bottom"],
}),
lumiAction({ endpointNames: ["top", "bottom"] }),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
lumiSetEventMode(),
],
},
{
zigbeeModel: ["lumi.switch.acn054"],
model: "ZNQBKG40LM",
vendor: "Aqara",
description: "Smart wall switch Z1 (triple rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3 } }),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["top", "center", "bottom"],
}),
lumiAction({ endpointNames: ["top", "center", "bottom"] }),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
lumiSetEventMode(),
],
},
{
zigbeeModel: ["lumi.switch.acn055"],
model: "ZNQBKG41LM",
vendor: "Aqara",
description: "Smart wall switch Z1 (quadruple rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3, wireless: 4 } }),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["top", "center", "bottom"],
}),
lumiAction({
actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
endpointNames: ["top", "center", "bottom", "wireless"],
}),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
lumiSetEventMode(),
],
},
{
zigbeeModel: ["lumi.switch.acn056"],
model: "ZNQBKG42LM",
vendor: "Aqara",
description: "Smart wall switch Z1 Pro (single rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
lumiOnOff({ operationMode: true, powerOutageMemory: "enum", lockRelay: true }),
lumiAction({ extraActions: ["slider_single", "slider_double", "slider_hold", "slider_up", "slider_down"] }),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
lumiSlider(),
lumiSwitchMode(),
],
},
{
zigbeeModel: ["lumi.switch.acn057"],
model: "ZNQBKG43LM",
vendor: "Aqara",
description: "Smart wall switch Z1 Pro (double rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { top: 1, bottom: 2 } }),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["top", "bottom"],
}),
lumiAction({
endpointNames: ["top", "bottom"],
extraActions: ["slider_single", "slider_double", "slider_hold", "slider_up", "slider_down"],
}),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
lumiSlider(),
lumiSwitchMode(),
],
},
{
zigbeeModel: ["lumi.switch.acn058"],
model: "ZNQBKG44LM",
vendor: "Aqara",
description: "Smart wall switch Z1 Pro (triple rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3 } }),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["top", "center", "bottom"],
}),
lumiAction({
endpointNames: ["top", "center", "bottom"],
extraActions: ["slider_single", "slider_double", "slider_hold", "slider_up", "slider_down"],
}),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
lumiSlider(),
lumiSwitchMode(),
],
},
{
zigbeeModel: ["lumi.switch.acn059"],
model: "ZNQBKG45LM",
vendor: "Aqara",
description: "Smart wall switch Z1 Pro (quadruple rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3, wireless: 4 } }),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["top", "center", "bottom"],
}),
lumiAction({
actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
endpointNames: ["top", "center", "bottom", "wireless"],
extraActions: ["slider_single", "slider_double", "slider_hold", "slider_up", "slider_down"],
}),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
lumiSlider(),
lumiSwitchMode(),
],
},
{
zigbeeModel: ["lumi.switch.acn061"],
model: "WS-K01D",
vendor: "Aqara",
description: "Smart wall switch H1 20A (with neutral, single rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
lumiOnOff({ operationMode: true, powerOutageMemory: "binary" }),
lumiAction({ actionLookup: { single: 1, double: 2 } }),
lumiElectricityMeter(),
lumiPower(),
lumiLedDisabledNight(),
lumiSetEventMode(),
lumiFlipIndicatorLight(),
],
},
{
zigbeeModel: ["lumi.remote.cagl02"],
model: "CTP-R01",
vendor: "Aqara",
whiteLabel: [{ vendor: "Aqara", model: "MFCZQ12LM" }],
description: "Cube T1 Pro",
meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
fromZigbee: [
lumi.fromZigbee.lumi_specific,
lumi.fromZigbee.lumi_action_multistate,
lumi.fromZigbee.lumi_action_analog,
fz.ignore_onoff_report,
],
toZigbee: [lumi.toZigbee.lumi_cube_operation_mode],
exposes: [
e.battery(),
e.battery_voltage(),
e.power_outage_count(false),
e
.enum("operation_mode", ea.SET, ["action_mode", "scene_mode"])
.withDescription("[Soft Switch]: There is a configuration window, opens once an hour on itself, " +
"only during which the cube will respond to mode switch. " +
"Mode switch will be scheduled to take effect when the window becomes available. " +
"You can also give it a throw action (no backward motion) to force a respond! " +
"Otherwise, you may open lid and click LINK once to make the cube respond immediately. " +
"[Hard Switch]: Open lid and click LINK button 5 times."),
e.cube_side("side"),
e
.action([
"shake",
"throw",
"tap",
"slide",
"flip180",
"flip90",
"hold",
"side_up",
"rotate_left",
"rotate_right",
"1_min_inactivity",
"flip_to_side",
])
.withDescription("Triggered action"),
e.cube_side("action_from_side"),
e.angle("action_angle"),
],
configure: async (device, coordinatorEndpoint) => {
device.softwareBuildID = `0.0.0_00${device.applicationVersion}`;
device.save();
const endpoint = device.getEndpoint(1);
await endpoint.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableDefaultResponse: true, disableResponse: true });
await endpoint.read("manuSpecificLumi", [0x148], {
manufacturerCode: manufacturerCode,
disableDefaultResponse: true,
disableResponse: true,
});
},
},
{
zigbeeModel: ["lumi.switch.acn040"],
model: "ZNQBKG31LM",
vendor: "Aqara",
description: "Smart wall switch E1 (with neutral, triple rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_switch_mode_switch,
lumi.toZigbee.lumi_flip_indicator_light,
],
endpoint: (device) => {
return { left: 1, center: 2, right: 3 };
},
meta: { multiEndpoint: true },
exposes: [
e.switch().withEndpoint("left"),
e.switch().withEndpoint("center"),
e.switch().withEndpoint("right"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e
.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
.withDescription("Decoupled mode for center button")
.withEndpoint("center"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e.action([
"single_left",
"double_left",
"single_center",
"double_center",
"single_right",
"double_right",
"single_left_center",
"double_left_center",
"single_left_right",
"double_left_right",
"single_center_right",
"double_center_right",
"single_all",
"double_all",
]),
e.power_outage_memory(),
e.device_temperature(),
e.flip_indicator_light(),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.acn029"],
model: "ZNQBKG24LM",
vendor: "Aqara",
description: "Smart wall switch H1M (with neutral, single rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_flip_indicator_light,
],
exposes: [
e.switch(),
e.power(),
e.energy(),
e.voltage(),
e.device_temperature(),
e.action(["single", "double"]),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
e.power_outage_memory(),
e.led_disabled_night(),
e.flip_indicator_light(),
],
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.acn030"],
model: "ZNQBKG25LM",
vendor: "Aqara",
description: "Smart wall switch H1M (with neutral, double rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_power],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_flip_indicator_light,
],
endpoint: (device) => {
return { left: 1, right: 2 };
},
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
exposes: [
e.power(),
e.energy(),
e.voltage(),
e.switch().withEndpoint("left"),
e.switch().withEndpoint("right"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e.action([
"single_left",
"double_left",
"single_right",
"double_right",
"single_left_right",
"double_left_right",
"single_all",
"double_all",
]),
e.power_outage_memory(),
e.led_disabled_night(),
e.device_temperature(),
e.flip_indicator_light(),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.switch.acn031"],
model: "ZNQBKG26LM",
vendor: "Aqara",
description: "Smart wall switch H1M (with neutral, triple rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_power],
toZigbee: [
tz.on_off,
lumi.toZigbee.lumi_switch_operation_mode_opple,
lumi.toZigbee.lumi_switch_power_outage_memory,
lumi.toZigbee.lumi_led_disabled_night,
lumi.toZigbee.lumi_flip_indicator_light,
],
endpoint: (device) => {
return { left: 1, center: 2, right: 3 };
},
meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
exposes: [
e.power(),
e.energy(),
e.voltage(),
e.switch().withEndpoint("left"),
e.switch().withEndpoint("center"),
e.switch().withEndpoint("right"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
e
.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
.withDescription("Decoupled mode for center button")
.withEndpoint("center"),
e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
e.action([
"single_left",
"double_left",
"single_center",
"double_center",
"single_right",
"double_right",
"single_left_center",
"double_left_center",
"single_left_right",
"double_left_right",
"single_center_right",
"double_center_right",
"single_all",
"double_all",
]),
e.power_outage_memory(),
e.led_disabled_night(),
e.device_temperature(),
e.flip_indicator_light(),
],
configure: async (device, coordinatorEndpoint) => {
await device.getEndpoint(1).write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
},
extend: [lumiZigbeeOTA(), lumiPreventReset()],
},
{
zigbeeModel: ["lumi.plug.aeu001"],
model: "WP-P01D",
vendor: "Aqara",
description: "Smart wall outlet H2 EU",
extend: [
lumiZigbeeOTA(),
lumiOnOff({ powerOutageMemory: "enum" }),
lumiPower(),
lumiElectricityMeter(),
lumiOverloadProtection(),
lumiLedIndicator(),
lumiButtonLock(),
m.binary({
name: "charging_protection",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0202, type: 0x10 },
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
description: "Turn off the outlet if the power is below the set limit for half an hour",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "charging_limit",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0206, type: 0x39 },
valueMin: 0.1,
valueMax: 2,
valueStep: 0.1,
unit: "W",
description: "Charging protection power limit",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode },
}),
],
},
{
zigbeeModel: ["lumi.light.acn031"],
model: "HCXDD12LM",
vendor: "Aqara",
description: "Ceiling light T1",
extend: [
m.deviceEndpoints({ endpoints: { white: 1, rgb: 2 } }),
lumiLight({ colorTemp: true, powerOutageMemory: "light", endpointNames: ["white"] }),
lumiLight({ colorTemp: true, deviceTemperature: false, powerOutageCount: false, color: { modes: ["xy", "hs"] }, endpointNames: ["rgb"] }),
lumiZigbeeOTA(),
],
},
{
zigbeeModel: ["lumi.light.acn032"],
model: "CL-L02D",
vendor: "Aqara",
description: "Ceiling light T1M",
extend: [
m.deviceEndpoints({ endpoints: { white: 1, rgb: 2 } }),
lumiLight({ colorTemp: true, endpointNames: ["white"] }),
lumiLight({ colorTemp: true, deviceTemperature: false, powerOutageCount: false, color: { modes: ["xy", "hs"] }, endpointNames: ["rgb"] }),
lumiZigbeeOTA(),
m.enumLookup({
name: "power_on_behaviour",
lookup: { on: 0, previous: 1, off: 2 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x0517, type: 0x20 },
description: "Controls the behavior when the device is powered on after power loss",
zigbeeCommandOptions: { manufacturerCode },
}),
],
},
{
zigbeeModel: ["lumi.switch.rkna01"],
model: "ZNXNKG01LM",
vendor: "Aqara",
description: "Smart rotary knob H1 (with neutral)",
extend: [
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { left: 1, center: 2, right: 3 } }),
lumiOnOff({ powerOutageMemory: "binary", endpointNames: ["left", "center", "right"] }),
lumiCommandMode(),
lumiAction({ actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
lumiKnobRotation(),
lumiElectricityMeter(),
lumiPower(),
lumiZigbeeOTA(),
],
},
{
zigbeeModel: ["lumi.valve.agl001"],
model: "VC-X01D",
vendor: "Aqara",
description: "Valve controller T1",
extend: [lumiZigbeeOTA(), m.onOff({ powerOnBehavior: false }), m.battery()],
},
{
zigbeeModel: ["lumi.switch.agl009"],
model: "WS-K07E",
vendor: "Aqara",
description: "Light switch H2 EU (single rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventLeave(),
m.deviceEndpoints({ endpoints: { up: 1, down: 4 } }),
m.bindCluster({ endpointNames: ["up", "down"], cluster: "manuSpecificLumi", clusterType: "input" }),
m.bindCluster({ endpointNames: ["up"], cluster: "genOnOff", clusterType: "input" }),
m.electricityMeter({ voltage: false }),
lumiLedIndicator(),
lumiFlipIndicatorLight(),
lumiAction({ endpointNames: ["up", "down"], actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
lumiOnOff({ powerOutageMemory: "enum", endpointNames: ["up"] }),
lumiOperationMode({ description: "Decoupled mode for switch", endpointName: "up" }),
lumiLockRelay({ description: "Lock switch", endpointName: "up" }),
lumiMultiClick({ description: "Multi-click mode for down button", endpointName: "down" }),
],
},
{
zigbeeModel: ["lumi.switch.agl010"],
model: "WS-K08E",
vendor: "Aqara",
description: "Light switch H2 EU (double rocker)",
extend: [
lumiZigbeeOTA(),
lumiPreventLeave(),
m.deviceEndpoints({ endpoints: { left: 1, right: 2, left_down: 4, right_down: 5 } }),
m.bindCluster({ endpointNames: ["left", "left_down", "right", "right_down"], cluster: "manuSpecificLumi", clusterType: "input" }),
m.bindCluster({ endpointNames: ["left", "right"], cluster: "genOnOff", clusterType: "input" }),
m.electricityMeter({ voltage: false }),
lumiLedIndicator(),
lumiFlipIndicatorLight(),
lumiAction({ endpointNames: ["left", "left_down", "right", "right_down"], actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
lumiOnOff({ powerOutageMemory: "enum", endpointNames: ["left", "right"] }),
lumiOperationMode({ description: "Decoupled mode for left switch", endpointName: "left" }),
lumiOperationMode({ description: "Decoupled mode for right switch", endpointName: "right" }),
lumiLockRelay({ description: "Lock left switch", endpointName: "left" }),
lumiLockRelay({ description: "Lock right switch", endpointName: "right" }),
lumiMultiClick({ description: "Multi-click mode for left down button", endpointName: "left_down" }),
lumiMultiClick({ description: "Multi-click mode for right down button", endpointName: "right_down" }),
],
},
{
zigbeeModel: ["lumi.switch.agl011"],
model: "KD-R01D",
vendor: "Aqara",
description: "Dimmer switch H2 EU",
extend: [
lumiZigbeeOTA(),
lumiPreventLeave(),
m.bindCluster({ cluster: "genOnOff", clusterType: "input" }),
m.bindCluster({ cluster: "genLevelCtrl", clusterType: "input" }),
lumiPower(),
lumiElectricityMeter(),
lumiLedIndicator(),
lumiFlipIndicatorLight(),
lumiPowerOnBehavior(),
m.light({ powerOnBehavior: false }),
lumiKnobRotation({ withButtonState: false }),
lumiOperationMode({ description: "Decoupled mode for knob" }),
lumiAction({ actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
lumiMultiClick(),
m.enumLookup({
name: "sensitivity",
lookup: { low: 720, medium: 360, high: 180 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x0234, type: 0x21 },
description: "Rotation sensitivity",
zigbeeCommandOptions: { manufacturerCode },
}),
m.enumLookup({
name: "phase",
lookup: { forward: 0, reverse: 1 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x030a, type: 0x20 },
description: "Dimming phase",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "min_brightness",
valueMin: 0,
valueMax: 99,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0515, type: 0x20 },
description: "Minimum brightness level",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "max_brightness",
valueMin: 1,
valueMax: 100,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0516, type: 0x20 },
description: "Maximum brightness level",
zigbeeCommandOptions: { manufacturerCode },
}),
],
},
{
zigbeeModel: ["lumi.switch.agl006"],
model: "WS-K04E",
vendor: "Aqara",
description: "Light Switch H2 US (quadruple rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3, wireless: 4 } }),
m.bindCluster({ endpointNames: ["top", "center", "bottom", "wireless"], cluster: "manuSpecificLumi", clusterType: "input" }),
m.bindCluster({ endpointNames: ["top", "center", "bottom"], cluster: "genOnOff", clusterType: "input" }),
lumiPower(),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["top", "center", "bottom"],
}),
lumiAction({
actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
endpointNames: ["top", "center", "bottom", "wireless"],
}),
lumiMultiClick({ description: "Multi-click mode for wireless button", endpointName: "wireless" }),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiSwitchMode(),
],
},
{
zigbeeModel: ["lumi.switch.agl004"],
model: "WS-K02E",
vendor: "Aqara",
description: "Light Switch H2 US (double rocker)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { top: 1, wireless: 2 } }),
m.bindCluster({ endpointNames: ["top", "wireless"], cluster: "manuSpecificLumi", clusterType: "input" }),
m.bindCluster({ endpointNames: ["top"], cluster: "genOnOff", clusterType: "input" }),
lumiPower(),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["top"],
}),
lumiAction({
actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
endpointNames: ["top", "wireless"],
}),
lumiMultiClick({ description: "Multi-click mode for wireless button", endpointName: "wireless" }),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiSwitchMode(),
],
},
{
zigbeeModel: ["lumi.sensor_ht.agl001"],
model: "TH-S04D",
vendor: "Aqara",
description: "Climate Sensor W100",
extend: [
lumiZigbeeOTA(),
m.temperature(),
m.humidity(),
lumiExternalSensor(),
m.deviceEndpoints({ endpoints: { plus: 1, center: 2, minus: 3 } }),
lumiAction({
actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
endpointNames: ["plus", "center", "minus"],
}),
m.binary({
name: "display_off",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0173, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN },
valueOn: [true, 1],
valueOff: [false, 0],
description: "Enables/disables auto display off",
access: "ALL",
entityCategory: "config",
zigbeeCommandOptions: { manufacturerCode },
reporting: false,
}),
m.numeric({
name: "high_temperature",
valueMin: 26,
valueMax: 60,
valueStep: 0.5,
scale: 100,
unit: "°C",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0167, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
description: "High temperature alert",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "low_temperature",
valueMin: -20,
valueMax: 20,
valueStep: 0.5,
scale: 100,
unit: "°C",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0166, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
description: "Low temperature alert",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "high_humidity",
valueMin: 65,
valueMax: 100,
valueStep: 1,
scale: 100,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x016e, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
description: "High humidity alert",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "low_humidity",
valueMin: 0,
valueMax: 30,
valueStep: 1,
scale: 100,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x016d, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
description: "Low humidity alert",
zigbeeCommandOptions: { manufacturerCode },
}),
m.enumLookup({
name: "sampling",
lookup: { low: 1, standard: 2, high: 3, custom: 4 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x0170, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
description: "Temperature and Humidity sampling settings",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "period",
valueMin: 0.5,
valueMax: 600,
valueStep: 0.5,
scale: 1000,
unit: "sec",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0162, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
description: "Sampling period",
zigbeeCommandOptions: { manufacturerCode },
}),
m.enumLookup({
name: "temp_report_mode",
lookup: { no: 0, threshold: 1, period: 2, threshold_period: 3 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x0165, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
description: "Temperature reporting mode",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "temp_period",
valueMin: 1,
valueMax: 10,
valueStep: 1,
scale: 1000,
unit: "sec",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0163, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
description: "Temperature reporting period",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "temp_threshold",
valueMin: 0.2,
valueMax: 3,
valueStep: 0.1,
scale: 100,
unit: "°C",
cluster: "manuSpecificLumi",
attribute: { ID: 0x0164, type: zigbee_herdsman_1.Zcl.DataType.UINT16 },
description: "Temperature reporting threshold",
zigbeeCommandOptions: { manufacturerCode },
}),
m.enumLookup({
name: "humi_report_mode",
lookup: { no: 0, threshold: 1, period: 2, threshold_period: 3 },
cluster: "manuSpecificLumi",
attribute: { ID: 0x016c, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
description: "Humidity reporting mode",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "humi_period",
valueMin: 1,
valueMax: 10,
valueStep: 1,
scale: 1000,
unit: "sec",
cluster: "manuSpecificLumi",
attribute: { ID: 0x016a, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
description: "Temperature reporting period",
zigbeeCommandOptions: { manufacturerCode },
}),
m.numeric({
name: "humi_threshold",
valueMin: 2,
valueMax: 10,
valueStep: 0.5,
scale: 100,
unit: "%",
cluster: "manuSpecificLumi",
attribute: { ID: 0x016b, type: zigbee_herdsman_1.Zcl.DataType.UINT16 },
description: "Humidity reporting threshold",
zigbeeCommandOptions: { manufacturerCode },
}),
m.identify(),
],
},
{
zigbeeModel: ["lumi.switch.agl005"],
model: "WS-K03E",
vendor: "Aqara",
description: "Light Switch H2 US (2 Buttons, 2 Channels)",
fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
extend: [
lumiZigbeeOTA(),
lumiPreventReset(),
m.deviceEndpoints({ endpoints: { up: 1, down: 2 } }),
m.bindCluster({ endpointNames: ["up", "down"], cluster: "manuSpecificLumi", clusterType: "input" }),
m.bindCluster({ endpointNames: ["up", "down"], cluster: "genOnOff", clusterType: "input" }),
lumiPower(),
lumiOnOff({
operationMode: true,
powerOutageMemory: "enum",
lockRelay: true,
endpointNames: ["up", "down"],
}),
lumiAction({
actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
endpointNames: ["up", "down"],
}),
lumiLedDisabledNight(),
lumiFlipIndicatorLight(),
lumiSwitchMode(),
],
},
];
//# sourceMappingURL=lumi.js.map