Skip to content

Commit

Permalink
Expose power_outage_memory and switch_type for Lonsonho TS110E_2g…
Browse files Browse the repository at this point in the history
…ang (#4393)

* Refs Koenkk/zigbee2mqtt#12952: `Lonsonho TS110E_2gang` - allow to configure switches type

* Refs Koenkk/zigbee2mqtt#12952: `extend.light_onoff_brightness` - allow to exclude `power_on_behavior` converters since they can conflict with manufacturer-specific ones

* Refs Koenkk/zigbee2mqtt#12952: `Lonsonho TS110E_2gang` - allow to configure `power_on_behavior`

* Refs Koenkk/zigbee2mqtt#12952: `Lonsonho TS110E_2gang` - replace `moes_power_on_behavior` coverter with `tuya_switch_power_outage_memory` since we don't want to expose the `READ` capability (returns incorrect value)

* Refs Koenkk/zigbee2mqtt#12952: `Lonsonho TS110E_2gang` - remove extra read command in the `configure` section

* Refs Koenkk/zigbee2mqtt#12952: fix linter errors

* Refs Koenkk/zigbee2mqtt#12952: revert formatting changes

* Refs Koenkk/zigbee2mqtt#12952: `lib/extend` - allow to exclude `power_on_behavior` converters for the rest of light variants

* Update lonsonho.js

* Update fromZigbee.js

* Update toZigbee.js

* Update lonsonho.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
  • Loading branch information
gorbunovav and Koenkk authored Jul 1, 2022
1 parent 7462d04 commit 73ef708
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 14 deletions.
52 changes: 50 additions & 2 deletions devices/lonsonho.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,47 @@ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/lega
const tz = require('../converters/toZigbee');
const reporting = require('../lib/reporting');
const extend = require('../lib/extend');
const utils = require('../lib/utils');
const e = exposes.presets;
const ea = exposes.access;

const fzLocal = {
TS110E_switch_type: {
cluster: 'genLevelCtrl',
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
const property = 0xfc02;
if (msg.data.hasOwnProperty(property)) {
const value = msg.data[property];
const lookup = {0: 'momentary', 1: 'toggle', 2: 'state'};
if (lookup.hasOwnProperty(value)) {
const propertyName = utils.postfixWithEndpointName('switch_type', msg, model);
return {[propertyName]: lookup[value]};
}
}
},
},
};

const tzLocal = {
TS110E_switch_type: {
key: ['switch_type'],
convertSet: async (entity, key, value, meta) => {
value = value.toLowerCase();
const lookup = {'momentary': 0, 'toggle': 1, 'state': 2};

utils.validateValue(value, Object.keys(lookup));
const payload = lookup[value];

await entity.write('genLevelCtrl', {0xfc02: {value: payload, type: 0x20}});
return {state: {switch_type: value}};
},
convertGet: async (entity, key, meta) => {
await entity.read('genLevelCtrl', [0xfc02]);
},
},
};

