zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
453 lines • 20.6 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 exposes = __importStar(require("../lib/exposes"));
const m = __importStar(require("../lib/modernExtend"));
const ea = exposes.access;
const VSMART_MANUFACTURER_CODE = 0x1379;
const COMMAND_DELAY_MS = 100;
const HOUR_TO_PERIOD_MULTIPLIER = 4;
const MAX_PERCENTAGE = 100;
const MAX_HOUR = 23;
const MIN_HOUR = 0;
const createLedIntensityConverter = (fieldName, endpointIndex, periodName) => ({
key: [fieldName],
convertSet: async (entity, key, value) => {
const percentage = Number(value);
if (Number.isNaN(percentage) || percentage < 0 || percentage > MAX_PERCENTAGE) {
throw new Error(`Invalid ${periodName} LED intensity. Expected: 0-${MAX_PERCENTAGE}%`);
}
const intensity = Math.round((percentage * 255) / MAX_PERCENTAGE);
const payload = { data: [intensity, endpointIndex, 0] };
await entity.command("vsmartSwitchControl", "setLedIntensity", payload, {
manufacturerCode: VSMART_MANUFACTURER_CODE,
disableDefaultResponse: true,
});
return {
state: {
[key]: percentage,
},
};
},
});
const mLocal = {
customCluster: () => m.deviceAddCustomCluster("vsmartSwitchControl", {
name: "vsmartSwitchControl",
ID: 0x0000,
manufacturerCode: VSMART_MANUFACTURER_CODE,
attributes: {},
commands: {
setLedColor: {
name: "setLedColor",
ID: 0xf3,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
setVibrationIntensity: {
name: "setVibrationIntensity",
ID: 0xf0,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
setLedBrightnessLevel: {
name: "setLedBrightnessLevel",
ID: 0xf4,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
setLedIntensity: {
name: "setLedIntensity",
ID: 0xf2,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
setTimePeriod: {
name: "setTimePeriod",
ID: 0xf5,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
},
commandsResponse: {
setLedColor: {
name: "setLedColor",
ID: 0xf3,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
setVibrationIntensity: {
name: "setVibrationIntensity",
ID: 0xf0,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
setLedBrightnessLevel: {
name: "setLedBrightnessLevel",
ID: 0xf4,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
setLedIntensity: {
name: "setLedIntensity",
ID: 0xf2,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
setTimePeriod: {
name: "setTimePeriod",
ID: 0xf5,
parameters: [{ name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.LIST_UINT8 }],
},
},
}),
ledColorControl: () => {
const exposes_list = [
exposes
.text("led_indicator_color_on", ea.SET)
.withDescription("LED indicator color when switch is ON (hex format: #RRGGBB, e.g., #ff0000 for red)"),
exposes
.text("led_indicator_color_off", ea.SET)
.withDescription("LED indicator color when switch is OFF (hex format: #RRGGBB, e.g., #ffffff for white)"),
];
const toZigbee = [
{
key: ["led_indicator_color_on", "led_indicator_color_off"],
convertSet: async (entity, key, value) => {
const hexColor = String(value).trim();
const hexMatch = hexColor.match(/^#?([0-9a-fA-F]{6})$/);
if (!hexMatch) {
throw new Error("Invalid color format. Expected hex format: #RRGGBB (e.g., #ff0000)");
}
const hex = hexMatch[1];
const r = Number.parseInt(hex.substring(0, 2), 16);
const g = Number.parseInt(hex.substring(2, 4), 16);
const b = Number.parseInt(hex.substring(4, 6), 16);
const state = key === "led_indicator_color_on" ? 0x01 : 0x00;
const payload = {
data: [r, g, b, state],
};
await entity.command("vsmartSwitchControl", "setLedColor", payload, {
manufacturerCode: VSMART_MANUFACTURER_CODE,
disableDefaultResponse: true,
});
return {
state: {
[key]: `#${hex.toLowerCase()}`,
},
};
},
},
];
return { exposes: exposes_list, toZigbee, isModernExtend: true };
},
vibrationIntensityControl: () => {
const exposes_list = [
exposes
.numeric("vibration_intensity", ea.SET)
.withValueMin(0)
.withValueMax(MAX_PERCENTAGE)
.withValueStep(1)
.withUnit("%")
.withDescription("Button vibration intensity (0-100%)"),
];
const toZigbee = [
{
key: ["vibration_intensity"],
convertSet: async (entity, key, value) => {
const intensity = Number(value);
if (typeof value === "undefined" || Number.isNaN(intensity) || intensity < 0 || intensity > MAX_PERCENTAGE) {
throw new Error(`Invalid vibration intensity. Expected: 0-${MAX_PERCENTAGE}`);
}
const byteValue = Math.round((intensity / MAX_PERCENTAGE) * 255);
const payload = { data: [byteValue] };
await entity.command("vsmartSwitchControl", "setVibrationIntensity", payload, {
manufacturerCode: VSMART_MANUFACTURER_CODE,
disableDefaultResponse: true,
});
return { state: { [key]: intensity } };
},
},
];
return { exposes: exposes_list, toZigbee, isModernExtend: true };
},
timePeriodControl: () => {
const exposes_list = [
exposes
.composite("time_periods", "time_periods", ea.SET)
.withFeature(exposes
.numeric("morning_start_hour", ea.SET)
.withValueMin(MIN_HOUR)
.withValueMax(MAX_HOUR)
.withValueStep(1)
.withUnit("h")
.withDescription("Morning period start hour (0-23)"))
.withFeature(exposes
.numeric("evening_start_hour", ea.SET)
.withValueMin(MIN_HOUR)
.withValueMax(MAX_HOUR)
.withValueStep(1)
.withUnit("h")
.withDescription("Evening period start hour (0-23)"))
.withFeature(exposes
.numeric("night_start_hour", ea.SET)
.withValueMin(MIN_HOUR)
.withValueMax(MAX_HOUR)
.withValueStep(1)
.withUnit("h")
.withDescription("Night period start hour (0-23)"))
.withDescription("Time period settings for switch behavior. Morning must start before evening, evening must start before night."),
];
const toZigbee = [
{
key: ["time_periods"],
convertSet: async (entity, key, value) => {
const periods = value;
const morningHour = Number(periods.morning_start_hour);
const eveningHour = Number(periods.evening_start_hour);
const nightHour = Number(periods.night_start_hour);
if (Number.isNaN(morningHour) || morningHour < MIN_HOUR || morningHour > MAX_HOUR) {
throw new Error(`Invalid morning start hour. Expected: ${MIN_HOUR}-${MAX_HOUR}`);
}
if (Number.isNaN(eveningHour) || eveningHour < MIN_HOUR || eveningHour > MAX_HOUR) {
throw new Error(`Invalid evening start hour. Expected: ${MIN_HOUR}-${MAX_HOUR}`);
}
if (Number.isNaN(nightHour) || nightHour < MIN_HOUR || nightHour > MAX_HOUR) {
throw new Error(`Invalid night start hour. Expected: ${MIN_HOUR}-${MAX_HOUR}`);
}
if (morningHour >= eveningHour) {
throw new Error(`Morning period (${morningHour}:00) must start before evening period (${eveningHour}:00)`);
}
if (eveningHour >= nightHour) {
throw new Error(`Evening period (${eveningHour}:00) must start before night period (${nightHour}:00)`);
}
// Convert all hours to period values (hour * HOUR_TO_PERIOD_MULTIPLIER)
const periodValues = [
morningHour * HOUR_TO_PERIOD_MULTIPLIER,
eveningHour * HOUR_TO_PERIOD_MULTIPLIER,
nightHour * HOUR_TO_PERIOD_MULTIPLIER,
];
const payload = { data: periodValues };
await entity.command("vsmartSwitchControl", "setTimePeriod", payload, {
manufacturerCode: VSMART_MANUFACTURER_CODE,
disableDefaultResponse: true,
});
return {
state: {
[key]: periods,
},
};
},
},
];
return { exposes: exposes_list, toZigbee, isModernExtend: true };
},
ledIntensityControl: () => {
const exposes_list = [
exposes
.numeric("morning_led_intensity", ea.SET)
.withValueMin(0)
.withValueMax(MAX_PERCENTAGE)
.withValueStep(1)
.withUnit("%")
.withDescription("LED intensity for morning period (0-100%)"),
exposes
.numeric("evening_led_intensity", ea.SET)
.withValueMin(0)
.withValueMax(MAX_PERCENTAGE)
.withValueStep(1)
.withUnit("%")
.withDescription("LED intensity for evening period (0-100%)"),
exposes
.numeric("night_led_intensity", ea.SET)
.withValueMin(0)
.withValueMax(MAX_PERCENTAGE)
.withValueStep(1)
.withUnit("%")
.withDescription("LED intensity for night period (0-100%)"),
];
const toZigbee = [
createLedIntensityConverter("morning_led_intensity", 0, "morning"),
createLedIntensityConverter("evening_led_intensity", 1, "evening"),
createLedIntensityConverter("night_led_intensity", 2, "night"),
];
return { exposes: exposes_list, toZigbee, isModernExtend: true };
},
ledBrightnessLevelsControl: () => {
const exposes_list = [
exposes
.composite("led_brightness_levels", "led_brightness_levels", ea.SET)
.withFeature(exposes
.numeric("low_brightness_percent", ea.SET)
.withValueMin(0)
.withValueMax(MAX_PERCENTAGE)
.withValueStep(1)
.withUnit("%")
.withDescription("Low brightness level percentage (0-100%)"))
.withFeature(exposes
.numeric("medium_brightness_percent", ea.SET)
.withValueMin(0)
.withValueMax(MAX_PERCENTAGE)
.withValueStep(1)
.withUnit("%")
.withDescription("Medium brightness level percentage (0-100%)"))
.withFeature(exposes
.numeric("high_brightness_percent", ea.SET)
.withValueMin(0)
.withValueMax(MAX_PERCENTAGE)
.withValueStep(1)
.withUnit("%")
.withDescription("High brightness level percentage (0-100%)"))
.withDescription("LED brightness levels for different intensity settings. Low must be lower than medium, Medium must be lower than high."),
];
const toZigbee = [
{
key: ["led_brightness_levels"],
convertSet: async (entity, key, value) => {
const levels = value;
const lowPercent = Number(levels.low_brightness_percent);
const mediumPercent = Number(levels.medium_brightness_percent);
const highPercent = Number(levels.high_brightness_percent);
if (Number.isNaN(lowPercent) || lowPercent < 0 || lowPercent > MAX_PERCENTAGE) {
throw new Error(`Invalid low brightness percentage. Expected: 0-${MAX_PERCENTAGE}`);
}
if (Number.isNaN(mediumPercent) || mediumPercent < 0 || mediumPercent > MAX_PERCENTAGE) {
throw new Error(`Invalid medium brightness percentage. Expected: 0-${MAX_PERCENTAGE}`);
}
if (Number.isNaN(highPercent) || highPercent < 0 || highPercent > MAX_PERCENTAGE) {
throw new Error(`Invalid high brightness percentage. Expected: 0-${MAX_PERCENTAGE}`);
}
if (lowPercent >= mediumPercent) {
throw new Error(`Low brightness (${lowPercent}%) must be lower than medium brightness (${mediumPercent}%)`);
}
if (mediumPercent >= highPercent) {
throw new Error(`Medium brightness (${mediumPercent}%) must be lower than high brightness (${highPercent}%)`);
}
const lowBrightness = Math.round((lowPercent * 255) / MAX_PERCENTAGE);
const mediumBrightness = Math.round((mediumPercent * 255) / MAX_PERCENTAGE);
const highBrightness = Math.round((highPercent * 255) / MAX_PERCENTAGE);
const commands = [{ data: [0, highBrightness] }, { data: [1, mediumBrightness] }, { data: [2, lowBrightness] }];
for (let i = 0; i < commands.length; i++) {
await entity.command("vsmartSwitchControl", "setLedBrightnessLevel", commands[i], {
manufacturerCode: VSMART_MANUFACTURER_CODE,
disableDefaultResponse: true,
});
if (i < commands.length - 1) {
await new Promise((resolve) => setTimeout(resolve, COMMAND_DELAY_MS));
}
}
return {
state: {
[key]: levels,
},
};
},
},
];
return { exposes: exposes_list, toZigbee, isModernExtend: true };
},
};
exports.definitions = [
{
zigbeeModel: ["HS-SWL100ZB-VNM", "HS-SWN100ZB-VNM", "HS-SWB100ZB-VNM", "HS-SRW100ZB-VNM"],
model: "HS-SW100ZB-VNM",
vendor: "VSmart",
description: "Wall switch 1 gang",
extend: [
m.onOff({ powerOnBehavior: false }),
mLocal.customCluster(),
mLocal.ledColorControl(),
mLocal.vibrationIntensityControl(),
mLocal.timePeriodControl(),
mLocal.ledIntensityControl(),
mLocal.ledBrightnessLevelsControl(),
],
},
{
zigbeeModel: ["HS-SWL200ZB-VNM", "HS-SWN200ZB-VNM", "HS-SWB200ZB-VNM", "HS-SRW200ZB-VNM"],
model: "HS-SW200ZB-VNM",
vendor: "VSmart",
description: "Wall switch 2 gang",
extend: [
m.deviceEndpoints({ endpoints: { 1: 1, 2: 2 } }),
m.onOff({ powerOnBehavior: false, endpointNames: ["1", "2"] }),
mLocal.customCluster(),
mLocal.ledColorControl(),
mLocal.vibrationIntensityControl(),
mLocal.timePeriodControl(),
mLocal.ledIntensityControl(),
mLocal.ledBrightnessLevelsControl(),
],
},
{
zigbeeModel: ["HS-SWL300ZB-VNM"],
model: "HS-SW300ZB-VNM",
vendor: "VSmart",
description: "Wall switch 3 gang",
extend: [
m.deviceEndpoints({ endpoints: { 1: 1, 2: 2, 3: 3 } }),
m.onOff({ powerOnBehavior: false, endpointNames: ["1", "2", "3"] }),
mLocal.customCluster(),
mLocal.ledColorControl(),
mLocal.vibrationIntensityControl(),
mLocal.timePeriodControl(),
mLocal.ledIntensityControl(),
mLocal.ledBrightnessLevelsControl(),
],
},
{
zigbeeModel: ["HS-SWL400ZB-VNM"],
model: "HS-SW400ZB-VNM",
vendor: "VSmart",
description: "Wall switch 4 gang",
extend: [
m.deviceEndpoints({ endpoints: { 1: 1, 2: 2, 3: 3, 4: 4 } }),
m.onOff({ powerOnBehavior: false, endpointNames: ["1", "2", "3", "4"] }),
mLocal.customCluster(),
mLocal.ledColorControl(),
mLocal.vibrationIntensityControl(),
mLocal.timePeriodControl(),
mLocal.ledIntensityControl(),
mLocal.ledBrightnessLevelsControl(),
],
},
{
zigbeeModel: ["HS-SEDR00ZB-VNM"],
model: "HS-SEDR00ZB-VNM",
vendor: "VSmart",
description: "Door/window sensor",
extend: [m.iasZoneAlarm({ zoneType: "contact", zoneAttributes: ["alarm_1", "battery_low", "tamper"], invertAlarm: true })],
},
{
zigbeeModel: ["HS-SEOC00ZB-VNM"],
model: "HS-SEOC00ZB-VNM",
vendor: "VSmart",
description: "Occupancy sensor",
extend: [m.battery(), m.occupancy()],
},
];
//# sourceMappingURL=vsmart.js.map