zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
681 lines • 32.5 kB
JavaScript
;
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 });
exports.legacy = exports.ikeaMediaCommands = exports.ikeaArrowClick = exports.ikeaDotsClick = exports.styrbarCommandOn = exports.tradfriCommandsLevelCtrl = exports.tradfriCommandsOnOff = exports.tradfriRequestedBrightness = exports.tradfriOccupancy = exports.ikeaConfigureGenPollCtrl = exports.ikeaVoc = exports.ikeaAirPurifier = exports.ikeaConfigureRemote = exports.ikeaBattery = exports.ikeaOta = exports.ikeaLight = exports.manufacturerOptions = void 0;
const exposes_1 = require("../lib/exposes");
const utils_1 = require("../lib/utils");
const modernExtend_1 = require("../lib/modernExtend");
const ota_1 = require("../lib/ota");
const toZigbee_1 = __importDefault(require("../converters/toZigbee"));
const constants = __importStar(require("../lib/constants"));
const reporting = __importStar(require("../lib/reporting"));
const globalStore = __importStar(require("../lib/store"));
const zigbeeHerdsman = __importStar(require("zigbee-herdsman/dist"));
const semver = __importStar(require("semver"));
exports.manufacturerOptions = { manufacturerCode: zigbeeHerdsman.Zcl.ManufacturerCode.IKEA_OF_SWEDEN };
const bulbOnEvent = async (type, data, device, options, state) => {
/**
* IKEA bulbs lose their configured reportings when losing power.
* A deviceAnnounce indicates they are powered on again.
* Reconfigure the configured reoprting here.
*
* Additionally some other information is lost like
* color_options.execute_if_off. We also restore these.
*
* NOTE: binds are not lost so rebinding is not needed!
*/
if (type === 'deviceAnnounce') {
for (const endpoint of device.endpoints) {
for (const c of endpoint.configuredReportings) {
await endpoint.configureReporting(c.cluster.name, [{
attribute: c.attribute.name, minimumReportInterval: c.minimumReportInterval,
maximumReportInterval: c.maximumReportInterval, reportableChange: c.reportableChange,
}]);
}
}
// NOTE: execute_if_off default is false
// we only restore if true, to save unneeded network writes
const colorOptions = state.color_options;
if (colorOptions?.execute_if_off === true) {
device.endpoints[0].write('lightingColorCtrl', { 'options': 1 });
}
const levelConfig = state.level_config;
if (levelConfig?.execute_if_off === true) {
device.endpoints[0].write('genLevelCtrl', { 'options': 1 });
}
if (levelConfig?.on_level !== undefined) {
const onLevelRaw = levelConfig.on_level;
let onLevel;
if (typeof onLevelRaw === 'string' && onLevelRaw.toLowerCase() == 'previous') {
onLevel = 255;
}
else {
onLevel = Number(onLevelRaw);
}
if (onLevel > 255)
onLevel = 254;
if (onLevel < 1)
onLevel = 1;
device.endpoints[0].write('genLevelCtrl', { onLevel: onLevel });
}
}
};
function ikeaLight(args) {
const colorTemp = args?.colorTemp ? (args.colorTemp === true ? { range: [250, 454] } : args.colorTemp) : undefined;
const result = (0, modernExtend_1.light)({ ...args, colorTemp });
result.ota = ota_1.tradfri;
result.onEvent = bulbOnEvent;
if ((0, utils_1.isObject)(args?.colorTemp) && args.colorTemp.viaColor) {
result.toZigbee = (0, utils_1.replaceInArray)(result.toZigbee, [toZigbee_1.default.light_color_colortemp], [toZigbee_1.default.light_color_and_colortemp_via_color]);
}
if (args?.colorTemp || args?.color) {
result.exposes.push(exposes_1.presets.light_color_options());
}
return result;
}
exports.ikeaLight = ikeaLight;
function ikeaOta() {
return (0, modernExtend_1.ota)(ota_1.tradfri);
}
exports.ikeaOta = ikeaOta;
function ikeaBattery() {
const exposes = [
exposes_1.presets.numeric('battery', exposes_1.access.STATE_GET).withUnit('%')
.withDescription('Remaining battery in %')
.withValueMin(0).withValueMax(100).withCategory('diagnostic'),
];
const fromZigbee = [{
cluster: 'genPowerCfg',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
const payload = {};
if (msg.data.hasOwnProperty('batteryPercentageRemaining') && (msg.data['batteryPercentageRemaining'] < 255)) {
// Some devices do not comply to the ZCL and report a
// batteryPercentageRemaining of 100 when the battery is full (should be 200).
//
// IKEA corrected this on newer remote fw version, but many people are still
// 2.2.010 which is the last version supporting group bindings. We try to be
// smart and pick the correct one for IKEA remotes.
let dividePercentage = true;
// If softwareBuildID is below 2.4.0 it should not be divided
if (semver.lt(meta.device.softwareBuildID, '2.4.0', true)) {
dividePercentage = false;
}
let percentage = msg.data['batteryPercentageRemaining'];
percentage = dividePercentage ? percentage / 2 : percentage;
payload.battery = (0, utils_1.precisionRound)(percentage, 2);
}
return payload;
},
}];
const toZigbee = [{
key: ['battery'],
convertGet: async (entity, key, meta) => {
await entity.read('genPowerCfg', ['batteryPercentageRemaining']);
},
}];
const defaultReporting = { min: '1_HOUR', max: 'MAX', change: 10 };
const configure = async (device, coordinatorEndpoint, definition) => {
await (0, modernExtend_1.setupAttributes)(device, coordinatorEndpoint, 'genPowerCfg', [
{ attribute: 'batteryPercentageRemaining', ...defaultReporting },
]);
};
return { exposes, fromZigbee, toZigbee, configure, isModernExtend: true };
}
exports.ikeaBattery = ikeaBattery;
function ikeaConfigureRemote() {
const configure = async (device, coordinatorEndpoint, definition) => {
// Firmware 2.3.075 >= only supports binding to endpoint, before only to group
// - https://github.com/Koenkk/zigbee2mqtt/issues/2772#issuecomment-577389281
// - https://github.com/Koenkk/zigbee2mqtt/issues/7716
const endpoint = device.getEndpoint(1);
const version = device.softwareBuildID.split('.').map((n) => Number(n));
const bindTarget = version[0] > 2 || (version[0] == 2 && version[1] > 3) || (version[0] == 2 && version[1] == 3 && version[2] >= 75) ?
coordinatorEndpoint : constants.defaultBindGroup;
await endpoint.bind('genOnOff', bindTarget);
};
return { configure, isModernExtend: true };
}
exports.ikeaConfigureRemote = ikeaConfigureRemote;
function ikeaAirPurifier() {
const exposes = [
exposes_1.presets.fan().withModes(['off', 'auto', '1', '2', '3', '4', '5', '6', '7', '8', '9']),
exposes_1.presets.numeric('fan_speed', exposes_1.access.STATE_GET).withValueMin(0).withValueMax(9)
.withDescription('Current fan speed'),
exposes_1.presets.numeric('pm25', exposes_1.access.STATE_GET).withLabel('PM25').withUnit('µg/m³')
.withDescription('Measured PM2.5 (particulate matter) concentration'),
exposes_1.presets.enum('air_quality', exposes_1.access.STATE_GET, [
'excellent', 'good', 'moderate', 'poor',
'unhealthy', 'hazardous', 'out_of_range',
'unknown',
]).withDescription('Calculated air quality'),
exposes_1.presets.binary('led_enable', exposes_1.access.ALL, true, false).withDescription('Controls the LED').withCategory('config'),
exposes_1.presets.binary('child_lock', exposes_1.access.ALL, true, false).withDescription('Controls physical input on the device').withCategory('config'),
exposes_1.presets.binary('replace_filter', exposes_1.access.STATE_GET, true, false)
.withDescription('Indicates if the filter is older than 6 months and needs replacing')
.withCategory('diagnostic'),
exposes_1.presets.numeric('filter_age', exposes_1.access.STATE_GET).withDescription('Time the filter has been used in minutes').withCategory('diagnostic'),
];
const fromZigbee = [
{
cluster: 'manuSpecificIkeaAirPurifier',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
const state = {};
if (msg.data.hasOwnProperty('particulateMatter25Measurement')) {
const pm25Property = (0, utils_1.postfixWithEndpointName)('pm25', msg, model, meta);
let pm25 = parseFloat(msg.data['particulateMatter25Measurement']);
// Air Quality
// Scale based on EU AQI (https://www.eea.europa.eu/themes/air/air-quality-index)
// Using German IAQ labels to match the Develco Air Quality Sensor
let airQuality;
const airQualityProperty = (0, utils_1.postfixWithEndpointName)('air_quality', msg, model, meta);
if (pm25 <= 10) {
airQuality = 'excellent';
}
else if (pm25 <= 20) {
airQuality = 'good';
}
else if (pm25 <= 25) {
airQuality = 'moderate';
}
else if (pm25 <= 50) {
airQuality = 'poor';
}
else if (pm25 <= 75) {
airQuality = 'unhealthy';
}
else if (pm25 <= 800) {
airQuality = 'hazardous';
}
else if (pm25 < 65535) {
airQuality = 'out_of_range';
}
else {
airQuality = 'unknown';
}
pm25 = (pm25 == 65535) ? -1 : pm25;
state[pm25Property] = pm25;
state[airQualityProperty] = airQuality;
}
if (msg.data.hasOwnProperty('filterRunTime')) {
// Filter needs to be replaced after 6 months
state['replace_filter'] = (parseInt(msg.data['filterRunTime']) >= 259200);
state['filter_age'] = parseInt(msg.data['filterRunTime']);
}
if (msg.data.hasOwnProperty('controlPanelLight')) {
state['led_enable'] = (msg.data['controlPanelLight'] == 0);
}
if (msg.data.hasOwnProperty('childLock')) {
state['child_lock'] = (msg.data['childLock'] == 0);
}
if (msg.data.hasOwnProperty('fanSpeed')) {
let fanSpeed = msg.data['fanSpeed'];
if (fanSpeed >= 10) {
fanSpeed = (((fanSpeed - 5) * 2) / 10);
}
else {
fanSpeed = 0;
}
state['fan_speed'] = fanSpeed;
}
if (msg.data.hasOwnProperty('fanMode')) {
let fanMode = msg.data['fanMode'];
if (fanMode >= 10) {
fanMode = (((fanMode - 5) * 2) / 10).toString();
}
else if (fanMode == 1) {
fanMode = 'auto';
}
else {
fanMode = 'off';
}
state['fan_mode'] = fanMode;
state['fan_state'] = (fanMode === 'off' ? 'OFF' : 'ON');
}
return state;
},
},
];
const toZigbee = [
{
key: ['fan_mode', 'fan_state'],
convertSet: async (entity, key, value, meta) => {
if (key == 'fan_state' && typeof value === 'string' && value.toLowerCase() == 'on') {
value = 'auto';
}
else {
value = value.toString().toLowerCase();
}
let fanMode;
switch (value) {
case 'off':
fanMode = 0;
break;
case 'auto':
fanMode = 1;
break;
default:
fanMode = ((Number(value) / 2.0) * 10) + 5;
}
await entity.write('manuSpecificIkeaAirPurifier', { 'fanMode': fanMode }, exports.manufacturerOptions);
return { state: { fan_mode: value, fan_state: value === 'off' ? 'OFF' : 'ON' } };
},
convertGet: async (entity, key, meta) => {
await entity.read('manuSpecificIkeaAirPurifier', ['fanMode']);
},
},
{
key: ['fan_speed'],
convertGet: async (entity, key, meta) => {
await entity.read('manuSpecificIkeaAirPurifier', ['fanSpeed']);
},
},
{
key: ['pm25', 'air_quality'],
convertGet: async (entity, key, meta) => {
await entity.read('manuSpecificIkeaAirPurifier', ['particulateMatter25Measurement']);
},
},
{
key: ['replace_filter', 'filter_age'],
convertGet: async (entity, key, meta) => {
await entity.read('manuSpecificIkeaAirPurifier', ['filterRunTime']);
},
},
{
key: ['child_lock'],
convertSet: async (entity, key, value, meta) => {
await entity.write('manuSpecificIkeaAirPurifier', { 'childLock': ((value) ? 0 : 1) }, exports.manufacturerOptions);
return { state: { child_lock: ((value) ? true : false) } };
},
convertGet: async (entity, key, meta) => {
await entity.read('manuSpecificIkeaAirPurifier', ['childLock']);
},
},
{
key: ['led_enable'],
convertSet: async (entity, key, value, meta) => {
await entity.write('manuSpecificIkeaAirPurifier', { 'controlPanelLight': ((value) ? 0 : 1) }, exports.manufacturerOptions);
return { state: { led_enable: ((value) ? true : false) } };
},
convertGet: async (entity, key, meta) => {
await entity.read('manuSpecificIkeaAirPurifier', ['controlPanelLight']);
},
},
];
const configure = async (device, coordinatorEndpoint, definition) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ['manuSpecificIkeaAirPurifier']);
await endpoint.configureReporting('manuSpecificIkeaAirPurifier', [{ attribute: 'particulateMatter25Measurement',
minimumReportInterval: modernExtend_1.timeLookup['1_MINUTE'], maximumReportInterval: modernExtend_1.timeLookup['1_HOUR'], reportableChange: 1 }], exports.manufacturerOptions);
await endpoint.configureReporting('manuSpecificIkeaAirPurifier', [{ attribute: 'filterRunTime',
minimumReportInterval: modernExtend_1.timeLookup['1_HOUR'], maximumReportInterval: modernExtend_1.timeLookup['1_HOUR'], reportableChange: 0 }], exports.manufacturerOptions);
await endpoint.configureReporting('manuSpecificIkeaAirPurifier', [{ attribute: 'fanMode',
minimumReportInterval: 0, maximumReportInterval: modernExtend_1.timeLookup['1_HOUR'], reportableChange: 1 }], exports.manufacturerOptions);
await endpoint.configureReporting('manuSpecificIkeaAirPurifier', [{ attribute: 'fanSpeed',
minimumReportInterval: 0, maximumReportInterval: modernExtend_1.timeLookup['1_HOUR'], reportableChange: 1 }], exports.manufacturerOptions);
await endpoint.read('manuSpecificIkeaAirPurifier', ['controlPanelLight', 'childLock', 'filterRunTime']);
};
return { exposes, fromZigbee, toZigbee, configure, isModernExtend: true };
}
exports.ikeaAirPurifier = ikeaAirPurifier;
function ikeaVoc(args) {
return (0, modernExtend_1.numeric)({
name: 'voc_index',
label: 'VOC index',
cluster: 'msIkeaVocIndexMeasurement',
attribute: 'measuredValue',
reporting: { min: '1_MINUTE', max: '2_MINUTES', change: 1 },
description: 'Sensirion VOC index',
access: 'STATE',
...args,
});
}
exports.ikeaVoc = ikeaVoc;
function ikeaConfigureGenPollCtrl(args) {
args = { endpointId: 1, ...args };
const configure = async (device, coordinatorEndpoint, definition) => {
const endpoint = device.getEndpoint(args.endpointId);
if (Number(device?.softwareBuildID?.split('.')[0]) >= 24) {
await endpoint.write('genPollCtrl', { 'checkinInterval': 172800 });
}
};
return { configure, isModernExtend: true };
}
exports.ikeaConfigureGenPollCtrl = ikeaConfigureGenPollCtrl;
function tradfriOccupancy() {
const exposes = [
exposes_1.presets.binary('occupancy', exposes_1.access.STATE, true, false).withDescription('Indicates whether the device detected occupancy'),
exposes_1.presets.binary('illuminance_above_threshold', exposes_1.access.STATE, true, false)
.withDescription('Indicates whether the device detected bright light (works only in night mode)')
.withCategory('diagnostic'),
];
const fromZigbee = [{
cluster: 'genOnOff',
type: 'commandOnWithTimedOff',
options: [exposes_1.options.occupancy_timeout(), exposes_1.options.illuminance_below_threshold_check()],
convert: (model, msg, publish, options, meta) => {
const onlyWhenOnFlag = (msg.data.ctrlbits & 1) != 0;
if (onlyWhenOnFlag &&
(!options || !options.hasOwnProperty('illuminance_below_threshold_check') ||
options.illuminance_below_threshold_check) &&
!globalStore.hasValue(msg.endpoint, 'timer'))
return;
const timeout = options && options.hasOwnProperty('occupancy_timeout') ?
Number(options.occupancy_timeout) : msg.data.ontime / 10;
// Stop existing timer because motion is detected and set a new one.
clearTimeout(globalStore.getValue(msg.endpoint, 'timer'));
globalStore.clearValue(msg.endpoint, 'timer');
if (timeout !== 0) {
const timer = setTimeout(() => {
publish({ occupancy: false });
globalStore.clearValue(msg.endpoint, 'timer');
}, timeout * 1000);
globalStore.putValue(msg.endpoint, 'timer', timer);
}
return { occupancy: true, illuminance_above_threshold: onlyWhenOnFlag };
},
}];
return { exposes, fromZigbee, isModernExtend: true };
}
exports.tradfriOccupancy = tradfriOccupancy;
function tradfriRequestedBrightness() {
const exposes = [
exposes_1.presets.numeric('requested_brightness_level', exposes_1.access.STATE).withValueMin(76).withValueMax(254).withCategory('diagnostic'),
exposes_1.presets.numeric('requested_brightness_percent', exposes_1.access.STATE).withValueMin(30).withValueMax(100).withCategory('diagnostic'),
];
const fromZigbee = [{
// Possible values are 76 (30%) or 254 (100%)
cluster: 'genLevelCtrl',
type: 'commandMoveToLevelWithOnOff',
convert: (model, msg, publish, options, meta) => {
return {
requested_brightness_level: msg.data.level,
requested_brightness_percent: (0, utils_1.mapNumberRange)(msg.data.level, 0, 254, 0, 100),
};
},
}];
return { exposes, fromZigbee, isModernExtend: true };
}
exports.tradfriRequestedBrightness = tradfriRequestedBrightness;
function tradfriCommandsOnOff() {
const exposes = [exposes_1.presets.action(['toggle'])];
const fromZigbee = [{
cluster: 'genOnOff',
type: 'commandToggle',
convert: (model, msg, publish, options, meta) => {
return { action: (0, utils_1.postfixWithEndpointName)('toggle', msg, model, meta) };
},
}];
return { exposes, fromZigbee, isModernExtend: true };
}
exports.tradfriCommandsOnOff = tradfriCommandsOnOff;
function tradfriCommandsLevelCtrl() {
const actionLookup = {
commandStepWithOnOff: 'brightness_up_click',
commandStep: 'brightness_down_click',
commandMoveWithOnOff: 'brightness_up_hold',
commandStopWithOnOff: 'brightness_up_release',
commandMove: 'brightness_down_hold',
commandStop: 'brightness_down_release',
commandMoveToLevelWithOnOff: 'toggle_hold',
};
const exposes = [exposes_1.presets.action(Object.values(actionLookup))];
const fromZigbee = [{
cluster: 'genLevelCtrl',
type: [
'commandStepWithOnOff', 'commandStep', 'commandMoveWithOnOff', 'commandStopWithOnOff', 'commandMove', 'commandStop',
'commandMoveToLevelWithOnOff',
],
convert: (model, msg, publish, options, meta) => {
return { action: actionLookup[msg.type] };
},
}];
return { exposes, fromZigbee, isModernExtend: true };
}
exports.tradfriCommandsLevelCtrl = tradfriCommandsLevelCtrl;
function styrbarCommandOn() {
// The STYRBAR sends an on +- 500ms after the arrow release. We don't want to send the ON action in this case.
// https://github.com/Koenkk/zigbee2mqtt/issues/13335
const exposes = [exposes_1.presets.action(['on'])];
const fromZigbee = [{
cluster: 'genOnOff',
type: 'commandOn',
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.hasAlreadyProcessedMessage)(msg, model))
return;
const arrowReleaseAgo = Date.now() - globalStore.getValue(msg.endpoint, 'arrow_release', 0);
if (arrowReleaseAgo > 700) {
return { action: 'on' };
}
},
}];
return { exposes, fromZigbee, isModernExtend: true };
}
exports.styrbarCommandOn = styrbarCommandOn;
function ikeaDotsClick(args) {
args = {
actionLookup: {
'commandAction1': 'initial_press',
'commandAction2': 'long_press',
'commandAction3': 'short_release',
'commandAction4': 'long_release',
'commandAction6': 'double_press',
},
dotsPrefix: false,
...args,
};
const actions = args.endpointNames.map((b) => Object.values(args.actionLookup).map((a) => args.dotsPrefix ? `dots_${b}_${a}` : `${b}_${a}`)).flat();
const exposes = [exposes_1.presets.action(actions)];
const fromZigbee = [
{
// For remotes with firmware 1.0.012 (20211214)
cluster: 64639,
type: 'raw',
convert: (model, msg, publish, options, meta) => {
if (!Buffer.isBuffer(msg.data))
return;
let action;
const button = msg.data[5];
switch (msg.data[6]) {
case 1:
action = 'initial_press';
break;
case 2:
action = 'double_press';
break;
case 3:
action = 'long_press';
break;
}
return { action: args.dotsPrefix ? `dots_${button}_${action}` : `${button}_${action}` };
},
},
{
// For remotes with firmware 1.0.32 (20221219) an SOMRIG
cluster: 'tradfriButton',
type: ['commandAction1', 'commandAction2', 'commandAction3', 'commandAction4', 'commandAction6'],
convert: (model, msg, publish, options, meta) => {
const button = (0, utils_1.getEndpointName)(msg, model, meta);
const action = (0, utils_1.getFromLookup)(msg.type, args.actionLookup);
return { action: args.dotsPrefix ? `dots_${button}_${action}` : `${button}_${action}` };
},
},
];
const configure = (0, modernExtend_1.setupConfigureForBinding)('tradfriButton', 'output', args.endpointNames);
return { exposes, fromZigbee, configure, isModernExtend: true };
}
exports.ikeaDotsClick = ikeaDotsClick;
function ikeaArrowClick(args) {
args = {
styrbar: false,
...args,
};
const actions = ['arrow_left_click', 'arrow_left_hold', 'arrow_left_release',
'arrow_right_click', 'arrow_right_hold', 'arrow_right_release'];
const exposes = [exposes_1.presets.action(actions)];
const fromZigbee = [
{
cluster: 'genScenes',
type: 'commandTradfriArrowSingle',
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.hasAlreadyProcessedMessage)(msg, model))
return;
if (msg.data.value === 2)
return; // This is send on toggle hold
const direction = msg.data.value === 257 ? 'left' : 'right';
return { action: `arrow_${direction}_click` };
},
},
{
cluster: 'genScenes',
type: 'commandTradfriArrowRelease',
options: [exposes_1.options.legacy()],
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.hasAlreadyProcessedMessage)(msg, model))
return;
if (args.styrbar)
globalStore.putValue(msg.endpoint, 'arrow_release', Date.now());
const direction = globalStore.getValue(msg.endpoint, 'direction');
if (direction) {
globalStore.clearValue(msg.endpoint, 'direction');
const duration = msg.data.value / 1000;
const result = { action: `arrow_${direction}_release`, duration, action_duration: duration };
if (!(0, utils_1.isLegacyEnabled)(options))
delete result.duration;
return result;
}
},
},
];
const configure = (0, modernExtend_1.setupConfigureForBinding)('genScenes', 'output');
return { exposes, fromZigbee, configure, isModernExtend: true };
}
exports.ikeaArrowClick = ikeaArrowClick;
function ikeaMediaCommands() {
const actions = ['track_previous', 'track_next', 'volume_up',
'volume_down', 'volume_up_hold', 'volume_down_hold'];
const exposes = [exposes_1.presets.action(actions)];
const fromZigbee = [
{
cluster: 'genLevelCtrl',
type: 'commandMoveWithOnOff',
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.hasAlreadyProcessedMessage)(msg, model))
return;
const direction = msg.data.movemode === 1 ? 'down' : 'up';
return { action: `volume_${direction}` };
},
},
{
cluster: 'genLevelCtrl',
type: 'commandMove',
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.hasAlreadyProcessedMessage)(msg, model))
return;
const direction = msg.data.movemode === 1 ? 'down_hold' : 'up_hold';
return { action: `volume_${direction}` };
},
},
{
cluster: 'genLevelCtrl',
type: 'commandStep',
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.hasAlreadyProcessedMessage)(msg, model))
return;
const direction = msg.data.stepmode === 1 ? 'previous' : 'next';
return { action: `track_${direction}` };
},
},
];
const configure = (0, modernExtend_1.setupConfigureForBinding)('genLevelCtrl', 'output');
return { exposes, fromZigbee, configure, isModernExtend: true };
}
exports.ikeaMediaCommands = ikeaMediaCommands;
exports.legacy = {
fromZigbee: {
E1744_play_pause: {
cluster: 'genOnOff',
type: 'commandToggle',
options: [exposes_1.options.legacy()],
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.isLegacyEnabled)(options)) {
return { action: 'play_pause' };
}
},
},
E1744_skip: {
cluster: 'genLevelCtrl',
type: 'commandStep',
options: [exposes_1.options.legacy()],
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.isLegacyEnabled)(options)) {
const direction = msg.data.stepmode === 1 ? 'backward' : 'forward';
return {
action: `skip_${direction}`,
step_size: msg.data.stepsize,
transition_time: msg.data.transtime,
};
}
},
},
E1743_brightness_down: {
cluster: 'genLevelCtrl',
type: 'commandMove',
options: [exposes_1.options.legacy()],
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.isLegacyEnabled)(options)) {
return { click: 'brightness_down' };
}
},
},
E1743_brightness_up: {
cluster: 'genLevelCtrl',
type: 'commandMoveWithOnOff',
options: [exposes_1.options.legacy()],
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.isLegacyEnabled)(options)) {
return { click: 'brightness_up' };
}
},
},
E1743_brightness_stop: {
cluster: 'genLevelCtrl',
type: 'commandStopWithOnOff',
options: [exposes_1.options.legacy()],
convert: (model, msg, publish, options, meta) => {
if ((0, utils_1.isLegacyEnabled)(options)) {
return { click: 'brightness_stop' };
}
},
},
},
toZigbee: {},
};
//# sourceMappingURL=ikea.js.map