From 290358f8c1099ff89cdf1600cea3952fe776b4e8 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Mon, 11 Mar 2024 21:38:33 +0100 Subject: [PATCH 1/2] feat!: Remove legacy extend support --- src/index.ts | 112 +++++++++++++++++----------------------------- src/lib/extend.ts | 23 ---------- src/lib/types.ts | 18 +------- 3 files changed, 43 insertions(+), 110 deletions(-) delete mode 100644 src/lib/extend.ts diff --git a/src/index.ts b/src/index.ts index dc97c1e9b77b7..703e8dcc2b520 100644 --- a/src/index.ts +++ b/src/index.ts @@ -93,86 +93,58 @@ function validateDefinition(definition: Definition) { function processExtensions(definition: Definition): Definition { if ('extend' in definition) { - if (Array.isArray(definition.extend)) { - // Modern extend, merges properties, e.g. when both extend and definition has toZigbee, toZigbee will be combined - let {extend, toZigbee, fromZigbee, exposes, meta, endpoint, configure: definitionConfigure, onEvent, ota, ...definitionWithoutExtend} = definition; - if (typeof exposes === 'function') { - assert.fail(`'${definition.model}' has function exposes which is not allowed`); - } + if (!Array.isArray(definition.extend)) { + assert.fail(`'${definition.model}' has legacy extend which is not supported anymore`); + } + // Modern extend, merges properties, e.g. when both extend and definition has toZigbee, toZigbee will be combined + let {extend, toZigbee, fromZigbee, exposes, meta, endpoint, configure: definitionConfigure, onEvent, ota, ...definitionWithoutExtend} = definition; + if (typeof exposes === 'function') { + assert.fail(`'${definition.model}' has function exposes which is not allowed`); + } - toZigbee = [...toZigbee ?? []]; - fromZigbee = [...fromZigbee ?? []]; - exposes = [...exposes ?? []]; - const configures: Configure[] = definitionConfigure ? [definitionConfigure] : []; + toZigbee = [...toZigbee ?? []]; + fromZigbee = [...fromZigbee ?? []]; + exposes = [...exposes ?? []]; + const configures: Configure[] = definitionConfigure ? [definitionConfigure] : []; - for (const ext of extend) { - if (!ext.isModernExtend) { - assert.fail(`'${definition.model}' has legacy extend in modern extend`); - } - if (ext.toZigbee) toZigbee.push(...ext.toZigbee); - if (ext.fromZigbee) fromZigbee.push(...ext.fromZigbee); - if (ext.exposes) exposes.push(...ext.exposes); - if (ext.meta) meta = {...ext.meta, ...meta}; - if (ext.configure) configures.push(ext.configure); - if (ext.ota) { - if (ota) { - assert.fail(`'${definition.model}' has multiple 'ota', this is not allowed`); - } - ota = ext.ota; - } - if (ext.endpoint) { - if (endpoint) { - assert.fail(`'${definition.model}' has multiple 'endpoint', this is not allowed`); - } - endpoint = ext.endpoint; + for (const ext of extend) { + if (!ext.isModernExtend) { + assert.fail(`'${definition.model}' has legacy extend in modern extend`); + } + if (ext.toZigbee) toZigbee.push(...ext.toZigbee); + if (ext.fromZigbee) fromZigbee.push(...ext.fromZigbee); + if (ext.exposes) exposes.push(...ext.exposes); + if (ext.meta) meta = {...ext.meta, ...meta}; + if (ext.configure) configures.push(ext.configure); + if (ext.ota) { + if (ota) { + assert.fail(`'${definition.model}' has multiple 'ota', this is not allowed`); } - if (ext.onEvent) { - if (onEvent) { - assert.fail(`'${definition.model}' has multiple 'onEvent', this is not allowed`); - } - onEvent = ext.onEvent; + ota = ext.ota; + } + if (ext.endpoint) { + if (endpoint) { + assert.fail(`'${definition.model}' has multiple 'endpoint', this is not allowed`); } + endpoint = ext.endpoint; } - - let configure: Configure = null; - if (configures.length !== 0) { - configure = async (device, coordinatorEndpoint, logger) => { - for (const func of configures) { - await func(device, coordinatorEndpoint, logger); - } + if (ext.onEvent) { + if (onEvent) { + assert.fail(`'${definition.model}' has multiple 'onEvent', this is not allowed`); } + onEvent = ext.onEvent; } - definition = {toZigbee, fromZigbee, exposes, meta, configure, endpoint, onEvent, ota, ...definitionWithoutExtend}; - } else { - // Legacy extend, overrides properties, e.g. when both extend and definition has toZigbee, definition toZigbee will be used - const {extend, ...definitionWithoutExtend} = definition; + } - if (extend.isModernExtend) { - assert.fail(`'${definition.model}' has modern extend in legacy extend`); - } - if (extend.configure && definition.configure) { - assert.fail(`'${definition.model}' has configure in extend and definition, this is not allowed`); - } - if (extend.ota && definition.ota) { - assert.fail(`'${definition.model}' has OTA in extend and definition, this is not allowed`); - } - if (extend.onEvent && definition.onEvent) { - assert.fail(`'${definition.model}' has onEvent in extend and definition, this is not allowed`); - } - if (typeof definition.exposes === 'function') { - assert.fail(`'${definition.model}' has function exposes which is not allowed`); + let configure: Configure = null; + if (configures.length !== 0) { + configure = async (device, coordinatorEndpoint, logger) => { + for (const func of configures) { + await func(device, coordinatorEndpoint, logger); + } } - - const toZigbee = [...definition.toZigbee ?? [], ...extend.toZigbee]; - const fromZigbee = [...definition.fromZigbee ?? [], ...extend.fromZigbee]; - const exposes = [...definition.exposes ?? [], ...extend.exposes]; - const meta = extend.meta || definitionWithoutExtend.meta ? { - ...extend.meta, - ...definitionWithoutExtend.meta, - } : undefined; - - definition = {...extend, toZigbee, fromZigbee, exposes, meta, ...definitionWithoutExtend}; } + definition = {toZigbee, fromZigbee, exposes, meta, configure, endpoint, onEvent, ota, ...definitionWithoutExtend}; } return definition diff --git a/src/lib/extend.ts b/src/lib/extend.ts deleted file mode 100644 index 7588143aabc99..0000000000000 --- a/src/lib/extend.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as exposes from './exposes'; -import tz from '../converters/toZigbee'; -import fz from '../converters/fromZigbee'; -import {Extend} from './types'; -const e = exposes.presets; - -const extend = { - switch: (options: Extend.options_switch={}): Extend => { - options = {disablePowerOnBehavior: false, toZigbee: [], fromZigbee: [], exposes: [], ...options}; - const exposes = [e.switch(), ...options.exposes]; - const fromZigbee = [fz.on_off, fz.ignore_basic_report, ...options.fromZigbee]; - const toZigbee = [tz.on_off, ...options.toZigbee]; - if (!options.disablePowerOnBehavior) { - exposes.push(e.power_on_behavior(['off', 'on', 'toggle', 'previous'])); - fromZigbee.push(fz.power_on_behavior); - toZigbee.push(tz.power_on_behavior); - } - return {exposes, fromZigbee, toZigbee}; - }, -}; - -export default extend; -module.exports = extend; diff --git a/src/lib/types.ts b/src/lib/types.ts index c73542466659f..d986cd9356325 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -159,16 +159,6 @@ export interface DefinitionMeta { export type Configure = (device: Zh.Device, coordinatorEndpoint: Zh.Endpoint, logger: Logger) => Promise; export type OnEvent = (type: OnEventType, data: OnEventData, device: Zh.Device, settings: KeyValue, state: KeyValue) => Promise; -export interface Extend { - fromZigbee: Fz.Converter[], - toZigbee: Tz.Converter[], - exposes: Expose[], - configure?: Configure, - meta?: DefinitionMeta, - ota?: DefinitionOta, - onEvent?: OnEvent, - isModernExtend?: false, -} export interface ModernExtend { fromZigbee?: Fz.Converter[], @@ -208,7 +198,7 @@ export type Definition = { ota?: DefinitionOta, generated?: boolean, } & ({ zigbeeModel: string[] } | { fingerprint: Fingerprint[] }) - & ({ extend: Extend | ModernExtend[], fromZigbee?: Fz.Converter[], toZigbee?: Tz.Converter[], + & ({ extend: ModernExtend[], fromZigbee?: Fz.Converter[], toZigbee?: Tz.Converter[], exposes?: (Expose[] | ((device: Zh.Device | undefined, options: KeyValue | undefined) => Expose[])) } | { fromZigbee: Fz.Converter[], toZigbee: Tz.Converter[], @@ -276,12 +266,6 @@ export namespace Tuya { export type MetaTuyaDataPoints = MetaTuyaDataPointsSingle[]; } -export namespace Extend { - export interface options_switch { - disablePowerOnBehavior?: boolean, toZigbee?: Tz.Converter[], fromZigbee?: Fz.Converter[], exposes?: Expose[] - } -} - export namespace Ota { export type OnProgress = (progress: number, remaining: number) => void; export interface Version {imageType: number, manufacturerCode: number, fileVersion: number} From 9063009e1601da20eca122f5c190b5f2e6fa0bd8 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Mon, 11 Mar 2024 21:45:23 +0100 Subject: [PATCH 2/2] update tests --- test/index.test.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/index.test.js b/test/index.test.js index 1b78c1ea710f7..7cb2e97d85aaa 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -577,12 +577,11 @@ describe('index.js', () => { expect(payload).toStrictEqual({temperature: 3.7}); // For multi endpoint property - const SPP04G = index.findByModel('SPP04G'); - expect(SPP04G.options.map((t) => t.name)).toStrictEqual(['power_calibration', 'power_precision','current_calibration', 'current_precision', - 'voltage_calibration', 'voltage_precision', 'energy_calibration', 'energy_precision', 'state_action']); + const AUA1ZBDSS = index.findByModel('AU-A1ZBDSS'); + expect(AUA1ZBDSS.options.map((t) => t.name)).toStrictEqual(['power_calibration', 'power_precision', 'transition', 'state_action']); payload = {power_left: 5.31}; options = {power_calibration: 100, power_precision: 0}; // calibration for power is percentual - index.postProcessConvertedFromZigbeeMessage(SPP04G, payload, options); + index.postProcessConvertedFromZigbeeMessage(AUA1ZBDSS, payload, options); expect(payload).toStrictEqual({power_left: 11}); const TS011F_plug_1 = index.definitions.find((d) => d.model == 'TS011F_plug_1');