zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
1,162 lines • 108 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 constants = __importStar(require("../lib/constants"));
const constants_1 = require("../lib/constants");
const exposes = __importStar(require("../lib/exposes"));
const logger_1 = require("../lib/logger");
const m = __importStar(require("../lib/modernExtend"));
const modernExtend_1 = require("../lib/modernExtend");
const namron = __importStar(require("../lib/namron"));
const reporting = __importStar(require("../lib/reporting"));
const reporting_1 = require("../lib/reporting");
const sunricher = __importStar(require("../lib/sunricher"));
const utils = __importStar(require("../lib/utils"));
const utils_1 = require("../lib/utils");
const NS = "zhc:sunricher";
const e = exposes.presets;
const ea = exposes.access;
const sunricherManufacturerCode = 0x1224;
const SRZGP2801K45C_LOOKUP = {
33: "press_on",
32: "press_off",
55: "press_high",
56: "press_low",
53: "hold_high",
54: "hold_low",
52: "high_low_release",
99: "cw_ww_release",
98: "cw_dec_ww_inc",
100: "ww_inc_cw_dec",
65: "r_g_b",
66: "b_g_r",
64: "rgb_release",
};
const fzLocal = {
SRZGP2801K45C: {
cluster: "greenPower",
type: ["commandNotification", "commandCommissioningNotification"],
convert: (model, msg, publish, options, meta) => {
const commandID = msg.data.commandID;
if (utils.hasAlreadyProcessedMessage(msg, model, msg.data.frameCounter, `${msg.device.ieeeAddr}_${commandID}`))
return;
if (commandID >= 0xe0)
return; // Skip op commands
return { action: utils.getFromLookup(commandID, SRZGP2801K45C_LOOKUP) };
},
},
ZG9095B: {
cluster: "hvacThermostat",
type: ["attributeReport", "readResponse"],
convert: (model, msg, _publish, _options, meta) => {
const result = {};
if (msg.data.minSetpointDeadBand !== undefined) {
const property = utils.postfixWithEndpointName("min_setpoint_deadband", msg, model, meta);
result[property] = utils.precisionRound(msg.data.minSetpointDeadBand, 2) / 10;
}
return result;
},
},
ZG2858A: {
cluster: "genBasic",
type: "write",
convert: (model, msg, publish, options, meta) => {
const number = msg.data["16389"];
const payload = { action: (0, utils_1.postfixWithEndpointName)(`scene_${number}`, msg, model, meta) };
if ((0, utils_1.hasAlreadyProcessedMessage)(msg, model))
return;
(0, utils_1.addActionGroup)(payload, msg, model);
return payload;
},
},
};
const tzLocal = {
ZG9095B: {
min_setpoint_deadband: {
key: ["min_setpoint_deadband"],
convertGet: async (entity, _key, _meta) => {
await entity.read("hvacThermostat", ["minSetpointDeadBand"]);
},
convertSet: async (entity, _key, value, _meta) => {
await entity.write("hvacThermostat", {
minSetpointDeadBand: Math.round(Number(value) * 10),
});
return { state: { min_setpoint_deadband: value } };
},
},
temperature_display: {
key: ["temperature_display"],
convertSet: async (entity, _key, value, _meta) => {
const lookup = { room: 0, set: 1, floor: 2 };
const payload = { 4104: { value: utils.getFromLookup(value, lookup), type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } };
await entity.write("hvacThermostat", payload, { manufacturerCode: 0x1224 });
return { state: { temperature_display: value } };
},
convertGet: async (entity, _key, _meta) => {
await entity.read("hvacThermostat", [0x1008], { manufacturerCode: 0x1224 });
},
},
sensor: {
key: ["sensor"],
convertSet: async (entity, _key, value, _meta) => {
const lookup = { room: 1, floor: 2 };
const payload = { 4099: { value: utils.getFromLookup(value, lookup), type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } };
await entity.write("hvacThermostat", payload, { manufacturerCode: 0x1224 });
return { state: { sensor: value } };
},
convertGet: async (entity, _key, _meta) => {
await entity.read("hvacThermostat", [0x1003], { manufacturerCode: 0x1224 });
},
},
lcd_brightness: {
key: ["lcd_brightness"],
convertSet: async (entity, _key, value, _meta) => {
const lookup = { low: 1, mid: 2, high: 3 };
const payload = { 4096: { value: utils.getFromLookup(value, lookup), type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } };
await entity.write("hvacThermostat", payload, { manufacturerCode: 0x1224 });
return { state: { lcd_brightness: value } };
},
convertGet: async (entity, _key, _meta) => {
await entity.read("hvacThermostat", [0x1000], { manufacturerCode: 0x1224 });
},
},
},
};
const sunricherModernExtend = {
zg2858A() {
return {
exposes: [
e
.enum("action", ea.STATE, ["scene_1", "scene_2", "scene_3", "scene_4", "scene_5", "scene_6"])
.withDescription("Triggered action (e.g. a button click)")
.withCategory("diagnostic"),
],
fromZigbee: [fzLocal.ZG2858A],
isModernExtend: true,
configure: [(0, modernExtend_1.setupConfigureForBinding)("genBasic", "output")],
};
},
};
async function syncTime(endpoint) {
try {
const time = Math.round((Date.now() - constants.OneJanuary2000) / 1000 + new Date().getTimezoneOffset() * -1 * 60);
const values = { time: time };
await endpoint.write("genTime", values);
}
catch {
/* Do nothing*/
logger_1.logger.warning(String(e), NS);
}
}
async function syncTimeWithTimeZone(endpoint) {
try {
const time = Math.round((Date.now() - constants.OneJanuary2000) / 1000);
const timeZone = new Date().getTimezoneOffset() * -1 * 60;
await endpoint.write("genTime", { time, timeZone });
}
catch {
logger_1.logger.error("Failed to sync time with time zone", NS);
}
}
exports.definitions = [
{
zigbeeModel: ["HK-DIM-PIR"],
model: "SR-ZG9032A-PIR",
vendor: "Sunricher",
description: "Zigbee motion sensor + light sensor + 0-10V dimming",
extend: [
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3 } }),
m.light({ endpointNames: ["1"] }),
m.occupancy({ endpointNames: ["2"] }),
m.illuminance({ endpointNames: ["3"] }),
m.commandsOnOff({ endpointNames: ["1"] }),
m.commandsLevelCtrl({ endpointNames: ["1"] }),
m.enumLookup({
name: "dimming_brightness_curve",
cluster: "genBasic",
attribute: { ID: 0x8806, type: 0x20 },
lookup: {
linear: 0x00,
gamma_1_5: 0x0f,
gamma_1_8: 0x12,
},
description: "Dimming brightness curve. Options: linear, gamma 1.5, gamma 1.8. Default: linear.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "motion_sensor_lux_threshold",
cluster: "genBasic",
attribute: { ID: 0x8903, type: 0x21 },
valueMin: 0,
valueMax: 65535,
description: "Daylight sensor lux threshold. When the measured lux is below this value, the light is allowed to turn on. Set to minimum value to disable this function. Default: disabled.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "motion_sensor_sensitivity",
cluster: "genBasic",
attribute: { ID: 0x8905, type: 0x20 },
valueMin: 0,
valueMax: 15,
description: "Motion sensor sensitivity. 0 is highest sensitivity, 15 is lowest. Default: 1.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.enumLookup({
name: "brightness_module_enable",
cluster: "genBasic",
attribute: { ID: 0x890c, type: 0x20 },
lookup: {
disabled: 0,
enabled: 1,
},
description: "Enable or disable the brightness module. Options: enabled, disabled. Default: enabled.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "light_on_time",
cluster: "genBasic",
attribute: { ID: 0x8902, type: 0x21 },
valueMin: 0,
valueMax: 65535,
unit: "s",
description: "Light on time (first delay). When motion is detected and then the area is vacated, this is the time the light stays on. Unit: seconds. Default: 60 seconds.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "pwm_brightness_value",
cluster: "genBasic",
attribute: { ID: 0x8908, type: 0x21 },
valueMin: 0,
valueMax: 1000,
unit: "lux",
description: "Brightness value for PWM output when motion is detected. 0 disables this function. Default: disabled.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "pwm_output_percentage",
cluster: "genBasic",
attribute: { ID: 0x8909, type: 0x20 },
valueMin: 0,
valueMax: 254,
unit: "%",
description: "PWM output percentage when motion is detected. Range: 0-100%. Default: 100%.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "light_status_after_first_delay",
cluster: "genBasic",
attribute: { ID: 0x890a, type: 0x20 },
valueMin: 0,
valueMax: 254,
unit: "%",
description: "Light status after the first delay expires, during the second delay. Range: 0-100%. Default: 0% (off).",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "second_delay_time",
cluster: "genBasic",
attribute: { ID: 0x8901, type: 0x21 },
valueMin: 0,
valueMax: 65535,
unit: "s",
description: "Duration of the second delay after the first delay expires. Unit: seconds. Default: 60 seconds.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "light_status_after_second_delay",
cluster: "genBasic",
attribute: { ID: 0x890b, type: 0x20 },
valueMin: 0,
valueMax: 254,
unit: "%",
description: "Light status after the second delay expires. Range: 0-100%. Default: 0% (off).",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "linearity_error_ratio_lux",
cluster: "genBasic",
attribute: { ID: 0x890d, type: 0x21 },
valueMin: 100,
valueMax: 10000,
description: "Linearity error ratio coefficient for LUX measurement. 1000 means 1000‰ (default). Increasing this value magnifies the LUX measurement linearly, decreasing minifies it.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
m.numeric({
name: "fixed_deviation_lux",
cluster: "genBasic",
attribute: { ID: 0x890e, type: 0x29 },
valueMin: -100,
valueMax: 100,
description: "Fixed deviation of LUX measurement. Positive value increases, negative value decreases the measured LUX.",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
],
},
{
zigbeeModel: ["ZGRC-KEY-047"],
model: "SR-ZG2868K12-DIM",
vendor: "Sunricher",
description: "ZigBee single color remote",
extend: [
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 } }),
m.battery(),
m.commandsOnOff({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsLevelCtrl({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsScenes({ commands: ["recall", "store"] }),
],
},
{
fingerprint: [
{ modelID: "ON/OFF (2CH)", manufacturerName: "Somfy" },
{ modelID: "ON/OFF (2CH)", manufacturerName: "Sunricher" },
],
model: "SR-ZG9001T2-SW",
vendor: "Sunricher",
description: "Zigbee 2-gang touch panel",
extend: [
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2 } }),
m.onOff({ endpointNames: ["1", "2"] }),
m.commandsOnOff({ endpointNames: ["1", "2"] }),
m.identify(),
sunricher.extend.externalSwitchType(),
],
},
{
zigbeeModel: ["ZG9041A-2R"],
model: "SR-ZG9041A-2R",
vendor: "Sunricher",
description: "Zigbee 2ch smart relay",
extend: [
m.identify(),
m.commandsScenes({ endpointNames: ["1", "2"] }),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3 } }),
m.onOff({ powerOnBehavior: false, endpointNames: ["1", "2"], configureReporting: true }),
m.electricityMeter({ endpointNames: ["3"] }),
],
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["ZGRC-KEY-043"],
model: "SR-ZG2868EK7-CCT",
vendor: "Sunricher",
description: "Zigbee lighting remote control",
extend: [m.battery(), m.commandsOnOff(), m.commandsLevelCtrl(), m.commandsColorCtrl(), m.commandsScenes()],
},
{
zigbeeModel: ["ZG9098A-WinOnly"],
model: "SR-ZG9081A",
vendor: "Sunricher",
description: "Zigbee curtain control module",
extend: [
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3 } }),
m.windowCovering({
controls: ["lift", "tilt"],
coverInverted: true,
configureReporting: true,
endpointNames: ["1"],
}),
m.electricityMeter({ endpointNames: ["3"] }),
m.enumLookup({
name: "curtain_type",
cluster: "closuresWindowCovering",
attribute: { ID: 0x1000, type: zigbee_herdsman_1.Zcl.DataType.ENUM8 },
lookup: {
normal: 0,
venetian_blind: 1,
},
description: "Configure curtain type",
access: "ALL",
entityCategory: "config",
}),
sunricher.extend.motorControl(),
m.identify(),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ["closuresWindowCovering"]);
await reporting.currentPositionLiftPercentage(endpoint);
await reporting.currentPositionTiltPercentage(endpoint);
},
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["ZG9100B-5A"],
model: "SR-ZG9041A-R",
vendor: "Sunricher",
description: "Zigbee smart relay module",
extend: [m.onOff({ powerOnBehavior: false }), m.electricityMeter(), sunricher.extend.externalSwitchType()],
},
{
zigbeeModel: ["ZG2819S-DIM"],
model: "SR-ZG2819S-DIM",
vendor: "Sunricher",
description: "Zigbee dim remote",
extend: [
m.identify(),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 } }),
m.battery(),
m.commandsOnOff({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsLevelCtrl({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsColorCtrl({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsScenes({ endpointNames: ["1", "2", "3", "4"] }),
],
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["HK-ZRC-K5&RS-TL-G"],
model: "SR-ZG2836D5-G4",
vendor: "Sunricher",
description: "Zigbee smart remote",
extend: [
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 } }),
m.battery(),
m.commandsOnOff({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsLevelCtrl({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsColorCtrl({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsScenes({ endpointNames: ["1", "2", "3", "4"] }),
],
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["HK-DIM-MW2"],
model: "SR-ZG9032A-MW",
vendor: "Sunricher",
description: "Zigbee compatible fixture with integrated occupancy sensor",
extend: [
m.identify(),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3 } }),
m.light({ configureReporting: true, endpointNames: ["1"] }),
m.occupancy({ endpointNames: ["2"] }),
m.illuminance({ endpointNames: ["3"] }),
m.commandsScenes({ endpointNames: ["1"] }),
m.commandsOnOff(),
m.commandsLevelCtrl(),
m.numeric({
name: "network_join_search_count",
cluster: "genBasic",
attribute: { ID: 0x9000, type: 0x20 },
valueMin: 1,
valueMax: 255,
description: "How many times will the device search and join a Zigbee network, searching every 15 seconds. Default: 2 (1~255, 255 means always searching)",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "light_pwm_frequency",
cluster: "genBasic",
attribute: { ID: 0x9001, type: 0x21 },
valueMin: 0,
valueMax: 65535,
description: "Light PWM Frequency. Works after reset power of the device. DO NOT set the PWM frequency too high which will affect the dimming resolution. Default: 3300",
entityCategory: "config",
access: "ALL",
}),
m.enumLookup({
name: "dimming_brightness_curve",
cluster: "genBasic",
attribute: { ID: 0x8806, type: 0x20 },
lookup: {
linear: 0x00,
gamma_1_5: 0x0f,
gamma_1_8: 0x12,
},
description: "Dimming brightness curve. Options: linear, gamma 1.5, gamma 1.8. Default: linear.",
entityCategory: "config",
access: "ALL",
}),
m.enumLookup({
name: "start_up_on_off",
cluster: "genOnOff",
attribute: { ID: 0x4003, type: 0x30 },
lookup: {
off: 0x00,
on: 0x01,
last_state: 0xff,
},
description: "Device power-on state. Options: off, on, restore previous state. Default: restore previous state.",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "motion_sensor_lux_threshold",
cluster: "genBasic",
attribute: { ID: 0x8903, type: 0x21 },
valueMin: 0,
valueMax: 65535,
description: "Daylight sensor lux threshold. When the measured lux is below this value, the light is allowed to turn on. Set to minimum value to disable this function. Default: disabled.",
entityCategory: "config",
access: "ALL",
}),
m.enumLookup({
name: "motion_sensor_operation_mode",
cluster: "genBasic",
attribute: { ID: 0x8904, type: 0x20 },
lookup: {
auto: 0x00,
manual: 0x01,
},
description: "Motion sensor operation mode. Options: auto (PWM output on motion), manual (PWM controlled by gateway or switch). Default: auto.",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "motion_sensor_sensitivity",
cluster: "genBasic",
attribute: { ID: 0x8905, type: 0x20 },
valueMin: 0,
valueMax: 15,
description: "Motion sensor sensitivity. 0 is highest sensitivity, 15 is lowest. Default: 1.",
entityCategory: "config",
access: "ALL",
}),
m.enumLookup({
name: "motion_sensor_microwave_detection",
cluster: "genBasic",
attribute: { ID: 0x8906, type: 0x20 },
lookup: {
disabled: 0x00,
enabled: 0x01,
},
description: "Enable or disable microwave detection. Options: enabled, disabled. Default: enabled.",
entityCategory: "config",
access: "ALL",
}),
m.enumLookup({
name: "touchlink_onoff_broadcast",
cluster: "genBasic",
attribute: { ID: 0x8907, type: 0x20 },
lookup: {
do_not_send: 0,
send: 1,
},
description: "Send ON/OFF command to touchlink or binding devices. Options: send, do not send. Default: send.",
entityCategory: "config",
access: "ALL",
}),
m.enumLookup({
name: "brightness_module_enable",
cluster: "genBasic",
attribute: { ID: 0x890c, type: 0x20 },
lookup: {
disabled: 0,
enabled: 1,
},
description: "Enable or disable the brightness module. Options: enabled, disabled. Default: enabled.",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "light_on_time",
cluster: "genBasic",
attribute: { ID: 0x8902, type: 0x21 },
valueMin: 0,
valueMax: 65535,
unit: "s",
description: "Light on time (first delay). When motion is detected and then the area is vacated, this is the time the light stays on. Unit: seconds. Default: 60 seconds.",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "pwm_brightness_value",
cluster: "genBasic",
attribute: { ID: 0x8908, type: 0x21 },
valueMin: 0,
valueMax: 1000,
unit: "lux",
description: "Brightness value for PWM output when motion is detected. 0 disables this function. Default: disabled.",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "pwm_output_percentage",
cluster: "genBasic",
attribute: { ID: 0x8909, type: 0x20 },
valueMin: 0,
valueMax: 254,
unit: "%",
description: "PWM output percentage when motion is detected. Range: 0-100%. Default: 100%.",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "light_status_after_first_delay",
cluster: "genBasic",
attribute: { ID: 0x890a, type: 0x20 },
valueMin: 0,
valueMax: 254,
unit: "%",
description: "Light status after the first delay expires, during the second delay. Range: 0-100%. Default: 0% (off).",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "second_delay_time",
cluster: "genBasic",
attribute: { ID: 0x8901, type: 0x21 },
valueMin: 0,
valueMax: 65535,
unit: "s",
description: "Duration of the second delay after the first delay expires. Unit: seconds. Default: 60 seconds.",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "light_status_after_second_delay",
cluster: "genBasic",
attribute: { ID: 0x890b, type: 0x20 },
valueMin: 0,
valueMax: 254,
unit: "%",
description: "Light status after the second delay expires. Range: 0-100%. Default: 0% (off).",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "linearity_error_ratio_lux",
cluster: "genBasic",
attribute: { ID: 0x890d, type: 0x21 },
valueMin: 100,
valueMax: 10000,
description: "Linearity error ratio coefficient for LUX measurement. 1000 means 1000‰ (default). Increasing this value magnifies the LUX measurement linearly, decreasing minifies it. For example, 1001 means 1.001x, 500 means 0.5x.",
entityCategory: "config",
access: "ALL",
}),
m.numeric({
name: "fixed_deviation_lux",
cluster: "genBasic",
attribute: { ID: 0x890e, type: 0x29 },
valueMin: -100,
valueMax: 100,
description: "Fixed deviation of LUX measurement. Signed 2-byte integer. Positive value increases, negative value decreases the measured LUX. For example, 100 means +100 LUX, -100 means -100 LUX.",
entityCategory: "config",
access: "ALL",
}),
],
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["ZG9098A-LightWin", "ZG9098A-Win"],
model: "SR-ZG9098A-Win",
vendor: "Sunricher",
description: "Zigbee curtain control module",
extend: [
sunricher.extend.configureReadModelID(),
m.commandsScenes({ endpointNames: ["1", "2"] }),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3 } }),
m.windowCovering({
controls: ["lift", "tilt"],
coverInverted: true,
configureReporting: true,
endpointNames: ["1"],
}),
m.electricityMeter({ endpointNames: ["3"] }),
m.enumLookup({
name: "dev_mode",
cluster: "genBasic",
attribute: { ID: 0x0001, type: 0x30 },
lookup: {
curtain: 0,
light: 1,
},
description: "Set device type (curtain or light)",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: 0x1224 },
}),
m.enumLookup({
name: "curtain_type",
cluster: "closuresWindowCovering",
attribute: { ID: 0x1000, type: zigbee_herdsman_1.Zcl.DataType.ENUM8 },
lookup: {
normal: 0,
venetian_blind: 1,
},
description: "Configure curtain type",
access: "ALL",
entityCategory: "config",
zigbeeCommandOptions: { manufacturerCode: sunricherManufacturerCode },
}),
sunricher.extend.motorControl(),
m.identify(),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ["closuresWindowCovering"]);
await reporting.currentPositionLiftPercentage(endpoint);
await reporting.currentPositionTiltPercentage(endpoint);
},
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["ZG9098A-Light", "ZG9098A-WinLight"],
model: "SR-ZG9098A-Light",
vendor: "Sunricher",
description: "Zigbee 2ch smart relay",
extend: [
sunricher.extend.configureReadModelID(),
m.identify(),
m.commandsScenes({ endpointNames: ["1", "2"] }),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3 } }),
m.onOff({ powerOnBehavior: false, endpointNames: ["1", "2"], configureReporting: true }),
m.electricityMeter({ endpointNames: ["3"] }),
m.enumLookup({
name: "dev_mode",
cluster: "genBasic",
attribute: { ID: 0x0001, type: 0x30 },
lookup: {
curtain: 0,
light: 1,
},
description: "Set device type (curtain/light)",
entityCategory: "config",
access: "ALL",
zigbeeCommandOptions: { manufacturerCode: 0x1224 },
}),
],
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["ZG2833K8_EU05"],
model: "SR-ZG9001K8-DIM",
vendor: "Sunricher",
description: "Zigbee 8 button wall switch",
extend: [
m.commandsOnOff({
endpointNames: ["1", "2", "3", "4"],
}),
m.battery(),
m.commandsLevelCtrl({
commands: ["brightness_move_up", "brightness_move_down", "brightness_stop"],
endpointNames: ["1", "2", "3", "4"],
}),
],
whiteLabel: [{ vendor: "Sunricher", model: "SR-ZG9001NK8-DIM" }],
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["HK-ZRC-K10N-E"],
model: "SR-ZG2856-Pro",
vendor: "Sunricher",
description: "Zigbee smart remote",
extend: [
m.battery(),
m.deviceAddCustomCluster("sunricherRemote", {
name: "sunricherRemote",
ID: 0xff03,
attributes: {},
commands: {
press: {
name: "press",
ID: 0x01,
parameters: [
{ name: "messageType", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
{ name: "button2", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
{ name: "button1", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
{ name: "pressType", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
],
},
},
commandsResponse: {},
}),
sunricher.extend.SRZG2856Pro(),
],
},
{
zigbeeModel: ["ZG9340"],
model: "SR-ZG9093TRV",
vendor: "Sunricher",
description: "Zigbee thermostatic radiator valve",
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: zigbee_herdsman_1.Zcl.Clusters.hvacThermostat.ID,
attributes: {
screenTimeout: {
name: "screenTimeout",
ID: 0x100d,
type: zigbee_herdsman_1.Zcl.DataType.UINT8,
manufacturerCode: sunricherManufacturerCode,
write: true,
max: 0xff,
},
antiFreezingTemp: {
name: "antiFreezingTemp",
ID: 0x1005,
type: zigbee_herdsman_1.Zcl.DataType.UINT8,
manufacturerCode: sunricherManufacturerCode,
write: true,
max: 0xff,
},
temperatureDisplayMode: {
name: "temperatureDisplayMode",
ID: 0x1008,
type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
manufacturerCode: sunricherManufacturerCode,
write: true,
max: 0xff,
},
windowOpenCheck: {
name: "windowOpenCheck",
ID: 0x1009,
type: zigbee_herdsman_1.Zcl.DataType.UINT8,
manufacturerCode: sunricherManufacturerCode,
write: true,
max: 0xff,
},
hysteresis: {
name: "hysteresis",
ID: 0x100a,
type: zigbee_herdsman_1.Zcl.DataType.UINT8,
manufacturerCode: sunricherManufacturerCode,
write: true,
max: 0xff,
},
windowOpenFlag: {
name: "windowOpenFlag",
ID: 0x100b,
type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
manufacturerCode: sunricherManufacturerCode,
write: true,
max: 0xff,
},
forcedHeatingTime: {
name: "forcedHeatingTime",
ID: 0x100e,
type: zigbee_herdsman_1.Zcl.DataType.UINT8,
manufacturerCode: sunricherManufacturerCode,
write: true,
max: 0xff,
},
errorCode: {
name: "errorCode",
ID: 0x2003,
type: zigbee_herdsman_1.Zcl.DataType.BITMAP8,
manufacturerCode: sunricherManufacturerCode,
write: true,
},
awayOrBoostMode: {
name: "awayOrBoostMode",
ID: 0x2002,
type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
manufacturerCode: sunricherManufacturerCode,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
sunricher.extend.thermostatPreset(),
sunricher.extend.thermostatCurrentHeatingSetpoint(),
m.battery(),
m.identify(),
m.numeric({
name: "screen_timeout",
cluster: "hvacThermostat",
attribute: "screenTimeout",
valueMin: 10,
valueMax: 30,
unit: "s",
description: "Screen Timeout for Inactivity (excluding gateway config). Range: 10-30s, Default: 10s",
access: "ALL",
entityCategory: "config",
}),
m.numeric({
name: "anti_freezing_temp",
cluster: "hvacThermostat",
attribute: "antiFreezingTemp",
valueMin: 0,
valueMax: 10,
unit: "°C",
description: "Anti Freezing(Low Temp) Mode Configuration. 0: disabled, 5~10: temperature (5°C by default)",
access: "ALL",
entityCategory: "config",
}),
m.enumLookup({
name: "temperature_display_mode",
cluster: "hvacThermostat",
attribute: "temperatureDisplayMode",
lookup: {
set_temp: 1,
room_temp: 2,
},
description: "Temperature Display Mode. 1: displays set temp, 2: displays room temp (default)",
access: "ALL",
}),
m.numeric({
name: "window_open_check",
cluster: "hvacThermostat",
attribute: "windowOpenCheck",
valueMin: 0,
valueMax: 10,
unit: "°C",
description: "The temperature threshold for Window Open Detect, value range 0~10, unit is 1°C, 0 means disabled, default value is 5",
access: "ALL",
entityCategory: "config",
}),
m.numeric({
name: "hysteresis",
cluster: "hvacThermostat",
attribute: "hysteresis",
valueMin: 5,
valueMax: 20,
valueStep: 0.1,
unit: "°C",
description: "Control hysteresis setting, range is 5-20, unit is 0.1°C, default value is 10. Because the sensor accuracy is 0.5°C, it is recommended not to set this value below 1°C to avoid affecting the battery life.",
access: "ALL",
entityCategory: "config",
}),
m.binary({
name: "window_open_flag",
cluster: "hvacThermostat",
attribute: "windowOpenFlag",
description: "Window open flag",
valueOn: ["opened", 1],
valueOff: ["not_opened", 0],
access: "STATE_GET",
}),
m.numeric({
name: "forced_heating_time",
cluster: "hvacThermostat",
attribute: "forcedHeatingTime",
valueMin: 10,
valueMax: 90,
unit: "10s",
description: "Forced heating time, range 10~90, unit is 10s, default value is 30(300s)",
access: "ALL",
entityCategory: "config",
}),
m.enumLookup({
name: "error_code",
cluster: "hvacThermostat",
attribute: "errorCode",
lookup: {
no_error: 0,
motor_error: 4,
motor_timeout: 5,
},
description: "Error code: 0=No hardware error, 4=Motor error (detected not running), 5=The motor runs exceeding the self-check time without finding the boundary",
access: "STATE_GET",
}),
m.enumLookup({
name: "temperature_display_unit",
cluster: "hvacUserInterfaceCfg",
attribute: { ID: 0x0000, type: 0x30 },
lookup: {
celsius: 0x00,
fahrenheit: 0x01,
},
description: "The temperature unit shown on the display",
access: "ALL",
entityCategory: "config",
}),
sunricher.extend.thermostatWeeklySchedule(),
sunricher.extend.thermostatChildLock(),
],
fromZigbee: [fz.thermostat],
toZigbee: [
tz.thermostat_local_temperature,
tz.thermostat_local_temperature_calibration,
tz.thermostat_running_state,
tz.thermostat_temperature_display_mode,
],
exposes: [
e
.climate()
.withLocalTemperature(ea.STATE_GET)
.withSetpoint("current_heating_setpoint", 5, 35, 0.1, ea.ALL)
.withLocalTemperatureCalibration(-30, 30, 0.5, ea.ALL)
.withPreset(["off", "auto", "away", "sleep", "manual", "forced"], "Preset of the thermostat. Manual: comfort temp (20°C), Auto: schedule temp (see schedule), " +
"Away: eco temp (6°C), Sleep: night temp (17°C), Forced: temporary heating with configurable duration (default 300s)")
.withSystemMode(["off", "auto", "heat", "sleep"], ea.ALL)
.withRunningState(["idle", "heat"]),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
const bindClusters = ["genBasic", "genPowerCfg", "hvacThermostat", "hvacUserInterfaceCfg", "genTime"];
const maxRetries = 3;
let retryCount = 0;
let bindSuccess = false;
while (retryCount < maxRetries) {
try {
if (!bindSuccess) {
await reporting.bind(endpoint, coordinatorEndpoint, bindClusters);
bindSuccess = true;
}
const configPromises = [
reporting.thermostatTemperature(endpoint),
reporting.thermostatOccupiedHeatingSetpoint(endpoint),
reporting.thermostatUnoccupiedHeatingSetpoint(endpoint),
reporting.thermostatRunningState(endpoint),
reporting.batteryPercentageRemaining(endpoint),
endpoint.configureReporting("hvacUserInterfaceCfg", (0, reporting_1.payload)("tempDisplayMode", 10, constants_1.repInterval.MINUTE, null)),
];
await Promise.all(configPromises);
const customAttributes = [
"screenTimeout",
"antiFreezingTemp",
"temperatureDisplayMode",
"windowOpenCheck",
"hysteresis",
"windowOpenFlag",
"forcedHeatingTime",
];
await Promise.all(customAttributes.map((attr) => endpoint.configureReporting("hvacThermostat", (0, reporting_1.payload)(attr, 10, constants_1.repInterval.MINUTE, null))));
const readPromises = [
endpoint.read("hvacUserInterfaceCfg", ["tempDisplayMode"]),
endpoint.read("hvacThermostat", ["localTemp", "runningState"]),
endpoint.read("hvacThermostat", [
"screenTimeout",
"antiFreezingTemp",
"temperatureDisplayMode",
"windowOpenCheck",
"hysteresis",
"windowOpenFlag",
"forcedHeatingTime",
"errorCode",
]),
];
await Promise.all(readPromises);
await syncTimeWithTimeZone(endpoint);
break;
}
catch (error) {
retryCount++;
logger_1.logger.warning(`Configure attempt ${retryCount} failed: ${error}`, NS);
if (retryCount === maxRetries) {
logger_1.logger.error(`Failed to configure device after ${maxRetries} attempts`, NS);
throw error;
}
await new Promise((resolve) => setTimeout(resolve, 2000 * retryCount));
}
}
},
},
{
zigbeeModel: ["HK-SENSOR-SMO"],
model: "SR-ZG9070A-SS",
vendor: "Sunricher",
description: "Smart photoelectric smoke alarm",
extend: [
m.battery(),
m.iasZoneAlarm({
zoneType: "smoke",
zoneAttributes: ["alarm_1", "alarm_2", "tamper", "battery_low"],
}),
m.iasWarning(),
],
},
{
zigbeeModel: ["HK-SENSOR-PRE"],
model: "SR-ZG9030F-PS",
vendor: "Sunricher",
description: "Smart human presence sensor",
extend: [
m.illuminance({ scale: (value) => value }),
m.occupancy(),
m.commandsOnOff(),
m.deviceAddCustomCluster("sunricherSensor", {
name: "sunricherSensor",
ID: 0xfc8b,
manufacturerCode: 0x120b,
attributes: {
indicatorLight: { name: "indicatorLight", ID: 0xf001, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
detectionArea: { name: "detectionArea", ID: 0xf002, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
illuminanceThreshold: { name: "illuminanceThreshold", ID: 0xf004, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
},
commands: {},
commandsResponse: {},
}),
sunricher.extend.indicatorLight(),
m.numeric({
name: "detection_area",
cluster: "sunricherSensor",
attribute: "detectionArea",
description: "Detection area range (default: 50%)",
valueMin: 0,
valueMax: 100,
valueStep: 1,
unit: "%",
access: "ALL",
entityCategory: "config",
}),
m.numeric({
name: "illuminance_threshold",
cluster: "sunricherSensor",
attribute: "illuminanceThreshold",
description: "Illuminance threshold for triggering (default: 100)",
valueMin: 10,
valueMax: 100,
valueStep: 1,
unit: "lx",
access: "ALL",
entityCategory: "config",
}),
],
},
{
zigbeeModel: ["HK-SENSOR-GAS"],
model: "SR-ZG9060A-GS",
vendor: "Sunricher",
description: "Smart combustible gas sensor",
ex