module.exports = [
{
fingerprint: [{modelID: 'TS130F', manufacturerName: '_TZ3000_vd43bbfq'}, {modelID: 'TS130F', manufacturerName: '_TZ3000_fccpjz5z'}],
Expand Down Expand Up @@ -221,9 +259,19 @@ module.exports = [
model: 'TS110E_2gang',
vendor: 'Lonsonho',
description: 'Zigbee smart dimmer module 2 gang with neutral',
extend: extend.light_onoff_brightness({noConfigure: true}),
fromZigbee: extend.light_onoff_brightness({disablePowerOnBehavior: true}).fromZigbee.concat([
fz.tuya_switch_power_outage_memory, fzLocal.TS110E_switch_type]),
toZigbee: extend.light_onoff_brightness({disablePowerOnBehavior: true}).toZigbee.concat([
tz.tuya_switch_power_outage_memory, tzLocal.TS110E_switch_type]),
meta: {multiEndpoint: true},
exposes: [e.light_brightness().withEndpoint('l1'), e.light_brightness().withEndpoint('l2')],
exposes: [
e.light_brightness().withEndpoint('l1'),
e.light_brightness().withEndpoint('l2'),
exposes.enum('power_outage_memory', ea.STATE_SET, ['on', 'off', 'restore']).withDescription('Recover state after power outage')
.withEndpoint('l1'),
exposes.presets.switch_type_2().withEndpoint('l1'),
exposes.presets.switch_type_2().withEndpoint('l2'),
],
configure: async (device, coordinatorEndpoint, logger) => {
await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
Expand Down
50 changes: 38 additions & 12 deletions lib/extend.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ const extend = {
return {exposes, fromZigbee, toZigbee};
},
light_onoff_brightness: (options={}) => {
options = {disableEffect: false, ...options};
options = {disableEffect: false, disablePowerOnBehavior: false, ...options};
const exposes = [e.light_brightness(), ...(!options.disableEffect ? [e.effect()] : [])];
const fromZigbee = [fz.on_off, fz.brightness, fz.level_config, fz.power_on_behavior, fz.ignore_basic_report];
const fromZigbee = [fz.on_off, fz.brightness, fz.level_config, fz.ignore_basic_report];
const toZigbee = [tz.light_onoff_brightness, tz.ignore_transition, tz.ignore_rate, tz.light_brightness_move,
tz.light_brightness_step, tz.level_config, tz.power_on_behavior, ...(!options.disableEffect ? [tz.effect] : [])];
tz.light_brightness_step, tz.level_config, ...(!options.disableEffect ? [tz.effect] : [])];

if (!options.disablePowerOnBehavior) {
fromZigbee.push(fz.power_on_behavior);
toZigbee.push(tz.power_on_behavior);
}

const result = {exposes, fromZigbee, toZigbee};
if (!options.noConfigure) {
Expand All @@ -28,18 +33,23 @@ const extend = {
return result;
},
light_onoff_brightness_colortemp: (options={}) => {
options = {disableEffect: false, disableColorTempStartup: false, ...options};
options = {disableEffect: false, disableColorTempStartup: false, disablePowerOnBehavior: false, ...options};
const exposes = [e.light_brightness_colortemp(options.colorTempRange), ...(!options.disableEffect ? [e.effect()] : [])];
const toZigbee = [tz.light_onoff_brightness, tz.light_colortemp, tz.ignore_transition, tz.ignore_rate, tz.light_brightness_move,
tz.light_colortemp_move, tz.light_brightness_step, tz.light_colortemp_step, tz.light_colortemp_startup, tz.level_config,
tz.power_on_behavior, tz.light_color_options, tz.light_color_mode, ...(!options.disableEffect ? [tz.effect] : [])];
const fromZigbee = [fz.color_colortemp, fz.on_off, fz.brightness, fz.level_config, fz.power_on_behavior, fz.ignore_basic_report];
tz.light_color_options, tz.light_color_mode, ...(!options.disableEffect ? [tz.effect] : [])];
const fromZigbee = [fz.color_colortemp, fz.on_off, fz.brightness, fz.level_config, fz.ignore_basic_report];

if (options.disableColorTempStartup) {
exposes[0].removeFeature('color_temp_startup');
toZigbee.splice(toZigbee.indexOf(tz.light_colortemp_startup), 1);
}

if (!options.disablePowerOnBehavior) {
fromZigbee.push(fz.power_on_behavior);
toZigbee.push(tz.power_on_behavior);
}

const result = {exposes, fromZigbee, toZigbee};
if (!options.noConfigure) {
result.configure = async (device, coordinatorEndpoint, logger) => {
Expand All @@ -50,14 +60,19 @@ const extend = {
return result;
},
light_onoff_brightness_color: (options={}) => {
options = {disableEffect: false, supportsHS: false, preferHS: false, ...options};
options = {disableEffect: false, supportsHS: false, preferHS: false, disablePowerOnBehavior: false, ...options};
const exposes = [(options.supportsHS ? e.light_brightness_color(options.preferHS) : e.light_brightness_colorxy()),
...(!options.disableEffect ? [e.effect()] : [])];
const fromZigbee = [fz.color_colortemp, fz.on_off, fz.brightness, fz.level_config, fz.power_on_behavior, fz.ignore_basic_report];
const fromZigbee = [fz.color_colortemp, fz.on_off, fz.brightness, fz.level_config, fz.ignore_basic_report];
const toZigbee = [tz.light_onoff_brightness, tz.light_color, tz.ignore_transition, tz.ignore_rate, tz.light_brightness_move,
tz.light_brightness_step, tz.level_config, tz.power_on_behavior, tz.light_hue_saturation_move,
tz.light_brightness_step, tz.level_config, tz.light_hue_saturation_move,
tz.light_hue_saturation_step, tz.light_color_options, tz.light_color_mode, ...(!options.disableEffect ? [tz.effect] : [])];

if (!options.disablePowerOnBehavior) {
fromZigbee.push(fz.power_on_behavior);
toZigbee.push(tz.power_on_behavior);
}

const result = {exposes, fromZigbee, toZigbee};
if (!options.noConfigure) {
result.configure = async (device, coordinatorEndpoint, logger) => {
Expand All @@ -68,21 +83,32 @@ const extend = {
return result;
},
light_onoff_brightness_colortemp_color: (options={}) => {
options = {disableEffect: false, supportsHS: false, disableColorTempStartup: false, preferHS: false, ...options};
options = {
disableEffect: false,
supportsHS: false,
disableColorTempStartup: false,
preferHS: false,
disablePowerOnBehavior: false,
...options};
const exposes = [(options.supportsHS ? e.light_brightness_colortemp_color(options.colorTempRange, options.preferHS) :
e.light_brightness_colortemp_colorxy(options.colorTempRange)), ...(!options.disableEffect ? [e.effect()] : [])];
const fromZigbee = [fz.color_colortemp, fz.on_off, fz.brightness, fz.level_config, fz.power_on_behavior, fz.ignore_basic_report];
const fromZigbee = [fz.color_colortemp, fz.on_off, fz.brightness, fz.level_config, fz.ignore_basic_report];
const toZigbee = [
tz.light_onoff_brightness, tz.light_color_colortemp, tz.ignore_transition, tz.ignore_rate, tz.light_brightness_move,
tz.light_colortemp_move, tz.light_brightness_step, tz.light_colortemp_step, tz.light_hue_saturation_move,
tz.light_hue_saturation_step, tz.light_colortemp_startup, tz.level_config, tz.power_on_behavior, tz.light_color_options,
tz.light_hue_saturation_step, tz.light_colortemp_startup, tz.level_config, tz.light_color_options,
tz.light_color_mode, ...(!options.disableEffect ? [tz.effect] : [])];

if (options.disableColorTempStartup) {
exposes[0].removeFeature('color_temp_startup');
toZigbee.splice(toZigbee.indexOf(tz.light_colortemp_startup), 1);
}

if (!options.disablePowerOnBehavior) {
fromZigbee.push(fz.power_on_behavior);
toZigbee.push(tz.power_on_behavior);
}

const result = {exposes, fromZigbee, toZigbee};
if (!options.noConfigure) {
result.configure = async (device, coordinatorEndpoint, logger) => {
Expand Down

0 comments on commit 73ef708

Please sign in to comment.