zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
1,301 lines (1,300 loc) • 78.8 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 fromZigbee_1 = __importDefault(require("../converters/fromZigbee"));
const toZigbee_1 = __importDefault(require("../converters/toZigbee"));
const exposes = __importStar(require("../lib/exposes"));
const globalStore = __importStar(require("../lib/store"));
const reporting = __importStar(require("../lib/reporting"));
const ota = __importStar(require("../lib/ota"));
const utils = __importStar(require("../lib/utils"));
const e = exposes.presets;
const ea = exposes.access;
const clickLookup = {
0: 'single',
1: 'release',
2: 'held',
3: 'double',
4: 'triple',
5: 'quadruple',
6: 'quintuple',
};
const buttonLookup = {
1: 'down',
2: 'up',
3: 'config',
4: 'aux_down',
5: 'aux_up',
6: 'aux_config',
};
const ledEffects = {
off: 0,
solid: 1,
fast_blink: 2,
slow_blink: 3,
pulse: 4,
chase: 5,
open_close: 6,
small_to_big: 7,
aurora: 8,
slow_falling: 9,
medium_falling: 10,
fast_falling: 11,
slow_rising: 12,
medium_rising: 13,
fast_rising: 14,
medium_blink: 15,
slow_chase: 16,
fast_chase: 17,
fast_siren: 18,
slow_siren: 19,
clear_effect: 255,
};
const individualLedEffects = {
off: 0,
solid: 1,
fast_blink: 2,
slow_blink: 3,
pulse: 4,
chase: 5,
falling: 6,
rising: 7,
aurora: 8,
clear_effect: 255,
};
const fanModes = { low: 2, smart: 4, medium: 86, high: 170, on: 255 };
const breezemodes = ['off', 'low', 'medium', 'high'];
const UINT8 = 32;
const BOOLEAN = 16;
const UINT16 = 33;
const INOVELLI = 0x122f;
// Converts brightness level to a fan mode
const intToFanMode = (value) => {
let selectedMode = 'low';
if (value >= fanModes.low) {
selectedMode = 'low';
}
if (value >= fanModes.medium) {
selectedMode = 'medium';
}
if (value >= fanModes.high) {
selectedMode = 'high';
}
if (value == 4) {
selectedMode = 'smart';
}
return selectedMode;
};
/**
* Convert speed string to int needed for breeze mode calculation.
* @param speedIn - speed string
* @returns low = 1, medium = 2, high = 3, off = 0
*/
const speedToInt = (speedIn) => {
switch (speedIn) {
case 'low': return 1;
case 'medium': return 2;
case 'high': return 3;
default: return 0;
}
};
// Create Expose list with Inovelli Parameters definitions
const attributesToExposeList = (ATTRIBUTES, exposesList) => {
Object.keys(ATTRIBUTES).forEach((key) => {
if (ATTRIBUTES[key].displayType === 'enum') {
const enumE = e
.enum(key, ATTRIBUTES[key].readOnly ? ea.STATE_GET : ea.ALL, Object.keys(ATTRIBUTES[key].values))
.withDescription(ATTRIBUTES[key].description);
exposesList.push(enumE);
}
else if (ATTRIBUTES[key].displayType === 'binary' ||
ATTRIBUTES[key].displayType === 'switch') {
exposesList.push(e
.binary(key, ATTRIBUTES[key].readOnly ? ea.STATE_GET : ea.ALL,
// @ts-expect-error
ATTRIBUTES[key].values.Enabled, ATTRIBUTES[key].values.Disabled)
.withDescription(ATTRIBUTES[key].description));
}
else {
const numeric = e
.numeric(key, ATTRIBUTES[key].readOnly ? ea.STATE_GET : ea.ALL)
.withValueMin(ATTRIBUTES[key].min)
.withValueMax(ATTRIBUTES[key].max);
if (ATTRIBUTES[key].values) {
Object.keys(ATTRIBUTES[key].values).forEach((value) => {
numeric.withPreset(value, ATTRIBUTES[key].values[value], '');
});
}
if (ATTRIBUTES[key].unit) {
numeric.withUnit(ATTRIBUTES[key].unit);
}
numeric.withDescription(ATTRIBUTES[key].description);
exposesList.push(numeric);
}
});
};
/**
* Common Attributes
*
* These attributes are shared between all devices with the manufacturer specific Inovelli cluster
* Some of the descriptions, max, min or value properties may be overridden for each device
*/
const COMMON_ATTRIBUTES = {
dimmingSpeedUpRemote: {
ID: 1,
dataType: UINT8,
min: 0,
max: 127,
description: 'This changes the speed that the light dims up when controlled from the hub. ' +
'A setting of 0 turns the light immediately on. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 25 (2.5s)',
},
dimmingSpeedUpLocal: {
ID: 2,
dataType: UINT8,
min: 0,
max: 127,
description: 'This changes the speed that the light dims up when controlled at the switch. ' +
'A setting of 0 turns the light immediately on. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.',
},
rampRateOffToOnRemote: {
ID: 3,
dataType: UINT8,
min: 0,
max: 127,
description: 'This changes the speed that the light turns on when controlled from the hub. ' +
'A setting of 0 turns the light immediately on. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.',
},
rampRateOffToOnLocal: {
ID: 4,
dataType: UINT8,
min: 0,
max: 127,
description: 'This changes the speed that the light turns on when controlled at the switch. ' +
'A setting of 0 turns the light immediately on. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.',
},
dimmingSpeedDownRemote: {
ID: 5,
dataType: UINT8,
min: 0,
max: 127,
description: 'This changes the speed that the light dims down when controlled from the hub. ' +
'A setting of 0 turns the light immediately off. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.',
},
dimmingSpeedDownLocal: {
ID: 6,
dataType: UINT8,
min: 0,
max: 127,
description: 'This changes the speed that the light dims down when controlled at the switch. ' +
'A setting of 0 turns the light immediately off. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpLocal setting.',
},
rampRateOnToOffRemote: {
ID: 7,
dataType: UINT8,
min: 0,
max: 127,
description: 'This changes the speed that the light turns off when controlled from the hub. ' +
'A setting of \'instant\' turns the light immediately off. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with rampRateOffToOnRemote setting.',
},
rampRateOnToOffLocal: {
ID: 8,
dataType: UINT8,
min: 0,
max: 127,
description: 'This changes the speed that the light turns off when controlled at the switch. ' +
'A setting of \'instant\' turns the light immediately off. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with rampRateOffToOnLocal setting.',
},
minimumLevel: {
ID: 9,
dataType: UINT8,
min: 1,
max: 253,
description: 'The minimum level that the dimmer allows the bulb to be dimmed to. ' +
'Useful when the user has an LED bulb that does not turn on or flickers at a lower level.',
},
maximumLevel: {
ID: 10,
dataType: UINT8,
min: 2,
max: 254,
description: 'The maximum level that the dimmer allows the bulb to be dimmed to.' +
'Useful when the user has an LED bulb that reaches its maximum level before the ' +
'dimmer value of 99 or when the user wants to limit the maximum brightness.',
},
invertSwitch: {
ID: 11,
dataType: BOOLEAN,
displayType: 'enum',
values: { Yes: 1, No: 0 },
min: 0,
max: 1,
description: 'Inverts the orientation of the switch.' +
' Useful when the switch is installed upside down. Essentially up becomes down and down becomes up.',
},
autoTimerOff: {
ID: 12,
min: 0,
max: 32767,
dataType: UINT16,
unit: 'seconds',
values: { Disabled: 0 },
description: 'Automatically turns the switch off after this many seconds.' +
' When the switch is turned on a timer is started. When the timer expires, the switch is turned off. 0 = Auto off is disabled.',
},
defaultLevelLocal: {
ID: 13,
dataType: UINT8,
min: 0,
max: 255,
description: 'Default level for the load when it is turned on at the switch.' +
' A setting of 255 means that the switch will return to the level that it was on before it was turned off.',
},
defaultLevelRemote: {
ID: 14,
dataType: UINT8,
min: 0,
max: 255,
description: 'Default level for the load when it is turned on from the hub.' +
' A setting of 255 means that the switch will return to the level that it was on before it was turned off.',
},
stateAfterPowerRestored: {
ID: 15,
dataType: UINT8,
min: 0,
max: 255,
description: 'The state the switch should return to when power is restored after power failure. 0 = off, 1-254 = level, 255 = previous.',
},
loadLevelIndicatorTimeout: {
ID: 17,
dataType: UINT8,
description: 'Shows the level that the load is at for x number of seconds after the load is adjusted' +
' and then returns to the Default LED state. 0 = Stay Off, 1-10 = seconds, 11 = Stay On.',
displayType: 'enum',
values: {
'Stay Off': 0,
'1 Second': 1,
'2 Seconds': 2,
'3 Seconds': 3,
'4 Seconds': 4,
'5 Seconds': 5,
'6 Seconds': 6,
'7 Seconds': 7,
'8 Seconds': 8,
'9 Seconds': 9,
'10 Seconds': 10,
'Stay On': 11,
},
min: 0,
max: 11,
},
powerType: {
ID: 21,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Non Neutral': 0, 'Neutral': 1 },
min: 0,
max: 1,
readOnly: true,
description: 'Set the power type for the device.',
},
switchType: {
ID: 22,
dataType: UINT8,
displayType: 'enum',
values: { 'Single Pole': 0, '3-Way Dumb Switch': 1, '3-Way Aux Switch': 2, 'Single-Pole Full Sine Wave': 3 },
min: 0,
max: 3,
description: 'Set the switch configuration.',
},
internalTemperature: {
ID: 32,
dataType: UINT8,
min: 0,
max: 127,
readOnly: true,
description: 'The temperature measured by the temperature sensor inside the chip, in degrees Celsius',
},
overheat: {
ID: 33,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'No Alert': 0, 'Overheated': 1 },
min: 0,
max: 1,
readOnly: true,
description: 'Indicates if the internal chipset is currently in an overheated state.',
},
buttonDelay: {
ID: 50,
dataType: UINT8,
values: {
'0ms': 0,
'100ms': 1,
'200ms': 2,
'300ms': 3,
'400ms': 4,
'500ms': 5,
'600ms': 6,
'700ms': 7,
'800ms': 8,
'900ms': 9,
},
displayType: 'enum',
min: 0,
max: 9,
description: 'This will set the button press delay. 0 = no delay (Disables Button Press Events),' +
'Default = 500ms.',
},
deviceBindNumber: {
ID: 51,
dataType: UINT8,
readOnly: true,
description: 'The number of devices currently bound (excluding gateways) and counts one group as two devices',
},
smartBulbMode: {
ID: 52,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Disabled': 0, 'Smart Bulb Mode': 1 },
description: 'For use with Smart Bulbs that need constant power and are controlled via commands rather than power.',
},
doubleTapUpToParam55: {
ID: 53,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Disabled': 0, 'Enabled': 1 },
description: 'Enable or Disable setting level to parameter 55 on double-tap UP.',
},
doubleTapDownToParam56: {
ID: 54,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Disabled': 0, 'Enabled': 1 },
description: 'Enable or Disable setting level to parameter 56 on double-tap DOWN.',
},
brightnessLevelForDoubleTapUp: {
ID: 55,
dataType: UINT8,
min: 2,
max: 255,
description: 'Set this level on double-tap UP (if enabled by P53). 255 = send ON command.',
},
brightnessLevelForDoubleTapDown: {
ID: 56,
dataType: UINT8,
min: 0,
max: 255,
description: 'Set this level on double-tap DOWN (if enabled by P54). 255 = send OFF command.',
},
ledColorWhenOn: {
ID: 95,
dataType: UINT8,
min: 0,
max: 255,
values: {
Red: 0,
Orange: 21,
Yellow: 42,
Green: 85,
Cyan: 127,
Blue: 170,
Violet: 212,
Pink: 234,
White: 255,
},
description: 'Set the color of the LED Indicator when the load is on.',
},
ledColorWhenOff: {
ID: 96,
dataType: UINT8,
min: 0,
max: 255,
values: {
Red: 0,
Orange: 21,
Yellow: 42,
Green: 85,
Cyan: 127,
Blue: 170,
Violet: 212,
Pink: 234,
White: 255,
},
description: 'Set the color of the LED Indicator when the load is off.',
},
ledIntensityWhenOn: {
ID: 97,
dataType: UINT8,
min: 0,
max: 100,
description: 'Set the intensity of the LED Indicator when the load is on.',
},
ledIntensityWhenOff: {
ID: 98,
dataType: UINT8,
min: 0,
max: 100,
description: 'Set the intensity of the LED Indicator when the load is off.',
},
singleTapBehavior: {
ID: 120,
dataType: UINT8,
displayType: 'enum',
values: { 'Old Behavior': 0, 'New Behavior': 1, 'Down Always Off': 2 },
description: 'Behavior of single tapping the on or off button. Old behavior turns the switch on or off. ' +
'New behavior cycles through the levels set by P131-133. Down Always Off is like the new behavior but ' +
'down always turns the switch off instead of going to next lower speed.',
},
fanTimerMode: {
ID: 121,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Disabled': 0, 'Enabled': 1 },
description: 'Enable or disable advanced timer mode to have the switch act like a bathroom fan timer',
},
fanControlMode: {
ID: 130,
dataType: UINT8,
displayType: 'enum',
values: { 'Disabled': 0, 'Multi Tap': 1, 'Cycle': 2 },
description: 'Which mode to use when binding EP3 (config button) to another device (like a fan module).',
},
lowLevelForFanControlMode: {
ID: 131,
dataType: UINT8,
min: 2,
max: 254,
description: 'Level to send to device bound to EP3 when set to low.',
},
mediumLevelForFanControlMode: {
ID: 132,
dataType: UINT8,
min: 2,
max: 254,
description: 'Level to send to device bound to EP3 when set to medium.',
},
highLevelForFanControlMode: {
ID: 133,
dataType: UINT8,
min: 2,
max: 254,
description: 'Level to send to device bound to EP3 when set to high.',
},
ledColorForFanControlMode: {
ID: 134,
dataType: UINT8,
min: 0,
max: 255,
values: {
Red: 0,
Orange: 21,
Yellow: 42,
Green: 85,
Cyan: 127,
Blue: 170,
Violet: 212,
Pink: 234,
White: 255,
},
description: 'LED color used to display fan control mode.',
},
auxSwitchUniqueScenes: {
ID: 123,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Disabled': 0, 'Enabled': 1 },
description: 'Have unique scene numbers for scenes activated with the aux switch.',
},
bindingOffToOnSyncLevel: {
ID: 125,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Disabled': 0, 'Enabled': 1 },
description: 'Send Move_To_Level using Default Level with Off/On to bound devices.',
},
localProtection: {
ID: 256,
dataType: BOOLEAN,
values: { Disabled: 0, Enabled: 1 },
description: 'Ability to control switch from the wall.',
displayType: 'enum',
},
remoteProtection: {
ID: 257,
dataType: BOOLEAN,
values: { Disabled: 0, Enabled: 1 },
readOnly: true,
description: 'Ability to control switch from the hub.',
displayType: 'enum',
},
onOffLedMode: {
ID: 259,
min: 0,
max: 1,
values: { All: 0, One: 1 },
dataType: BOOLEAN,
description: 'When the device is in On/Off mode, use full LED bar or just one LED.',
displayType: 'enum',
},
firmwareUpdateInProgressIndicator: {
ID: 260,
dataType: BOOLEAN,
values: { Disabled: 0, Enabled: 1 },
description: 'Display progress on LED bar during firmware update.',
displayType: 'enum',
},
defaultLed1ColorWhenOn: {
ID: 60,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed1ColorWhenOff: {
ID: 61,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed1IntensityWhenOn: {
ID: 62,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed1IntensityWhenOff: {
ID: 63,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed2ColorWhenOn: {
ID: 65,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed2ColorWhenOff: {
ID: 66,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed2IntensityWhenOn: {
ID: 67,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed2IntensityWhenOff: {
ID: 68,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed3ColorWhenOn: {
ID: 70,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed3ColorWhenOff: {
ID: 71,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed3IntensityWhenOn: {
ID: 72,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed3IntensityWhenOff: {
ID: 73,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed4ColorWhenOn: {
ID: 75,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed4ColorWhenOff: {
ID: 76,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed4IntensityWhenOn: {
ID: 77,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed4IntensityWhenOff: {
ID: 78,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed5ColorWhenOn: {
ID: 80,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed5ColorWhenOff: {
ID: 81,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed5IntensityWhenOn: {
ID: 82,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed5IntensityWhenOff: {
ID: 83,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed6ColorWhenOn: {
ID: 85,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed6ColorWhenOff: {
ID: 86,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed6IntensityWhenOn: {
ID: 87,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed6IntensityWhenOff: {
ID: 88,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed7ColorWhenOn: {
ID: 90,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed7ColorWhenOff: {
ID: 91,
dataType: UINT8,
min: 0,
max: 255,
description: '0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.',
},
defaultLed7IntensityWhenOn: {
ID: 92,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.',
},
defaultLed7IntensityWhenOff: {
ID: 93,
dataType: UINT8,
min: 0,
max: 101,
description: 'Intesity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.',
},
outputMode: {
ID: 258,
min: 0,
max: 1,
values: { 'Dimmer': 0, 'On/Off': 1 },
dataType: BOOLEAN,
description: 'Use device as a Dimmer or an On/Off switch.',
displayType: 'enum',
},
doubleTapClearNotifications: {
ID: 262,
dataType: BOOLEAN,
min: 0,
max: 1,
description: 'Double-Tap the Config button to clear notifications.',
values: { 'Enabled (Default)': 0, 'Disabled': 1 },
displayType: 'enum',
},
fanLedLevelType: {
ID: 263,
dataType: UINT8,
min: 0,
max: 10,
values: { 'Limitless (like VZM31)': 0, 'Adaptive LED': 10 },
description: 'Level display of the LED Strip',
},
};
const VZM31_ATTRIBUTES = {
...COMMON_ATTRIBUTES,
activePowerReports: {
ID: 18,
dataType: UINT8,
min: 0,
max: 100,
description: 'Percent power level change that will result in a new power report being sent. 0 = Disabled',
},
periodicPowerAndEnergyReports: {
ID: 19,
min: 0,
max: 32767,
dataType: UINT16,
description: 'Time period between consecutive power & energy reports being sent (in seconds). The timer is reset after each report is sent.',
},
activeEnergyReports: {
ID: 20,
dataType: UINT16,
min: 0,
max: 32767,
description: 'Energy reports Energy level change which will result in sending a new energy report.' +
'0 = disabled, 1-32767 = 0.01kWh-327.67kWh. Default setting: 10 (0.1 kWh)',
},
quickStartTime: {
ID: 23,
dataType: UINT8,
min: 0,
max: 60,
description: 'Duration of full power output while lamp tranisitions from Off to On. In 60th of second. 0 = disable, 1 = 1/60s, 60 = 1s',
},
quickStartLevel: {
ID: 24,
dataType: UINT8,
min: 1,
max: 254,
description: 'Level of power output during Quick Start Light time (P23).',
},
higherOutputInNonNeutral: {
ID: 25,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Disabled (default)': 0, 'Enabled': 1 },
min: 0,
max: 1,
description: 'Increase level in non-neutral mode',
},
ledBarScaling: {
ID: 100,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Gen3 method (VZM-style)': 0, 'Gen2 method (LZW-style)': 1 },
description: 'Method used for scaling.',
},
relayClick: {
ID: 261,
dataType: BOOLEAN,
min: 0,
max: 1,
description: 'In neutral on/off setups, the default is to have a clicking sound to notify you that the relay ' +
'is open or closed. You may disable this sound by creating a, “simulated” on/off where the switch ' +
'only will turn onto 100 or off to 0.',
values: { 'Disabled (Click Sound On)': 0, 'Enabled (Click Sound Off)': 1 },
displayType: 'enum',
},
};
const VZM35_ATTRIBUTES = {
...COMMON_ATTRIBUTES,
minimumLevel: {
...COMMON_ATTRIBUTES.minimumLevel,
description: '1-84: The level corresponding to the fan is Low, Medium, High. ' +
'85-170: The level corresponding to the fan is Medium, Medium, High. ' +
'170-254: The level corresponding to the fan is High, High, High ',
},
maximumLevel: {
...COMMON_ATTRIBUTES.maximumLevel,
description: '2-84: The level corresponding to the fan is Low, Medium, High.',
},
switchType: {
...COMMON_ATTRIBUTES.switchType,
values: { 'Single Pole': 0, 'Aux Switch': 1 },
max: 1,
},
smartBulbMode: {
...COMMON_ATTRIBUTES.smartBulbMode,
description: 'For use with Smart Fans that need constant power and are controlled via commands rather than power.',
values: { 'Disabled': 0, 'Smart Fan Mode': 1 },
},
quickStartTime: {
ID: 23,
dataType: UINT8,
min: 0,
max: 60,
description: 'Duration of full power output while fan tranisitions from Off to On. In 60th of second. 0 = disable, 1 = 1/60s, 60 = 1s',
},
nonNeutralAuxMediumGear: {
ID: 30,
dataType: UINT8,
min: 42,
max: 135,
description: 'Identification value in Non-nuetral, medium gear, aux switch',
},
nonNeutralAuxLowGear: {
ID: 31,
dataType: UINT8,
min: 42,
max: 135,
description: 'Identification value in Non-nuetral, low gear, aux switch',
},
outputMode: {
...COMMON_ATTRIBUTES.outputMode,
values: { 'Ceiling Fan (3-Speed)': 0, 'Exhaust Fan (On/Off)': 1 },
description: 'Use device in ceiling fan (3-Speed) or in exhaust fan (On/Off) mode.',
},
};
const VZM36_ATTRIBUTES = {
dimmingSpeedUpRemote_1: { ...COMMON_ATTRIBUTES.dimmingSpeedUpRemote },
rampRateOffToOnRemote_1: { ...COMMON_ATTRIBUTES.rampRateOffToOnRemote },
dimmingSpeedDownRemote_1: { ...COMMON_ATTRIBUTES.dimmingSpeedDownRemote },
rampRateOnToOffRemote_1: { ...COMMON_ATTRIBUTES.rampRateOnToOffRemote },
minimumLevel_1: { ...COMMON_ATTRIBUTES.minimumLevel },
maximumLevel_1: { ...COMMON_ATTRIBUTES.maximumLevel },
autoTimerOff_1: {
...COMMON_ATTRIBUTES.autoTimerOff,
description: 'Automatically turns the light off after this many seconds.' +
' When the light is turned on a timer is started. When the timer expires, the light is turned off. 0 = Auto off is disabled.',
},
defaultLevelRemote_1: {
...COMMON_ATTRIBUTES.defaultLevelRemote,
description: 'Default level for the light when it is turned on from the hub.' +
' A setting of 255 means that the light will return to the level that it was on before it was turned off.',
},
stateAfterPowerRestored_1: {
...COMMON_ATTRIBUTES.stateAfterPowerRestored,
description: 'The state the light should return to when power is restored after power failure. 0 = off, 1-254 = level, 255 = previous.',
},
higherOutputInNonNeutral_1: {
ID: 25,
dataType: BOOLEAN,
displayType: 'enum',
values: { 'Disabled (default)': 0, 'Enabled': 1 },
min: 0,
max: 1,
description: 'Increase level in non-neutral mode for light.',
},
quickStartTime_1: {
ID: 23,
dataType: UINT8,
min: 0,
max: 60,
description: 'Duration of full power output while lamp tranisitions from Off to On. In 60th of second. 0 = disable, 1 = 1/60s, 60 = 1s',
},
quickStartLevel_1: {
ID: 24,
dataType: UINT8,
min: 1,
max: 254,
description: 'Level of power output during Quick Start Light time (P23).',
},
smartBulbMode_1: { ...COMMON_ATTRIBUTES.smartBulbMode },
ledColorWhenOn_1: { ...COMMON_ATTRIBUTES.ledColorWhenOn },
ledIntensityWhenOn_1: { ...COMMON_ATTRIBUTES.ledIntensityWhenOn },
// remote protection is readonly...
outputMode_1: { ...COMMON_ATTRIBUTES.outputMode },
// Endpoint 2 (Fan)
dimmingSpeedUpRemote_2: {
...COMMON_ATTRIBUTES.dimmingSpeedUpRemote,
description: 'This changes the speed that the fan ramps up when controlled from the hub. ' +
'A setting of 0 turns the fan immediately on. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 25 (2.5s)',
},
rampRateOffToOnRemote_2: {
...COMMON_ATTRIBUTES.rampRateOffToOnRemote,
description: 'This changes the speed that the fan turns on when controlled from the hub. ' +
'A setting of 0 turns the fan immediately on. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.',
},
dimmingSpeedDownRemote_2: {
...COMMON_ATTRIBUTES.dimmingSpeedDownRemote,
description: 'This changes the speed that the fan ramps down when controlled from the hub. ' +
'A setting of 0 turns the fan immediately off. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.',
},
rampRateOnToOffRemote_2: {
...COMMON_ATTRIBUTES.rampRateOnToOffRemote,
description: 'This changes the speed that the fan turns off when controlled from the hub. ' +
'A setting of \'instant\' turns the fan immediately off. Increasing the value slows down the transition speed. ' +
'Every number represents 100ms. Default = 127 - Keep in sync with rampRateOffToOnRemote setting.',
},
minimumLevel_2: {
...COMMON_ATTRIBUTES.minimumLevel,
description: 'The minimum level that the fan can be set to.',
},
maximumLevel_2: {
...COMMON_ATTRIBUTES.maximumLevel,
description: 'The maximum level that the fan can be set to.',
},
autoTimerOff_2: {
...COMMON_ATTRIBUTES.autoTimerOff,
description: 'Automatically turns the fan off after this many seconds.' +
' When the fan is turned on a timer is started. When the timer expires, the switch is turned off. 0 = Auto off is disabled.',
},
defaultLevelRemote_2: {
...COMMON_ATTRIBUTES.defaultLevelRemote,
description: 'Default level for the fan when it is turned on from the hub.' +
' A setting of 255 means that the fan will return to the level that it was on before it was turned off.',
},
stateAfterPowerRestored_2: {
...COMMON_ATTRIBUTES.stateAfterPowerRestored,
description: 'The state the fan should return to when power is restored after power failure. 0 = off, 1-254 = level, 255 = previous.',
},
quickStartTime_2: {
ID: 23,
dataType: UINT8,
min: 0,
max: 60,
description: 'Duration of full power output while fan tranisitions from Off to On. In 60th of second. 0 = disable, 1 = 1/60s, 60 = 1s',
},
// power type readonly
// internal temp readonly
// overheat readonly
smartBulbMode_2: {
...COMMON_ATTRIBUTES.smartBulbMode,
values: { 'Disabled': 0, 'Smart Fan Mode': 1 },
description: 'For use with Smart Fans that need constant power and are controlled via commands rather than power.',
},
// remote protection readonly..
outputMode_2: {
...COMMON_ATTRIBUTES.outputMode,
values: { 'Ceiling Fan (3-Speed)': 0, 'Exhaust Fan (On/Off)': 1 },
description: 'Use device in ceiling fan (3-Speed) or in exhaust fan (On/Off) mode.',
},
};
const tzLocal = {
inovelli_parameters: (ATTRIBUTES) => ({
key: Object.keys(ATTRIBUTES).filter((a) => !ATTRIBUTES[a].readOnly),
convertSet: async (entity, key, value, meta) => {
// Check key to see if there is an endpoint postfix for the VZM36
const keysplit = key.split('_');
let entityToUse = entity;
if (keysplit.length === 2) {
entityToUse = meta.device.getEndpoint(Number(keysplit[1]));
}
if (!(key in ATTRIBUTES)) {
return;
}
const payload = {
[ATTRIBUTES[key].ID]: {
value: ATTRIBUTES[key].displayType === 'enum' ?
// @ts-expect-error
ATTRIBUTES[key].values[value] :
value,
type: ATTRIBUTES[key].dataType,
},
};
await entityToUse.write('manuSpecificInovelli', payload, {
manufacturerCode: INOVELLI,
});
return {
state: {
[key]: value,
},
};
},
convertGet: async (entity, key, meta) => {
// Check key to see if there is an endpoint postfix for the VZM36
const keysplit = key.split('_');
let entityToUse = entity;
let keyToUse = key;
if (keysplit.length === 2) {
entityToUse = meta.device.getEndpoint(Number(keysplit[1]));
keyToUse = keysplit[0];
}
await entityToUse.read('manuSpecificInovelli', [keyToUse], {
manufacturerCode: INOVELLI,
});
},
}),
inovelli_parameters_readOnly: (ATTRIBUTES) => ({
key: Object.keys(ATTRIBUTES).filter((a) => ATTRIBUTES[a].readOnly),
convertGet: async (entity, key, meta) => {
// Check key to see if there is an endpoint postfix for the VZM36
const keysplit = key.split('_');
let entityToUse = entity;
let keyToUse = key;
if (keysplit.length === 2) {
entityToUse = meta.device.getEndpoint(Number(keysplit[1]));
keyToUse = keysplit[0];
}
await entityToUse.read('manuSpecificInovelli', [keyToUse], {
manufacturerCode: INOVELLI,
});
},
}),
inovelli_led_effect: {
key: ['led_effect'],
convertSet: async (entity, key, values, meta) => {
await entity.command('manuSpecificInovelli', 'ledEffect', {
// @ts-expect-error
effect: ledEffects[values.effect],
// @ts-expect-error
color: Math.min(Math.max(0, values.color), 255),
// @ts-expect-error
level: Math.min(Math.max(0, values.level), 100),
// @ts-expect-error
duration: Math.min(Math.max(0, values.duration), 255),
}, { disableResponse: true, disableDefaultResponse: true });
return { state: { [key]: values } };
},
},
inovelli_individual_led_effect: {
key: ['individual_led_effect'],
convertSet: async (entity, key, values, meta) => {
await entity.command('manuSpecificInovelli', 'individualLedEffect', {
// @ts-expect-error
led: Math.min(Math.max(0, parseInt(values.led)), 7),
// @ts-expect-error
effect: individualLedEffects[values.effect],
// @ts-expect-error
color: Math.min(Math.max(0, values.color), 255),
// @ts-expect-error
level: Math.min(Math.max(0, values.level), 100),
// @ts-expect-error
duration: Math.min(Math.max(0, values.duration), 255),
}, { disableResponse: true, disableDefaultResponse: true });
return { state: { [key]: values } };
},
},
/**
* Inovelli VZM31SN has a default transition property that the device should
* fallback to if a transition is not specified by passing 0xffff
*/
light_onoff_brightness_inovelli: {
key: ['state', 'brightness', 'brightness_percent'],
convertSet: async (entity, key, value, meta) => {
const { message } = meta;
const transition = utils.getTransition(entity, 'brightness', meta);
const turnsOffAtBrightness1 = utils.getMetaValue(entity, meta.mapped, 'turnsOffAtBrightness1', 'allEqual', false);
let state = message.hasOwnProperty('state') ?
// @ts-expect-error
message.state.toLowerCase() :
undefined;
let brightness = undefined;
if (message.hasOwnProperty('brightness')) {
brightness = Number(message.brightness);
}
else if (message.hasOwnProperty('brightness_percent')) {
brightness = utils.mapNumberRange(Number(message.brightness_percent), 0, 100, 0, 255);
}
if (brightness !== undefined &&
(isNaN(brightness) || brightness < 0 || brightness > 255)) {
// Allow 255 value, changing this to 254 would be a breaking change.
throw new Error(`Brightness value of message: '${JSON.stringify(message)}' invalid, must be a number >= 0 and =< 254`);
}
if (state !== undefined &&
['on', 'off', 'toggle'].includes(state) === false) {
throw new Error(`State value of message: '${JSON.stringify(message)}' invalid, must be 'ON', 'OFF' or 'TOGGLE'`);
}
if (state === 'toggle' ||
state === 'off' ||
(brightness === undefined && state === 'on')) {
if (transition.specified && transition.time > 0) {
if (state === 'toggle') {
state = meta.state.state === 'ON' ? 'off' : 'on';
}
if (state === 'off' &&
meta.state.brightness &&
meta.state.state === 'ON') {
// https://github.com/Koenkk/zigbee2mqtt/issues/2850#issuecomment-580365633
// We need to remember the state before turning the device off as we need to restore
// it once we turn it on again.
// We cannot rely on the meta.state as when reporting is enabled the bulb will reports
// it brightness while decreasing the brightness.
globalStore.putValue(entity, 'brightness', meta.state.brightness);
globalStore.putValue(entity, 'turnedOffWithTransition', true);
}
const fallbackLevel = utils.getObjectProperty(meta.state, 'brightness', 254);
let level = state === 'off' ?
0 :
globalStore.getValue(entity, 'brightness', fallbackLevel);
if (state === 'on' && level === 0) {
level = turnsOffAtBrightness1 ? 2 : 1;
}
const payload = { level, transtime: transition.time };
await entity.command('genLevelCtrl', 'moveToLevelWithOnOff', payload, utils.getOptions(meta.mapped, entity));
const result = { state: { state: state.toUpperCase() } };
// @ts-expect-error
if (state === 'on')
result.state.brightness = level;
return result;
}
else {
// Store brightness where the bulb was turned off with as we need it when the bulb is turned on
// with transition.
if (meta.state.hasOwnProperty('brightness') && state === 'off') {
globalStore.putValue(entity, 'brightness', meta.state.brightness);
globalStore.putValue(entity, 'turnedOffWithTransition', true);
}
const result = await inovelliOnOffConvertSet(entity, 'state', state, meta);
// @ts-expect-error
result.readAfterWriteTime = 0;
if (result.state &&
result.state.state === 'ON' &&
meta.state.brightness === 0) {
// @ts-expect-error
result.state.brightness = 1;
}
return result;
}
}
else {
brightness = Math.min(254, brightness);
if (brightness === 1 && turnsOffAtBrightness1) {
brightness = 2;
}
globalStore.putValue(entity, 'brightness', brightness);
await entity.command('genLevelCtrl', 'moveToLevelWithOnOff', {
level: Number(brightness),
transtime: !transition.specified ? 0xffff : transition.time,
}, utils.getOptions(meta.mapped, entity));
const defaultTransitionTime = await entity.read('manuSpecificInovelli', ['rampRateOnToOffRemote']);
return {
state: {
state: brightness === 0 ? 'OFF' : 'ON',
brightness: Number(brightness),
},
readAfterWriteTime: transition.time === 0 ?
// @ts-expect-error
defaultTransitionTime.rampRateOnToOffRemote * 100 :
transition.time * 100, // need on speed
};
}
},
convertGet: async (entity, key, meta) => {
if (key === 'brightness') {
await entity.read('genLevelCtrl', ['currentLevel']);
}
else if (key === 'state') {
await toZigbee_1.default.on_off.convertGet(entity, key, meta);
}
},
},
fan_mode: {
key: ['fan_mode'],
convertSet: async (entity, key, value, meta) => {
await entity.command('genLevelCtrl', 'moveToLevelWithOnOff', {
level: fanModes[value],
transtime: 0xffff,
}, utils.getOptions(meta.mapped, entity));
return {
state: {
[key]: value,
state: 'ON',
},
};
},
convertGet: async (entity, key, meta) => {
await entity.read('genLevelCtrl', ['currentLevel']);
},
},
fan_state: {
key: ['fan_state'],
convertSet: async (entity, key, value, meta) => {
const state = meta.message.hasOwnProperty('fan_state') ?
meta.message.fan_state.toString().toLowerCase() :
null;
utils.validateValue(state, ['toggle', 'off', 'on']);
await entity.command('genOnOff', state, {}, utils.getOptions(meta.mapped, entity));
if (state === 'toggle') {
const currentState = meta.state[`state${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`];
return currentState ?
{ state: { fan_state: currentState === 'OFF' ? 'ON' : 'OFF' } } :
{};
}
else {
return { state: { fan_state: state.toString().toUpperCase() } };
}
},
convertGet: async (entity, key, meta) => {
await entity.read('genOnOff', ['onOff']);
},
},
vzm36_fan_mode: {
key: ['fan_mode'],
convertSet: async (entity, key, value, meta) => {
const endpoint = meta.device.getEndpoint(2);
await endpoint.command('genLevelCtrl', 'moveToLevelWithOnOff', {
level: fanModes[value],
transtime: 0xffff,
}, utils.getOptions(meta.mapped, entity));
meta.state[key] = value;
return {
state: {
[key]: value,
fan_state: 'ON',
},
};
},
convertGet: async (entity, key, meta) => {