zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
538 lines • 25 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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const exposes = __importStar(require("../lib/exposes"));
const fromZigbee_1 = __importDefault(require("../converters/fromZigbee"));
const toZigbee_1 = __importDefault(require("../converters/toZigbee"));
const reporting = __importStar(require("../lib/reporting"));
const constants = __importStar(require("../lib/constants"));
const e = exposes.presets;
const ea = exposes.access;
const utils_1 = require("../lib/utils");
const modernExtend = __importStar(require("../lib/modernExtend"));
const { forcePowerSource, temperature, humidity, co2, deviceEndpoints, onOff, illuminance, occupancy, ota, } = modernExtend;
const sprutCode = 0x6666;
const manufacturerOptions = { manufacturerCode: sprutCode };
const switchActionValues = ['OFF', 'ON'];
const co2Lookup = {
co2_autocalibration: 'sprutCO2AutoCalibration',
co2_manual_calibration: 'sprutCO2Calibration',
};
const fzLocal = {
temperature: {
cluster: 'msTemperatureMeasurement',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
const temperature = parseFloat(msg.data['measuredValue']) / 100.0;
return { temperature };
},
},
occupancy_level: {
cluster: 'msOccupancySensing',
type: ['readResponse', 'attributeReport'],
convert: (model, msg, publish, options, meta) => {
if (msg.data.hasOwnProperty('sprutOccupancyLevel')) {
return { occupancy_level: msg.data['sprutOccupancyLevel'] };
}
},
},
voc: {
cluster: 'sprutVoc',
type: ['readResponse', 'attributeReport'],
convert: (model, msg, publish, options, meta) => {
if (msg.data.hasOwnProperty('voc')) {
return { voc: msg.data['voc'] };
}
},
},
noise: {
cluster: 'sprutNoise',
type: ['readResponse', 'attributeReport'],
convert: (model, msg, publish, options, meta) => {
if (msg.data.hasOwnProperty('noise')) {
return { noise: msg.data['noise'].toFixed(2) };
}
},
},
noise_detected: {
cluster: 'sprutNoise',
type: ['readResponse', 'attributeReport'],
convert: (model, msg, publish, options, meta) => {
if (msg.data.hasOwnProperty('noiseDetected')) {
return { noise_detected: msg.data['noiseDetected'] === 1 };
}
},
},
occupancy_timeout: {
cluster: 'msOccupancySensing',
type: ['readResponse', 'attributeReport'],
convert: (model, msg, publish, options, meta) => {
return { occupancy_timeout: msg.data['pirOToUDelay'] };
},
},
noise_timeout: {
cluster: 'sprutNoise',
type: ['readResponse', 'attributeReport'],
convert: (model, msg, publish, options, meta) => {
return { noise_timeout: msg.data['noiseAfterDetectDelay'] };
},
},
occupancy_sensitivity: {
cluster: 'msOccupancySensing',
type: ['readResponse', 'attributeReport'],
convert: (model, msg, publish, options, meta) => {
return { occupancy_sensitivity: msg.data['sprutOccupancySensitivity'] };
},
},
noise_detect_level: {
cluster: 'sprutNoise',
type: ['readResponse', 'attributeReport'],
convert: (model, msg, publish, options, meta) => {
return { noise_detect_level: msg.data['noiseDetectLevel'] };
},
},
co2_mh_z19b_config: {
cluster: 'msCO2',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
if (msg.data.hasOwnProperty('sprutCO2AutoCalibration')) {
return { co2_autocalibration: switchActionValues[msg.data['sprutCO2AutoCalibration']] };
}
if (msg.data.hasOwnProperty('sprutCO2Calibration')) {
return { co2_manual_calibration: switchActionValues[msg.data['sprutCO2Calibration']] };
}
},
},
th_heater: {
cluster: 'msRelativeHumidity',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
if (msg.data.hasOwnProperty('sprutHeater')) {
return { th_heater: switchActionValues[msg.data['sprutHeater']] };
}
},
},
};
const tzLocal = {
sprut_ir_remote: {
key: ['play_store', 'learn_start', 'learn_stop', 'clear_store', 'play_ram', 'learn_ram_start', 'learn_ram_stop'],
convertSet: async (entity, key, value, meta) => {
const options = {
frameType: 0, manufacturerCode: sprutCode, disableDefaultResponse: true,
disableResponse: true, reservedBits: 0, direction: 0, writeUndiv: false,
// @ts-expect-error
transactionSequenceNumber: null,
};
switch (key) {
case 'play_store':
await entity.command('sprutIrBlaster', 'playStore', { param: value['rom'] }, options);
break;
case 'learn_start':
await entity.command('sprutIrBlaster', 'learnStart', { value: value['rom'] }, options);
break;
case 'learn_stop':
await entity.command('sprutIrBlaster', 'learnStop', { value: value['rom'] }, options);
break;
case 'clear_store':
await entity.command('sprutIrBlaster', 'clearStore', {}, options);
break;
case 'play_ram':
await entity.command('sprutIrBlaster', 'playRam', {}, options);
break;
case 'learn_ram_start':
await entity.command('sprutIrBlaster', 'learnRamStart', {}, options);
break;
case 'learn_ram_stop':
await entity.command('sprutIrBlaster', 'learnRamStop', {}, options);
break;
}
},
},
occupancy_timeout: {
key: ['occupancy_timeout'],
convertSet: async (entity, key, value, meta) => {
const number = (0, utils_1.toNumber)(value, 'occupancy_timeout');
await entity.write('msOccupancySensing', { pirOToUDelay: number }, (0, utils_1.getOptions)(meta.mapped, entity));
return { state: { [key]: number } };
},
convertGet: async (entity, key, meta) => {
await entity.read('msOccupancySensing', ['pirOToUDelay']);
},
},
noise_timeout: {
key: ['noise_timeout'],
convertSet: async (entity, key, value, meta) => {
let number = (0, utils_1.toNumber)(value, 'noise_timeout');
number *= 1;
await entity.write('sprutNoise', { noiseAfterDetectDelay: number }, (0, utils_1.getOptions)(meta.mapped, entity));
return { state: { [key]: number } };
},
convertGet: async (entity, key, meta) => {
await entity.read('sprutNoise', ['noiseAfterDetectDelay']);
},
},
occupancy_sensitivity: {
key: ['occupancy_sensitivity'],
convertSet: async (entity, key, value, meta) => {
let number = (0, utils_1.toNumber)(value, 'occupancy_sensitivity');
number *= 1;
const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
await entity.write('msOccupancySensing', { 'sprutOccupancySensitivity': number }, options);
return { state: { [key]: number } };
},
convertGet: async (entity, key, meta) => {
await entity.read('msOccupancySensing', ['sprutOccupancySensitivity'], manufacturerOptions);
},
},
noise_detect_level: {
key: ['noise_detect_level'],
convertSet: async (entity, key, value, meta) => {
let number = (0, utils_1.toNumber)(value, 'noise_detect_level');
number *= 1;
const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
await entity.write('sprutNoise', { 'noiseDetectLevel': number }, options);
return { state: { [key]: number } };
},
convertGet: async (entity, key, meta) => {
await entity.read('sprutNoise', ['noiseDetectLevel'], manufacturerOptions);
},
},
temperature_offset: {
key: ['temperature_offset'],
convertSet: async (entity, key, value, meta) => {
let number = (0, utils_1.toNumber)(value, 'temperature_offset');
number *= 1;
const newValue = number * 100.0;
const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
await entity.write('msTemperatureMeasurement', { 'sprutTemperatureOffset': newValue }, options);
return { state: { [key]: number } };
},
},
co2_mh_z19b_config: {
key: ['co2_autocalibration', 'co2_manual_calibration'],
convertSet: async (entity, key, value, meta) => {
let newValue = value;
(0, utils_1.assertString)(value, 'co2_autocalibration/co2_manual_calibration');
newValue = switchActionValues.indexOf(value);
const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
await entity.write('msCO2', { [(0, utils_1.getFromLookup)(key, co2Lookup)]: newValue }, options);
return { state: { [key]: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read('msCO2', [(0, utils_1.getFromLookup)(key, co2Lookup)], manufacturerOptions);
},
},
th_heater: {
key: ['th_heater'],
convertSet: async (entity, key, value, meta) => {
let newValue = value;
(0, utils_1.assertString)(value, 'th_heater');
newValue = switchActionValues.indexOf(value);
const options = (0, utils_1.getOptions)(meta.mapped, entity, manufacturerOptions);
await entity.write('msRelativeHumidity', { 'sprutHeater': newValue }, options);
return { state: { [key]: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read('msRelativeHumidity', ['sprutHeater'], manufacturerOptions);
},
},
};
const sprutModernExtend = {
sprutActivityIndicator: (args) => modernExtend.binary({
name: 'activity_led',
cluster: 'genBinaryOutput',
attribute: 'presentValue',
description: 'Controls green activity LED',
reporting: { attribute: 'presentValue', min: 'MIN', max: 'MAX', change: 1 },
valueOn: [true, 1],
valueOff: [false, 0],
access: 'ALL',
entityCategory: 'config',
...args,
}),
sprutTemperatureOffset: (args) => modernExtend.numeric({
name: 'temperature_offset',
cluster: 'msTemperatureMeasurement',
attribute: 'sprutTemperatureOffset',
description: 'Self-heating compensation. The compensation value is subtracted from the measured temperature (default: 0)',
valueMin: -10,
valueMax: 10,
unit: '°C',
scale: 100,
access: 'ALL',
entityCategory: 'config',
zigbeeCommandOptions: manufacturerOptions,
...args,
}),
sprutThHeater: (args) => modernExtend.binary({
name: 'th_heater',
cluster: 'msRelativeHumidity',
attribute: 'sprutHeater',
description: 'Turn on when working in conditions of high humidity (more than 70 %, RH) or condensation, ' +
'if the sensor shows 0 or 100 %.',
valueOn: [true, 1],
valueOff: [false, 0],
access: 'ALL',
entityCategory: 'config',
zigbeeCommandOptions: manufacturerOptions,
...args,
}),
sprutOccupancyLevel: (args) => modernExtend.numeric({
name: 'occupancy_level',
cluster: 'msOccupancySensing',
attribute: 'sprutOccupancyLevel',
reporting: { min: '10_SECONDS', max: '1_MINUTE', change: 5 },
description: 'Measured occupancy level',
access: 'STATE_GET',
entityCategory: 'diagnostic',
...args,
}),
sprutOccupancyTimeout: (args) => modernExtend.numeric({
name: 'occupancy_timeout',
cluster: 'msOccupancySensing',
attribute: 'pirOToUDelay',
description: 'Time in seconds after which occupancy is cleared after detecting it (default: 60)',
valueMin: 0,
valueMax: 2000,
unit: 's',
access: 'ALL',
entityCategory: 'config',
...args,
}),
sprutOccupancySensitivity: (args) => modernExtend.numeric({
name: 'occupancy_sensitivity',
cluster: 'msOccupancySensing',
attribute: 'sprutOccupancySensitivity',
description: 'If the sensor is triggered by the slightest movement, reduce the sensitivity, ' +
'otherwise increase it (default: 50)',
valueMin: 0,
valueMax: 2000,
access: 'ALL',
entityCategory: 'config',
zigbeeCommandOptions: manufacturerOptions,
...args,
}),
sprutNoise: (args) => modernExtend.numeric({
name: 'noise',
cluster: 'sprutNoise',
attribute: 'noise',
reporting: { min: '10_SECONDS', max: '1_MINUTE', change: 5 },
description: 'Measured noise level',
unit: 'dBA',
precision: 2,
access: 'STATE_GET',
entityCategory: 'diagnostic',
...args,
}),
sprutNoiseDetectLevel: (args) => modernExtend.numeric({
name: 'noise_detect_level',
cluster: 'sprutNoise',
attribute: 'noiseDetectLevel',
description: 'The minimum noise level at which the detector will work (default: 50)',
valueMin: 0,
valueMax: 150,
unit: 'dBA',
access: 'ALL',
entityCategory: 'config',
zigbeeCommandOptions: manufacturerOptions,
...args,
}),
sprutNoiseDetected: (args) => modernExtend.binary({
name: 'noise_detected',
cluster: 'sprutNoise',
attribute: 'noiseDetected',
valueOn: [true, 1],
valueOff: [false, 0],
description: 'Indicates whether the device detected noise',
access: 'STATE_GET',
...args,
}),
sprutNoiseTimeout: (args) => modernExtend.numeric({
name: 'noise_timeout',
cluster: 'sprutNoise',
attribute: 'noiseAfterDetectDelay',
description: 'Time in seconds after which noise is cleared after detecting it (default: 60)',
valueMin: 0,
valueMax: 2000,
unit: 's',
access: 'ALL',
entityCategory: 'config',
...args,
}),
sprutVoc: (args) => modernExtend.numeric({
name: 'voc',
label: 'VOC',
cluster: 'sprutVoc',
attribute: 'voc',
reporting: { min: '10_SECONDS', max: '1_MINUTE', change: 10 },
description: 'Measured VOC level',
unit: 'µg/m³',
access: 'STATE_GET',
...args,
}),
sprutIrBlaster: () => {
const toZigbee = [{
key: ['play_store', 'learn_start', 'learn_stop', 'clear_store', 'play_ram', 'learn_ram_start', 'learn_ram_stop'],
convertSet: async (entity, key, value, meta) => {
const options = {
frameType: 0, manufacturerCode: sprutCode, disableDefaultResponse: true,
disableResponse: true, reservedBits: 0, direction: 0, writeUndiv: false,
// @ts-expect-error
transactionSequenceNumber: null,
};
switch (key) {
case 'play_store':
await entity.command('sprutIrBlaster', 'playStore', { param: value['rom'] }, options);
break;
case 'learn_start':
await entity.command('sprutIrBlaster', 'learnStart', { value: value['rom'] }, options);
break;
case 'learn_stop':
await entity.command('sprutIrBlaster', 'learnStop', { value: value['rom'] }, options);
break;
case 'clear_store':
await entity.command('sprutIrBlaster', 'clearStore', {}, options);
break;
case 'play_ram':
await entity.command('sprutIrBlaster', 'playRam', {}, options);
break;
case 'learn_ram_start':
await entity.command('sprutIrBlaster', 'learnRamStart', {}, options);
break;
case 'learn_ram_stop':
await entity.command('sprutIrBlaster', 'learnRamStop', {}, options);
break;
}
},
}];
const configure = async (device, coordinatorEndpoint, definition) => {
const endpoint1 = device.getEndpoint(1);
await reporting.bind(endpoint1, coordinatorEndpoint, ['sprutIrBlaster']);
device.save();
};
return { toZigbee, configure, isModernExtend: true };
},
};
const { sprutActivityIndicator, sprutOccupancyLevel, sprutNoise, sprutVoc, sprutNoiseDetected, sprutOccupancyTimeout, sprutNoiseTimeout, sprutTemperatureOffset, sprutThHeater, sprutOccupancySensitivity, sprutNoiseDetectLevel, sprutIrBlaster, } = sprutModernExtend;
const definitions = [
{
zigbeeModel: ['WBMSW3'],
model: 'WB-MSW-ZIGBEE v.3',
vendor: 'Wirenboard',
description: 'Wall-mounted multi sensor',
fromZigbee: [fzLocal.temperature, fromZigbee_1.default.illuminance, fromZigbee_1.default.humidity, fromZigbee_1.default.occupancy, fzLocal.occupancy_level, fromZigbee_1.default.co2, fzLocal.voc,
fzLocal.noise, fzLocal.noise_detected, fromZigbee_1.default.on_off, fzLocal.occupancy_timeout, fzLocal.noise_timeout, fzLocal.co2_mh_z19b_config,
fzLocal.th_heater, fzLocal.occupancy_sensitivity, fzLocal.noise_detect_level],
toZigbee: [toZigbee_1.default.on_off, tzLocal.sprut_ir_remote, tzLocal.occupancy_timeout, tzLocal.noise_timeout, tzLocal.co2_mh_z19b_config,
tzLocal.th_heater, tzLocal.temperature_offset, tzLocal.occupancy_sensitivity, tzLocal.noise_detect_level],
exposes: [e.temperature(), e.illuminance(), e.illuminance_lux(), e.humidity(), e.occupancy(), e.occupancy_level(), e.co2(),
e.voc(), e.noise(), e.noise_detected(), e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
e.switch().withEndpoint('l3'),
e.numeric('noise_timeout', ea.ALL).withValueMin(0).withValueMax(2000).withUnit('s').withCategory('config')
.withDescription('Time in seconds after which noise is cleared after detecting it (default: 60)'),
e.numeric('occupancy_timeout', ea.ALL).withValueMin(0).withValueMax(2000).withUnit('s').withCategory('config')
.withDescription('Time in seconds after which occupancy is cleared after detecting it (default: 60)'),
e.numeric('temperature_offset', ea.SET).withValueMin(-10).withValueMax(10).withUnit('°C').withCategory('config')
.withDescription('Self-heating compensation. The compensation value is subtracted from the measured temperature'),
e.numeric('occupancy_sensitivity', ea.ALL).withValueMin(0).withValueMax(2000).withCategory('config')
.withDescription('If the sensor is triggered by the slightest movement, reduce the sensitivity, ' +
'otherwise increase it (default: 50)'),
e.numeric('noise_detect_level', ea.ALL).withValueMin(0).withValueMax(150).withUnit('dBA').withCategory('config')
.withDescription('The minimum noise level at which the detector will work (default: 50)'),
e.enum('co2_autocalibration', ea.ALL, switchActionValues).withCategory('config')
.withDescription('Automatic calibration of the CO2 sensor. If ON, the CO2 sensor will automatically calibrate ' +
'every 7 days. (MH-Z19B sensor)'),
e.enum('co2_manual_calibration', ea.ALL, switchActionValues).withCategory('config')
.withDescription('Ventilate the room for 20 minutes, turn on manual calibration, and turn it off after one second. ' +
'After about 5 minutes the CO2 sensor will show 400ppm. Calibration completed. (MH-Z19B sensor)'),
e.enum('th_heater', ea.ALL, switchActionValues).withCategory('config')
.withDescription('Turn on when working in conditions of high humidity (more than 70 %, RH) or condensation, ' +
'if the sensor shows 0 or 100 %.'),
],
configure: async (device, coordinatorEndpoint) => {
const endpoint1 = device.getEndpoint(1);
const binds = ['genBasic', 'msTemperatureMeasurement', 'msIlluminanceMeasurement', 'msRelativeHumidity',
'msOccupancySensing', 'msCO2', 'sprutVoc', 'sprutNoise', 'sprutIrBlaster', 'genOta'];
await reporting.bind(endpoint1, coordinatorEndpoint, binds);
// report configuration
await reporting.temperature(endpoint1);
await reporting.illuminance(endpoint1);
await reporting.humidity(endpoint1);
await reporting.occupancy(endpoint1);
let payload = reporting.payload('sprutOccupancyLevel', 10, constants.repInterval.MINUTE, 5);
await endpoint1.configureReporting('msOccupancySensing', payload, manufacturerOptions);
payload = reporting.payload('noise', 10, constants.repInterval.MINUTE, 5);
await endpoint1.configureReporting('sprutNoise', payload);
// led_red
await device.getEndpoint(2).read('genOnOff', ['onOff']);
// led_green
await device.getEndpoint(3).read('genOnOff', ['onOff']);
// buzzer
await device.getEndpoint(4).read('genOnOff', ['onOff']);
},
endpoint: (device) => {
return { 'default': 1, 'l1': 2, 'l2': 3, 'l3': 4 };
},
meta: { multiEndpoint: true, multiEndpointSkip: ['humidity'] },
extend: [ota()],
},
{
zigbeeModel: ['WBMSW4'],
model: 'WB-MSW-ZIGBEE v.4',
vendor: 'Wirenboard',
description: 'Wall-mounted multi sensor',
extend: [
forcePowerSource({ powerSource: 'Mains (single phase)' }),
deviceEndpoints({
endpoints: { 'default': 1, 'l1': 2, 'l2': 3, 'l3': 4, 'indicator': 5 },
}),
onOff({ powerOnBehavior: false, endpointNames: ['l1', 'l2', 'l3'] }),
sprutActivityIndicator({ endpointName: 'indicator' }),
temperature(),
sprutTemperatureOffset(),
humidity(),
sprutThHeater(),
co2(),
illuminance(),
occupancy(),
sprutOccupancySensitivity(),
sprutOccupancyLevel(),
sprutOccupancyTimeout(),
sprutNoise(),
sprutNoiseDetectLevel(),
sprutNoiseDetected(),
sprutNoiseTimeout(),
sprutVoc(),
sprutIrBlaster(),
ota(),
],
},
];
exports.default = definitions;
module.exports = definitions;
//# sourceMappingURL=wirenboard.js.map