zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
1,126 lines • 52.7 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 develco_1 = require("../lib/develco");
const exposes = __importStar(require("../lib/exposes"));
const logger_1 = require("../lib/logger");
const m = __importStar(require("../lib/modernExtend"));
const reporting = __importStar(require("../lib/reporting"));
const utils = __importStar(require("../lib/utils"));
const e = exposes.presets;
const ea = exposes.access;
const NS = "zhc:develco";
// develco specific cosntants
const manufacturerOptions = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DEVELCO };
/* MOSZB-1xx - ledControl - bitmap8 - r/w
* 0x00 Disable LED when movement is detected.
* 0x01 Enables periodic fault flashes. These flashes are used to indicate e.g. low battery level.
* 0x02 Enables green application defined LED. This is e.g. used to indicate motion detection.
* Default value 0xFF ( seems to be fault + motion)
*/
const develcoLedControlMap = {
0: "off",
1: "fault_only",
2: "motion_only",
255: "both",
};
// develco specific converters
const develco = {
fz: {
// Some Develco devices report strange values sometimes
// https://github.com/Koenkk/zigbee2mqtt/issues/13329
electrical_measurement: {
...fz.electrical_measurement,
convert: (model, msg, publish, options, meta) => {
if (!Number.isNaN(msg.data.rmsVoltage) && !Number.isNaN(msg.data.rmsCurrent) && !Number.isNaN(msg.data.activePower)) {
return fz.electrical_measurement.convert(model, msg, publish, options, meta);
}
},
},
metering: {
...fz.metering,
convert: (model, msg, publish, options, meta) => {
if (!Number.isNaN(msg.data.instantaneousDemand) && msg.data.currentSummDelivered !== 0) {
return fz.metering.convert(model, msg, publish, options, meta);
}
},
},
pulse_configuration: {
cluster: "seMetering",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.develcoPulseConfiguration !== undefined) {
result[utils.postfixWithEndpointName("pulse_configuration", msg, model, meta)] = msg.data.develcoPulseConfiguration;
}
return result;
},
},
interface_mode: {
cluster: "seMetering",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.develcoInterfaceMode !== undefined) {
result[utils.postfixWithEndpointName("interface_mode", msg, model, meta)] =
constants.develcoInterfaceMode[msg.data.develcoInterfaceMode] !== undefined
? constants.develcoInterfaceMode[msg.data.develcoInterfaceMode]
: msg.data.develcoInterfaceMode;
}
if (msg.data.status !== undefined) {
result.battery_low = (msg.data.status & 2) > 0;
result.check_meter = (msg.data.status & 1) > 0;
}
return result;
},
},
fault_status: {
cluster: "genBinaryInput",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.reliability !== undefined) {
const lookup = { 0: "no_fault_detected", 7: "unreliable_other", 8: "process_error" };
result.reliability = utils.getFromLookup(msg.data.reliability, lookup);
}
if (msg.data.statusFlags !== undefined) {
result.fault = msg.data.statusFlags === 1;
}
return result;
},
},
led_control: {
cluster: "genBasic",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const state = {};
if (msg.data.develcoLedControl !== undefined) {
state.led_control = utils.getFromLookup(msg.data.develcoLedControl, develcoLedControlMap);
}
return state;
},
},
ias_occupancy_timeout: {
cluster: "ssIasZone",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const state = {};
if (msg.data.develcoAlarmOffDelay !== undefined) {
state.occupancy_timeout = msg.data.develcoAlarmOffDelay;
}
return state;
},
},
metering_emizb132: {
cluster: "seMetering",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
if (utils.hasAlreadyProcessedMessage(msg, model))
return;
const payload = {};
const multiplier = 1; // msg.endpoint.getClusterAttributeValue("seMetering", "multiplier") as number;
const divisor = 1000; // msg.endpoint.getClusterAttributeValue("seMetering", "divisor") as number;
const factor = multiplier && divisor ? multiplier / divisor : null;
if (msg.data.currentSummDelivered !== undefined) {
const value = msg.data.currentSummDelivered;
if (value === 0 || value === 0xffffffffffff || Number.isNaN(value)) {
return;
}
const property = utils.postfixWithEndpointName("energy", msg, model, meta);
payload[property] = value * (factor ?? 1);
}
if (msg.data.currentSummReceived !== undefined) {
const value = msg.data.currentSummReceived;
const property = utils.postfixWithEndpointName("produced_energy", msg, model, meta);
payload[property] = value * (factor ?? 1);
}
return payload;
},
},
electrical_measurement_emizb132: {
cluster: "haElectricalMeasurement",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const interfaceModeLookup = {
norwegian_han: { value: 0x0200, acCurrentDivisor: 10 },
norwegian_han_extra_load: { value: 0x0201, acCurrentDivisor: 10 },
aidon_meter: { value: 0x0202, acCurrentDivisor: 10 },
kaifa_and_kamstrup: { value: 0x0203, acCurrentDivisor: 1000 },
};
const result = fz.electrical_measurement.convert(model, msg, publish, options, meta);
// Divisor for current depends on interface_mode, adjust converted values
if (result && typeof result === "object") {
const currentMode = meta.state?.interface_mode || "norwegian_han";
const divisor = interfaceModeLookup[currentMode]?.acCurrentDivisor || 10;
const clusterDivisor = msg.endpoint.getClusterAttributeValue("haElectricalMeasurement", "acCurrentDivisor");
if (result.current !== undefined) {
result.current = (result.current * clusterDivisor) / divisor;
}
if (result.current_phase_b !== undefined) {
result.current_phase_b = (result.current_phase_b * clusterDivisor) / divisor;
}
if (result.current_phase_c !== undefined) {
result.current_phase_c = (result.current_phase_c * clusterDivisor) / divisor;
}
}
return result;
},
},
ias_smoke_alarm_1_develco: {
cluster: "ssIasZone",
type: "commandStatusChangeNotification",
convert: (model, msg, publish, options, meta) => {
const zoneStatus = msg.data.zonestatus;
return {
smoke: (zoneStatus & 1) > 0,
battery_low: (zoneStatus & (1 << 3)) > 0,
supervision_reports: (zoneStatus & (1 << 4)) > 0,
restore_reports: (zoneStatus & (1 << 5)) > 0,
test: (zoneStatus & (1 << 8)) > 0,
};
},
},
},
tz: {
pulse_configuration: {
key: ["pulse_configuration"],
convertSet: async (entity, key, value, meta) => {
await entity.write("seMetering", { develcoPulseConfiguration: value }, manufacturerOptions);
return { state: { pulse_configuration: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("seMetering", ["develcoPulseConfiguration"], manufacturerOptions);
},
},
interface_mode: {
key: ["interface_mode"],
convertSet: async (entity, key, value, meta) => {
const payload = { develcoInterfaceMode: utils.getKey(constants.develcoInterfaceMode, value, undefined, Number) };
await entity.write("seMetering", payload, manufacturerOptions);
return { state: { interface_mode: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("seMetering", ["develcoInterfaceMode"], manufacturerOptions);
},
},
current_summation: {
key: ["current_summation"],
convertSet: async (entity, key, value, meta) => {
await entity.write("seMetering", { develcoCurrentSummation: value }, manufacturerOptions);
return { state: { current_summation: value } };
},
},
led_control: {
key: ["led_control"],
convertSet: async (entity, key, value, meta) => {
const ledControl = utils.getKey(develcoLedControlMap, value, value, Number);
await entity.write("genBasic", { develcoLedControl: ledControl }, manufacturerOptions);
return { state: { led_control: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("genBasic", ["develcoLedControl"], manufacturerOptions);
},
},
ias_occupancy_timeout: {
key: ["occupancy_timeout"],
convertSet: async (entity, key, value, meta) => {
let timeoutValue = utils.toNumber(value, "occupancy_timeout");
if (timeoutValue < 5) {
logger_1.logger.warning(`Minimum occupancy_timeout is 5, using 5 instead of ${timeoutValue}!`, NS);
timeoutValue = 5;
}
await entity.write("ssIasZone", { develcoAlarmOffDelay: timeoutValue }, manufacturerOptions);
return { state: { occupancy_timeout: timeoutValue } };
},
convertGet: async (entity, key, meta) => {
await entity.read("ssIasZone", ["develcoAlarmOffDelay"], manufacturerOptions);
},
},
arm_mode: {
key: ["arm_mode"],
convertSet: async (entity, key, value, meta) => {
utils.assertObject(value, key);
await tz.arm_mode.convertSet?.(entity, key, { ...value, audiblenotif: value.audiblenotif ?? 1 }, meta);
},
},
},
};
exports.definitions = [
{
zigbeeModel: ["SPLZB-131"],
model: "SPLZB-131",
vendor: "Develco",
description: "Power plug",
toZigbee: [tz.on_off],
ota: true,
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.deviceTemperature(),
m.electricityMeter({ acFrequency: true, fzMetering: develco.fz.metering, fzElectricalMeasurement: develco.fz.electrical_measurement }),
m.onOff({ powerOnBehavior: false, configureReporting: false }),
],
endpoint: (device) => {
return { default: 2 };
},
configure: async (device, coordinatorEndpoint) => {
// Device also has genOnOff on endpoint 1, but that fails to setup, disable configureReporting in m.onOff above
// and configure it for endpoint 2 here instead.
// https://github.com/Koenkk/zigbee2mqtt/issues/29548
await reporting.onOff(device.getEndpoint(2));
},
},
{
zigbeeModel: ["SPLZB-132"],
model: "SPLZB-132",
vendor: "Develco",
description: "Power plug",
ota: true,
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.deviceTemperature(),
m.electricityMeter({ acFrequency: true, fzMetering: develco.fz.metering, fzElectricalMeasurement: develco.fz.electrical_measurement }),
m.onOff(),
],
endpoint: (device) => {
return { default: 2 };
},
},
{
zigbeeModel: ["SPLZB-134"],
model: "SPLZB-134",
vendor: "Develco",
description: "Power plug (type G)",
ota: true,
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.deviceTemperature(),
m.electricityMeter({ acFrequency: true, fzMetering: develco.fz.metering, fzElectricalMeasurement: develco.fz.electrical_measurement }),
m.onOff(),
],
endpoint: (device) => {
return { default: 2 };
},
},
{
zigbeeModel: ["SPLZB-137"],
model: "SPLZB-137",
vendor: "Develco",
description: "Power plug",
fromZigbee: [fz.on_off, develco.fz.electrical_measurement, develco.fz.metering],
toZigbee: [tz.on_off],
ota: true,
exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.ac_frequency()],
extend: [develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(), develco_1.develcoModernExtend.readGenBasicPrimaryVersions()],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(2);
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "haElectricalMeasurement", "seMetering"]);
await reporting.onOff(endpoint);
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint, true);
await reporting.activePower(endpoint);
await reporting.rmsCurrent(endpoint);
await reporting.rmsVoltage(endpoint);
await reporting.readMeteringMultiplierDivisor(endpoint);
await reporting.currentSummDelivered(endpoint);
await reporting.acFrequency(endpoint);
},
endpoint: (device) => {
return { default: 2 };
},
},
{
zigbeeModel: ["SMRZB-143"],
model: "SMRZB-143",
vendor: "Develco",
description: "Smart cable",
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.deviceTemperature(),
m.electricityMeter({ acFrequency: true, fzMetering: develco.fz.metering, fzElectricalMeasurement: develco.fz.electrical_measurement }),
m.onOff(),
],
endpoint: (device) => {
return { default: 2 };
},
},
{
zigbeeModel: ["EMIZB-132"],
model: "EMIZB-132",
vendor: "Develco",
description: "Wattle AMS HAN power-meter sensor",
version: "0.0.1",
ota: true,
extend: [
develco_1.develcoModernExtend.addCustomDevelcoSeMeteringCluster(),
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
m.numeric({
name: "power",
cluster: "haElectricalMeasurement",
attribute: "totalActivePower",
description: "Total active power.",
unit: "W",
access: "STATE_GET",
reporting: { min: 5, max: "1_HOUR", change: 1 },
}),
m.numeric({
name: "power_reactive",
cluster: "haElectricalMeasurement",
attribute: "totalReactivePower",
description: "Total reactive power.",
unit: "VAr",
access: "STATE_GET",
reporting: { min: 5, max: "1_HOUR", change: 1 },
}),
m.enumLookup({
name: "interface_mode",
cluster: "seMetering",
attribute: "develcoInterfaceMode",
description: "Specifies the configuration of the external HAN port interface.",
entityCategory: "config",
access: "ALL",
lookup: {
norwegian_han: 0x0200,
norwegian_han_extra_load: 0x0201,
aidon_meter: 0x0202,
kaifa_and_kamstrup: 0x0203,
},
zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DEVELCO },
}),
m.electricityMeter({
power: false,
voltage: { divisor: 10 },
current: { divisor: 10 },
threePhase: true,
energy: { divisor: 1000, multiplier: 1 },
producedEnergy: { divisor: 1000, multiplier: 1 },
fzMetering: develco.fz.metering_emizb132,
fzElectricalMeasurement: develco.fz.electrical_measurement_emizb132,
}),
],
},
{
zigbeeModel: ["SMSZB-120", "GWA1512_SmokeSensor"],
model: "SMSZB-120",
vendor: "Develco",
description: "Smoke detector with siren",
whiteLabel: [
{ vendor: "Frient", model: "94430", description: "Smart Intelligent Smoke Alarm" },
{ vendor: "Cavius", model: "2103", description: "RF SMOKE ALARM, 5 YEAR 65MM" },
],
fromZigbee: [develco.fz.ias_smoke_alarm_1_develco, fz.ias_enroll, fz.ias_wd, develco.fz.fault_status],
toZigbee: [tz.warning, tz.ias_max_duration, tz.warning_simple],
ota: true,
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(), // TODO: ep 38
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(35);
// Device supports only 4 binds (otherwise you get TABLE_FULL error)
// https://github.com/Koenkk/zigbee2mqtt/issues/23684
if (endpoint.binds.some((b) => b.cluster.name === "genPollCtrl")) {
await endpoint.unbind("genPollCtrl", coordinatorEndpoint);
}
await reporting.bind(endpoint, coordinatorEndpoint, ["ssIasZone", "ssIasWd", "genBinaryInput"]);
await endpoint.read("ssIasZone", ["iasCieAddr", "zoneState", "zoneId"]);
await endpoint.read("genBinaryInput", ["reliability", "statusFlags"]);
await endpoint.read("ssIasWd", ["maxDuration"]);
},
endpoint: (device) => {
return { default: 35 };
},
exposes: [
e.smoke(),
e.battery_low(),
e.test(),
e.numeric("max_duration", ea.ALL).withUnit("s").withValueMin(0).withValueMax(600).withDescription("Duration of Siren"),
e.binary("alarm", ea.SET, "START", "OFF").withDescription("Manual Start of Siren"),
e
.enum("reliability", ea.STATE, ["no_fault_detected", "unreliable_other", "process_error"])
.withDescription("Indicates reason if any fault"),
e.binary("fault", ea.STATE, true, false).withDescription("Indicates whether the device are in fault state"),
],
},
{
zigbeeModel: ["SPLZB-141"],
model: "SPLZB-141",
vendor: "Develco",
description: "Power plug",
fromZigbee: [fz.on_off, develco.fz.electrical_measurement, develco.fz.metering],
toZigbee: [tz.on_off],
ota: true,
exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.ac_frequency()],
extend: [develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(), develco_1.develcoModernExtend.readGenBasicPrimaryVersions()],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(2);
await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "haElectricalMeasurement", "seMetering"]);
await reporting.onOff(endpoint);
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
await reporting.activePower(endpoint);
await reporting.rmsCurrent(endpoint);
await reporting.rmsVoltage(endpoint);
await reporting.readMeteringMultiplierDivisor(endpoint);
await reporting.currentSummDelivered(endpoint);
await reporting.acFrequency(endpoint);
},
endpoint: (device) => {
return { default: 2 };
},
},
{
zigbeeModel: ["HESZB-120"],
model: "HESZB-120",
vendor: "Develco",
description: "Fire detector with siren",
whiteLabel: [{ vendor: "Frient", model: "94431", description: "Smart Intelligent Heat Alarm" }],
fromZigbee: [develco.fz.ias_smoke_alarm_1_develco, fz.ias_enroll, fz.ias_wd, develco.fz.fault_status],
toZigbee: [tz.warning, tz.ias_max_duration, tz.warning_simple],
ota: true,
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(), // TODO: ep 38
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(35);
// Device supports only 4 binds (otherwise you get TABLE_FULL error)
// https://github.com/Koenkk/zigbee2mqtt/issues/23684
if (endpoint.binds.some((b) => b.cluster.name === "genPollCtrl")) {
await endpoint.unbind("genPollCtrl", coordinatorEndpoint);
}
await reporting.bind(endpoint, coordinatorEndpoint, ["ssIasZone", "ssIasWd", "genBinaryInput"]);
await endpoint.read("ssIasZone", ["iasCieAddr", "zoneState", "zoneId"]);
await endpoint.read("genBinaryInput", ["reliability", "statusFlags"]);
await endpoint.read("ssIasWd", ["maxDuration"]);
},
endpoint: (device) => {
return { default: 35 };
},
exposes: [
e.smoke(),
e.battery_low(),
e.test(),
e.numeric("max_duration", ea.ALL).withUnit("s").withValueMin(0).withValueMax(600).withDescription("Duration of Siren"),
e.binary("alarm", ea.SET, "START", "OFF").withDescription("Manual Start of Siren"),
e
.enum("reliability", ea.STATE, ["no_fault_detected", "unreliable_other", "process_error"])
.withDescription("Indicates reason if any fault"),
e.binary("fault", ea.STATE, true, false).withDescription("Indicates whether the device are in fault state"),
],
},
{
zigbeeModel: ["WISZB-120"],
model: "WISZB-120",
vendor: "Develco",
description: "Window sensor",
fromZigbee: [fz.ias_contact_alarm_1],
toZigbee: [],
exposes: [e.contact(), e.battery_low(), e.tamper()],
ota: true,
endpoint: (device) => {
return { default: 35 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(), // TODO: ep 38
m.battery({
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: true,
}),
],
},
{
zigbeeModel: ["WISZB-121"],
model: "WISZB-121",
vendor: "Develco",
description: "Window sensor",
fromZigbee: [fz.ias_contact_alarm_1],
toZigbee: [],
exposes: [e.contact(), e.battery_low(), e.tamper()],
ota: true,
endpoint: (device) => {
return { default: 35 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
},
{
zigbeeModel: ["WISZB-134"],
model: "WISZB-134",
vendor: "Develco",
description: "Window/door sensor",
ota: true,
endpoint: () => ({ default: 35 }),
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
m.iasZoneAlarm({ zoneType: "contact", zoneAttributes: ["alarm_1", "battery_low", "tamper"] }),
m.battery({
voltageToPercentage: "3V_2100",
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
},
{
zigbeeModel: ["WISZB-137"],
model: "WISZB-137",
vendor: "Develco",
description: "Vibration sensor",
fromZigbee: [fz.ias_vibration_alarm_1],
toZigbee: [],
exposes: [e.battery_low(), e.vibration(), e.tamper()],
endpoint: (device) => {
return { default: 38 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(),
m.battery({
voltageToPercentage: "3V_2100",
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
},
{
zigbeeModel: ["WISZB-138", "GWA1513_WindowSensor"],
model: "WISZB-138",
vendor: "Develco",
description: "Window sensor",
fromZigbee: [fz.ias_contact_alarm_1],
toZigbee: [],
exposes: [e.contact(), e.battery_low()],
endpoint: (device) => {
return { default: 35 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(),
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
},
{
zigbeeModel: ["MOSZB-130"],
model: "MOSZB-130",
vendor: "Develco",
description: "Motion sensor",
fromZigbee: [fz.ias_occupancy_alarm_1],
toZigbee: [],
exposes: [e.occupancy(), e.battery_low(), e.tamper()],
},
{
zigbeeModel: ["MOSZB-140", "GWA1511_MotionSensor"],
model: "MOSZB-140",
vendor: "Develco",
description: "Motion sensor",
fromZigbee: [fz.ias_occupancy_alarm_1, develco.fz.led_control, develco.fz.ias_occupancy_timeout],
toZigbee: [develco.tz.led_control, develco.tz.ias_occupancy_timeout],
exposes: (device, options) => {
const dynExposes = [];
dynExposes.push(e.occupancy());
if (utils.isDummyDevice(device) || Number(device.softwareBuildID?.split(".")[0]) >= 3) {
dynExposes.push(e.numeric("occupancy_timeout", ea.ALL).withUnit("s").withValueMin(5).withValueMax(65535));
}
dynExposes.push(e.tamper());
dynExposes.push(e.battery_low());
if (utils.isDummyDevice(device) || Number(device?.softwareBuildID?.split(".")[0]) >= 4) {
dynExposes.push(e.enum("led_control", ea.ALL, ["off", "fault_only", "motion_only", "both"]).withDescription("Control LED indicator usage."));
}
return dynExposes;
},
ota: true,
endpoint: (device) => {
return { default: 35 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoIasZone(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
// Prevent excessive reports
// https://github.com/Koenkk/zigbee-herdsman-converters/pull/10081
develco_1.develcoModernExtend.temperature({ reporting: { min: 60, max: 3600, change: 100 } }),
m.illuminance({ reporting: { min: 300, max: 3600, change: 100 } }),
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
configure: async (device, coordinatorEndpoint) => {
// zigbee2mqtt#14277 some features are not available on older firmwares
// modernExtend's readGenBasicPrimaryVersions is called before this one, should be fine
const endpoint35 = device.getEndpoint(35);
if (Number(device?.softwareBuildID?.split(".")[0]) >= 3) {
await endpoint35.read("ssIasZone", ["develcoAlarmOffDelay"], manufacturerOptions);
}
if (Number(device?.softwareBuildID?.split(".")[0]) >= 4) {
await endpoint35.read("genBasic", ["develcoLedControl"], manufacturerOptions);
}
},
},
{
zigbeeModel: ["MOSZB-141"],
model: "MOSZB-141",
vendor: "Develco",
description: "Motion sensor",
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
m.iasZoneAlarm({ zoneType: "occupancy", zoneAttributes: ["alarm_1", "battery_low"] }),
],
},
{
whiteLabel: [{ vendor: "Frient", model: "MOSZB-153", description: "Motion Sensor 2 Pet" }],
zigbeeModel: ["MOSZB-153"],
model: "MOSZB-153",
vendor: "Develco",
description: "Motion sensor 2 pet",
fromZigbee: [develco.fz.led_control, develco.fz.ias_occupancy_timeout],
toZigbee: [develco.tz.led_control, develco.tz.ias_occupancy_timeout],
exposes: (device, options) => {
const dynExposes = [];
if (utils.isDummyDevice(device) || Number(device?.softwareBuildID?.split(".")[0]) >= 2) {
dynExposes.push(e.numeric("occupancy_timeout", ea.ALL).withUnit("s").withValueMin(5).withValueMax(65535));
dynExposes.push(e.enum("led_control", ea.ALL, ["off", "fault_only", "motion_only", "both"]).withDescription("Control LED indicator usage."));
}
return dynExposes;
},
ota: true,
endpoint: (device) => {
return { default: 35 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoIasZone(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(),
m.illuminance({ reporting: { min: 60, max: 3600, change: 500 } }),
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
m.iasZoneAlarm({ zoneType: "occupancy", zoneAttributes: ["alarm_1"] }),
],
configure: async (device, coordinatorEndpoint) => {
if (device?.softwareBuildID && Number(device.softwareBuildID.split(".")[0]) >= 2) {
const endpoint35 = device.getEndpoint(35);
await endpoint35.read("ssIasZone", ["develcoAlarmOffDelay"], manufacturerOptions);
await endpoint35.read("genBasic", ["develcoLedControl"], manufacturerOptions);
}
},
},
{
whiteLabel: [{ vendor: "Frient", model: "HMSZB-120", description: "Temperature & humidity sensor", fingerprint: [{ modelID: "HMSZB-120" }] }],
zigbeeModel: ["HMSZB-110", "HMSZB-120"],
model: "HMSZB-110",
vendor: "Develco",
description: "Temperature & humidity sensor",
ota: true,
endpoint: (device) => {
return { default: 38 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(),
m.humidity(),
m.battery({
voltageToPercentage: { min: 2500, max: 3200 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
develco_1.develcoModernExtend.batteryLowAA(),
],
},
{
zigbeeModel: ["ZHEMI101"],
model: "ZHEMI101",
vendor: "Develco",
description: "Energy meter",
fromZigbee: [develco.fz.metering, develco.fz.pulse_configuration, develco.fz.interface_mode],
toZigbee: [develco.tz.pulse_configuration, develco.tz.interface_mode, develco.tz.current_summation],
endpoint: (device) => {
return { default: 2 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.addCustomDevelcoSeMeteringCluster(),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(2);
await reporting.bind(endpoint, coordinatorEndpoint, ["seMetering"]);
await reporting.instantaneousDemand(endpoint);
await reporting.readMeteringMultiplierDivisor(endpoint);
},
exposes: [
e.power(),
e.energy(),
e.battery_low(),
e
.numeric("pulse_configuration", ea.ALL)
.withValueMin(0)
.withValueMax(65535)
.withDescription("Pulses per kwh. Default 1000 imp/kWh. Range 0 to 65535"),
e
.enum("interface_mode", ea.ALL, ["electricity", "gas", "water", "kamstrup-kmp", "linky", "IEC62056-21", "DSMR-2.3", "DSMR-4.0"])
.withDescription("Operating mode/probe"),
e
.numeric("current_summation", ea.SET)
.withDescription("Current summation value sent to the display. e.g. 570 = 0,570 kWh")
.withValueMin(0)
.withValueMax(268435455),
e.binary("check_meter", ea.STATE, true, false).withDescription("Is true if communication problem with meter is experienced"),
],
},
{
zigbeeModel: ["SMRZB-332"],
model: "SMRZB-332",
vendor: "Develco",
description: "Smart relay DIN",
fromZigbee: [fz.on_off, develco.fz.metering],
toZigbee: [tz.on_off],
exposes: [e.power(), e.energy(), e.switch()],
endpoint: (device) => {
return { default: 2 };
},
extend: [develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(), develco_1.develcoModernExtend.readGenBasicPrimaryVersions()],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(2);
await reporting.bind(endpoint, coordinatorEndpoint, ["seMetering"]);
await reporting.instantaneousDemand(endpoint);
await reporting.readMeteringMultiplierDivisor(endpoint);
},
},
{
zigbeeModel: ["FLSZB-110"],
model: "FLSZB-110",
vendor: "Develco",
description: "Flood alarm device ",
fromZigbee: [fz.ias_water_leak_alarm_1],
toZigbee: [],
ota: true,
exposes: [e.battery_low(), e.tamper(), e.water_leak()],
endpoint: (device) => {
return { default: 35 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(), // TODO: ep 38
m.battery({
voltageToPercentage: { min: 2800, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
},
{
zigbeeModel: ["AQSZB-110"],
model: "AQSZB-110",
vendor: "Develco",
description: "Air quality sensor",
ota: true,
endpoint: (device) => {
return { default: 38 };
},
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoAirQuality(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.voc(),
develco_1.develcoModernExtend.airQuality(),
develco_1.develcoModernExtend.temperature(),
m.humidity(),
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
develco_1.develcoModernExtend.batteryLowAA(),
],
},
{
zigbeeModel: ["SIRZB-110"],
model: "SIRZB-110",
vendor: "Develco",
description: "Customizable siren",
fromZigbee: [fz.ias_enroll, fz.ias_wd, fz.ias_siren],
toZigbee: [tz.warning, tz.warning_simple, tz.ias_max_duration, tz.squawk],
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
develco_1.develcoModernExtend.temperature(),
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(43);
await reporting.bind(endpoint, coordinatorEndpoint, ["ssIasZone", "ssIasWd", "genBasic"]);
await endpoint.read("ssIasZone", ["iasCieAddr", "zoneState", "zoneId"]);
await endpoint.read("ssIasWd", ["maxDuration"]);
const endpoint2 = device.getEndpoint(1);
await reporting.bind(endpoint2, coordinatorEndpoint, ["genOnOff"]);
},
endpoint: (device) => {
return { default: 43 };
},
exposes: [
e.battery_low(),
e.test(),
e.warning(),
e.squawk(),
e.numeric("max_duration", ea.ALL).withUnit("s").withValueMin(0).withValueMax(900).withDescription("Max duration of the siren"),
e.binary("alarm", ea.SET, "START", "OFF").withDescription("Manual start of the siren"),
],
},
{
zigbeeModel: ["SIRZB-111"],
model: "SIRZB-111",
vendor: "Develco",
description: "Customizable siren",
fromZigbee: [fz.ias_enroll, fz.ias_wd, fz.ias_siren],
toZigbee: [tz.warning, tz.warning_simple, tz.ias_max_duration, tz.squawk],
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
m.battery({
voltageToPercentage: { min: 2500, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(43);
await reporting.bind(endpoint, coordinatorEndpoint, ["ssIasZone", "ssIasWd", "genBasic"]);
await endpoint.read("ssIasZone", ["iasCieAddr", "zoneState", "zoneId"]);
await endpoint.read("ssIasWd", ["maxDuration"]);
const endpoint2 = device.getEndpoint(1);
await reporting.bind(endpoint2, coordinatorEndpoint, ["genOnOff"]);
},
endpoint: (device) => {
return { default: 43 };
},
exposes: [
e.battery_low(),
e.test(),
e.warning(),
e.squawk(),
e.numeric("max_duration", ea.ALL).withUnit("s").withValueMin(0).withValueMax(900).withDescription("Max duration of the siren"),
e.binary("alarm", ea.SET, "START", "OFF").withDescription("Manual start of the siren"),
],
},
{
zigbeeModel: ["KEPZB-110"],
model: "KEYZB-110",
vendor: "Develco",
description: "Keypad",
whiteLabel: [{ vendor: "Frient", model: "KEPZB-110" }],
fromZigbee: [
fz.command_arm_with_transaction,
fz.command_emergency,
fz.ias_no_alarm,
fz.ignore_iaszone_attreport,
fz.ignore_iasace_commandgetpanelstatus,
],
toZigbee: [develco.tz.arm_mode],
exposes: [
e.battery_low(),
e.tamper(),
e.text("action_code", ea.STATE).withDescription("Pin code introduced."),
e.numeric("action_transaction", ea.STATE).withDescription("Last action transaction number."),
e.text("action_zone", ea.STATE).withDescription("Alarm zone. Default value 23"),
e.action(["disarm", "arm_day_zones", "arm_night_zones", "arm_all_zones", "exit_delay", "emergency"]),
],
ota: true,
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
m.battery({
voltageToPercentage: { min: 3000, max: 4200 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}),
m.iasGetPanelStatusResponse({ audiblenotif: 1 }),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(44);
const clusters = ["ssIasZone", "ssIasAce", "genIdentify"];
await reporting.bind(endpoint, coordinatorEndpoint, clusters);
},
endpoint: (device) => {
return { default: 44 };
},
},
{
zigbeeModel: ["IOMZB-110"],
model: "IOMZB-110",
vendor: "Develco",
description: "IO module",
meta: { multiEndpoint: true },
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
m.deviceEndpoints({
endpoints: { l1: 112, l2: 113, l3: 114, l4: 115, l11: 116, l12: 117 },
}),
...["l1", "l2", "l3", "l4"].map((ep, i) => m.binary({
name: "input",
cluster: "genBinaryInput",
attribute: "presentValue",
description: `State of input ${i + 1}`,
access: "STATE_GET",
endpointName: ep,
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
reporting: {
min: 0,
max: "1_HOUR",
change: null,
},
})),
m.onOff({
powerOnBehavior: false,
endpointNames: ["l11", "l12"],
}),
develco_1.develcoModernExtend.customPulseTrigger({
endpointNames: ["l11", "l12"],
}),
],
},
{
zigbeeModel: ["SBTZB-110"],
model: "SBTZB-110",
vendor: "Develco",
description: "Smart button",
fromZigbee: [fz.ewelink_action],
toZigbee: [],
ota: true,
exposes: [e.action(["single"])],
extend: [
develco_1.develcoModernExtend.addCustomClusterManuSpecificDevelcoGenBasic(),
develco_1.develcoModernExtend.readGenBasicPrimaryVersions(),
m.battery({
voltageToPercentage: { min: 2200, max: 3000 },
percentage: true,
voltage: true,
lowStatus: false,
voltageReporting: true,
percentageReporting: false,
}