From e5f83afbe74824f69ab7debd8513611e125477f4 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Fri, 10 Jan 2025 20:46:37 +0100 Subject: [PATCH 1/8] fix: Fix configure reporting failing for QBKG20LM https://github.com/Koenkk/zigbee2mqtt/issues/25674 --- src/lib/lumi.ts | 2 ++ src/lib/modernExtend.ts | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib/lumi.ts b/src/lib/lumi.ts index 5aaa539252389..a65864397fa9b 100644 --- a/src/lib/lumi.ts +++ b/src/lib/lumi.ts @@ -1906,6 +1906,7 @@ export const lumiModernExtend = { access: 'ALL', entityCategory: 'config', zigbeeCommandOptions: {manufacturerCode}, + reporting: false, ...args, }), lumiButtonLock: (args?: Partial) => @@ -1932,6 +1933,7 @@ export const lumiModernExtend = { access: 'ALL', entityCategory: 'config', zigbeeCommandOptions: {manufacturerCode}, + reporting: false, ...args, }), lumiPreventReset: (): ModernExtend => { diff --git a/src/lib/modernExtend.ts b/src/lib/modernExtend.ts index 762694b138085..f6e7d43ef189b 100644 --- a/src/lib/modernExtend.ts +++ b/src/lib/modernExtend.ts @@ -2210,7 +2210,7 @@ export interface BinaryArgs { description: string; zigbeeCommandOptions?: {manufacturerCode: number}; endpointName?: string; - reporting?: ReportingConfig; + reporting?: false | ReportingConfig; access?: 'STATE' | 'STATE_GET' | 'STATE_SET' | 'SET' | 'ALL'; entityCategory?: 'config' | 'diagnostic'; } @@ -2258,7 +2258,10 @@ export function binary(args: BinaryArgs): ModernExtend { }, ]; - const configure: Configure[] = [setupConfigureForReporting(cluster, attribute, reporting, access)]; + const configure: Configure[] = []; + if (reporting) { + configure.push(setupConfigureForReporting(cluster, attribute, reporting, access)); + } return {exposes: [expose], fromZigbee, toZigbee, configure, isModernExtend: true}; } From 9c4c27081846d9af49fc44df26444db782c2fc8b Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Fri, 10 Jan 2025 20:48:31 +0100 Subject: [PATCH 2/8] feat(add): Add --- src/converters/fromZigbee.ts | 3 ++- src/converters/toZigbee.ts | 2 +- src/devices/custom_devices_diy.ts | 4 +++- src/lib/exposes.ts | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/converters/fromZigbee.ts b/src/converters/fromZigbee.ts index ad2b4d4043fb4..c04efd4068944 100644 --- a/src/converters/fromZigbee.ts +++ b/src/converters/fromZigbee.ts @@ -488,10 +488,11 @@ const converters1 = { illuminance: { cluster: 'msIlluminanceMeasurement', type: ['attributeReport', 'readResponse'], + options: [exposes.options.illuminance_raw()], convert: (model, msg, publish, options, meta) => { const illuminance = msg.data['measuredValue']; const illuminanceLux = illuminance === 0 ? 0 : Math.pow(10, (illuminance - 1) / 10000); - return {illuminance: illuminanceLux}; + return {illuminance: illuminanceLux, ...(options.illuminance_raw ? {illuminance_raw: illuminance} : {})}; }, } satisfies Fz.Converter, pressure: { diff --git a/src/converters/toZigbee.ts b/src/converters/toZigbee.ts index 1ca0db90ef53d..97b21582eb9ee 100644 --- a/src/converters/toZigbee.ts +++ b/src/converters/toZigbee.ts @@ -1894,7 +1894,7 @@ const converters2 = { }, } satisfies Tz.Converter, illuminance: { - key: ['illuminance'], + key: ['illuminance', 'illuminance_raw'], convertGet: async (entity, key, meta) => { await entity.read('msIlluminanceMeasurement', ['measuredValue']); }, diff --git a/src/devices/custom_devices_diy.ts b/src/devices/custom_devices_diy.ts index 3e87584a0f9d5..9e7964cd21f52 100644 --- a/src/devices/custom_devices_diy.ts +++ b/src/devices/custom_devices_diy.ts @@ -99,13 +99,15 @@ const fzLocal = { illuminance2: { cluster: 'msIlluminanceMeasurement', type: ['attributeReport', 'readResponse'], + options: [exposes.options.illuminance_raw()], convert: (model, msg, publish, options, meta) => { // multi-endpoint version based on the stastard onverter 'fz.illuminance' const illuminance = msg.data['measuredValue']; const illuminanceLux = illuminance === 0 ? 0 : Math.pow(10, (illuminance - 1) / 10000); const multiEndpoint = model.meta && model.meta.multiEndpoint !== undefined && model.meta.multiEndpoint; const property1 = multiEndpoint ? postfixWithEndpointName('illuminance', msg, model, meta) : 'illuminance'; - return {[property1]: illuminanceLux}; + const property2 = multiEndpoint ? postfixWithEndpointName('illuminance_raw', msg, model, meta) : 'illuminance_raw'; + return {[property1]: illuminanceLux, ...(options.illuminance_raw ? {[property2]: illuminance} : {})}; }, } satisfies Fz.Converter, pressure2: { diff --git a/src/lib/exposes.ts b/src/lib/exposes.ts index 809726df637ef..f72d3ad4a975a 100644 --- a/src/lib/exposes.ts +++ b/src/lib/exposes.ts @@ -789,6 +789,7 @@ export const options = { new Binary(`invert_cover`, access.SET, true, false).withDescription( `Inverts the cover position, false: open=100,close=0, true: open=0,close=100 (default false).`, ), + illuminance_raw: () => new Binary(`illuminance_raw`, access.SET, true, false).withDescription(`Expose the raw illuminance value.`), color_sync: () => new Binary(`color_sync`, access.SET, true, false).withDescription( `When enabled colors will be synced, e.g. if the light supports both color x/y and color temperature a conversion from color x/y to color temperature will be done when setting the x/y color (default true).`, From d91c79134c5976c9342e24b4faf8660e6ed94bc5 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Sun, 12 Jan 2025 14:19:30 +0100 Subject: [PATCH 3/8] u --- scripts/modernExtendRefactor.ts | 133 +++++++------------------------- 1 file changed, 29 insertions(+), 104 deletions(-) diff --git a/scripts/modernExtendRefactor.ts b/scripts/modernExtendRefactor.ts index 6467308d8c77b..7e78730ec9ec8 100644 --- a/scripts/modernExtendRefactor.ts +++ b/scripts/modernExtendRefactor.ts @@ -1,3 +1,5 @@ +// In the root of this repo, execute: `npx ts-node scripts/modernExtendRefactor.ts` + import {Project, QuoteKind, SyntaxKind} from 'ts-morph'; const project = new Project({ @@ -15,9 +17,12 @@ project.getSourceFiles().forEach((sourceFile) => { if (sourceFile.getBaseName() === 'index.ts') return; console.log(`Handling ${sourceFile.getBaseName()}`); + if (sourceFile.getBaseName().includes('philips')) { + return; + } + let changed = true; let save = false; - const type = 'mullerLichtLight'; while (changed) { changed = false; const definitions = sourceFile.getVariableStatementOrThrow('definitions').getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression); @@ -27,99 +32,31 @@ project.getSourceFiles().forEach((sourceFile) => { const childs = definition.getChildrenOfKind(SyntaxKind.PropertyAssignment); const model = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'model'); const extend = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'extend'); - // const exposes = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'exposes'); - // const configure = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'configure'); + const extendArray = extend?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression); + const exposes = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'exposes'); + const exposesArray = exposes?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression); + const configure = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'configure'); const fromZigbee = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'fromZigbee'); + const fromZigbeeArray = fromZigbee?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression); const toZigbee = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'toZigbee'); - // const meta = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'meta'); - // const endpoint = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'endpoint'); - - // const ota = childs.find((c) => c.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'ota'); - if (extend?.getFullText().includes('extend.light_onoff') && !fromZigbee && toZigbee?.getFullText().includes('tint_scene')) { - console.log(`Handling ${model?.getFullText().trim()}`); - toZigbee?.remove(); - const newOpts: {[s: string]: unknown} = {}; // {endpoints: eval(`(${endpoint.getFullText().split('return ')[1].split(';')[0]})`)}; - // configure?.remove(); - // endpoint?.remove(); - const extendFeatures = extend.getFullText().split('(')[0].split('_'); - if (extendFeatures.includes('colortemp')) { - newOpts.colorTemp = {range: null}; - } - if (extendFeatures.includes('color')) { - newOpts.color = true; - } - if (extendFeatures.includes('gradient')) { - newOpts.gradient = true; - } - let opts = extend?.getFullText().split('(')[1].slice(0, -1).trim(); - if (opts) { - if (opts[opts.length - 1] === ',') { - opts = opts.substring(0, opts.length - 1); - } - const evalOpts = Object.entries(eval(`(${opts})`)); - for (const [key, value] of evalOpts) { - if (key === 'colorTempRange') { - newOpts.colorTemp = {...(newOpts.colorTemp as object), range: value}; - } else if (key === 'disableColorTempStartup') { - // @ts-expect-error ignore - newOpts.colorTemp = {...newOpts.colorTemp, startup: !value}; - } else if (key === 'disablePowerOnBehavior') { - newOpts.powerOnBehavior = !value; - } else if (key === 'disableEffect') { - newOpts.effect = !value; - } else if (key === 'disableHueEffects') { - newOpts.hueEffect = !value; - } else if (key === 'supportsHueAndSaturation' || key === 'preferHueAndSaturation') { - // @ts-expect-error ignore - newOpts.color = {...newOpts.color, modes: evalOpts.preferHueAndSaturation ? ['hs', 'xy'] : ['xy', 'hs']}; - } else if (key === 'extraEffects') { - // @ts-expect-error ignore - newOpts.gradient = {...newOpts.gradient, extraEffects: value}; - } else if (key === 'noConfigure') { - // ignore - } else { - throw new Error(`Unsupported ${key} - ${value}`); - } - } + const fzIlluminance = fromZigbeeArray?.getElements().find((el) => el.getText() === 'fz.illuminance'); + if (fzIlluminance) { + fromZigbeeArray?.removeElement(fzIlluminance); + const exposesIlluminance = exposesArray?.getElements().find((el) => el.getText() === 'e.illuminance()'); + if (exposesIlluminance) { + exposesArray?.removeElement(exposesIlluminance); } - // if (meta) { - // for (const [key, value] of Object.entries(eval(`(${meta?.getFullText().replace('meta: ', '')})`))) { - // if (key === 'turnsOffAtBrightness1') { - // newOpts.turnsOffAtBrightness1 = value; - // } else if (key === 'applyRedFix') { - // // @ts-expect-error ignore - // newOpts.color = {...newOpts.color, applyRedFix: value}; - // } else if (key === 'supportsEnhancedHue') { - // // @ts-expect-error ignore - // newOpts.color = {...newOpts.color, enhancedHue: value}; - // } else if (key === 'multiEndpoint' || key === 'disableDefaultResponse') { - // // ignore - // } else { - // throw new Error(`Unsupported ${key} - ${value}`); - // } - // } - // // meta.remove(); - // } - // if (ota) { - // ota.remove(); - // } - localTotalDefinitionsWithModernExtend += 1; - extend.replaceWithText( - `extend: [${type}(${JSON.stringify(newOpts) - .split(`"`) - .join('') - .replace(`range:null`, `range:undefined`) - .replace(`xy`, `'xy'`) - .replace(`hs`, `'hs'`) - .replace(`({})`, `()`)})]`, - ); - changed = true; + if (!extend) { + definition.addPropertyAssignment({ + name: 'extend', + initializer: '[m.illuminance()]', + }); + } else { + extendArray?.addElement('m.illuminance()'); + } save = true; - break; - } else if (extend?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression)) { - localTotalDefinitionsWithModernExtend += 1; } } @@ -130,22 +67,10 @@ project.getSourceFiles().forEach((sourceFile) => { } if (save) { - const modernExtendImport = sourceFile - .getImportDeclarations() - .find((d) => d.getModuleSpecifierSourceFile()?.getBaseName() === 'modernExtend.ts'); - if (!modernExtendImport) { - sourceFile.addImportDeclaration({moduleSpecifier: '../lib/modernExtend', namedImports: [type]}); - } else { - if (!modernExtendImport.getNamedImports().find((i) => i.getName() === type)) { - modernExtendImport.addNamedImport(type); - } - } - - const extendImport = sourceFile.getImportDeclarations().find((d) => d.getModuleSpecifierSourceFile()?.getBaseName() === 'extend.ts'); - if (!sourceFile.getFullText().includes('extend.') && extendImport) { - extendImport.remove(); - } - + sourceFile.addImportDeclaration({ + moduleSpecifier: '../lib/modernExtend', + namespaceImport: 'm', + }); sourceFile.saveSync(); } }); From 71da53b9c2d0620cedd57867c7626fea36fdf0d1 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Sun, 12 Jan 2025 20:38:51 +0100 Subject: [PATCH 4/8] u --- src/devices/aurora_lighting.ts | 12 ++++------- src/devices/bosch.ts | 9 ++++---- src/devices/ctm.ts | 36 +++++++------------------------ src/devices/custom_devices_diy.ts | 28 ++++++++---------------- src/devices/datek.ts | 7 +++--- src/devices/diyruz.ts | 7 +++--- src/devices/fantem.ts | 5 +++-- src/devices/heiman.ts | 9 ++++---- src/devices/hzc_electric.ts | 6 ++++-- src/devices/immax.ts | 13 +++++------ src/devices/kmpcil.ts | 13 +++++------ src/devices/konke.ts | 6 ++++-- src/devices/leedarson.ts | 11 ++++++---- src/devices/lumi.ts | 20 ++++++----------- src/devices/moes.ts | 6 ++++-- src/devices/namron.ts | 8 +++---- src/devices/owon.ts | 8 +++---- src/devices/schneider_electric.ts | 9 ++++---- src/devices/sercomm.ts | 9 ++++---- src/devices/shinasystem.ts | 9 ++++---- src/devices/terncy.ts | 6 ++++-- src/devices/third_reality.ts | 6 ++++-- src/devices/tplink.ts | 9 ++++---- src/devices/tuya.ts | 31 +++++++++++++++----------- src/devices/wirenboard.ts | 6 ++---- src/lib/modernExtend.ts | 7 ++++-- 26 files changed, 136 insertions(+), 160 deletions(-) diff --git a/src/devices/aurora_lighting.ts b/src/devices/aurora_lighting.ts index c1fdf6df6435f..221ee81ae6fe9 100644 --- a/src/devices/aurora_lighting.ts +++ b/src/devices/aurora_lighting.ts @@ -2,6 +2,7 @@ import fz from '../converters/fromZigbee'; import tz from '../converters/toZigbee'; import * as exposes from '../lib/exposes'; import {identify, light} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {Configure, DefinitionWithExtend, Fz, OnEvent, Tz, Zh} from '../lib/types'; import * as utils from '../lib/utils'; @@ -176,14 +177,9 @@ const definitions: DefinitionWithExtend[] = [ model: 'AU-A1ZBPIRS', vendor: 'Aurora Lighting', description: 'AOne PIR sensor', - fromZigbee: [fz.ias_occupancy_alarm_1, fz.illuminance], - toZigbee: [], - configure: async (device, coordinatorEndpoint) => { - const endpoint = device.getEndpoint(39); - await reporting.bind(endpoint, coordinatorEndpoint, ['msIlluminanceMeasurement']); - await reporting.illuminance(endpoint); - }, - exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.illuminance()], + fromZigbee: [fz.ias_occupancy_alarm_1], + exposes: [e.occupancy(), e.battery_low(), e.tamper()], + extend: [m.illuminance()], }, { zigbeeModel: ['SingleSocket50AU'], diff --git a/src/devices/bosch.ts b/src/devices/bosch.ts index fc3f743f9da4c..30dcd8851d147 100644 --- a/src/devices/bosch.ts +++ b/src/devices/bosch.ts @@ -21,6 +21,7 @@ import { onOff, quirkCheckinInterval, } from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as globalStore from '../lib/store'; import {DefinitionWithExtend, Expose, Fz, KeyValue, ModernExtend, Tz} from '../lib/types'; @@ -1321,17 +1322,17 @@ const definitions: DefinitionWithExtend[] = [ model: 'RADON TriTech ZB', vendor: 'Bosch', description: 'Wireless motion detector', - fromZigbee: [fz.temperature, fz.battery, fz.ias_occupancy_alarm_1, fz.illuminance], + fromZigbee: [fz.temperature, fz.battery, fz.ias_occupancy_alarm_1], toZigbee: [], meta: {battery: {voltageToPercentage: {min: 2500, max: 3000}}}, configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); - await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'genPowerCfg', 'msIlluminanceMeasurement']); + await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'genPowerCfg']); await reporting.temperature(endpoint); await reporting.batteryVoltage(endpoint); - await reporting.illuminance(endpoint); }, - exposes: [e.temperature(), e.battery(), e.occupancy(), e.battery_low(), e.tamper(), e.illuminance()], + exposes: [e.temperature(), e.battery(), e.occupancy(), e.battery_low(), e.tamper()], + extend: [m.illuminance()], }, { zigbeeModel: ['ISW-ZPR1-WP13'], diff --git a/src/devices/ctm.ts b/src/devices/ctm.ts index ac23c19df1fbf..f2c2ea4b8bbb6 100644 --- a/src/devices/ctm.ts +++ b/src/devices/ctm.ts @@ -5,6 +5,7 @@ import tz from '../converters/toZigbee'; import * as constants from '../lib/constants'; import * as exposes from '../lib/exposes'; import {battery, identify, light, temperature} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend, Fz, KeyValue, Tz} from '../lib/types'; import * as utils from '../lib/utils'; @@ -1255,17 +1256,15 @@ const definitions: DefinitionWithExtend[] = [ model: 'MBD-S', vendor: 'CTM Lyng', description: 'MBD-S, motion detector with 16A relay', - fromZigbee: [fz.illuminance, fz.occupancy, fzLocal.ctm_mbd_device_enabled, fzLocal.ctm_relay_state], + fromZigbee: [fz.occupancy, fzLocal.ctm_mbd_device_enabled, fzLocal.ctm_relay_state], toZigbee: [tzLocal.ctm_mbd_device_enabled, tzLocal.ctm_relay_state], meta: {disableDefaultResponse: true}, ota: true, configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); - await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'msIlluminanceMeasurement', 'msOccupancySensing']); + await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'msOccupancySensing']); await endpoint.read('genOnOff', ['onOff']); await reporting.onOff(endpoint); - await endpoint.read('msIlluminanceMeasurement', ['measuredValue']); - await reporting.illuminance(endpoint); await endpoint.read('msOccupancySensing', ['occupancy']); await reporting.occupancy(endpoint); // Relay State @@ -1283,37 +1282,20 @@ const definitions: DefinitionWithExtend[] = [ {manufacturerCode: Zcl.ManufacturerCode.DATEK_WIRELESS_AS}, ); }, - exposes: [ - e.switch(), - e.illuminance(), - e.occupancy(), - e.binary('device_enabled', ea.ALL, 'ON', 'OFF').withDescription('Turn the device on or off'), - ], + exposes: [e.switch(), e.occupancy(), e.binary('device_enabled', ea.ALL, 'ON', 'OFF').withDescription('Turn the device on or off')], + extend: [m.illuminance()], }, { zigbeeModel: ['MBD Dim'], model: 'CTM_MBD_Dim', vendor: 'CTM Lyng', description: 'MBD Dim, motion detector with dimmer', - fromZigbee: [ - fz.illuminance, - fz.occupancy, - fzLocal.ctm_mbd_device_enabled, - fzLocal.ctm_relay_state, - fz.brightness, - fz.lighting_ballast_configuration, - ], + fromZigbee: [fz.occupancy, fzLocal.ctm_mbd_device_enabled, fzLocal.ctm_relay_state, fz.brightness, fz.lighting_ballast_configuration], toZigbee: [tzLocal.ctm_mbd_device_enabled, tzLocal.ctm_relay_state, tzLocal.ctm_mbd_brightness, tz.ballast_config], meta: {disableDefaultResponse: true}, configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); - await reporting.bind(endpoint, coordinatorEndpoint, [ - 'genOnOff', - 'genLevelCtrl', - 'lightingBallastCfg', - 'msIlluminanceMeasurement', - 'msOccupancySensing', - ]); + await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'lightingBallastCfg', 'msOccupancySensing']); await endpoint.read('genOnOff', ['onOff']); await reporting.onOff(endpoint); await endpoint.read('genLevelCtrl', ['currentLevel']); @@ -1343,8 +1325,6 @@ const definitions: DefinitionWithExtend[] = [ reportableChange: null, }, ]); - await endpoint.read('msIlluminanceMeasurement', ['measuredValue']); - await reporting.illuminance(endpoint); await endpoint.read('msOccupancySensing', ['occupancy']); await reporting.occupancy(endpoint); // Relay State @@ -1364,7 +1344,6 @@ const definitions: DefinitionWithExtend[] = [ }, exposes: [ e.light_brightness(), - e.illuminance(), e.occupancy(), e.binary('device_enabled', ea.ALL, 'ON', 'OFF').withDescription('Turn the device on or off'), e.numeric('ballast_minimum_level', ea.ALL).withValueMin(10).withValueMax(97).withDescription('Specifies the minimum brightness value'), @@ -1375,6 +1354,7 @@ const definitions: DefinitionWithExtend[] = [ .withValueMax(97) .withDescription('Specifies the initialisation light level. Can not be set lower than "ballast_minimum_level"'), ], + extend: [m.illuminance()], }, { fingerprint: [{modelID: 'DIMMER', manufacturerName: 'NorLum Dim OP'}], diff --git a/src/devices/custom_devices_diy.ts b/src/devices/custom_devices_diy.ts index 9e7964cd21f52..347f95b162d2f 100644 --- a/src/devices/custom_devices_diy.ts +++ b/src/devices/custom_devices_diy.ts @@ -19,6 +19,7 @@ import { quirkAddEndpointCluster, temperature, } from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend, Expose, Fz, KeyValue, KeyValueAny, Tz, Zh} from '../lib/types'; import {getFromLookup, getKey, isEndpoint, postfixWithEndpointName} from '../lib/utils'; @@ -696,25 +697,20 @@ const definitions: DefinitionWithExtend[] = [ model: 'ZeeFlora', vendor: 'Custom devices (DiY)', description: 'Flower sensor with rechargeable battery', - fromZigbee: [fz.temperature, fz.illuminance, fz.soil_moisture, fz.battery], + fromZigbee: [fz.temperature, fz.soil_moisture, fz.battery], toZigbee: [], meta: {multiEndpoint: true}, configure: async (device, coordinatorEndpoint) => { const firstEndpoint = device.getEndpoint(1); - await reporting.bind(firstEndpoint, coordinatorEndpoint, [ - 'genPowerCfg', - 'msTemperatureMeasurement', - 'msIlluminanceMeasurement', - 'msSoilMoisture', - ]); + await reporting.bind(firstEndpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 'msSoilMoisture']); const overrides = {min: 0, max: 3600, change: 0}; await reporting.batteryVoltage(firstEndpoint, overrides); await reporting.batteryPercentageRemaining(firstEndpoint, overrides); await reporting.temperature(firstEndpoint, overrides); - await reporting.illuminance(firstEndpoint, overrides); await reporting.soil_moisture(firstEndpoint, overrides); }, - exposes: [e.soil_moisture(), e.battery(), e.illuminance(), e.temperature()], + exposes: [e.soil_moisture(), e.battery(), e.temperature()], + extend: [m.illuminance()], }, { zigbeeModel: ['UT-01'], @@ -737,24 +733,18 @@ const definitions: DefinitionWithExtend[] = [ model: 'b-parasite', vendor: 'Custom devices (DiY)', description: 'b-parasite open source soil moisture sensor', - fromZigbee: [fz.temperature, fz.humidity, fz.battery, fz.soil_moisture, fz.illuminance], + fromZigbee: [fz.temperature, fz.humidity, fz.battery, fz.soil_moisture], toZigbee: [], - exposes: [e.temperature(), e.humidity(), e.battery(), e.soil_moisture(), e.illuminance()], + exposes: [e.temperature(), e.humidity(), e.battery(), e.soil_moisture()], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(10); - await reporting.bind(endpoint, coordinatorEndpoint, [ - 'genPowerCfg', - 'msTemperatureMeasurement', - 'msRelativeHumidity', - 'msSoilMoisture', - 'msIlluminanceMeasurement', - ]); + await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity', 'msSoilMoisture']); await reporting.batteryPercentageRemaining(endpoint); await reporting.temperature(endpoint); await reporting.humidity(endpoint); await reporting.soil_moisture(endpoint); - await reporting.illuminance(endpoint); }, + extend: [m.illuminance()], }, { zigbeeModel: ['MULTI-ZIG-SW'], diff --git a/src/devices/datek.ts b/src/devices/datek.ts index 2220701f247f3..caac95a618407 100644 --- a/src/devices/datek.ts +++ b/src/devices/datek.ts @@ -6,6 +6,7 @@ import * as constants from '../lib/constants'; import {repInterval} from '../lib/constants'; import * as exposes from '../lib/exposes'; import {electricityMeter, temperature} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend} from '../lib/types'; @@ -74,7 +75,6 @@ const definitions: DefinitionWithExtend[] = [ fz.battery, fz.occupancy, fz.occupancy_timeout, - fz.illuminance, fz.temperature, fz.ias_enroll, fz.ias_occupancy_alarm_1, @@ -85,11 +85,10 @@ const definitions: DefinitionWithExtend[] = [ configure: async (device, coordinatorEndpoint) => { const options = {manufacturerCode: Zcl.ManufacturerCode.DATEK_WIRELESS_AS}; const endpoint = device.getEndpoint(1); - const binds = ['msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing', 'ssIasZone']; + const binds = ['msTemperatureMeasurement', 'msOccupancySensing', 'ssIasZone']; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.occupancy(endpoint); await reporting.temperature(endpoint); - await reporting.illuminance(endpoint); const payload = [ { attribute: {ID: 0x4000, type: 0x10}, @@ -105,10 +104,10 @@ const definitions: DefinitionWithExtend[] = [ e.temperature(), e.occupancy(), e.battery_low(), - e.illuminance(), e.binary('led_on_motion', ea.ALL, true, false).withDescription('Enable/disable LED on motion'), e.numeric('occupancy_timeout', ea.ALL).withUnit('s').withValueMin(0).withValueMax(65535), ], + extend: [m.illuminance()], }, { zigbeeModel: ['ID Lock 150', 'ID Lock 202'], diff --git a/src/devices/diyruz.ts b/src/devices/diyruz.ts index 9469547e16c33..0acd799190b0d 100644 --- a/src/devices/diyruz.ts +++ b/src/devices/diyruz.ts @@ -3,6 +3,7 @@ import tz from '../converters/toZigbee'; import * as constants from '../lib/constants'; import * as exposes from '../lib/exposes'; import {deviceEndpoints, onOff} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend} from '../lib/types'; @@ -257,7 +258,7 @@ const definitions: DefinitionWithExtend[] = [ model: 'DIYRuZ_Flower', vendor: 'DIYRuZ', description: 'Flower sensor', - fromZigbee: [fz.temperature, fz.humidity, fz.illuminance, fz.soil_moisture, fz.pressure, fz.battery], + fromZigbee: [fz.temperature, fz.humidity, fz.soil_moisture, fz.pressure, fz.battery], toZigbee: [], meta: {multiEndpoint: true, multiEndpointSkip: ['humidity']}, endpoint: (device) => { @@ -271,7 +272,6 @@ const definitions: DefinitionWithExtend[] = [ 'msTemperatureMeasurement', 'msRelativeHumidity', 'msPressureMeasurement', - 'msIlluminanceMeasurement', 'msSoilMoisture', ]); await reporting.bind(secondEndpoint, coordinatorEndpoint, ['msTemperatureMeasurement']); @@ -281,7 +281,6 @@ const definitions: DefinitionWithExtend[] = [ await reporting.temperature(firstEndpoint, overrides); await reporting.humidity(firstEndpoint, overrides); await reporting.pressureExtended(firstEndpoint, overrides); - await reporting.illuminance(firstEndpoint, overrides); await reporting.soil_moisture(firstEndpoint, overrides); await reporting.temperature(secondEndpoint, overrides); await firstEndpoint.read('msPressureMeasurement', ['scale']); @@ -289,12 +288,12 @@ const definitions: DefinitionWithExtend[] = [ exposes: [ e.soil_moisture(), e.battery(), - e.illuminance(), e.humidity(), e.pressure(), e.temperature().withEndpoint('ds'), e.temperature().withEndpoint('bme'), ], + extend: [m.illuminance()], }, { zigbeeModel: ['DIYRuZ_AirSense'], diff --git a/src/devices/fantem.ts b/src/devices/fantem.ts index 788fe93e42921..a633c51542401 100644 --- a/src/devices/fantem.ts +++ b/src/devices/fantem.ts @@ -2,6 +2,7 @@ import fz from '../converters/fromZigbee'; import * as exposes from '../lib/exposes'; import * as legacy from '../lib/legacy'; import {light} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as tuya from '../lib/tuya'; import {DefinitionWithExtend} from '../lib/types'; @@ -44,13 +45,12 @@ const definitions: DefinitionWithExtend[] = [ model: 'ZB003-X', vendor: 'Fantem', description: '4 in 1 multi sensor', - fromZigbee: [fz.battery, fz.ignore_basic_report, fz.illuminance, legacy.fz.ZB003X, fz.ZB003X_attr, fz.ZB003X_occupancy], + fromZigbee: [fz.battery, fz.ignore_basic_report, legacy.fz.ZB003X, fz.ZB003X_attr, fz.ZB003X_occupancy], toZigbee: [legacy.tz.ZB003X], whiteLabel: [tuya.whitelabel('EFK', 'is-thpl-zb', '4 in 1 multi sensor', ['_TZ3210_0aqbrnts'])], exposes: [ e.occupancy(), e.tamper(), - e.illuminance(), e.temperature(), e.humidity(), e.battery(), @@ -76,6 +76,7 @@ const definitions: DefinitionWithExtend[] = [ e.enum('sensitivity', ea.STATE_SET, ['low', 'medium', 'high']).withDescription('PIR sensor sensitivity'), e.enum('keep_time', ea.STATE_SET, ['0', '30', '60', '120', '240', '480']).withDescription('PIR keep time in seconds'), ], + extend: [m.illuminance()], }, ]; diff --git a/src/devices/heiman.ts b/src/devices/heiman.ts index 849782b428c3c..04273903947c9 100644 --- a/src/devices/heiman.ts +++ b/src/devices/heiman.ts @@ -3,6 +3,7 @@ import tz from '../converters/toZigbee'; import * as constants from '../lib/constants'; import * as exposes from '../lib/exposes'; import {battery, iasZoneAlarm, light} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as tuya from '../lib/tuya'; import {DefinitionWithExtend, Reporting, Zh} from '../lib/types'; @@ -16,17 +17,15 @@ const definitions: DefinitionWithExtend[] = [ model: 'HS1MIS-3.0', vendor: 'HEIMAN', description: 'Smart occupancy sensor', - fromZigbee: [fz.occupancy, fz.battery, fz.illuminance], - toZigbee: [], - exposes: [e.occupancy(), e.battery(), e.illuminance()], + fromZigbee: [fz.occupancy, fz.battery], + exposes: [e.occupancy(), e.battery()], configure: async (device, cordinatorEndpoint) => { const endpoint1 = device.getEndpoint(1); await reporting.bind(endpoint1, cordinatorEndpoint, ['msOccupancySensing', 'genPowerCfg']); await reporting.batteryPercentageRemaining(endpoint1); await reporting.occupancy(endpoint1); - await reporting.bind(endpoint1, cordinatorEndpoint, ['msIlluminanceMeasurement']); - await reporting.illuminance(endpoint1); }, + extend: [m.illuminance()], }, { fingerprint: [{modelID: 'TS0212', manufacturerName: '_TYZB01_wpmo3ja3'}], diff --git a/src/devices/hzc_electric.ts b/src/devices/hzc_electric.ts index f48c1f22ed632..230a9190d446e 100644 --- a/src/devices/hzc_electric.ts +++ b/src/devices/hzc_electric.ts @@ -1,6 +1,7 @@ import fz from '../converters/fromZigbee'; import * as exposes from '../lib/exposes'; import {deviceEndpoints, electricityMeter, light} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend} from '../lib/types'; @@ -42,9 +43,10 @@ const definitions: DefinitionWithExtend[] = [ model: 'S902M-ZG', vendor: 'HZC Electric', description: 'Motion sensor', - fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.illuminance], + fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery], toZigbee: [], - exposes: [e.occupancy(), e.battery_low(), e.battery(), e.illuminance(), e.tamper()], + exposes: [e.occupancy(), e.battery_low(), e.battery(), e.tamper()], + extend: [m.illuminance()], }, { fingerprint: [{type: 'Router', manufacturerName: 'Shyugj', modelID: 'Dimmer-Switch-ZB3.0'}], diff --git a/src/devices/immax.ts b/src/devices/immax.ts index 46364e81cb968..ceff48fe34cf7 100644 --- a/src/devices/immax.ts +++ b/src/devices/immax.ts @@ -3,6 +3,7 @@ import tz from '../converters/toZigbee'; import * as exposes from '../lib/exposes'; import * as legacy from '../lib/legacy'; import {light} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as tuya from '../lib/tuya'; import {DefinitionWithExtend} from '../lib/types'; @@ -183,17 +184,17 @@ const definitions: DefinitionWithExtend[] = [ model: '07047L', vendor: 'Immax', description: 'Intelligent motion sensor', - fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.temperature, fz.illuminance, fz.humidity, fz.ignore_iaszone_report], + fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.temperature, fz.humidity, fz.ignore_iaszone_report], toZigbee: [], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); - const binds = ['msTemperatureMeasurement', 'msRelativeHumidity', 'msIlluminanceMeasurement']; + const binds = ['msTemperatureMeasurement', 'msRelativeHumidity']; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.temperature(endpoint); await reporting.humidity(endpoint); - await reporting.illuminance(endpoint); }, - exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(), e.temperature(), e.illuminance(), e.humidity()], + exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(), e.temperature(), e.humidity()], + extend: [m.illuminance()], }, { zigbeeModel: ['ColorTemperature'], @@ -215,13 +216,12 @@ const definitions: DefinitionWithExtend[] = [ model: '07502L', vendor: 'Immax', description: '4 in 1 multi sensor', - fromZigbee: [fz.battery, fz.ignore_basic_report, fz.illuminance, legacy.fz.ZB003X, fz.ZB003X_attr, fz.ZB003X_occupancy], + fromZigbee: [fz.battery, fz.ignore_basic_report, legacy.fz.ZB003X, fz.ZB003X_attr, fz.ZB003X_occupancy], toZigbee: [legacy.tz.ZB003X], exposes: [ e.occupancy(), e.tamper(), e.battery(), - e.illuminance(), e.temperature(), e.humidity(), e.numeric('reporting_time', ea.STATE_SET).withDescription('Reporting interval in minutes').withValueMin(0).withValueMax(1440), @@ -234,6 +234,7 @@ const definitions: DefinitionWithExtend[] = [ e.enum('sensitivity', ea.STATE_SET, ['low', 'medium', 'high']).withDescription('PIR sensor sensitivity'), e.enum('keep_time', ea.STATE_SET, ['0', '30', '60', '120', '240']).withDescription('PIR keep time in seconds'), ], + extend: [m.illuminance()], }, { fingerprint: tuya.fingerprint('TS0601', ['_TZE200_n9clpsht', '_TZE200_nyvavzbj', '_TZE200_moycceze']), diff --git a/src/devices/kmpcil.ts b/src/devices/kmpcil.ts index 150e363f834e7..e1b505355cb01 100644 --- a/src/devices/kmpcil.ts +++ b/src/devices/kmpcil.ts @@ -4,6 +4,7 @@ import fz from '../converters/fromZigbee'; import tz from '../converters/toZigbee'; import * as constants from '../lib/constants'; import * as exposes from '../lib/exposes'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as globalStore from '../lib/store'; import {DefinitionWithExtend, Fz, KeyValue, Publish} from '../lib/types'; @@ -84,9 +85,9 @@ const definitions: DefinitionWithExtend[] = [ model: 'KMPCIL_RES005', vendor: 'KMPCIL', description: 'Environment sensor', - exposes: [e.battery(), e.temperature(), e.humidity(), e.pressure(), e.illuminance().withAccess(ea.STATE_GET), e.occupancy(), e.switch()], - fromZigbee: [fz.battery, fz.temperature, fz.humidity, fz.pressure, fz.illuminance, fz.kmpcil_res005_occupancy, fz.kmpcil_res005_on_off], - toZigbee: [tz.kmpcil_res005_on_off, tz.illuminance], + exposes: [e.battery(), e.temperature(), e.humidity(), e.pressure(), e.occupancy(), e.switch()], + fromZigbee: [fz.battery, fz.temperature, fz.humidity, fz.pressure, fz.kmpcil_res005_occupancy, fz.kmpcil_res005_on_off], + toZigbee: [tz.kmpcil_res005_on_off], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(8); const binds = [ @@ -94,7 +95,6 @@ const definitions: DefinitionWithExtend[] = [ 'msTemperatureMeasurement', 'msRelativeHumidity', 'msPressureMeasurement', - 'msIlluminanceMeasurement', 'genBinaryInput', 'genBinaryOutput', ]; @@ -110,10 +110,6 @@ const definitions: DefinitionWithExtend[] = [ }, ]; await endpoint.configureReporting('genPowerCfg', payloadBattery); - const payload = [ - {attribute: 'measuredValue', minimumReportInterval: 5, maximumReportInterval: constants.repInterval.HOUR, reportableChange: 200}, - ]; - await endpoint.configureReporting('msIlluminanceMeasurement', payload); const payloadPressure = [ { // 0 = measuredValue, override dataType from int16 to uint16 @@ -148,6 +144,7 @@ const definitions: DefinitionWithExtend[] = [ ]; await endpoint.configureReporting('genBinaryOutput', payloadBinaryOutput); }, + extend: [m.illuminance()], }, { zigbeeModel: ['tagv1'], diff --git a/src/devices/konke.ts b/src/devices/konke.ts index f4f94c477dd0f..853fa053ff9fd 100644 --- a/src/devices/konke.ts +++ b/src/devices/konke.ts @@ -1,6 +1,7 @@ import fz from '../converters/fromZigbee'; import * as exposes from '../lib/exposes'; import {deviceEndpoints, light, onOff} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend, Fz} from '../lib/types'; import * as utils from '../lib/utils'; @@ -101,9 +102,10 @@ const definitions: DefinitionWithExtend[] = [ model: 'KK-ES-J01W', vendor: 'Konke', description: 'Temperature, relative humidity and illuminance sensor', - fromZigbee: [fz.battery, fz.illuminance, fz.humidity, fz.temperature], + fromZigbee: [fz.battery, fz.humidity, fz.temperature], toZigbee: [], - exposes: [e.battery(), e.battery_voltage(), e.illuminance(), e.humidity(), e.temperature()], + exposes: [e.battery(), e.battery_voltage(), e.humidity(), e.temperature()], + extend: [m.illuminance()], }, { zigbeeModel: ['3AFE241000040002'], diff --git a/src/devices/leedarson.ts b/src/devices/leedarson.ts index bd7d8d0ff65fa..7d9deb835d283 100644 --- a/src/devices/leedarson.ts +++ b/src/devices/leedarson.ts @@ -1,6 +1,7 @@ import fz from '../converters/fromZigbee'; import * as exposes from '../lib/exposes'; import {light} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend} from '../lib/types'; @@ -103,18 +104,20 @@ const definitions: DefinitionWithExtend[] = [ model: '5AA-SS-ZA-H0', vendor: 'Leedarson', description: 'Motion sensor', - fromZigbee: [fz.occupancy, fz.illuminance, fz.ignore_occupancy_report], + fromZigbee: [fz.occupancy, fz.ignore_occupancy_report], toZigbee: [], - exposes: [e.occupancy(), e.illuminance()], + exposes: [e.occupancy()], + extend: [m.illuminance()], }, { zigbeeModel: ['ZB-SMART-PIRTH-V1'], model: '7A-SS-ZABC-H0', vendor: 'Leedarson', description: '4-in-1-Sensor', - fromZigbee: [fz.battery, fz.ias_occupancy_alarm_1, fz.illuminance, fz.temperature, fz.humidity, fz.ignore_occupancy_report], + fromZigbee: [fz.battery, fz.ias_occupancy_alarm_1, fz.temperature, fz.humidity, fz.ignore_occupancy_report], toZigbee: [], - exposes: [e.battery(), e.occupancy(), e.temperature(), e.illuminance(), e.humidity()], + exposes: [e.battery(), e.occupancy(), e.temperature(), e.humidity()], + extend: [m.illuminance()], }, { zigbeeModel: ['ZB-MotionSensor-S0000'], diff --git a/src/devices/lumi.ts b/src/devices/lumi.ts index dfed086701b48..ce967236acf7d 100644 --- a/src/devices/lumi.ts +++ b/src/devices/lumi.ts @@ -1,6 +1,5 @@ import fz from '../converters/fromZigbee'; import tz from '../converters/toZigbee'; -import * as constants from '../lib/constants'; import * as exposes from '../lib/exposes'; import {logger} from '../lib/logger'; import * as lumi from '../lib/lumi'; @@ -22,6 +21,7 @@ import { temperature, windowCovering, } from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as globalStore from '../lib/store'; import {DefinitionWithExtend} from '../lib/types'; @@ -2994,17 +2994,10 @@ const definitions: DefinitionWithExtend[] = [ vendor: 'Xiaomi', whiteLabel: [{vendor: 'Xiaomi', model: 'YTC4043GL'}], description: 'Mi light sensor', - fromZigbee: [fz.battery, fz.illuminance, lumi.fromZigbee.lumi_specific], - toZigbee: [tz.illuminance], + fromZigbee: [fz.battery, lumi.fromZigbee.lumi_specific], meta: {battery: {voltageToPercentage: {min: 2850, max: 3000}}}, - extend: [quirkCheckinInterval('1_HOUR')], - configure: async (device, coordinatorEndpoint) => { - const endpoint = device.getEndpoint(1); - await reporting.bind(endpoint, coordinatorEndpoint, ['msIlluminanceMeasurement']); - await reporting.illuminance(endpoint, {min: 15, max: constants.repInterval.HOUR, change: 500}); - await endpoint.read('genPowerCfg', ['batteryVoltage']); - }, - exposes: [e.battery(), e.battery_voltage(), e.illuminance().withAccess(ea.STATE_GET)], + extend: [quirkCheckinInterval('1_HOUR'), m.illuminance()], + exposes: [e.battery(), e.battery_voltage()], }, { zigbeeModel: ['lumi.light.acn128'], @@ -3530,13 +3523,12 @@ const definitions: DefinitionWithExtend[] = [ model: 'GZCGQ11LM', vendor: 'Aqara', description: 'Light sensor T1', - fromZigbee: [fz.battery, fz.illuminance, lumi.fromZigbee.lumi_specific], + fromZigbee: [fz.battery, lumi.fromZigbee.lumi_specific], toZigbee: [lumi.toZigbee.lumi_detection_period], meta: {battery: {voltageToPercentage: {min: 2850, max: 3000}}}, exposes: [ e.battery(), e.battery_voltage(), - e.illuminance(), e .numeric('detection_period', exposes.access.ALL) .withValueMin(1) @@ -3549,7 +3541,7 @@ const definitions: DefinitionWithExtend[] = [ await device.getEndpoint(1).write('manuSpecificLumi', {mode: 1}, {manufacturerCode: manufacturerCode, disableResponse: true}); await endpoint.read('manuSpecificLumi', [0x0000], {manufacturerCode: manufacturerCode}); }, - extend: [quirkCheckinInterval('1_HOUR'), lumiZigbeeOTA()], + extend: [quirkCheckinInterval('1_HOUR'), lumiZigbeeOTA(), m.illuminance({reporting: false})], }, { zigbeeModel: ['lumi.plug.sacn03'], diff --git a/src/devices/moes.ts b/src/devices/moes.ts index 6eae185ef1736..49243ecb91b07 100644 --- a/src/devices/moes.ts +++ b/src/devices/moes.ts @@ -3,6 +3,7 @@ import tz from '../converters/toZigbee'; import * as exposes from '../lib/exposes'; import * as legacy from '../lib/legacy'; import {actionEnumLookup, battery, deviceEndpoints, onOff} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as tuya from '../lib/tuya'; import {DefinitionWithExtend} from '../lib/types'; @@ -313,9 +314,10 @@ const definitions: DefinitionWithExtend[] = [ model: 'ZSS-ZK-THL', vendor: 'Moes', description: 'Smart temperature and humidity meter with display', - fromZigbee: [fz.battery, fz.illuminance, fz.humidity, fz.temperature], + fromZigbee: [fz.battery, fz.humidity, fz.temperature], toZigbee: [], - exposes: [e.battery(), e.illuminance(), e.humidity(), e.temperature()], + exposes: [e.battery(), e.humidity(), e.temperature()], + extend: [m.illuminance()], }, { fingerprint: [ diff --git a/src/devices/namron.ts b/src/devices/namron.ts index f697f39d6f5da..3cfa2a80d5610 100644 --- a/src/devices/namron.ts +++ b/src/devices/namron.ts @@ -5,6 +5,7 @@ import tz from '../converters/toZigbee'; import * as constants from '../lib/constants'; import * as exposes from '../lib/exposes'; import {binary, electricityMeter, enumLookup, forcePowerSource, light, numeric, onOff} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as globalStore from '../lib/store'; import * as tuya from '../lib/tuya'; @@ -1383,18 +1384,17 @@ const definitions: DefinitionWithExtend[] = [ model: '4512770', vendor: 'Namron', description: 'Zigbee multisensor (white)', - fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.temperature, fz.humidity, fz.illuminance], + fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.temperature, fz.humidity], toZigbee: [], - exposes: [e.occupancy(), e.battery(), e.battery_voltage(), e.illuminance(), e.temperature(), e.humidity()], + exposes: [e.occupancy(), e.battery(), e.battery_voltage(), e.temperature(), e.humidity()], whiteLabel: [{vendor: 'Namron', model: '4512771', description: 'Zigbee multisensor (black)', fingerprint: [{modelID: '4512771'}]}], configure: async (device, coordinatorEndpoint) => { const endpoint3 = device.getEndpoint(3); const endpoint4 = device.getEndpoint(4); - const endpoint5 = device.getEndpoint(5); await reporting.bind(endpoint3, coordinatorEndpoint, ['msTemperatureMeasurement']); await reporting.bind(endpoint4, coordinatorEndpoint, ['msRelativeHumidity']); - await reporting.bind(endpoint5, coordinatorEndpoint, ['msIlluminanceMeasurement']); }, + extend: [m.illuminance()], }, { fingerprint: tuya.fingerprint('TS0601', ['_TZE204_p3lqqy2r']), diff --git a/src/devices/owon.ts b/src/devices/owon.ts index c46c208a68e33..bf380390c6bf2 100644 --- a/src/devices/owon.ts +++ b/src/devices/owon.ts @@ -2,6 +2,7 @@ import fz from '../converters/fromZigbee'; import tz from '../converters/toZigbee'; import * as exposes from '../lib/exposes'; import {battery, electricityMeter, forcePowerSource, iasZoneAlarm, onOff} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend, Fz, KeyValue, Tz} from '../lib/types'; @@ -162,22 +163,21 @@ const definitions: DefinitionWithExtend[] = [ model: 'PIR313-E', vendor: 'OWON', description: 'Motion sensor', - fromZigbee: [fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1, fz.temperature, fz.humidity, fz.occupancy_timeout, fz.illuminance], + fromZigbee: [fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1, fz.temperature, fz.humidity, fz.occupancy_timeout], toZigbee: [], - exposes: [e.occupancy(), e.tamper(), e.battery_low(), e.illuminance(), e.temperature(), e.humidity()], + exposes: [e.occupancy(), e.tamper(), e.battery_low(), e.temperature(), e.humidity()], configure: async (device, coordinatorEndpoint) => { const endpoint2 = device.getEndpoint(2); const endpoint3 = device.getEndpoint(3); if (device.modelID == 'PIR313') { - await reporting.bind(endpoint2, coordinatorEndpoint, ['msIlluminanceMeasurement']); await reporting.bind(endpoint3, coordinatorEndpoint, ['msTemperatureMeasurement', 'msRelativeHumidity']); } else { - await reporting.bind(endpoint3, coordinatorEndpoint, ['msIlluminanceMeasurement']); await reporting.bind(endpoint2, coordinatorEndpoint, ['msTemperatureMeasurement', 'msRelativeHumidity']); } device.powerSource = 'Battery'; device.save(); }, + extend: [m.illuminance()], }, { zigbeeModel: ['AC201'], diff --git a/src/devices/schneider_electric.ts b/src/devices/schneider_electric.ts index e0e75e737c200..85bedfb7cdb25 100644 --- a/src/devices/schneider_electric.ts +++ b/src/devices/schneider_electric.ts @@ -24,6 +24,7 @@ import { setupConfigureForReading, temperature, } from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend, Fz, KeyValue, ModernExtend, Tz} from '../lib/types'; import * as utils from '../lib/utils'; @@ -1667,16 +1668,16 @@ const definitions: DefinitionWithExtend[] = [ model: 'CCT595011', vendor: 'Schneider Electric', description: 'Wiser motion sensor', - fromZigbee: [fz.battery, fz.ias_enroll, fz.ias_occupancy_only_alarm_2, fz.illuminance], + fromZigbee: [fz.battery, fz.ias_enroll, fz.ias_occupancy_only_alarm_2], toZigbee: [], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); - const binds = ['genPowerCfg', 'msIlluminanceMeasurement']; + const binds = ['genPowerCfg']; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.batteryPercentageRemaining(endpoint); - await reporting.illuminance(endpoint, {min: 15, max: constants.repInterval.HOUR, change: 500}); }, - exposes: [e.battery(), e.illuminance(), e.occupancy()], + exposes: [e.battery(), e.occupancy()], + extend: [m.illuminance()], }, { zigbeeModel: ['CH/Socket/2'], diff --git a/src/devices/sercomm.ts b/src/devices/sercomm.ts index f4c639fe57b0f..5aff4600741c9 100644 --- a/src/devices/sercomm.ts +++ b/src/devices/sercomm.ts @@ -1,6 +1,7 @@ import fz from '../converters/fromZigbee'; import tz from '../converters/toZigbee'; import * as exposes from '../lib/exposes'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend} from '../lib/types'; @@ -127,17 +128,17 @@ const definitions: DefinitionWithExtend[] = [ model: 'SZ-PIR04N', vendor: 'Sercomm', description: 'PIR motion & temperature sensor', - fromZigbee: [fz.ias_occupancy_alarm_1, fz.illuminance, fz.temperature, fz.battery], + fromZigbee: [fz.ias_occupancy_alarm_1, fz.temperature, fz.battery], toZigbee: [], meta: {battery: {voltageToPercentage: {min: 2500, max: 3200}}}, configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); - await reporting.bind(endpoint, coordinatorEndpoint, ['msIlluminanceMeasurement', 'msTemperatureMeasurement', 'genPowerCfg']); - await reporting.illuminance(endpoint); + await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'genPowerCfg']); await reporting.temperature(endpoint); await reporting.batteryVoltage(endpoint); }, - exposes: [e.occupancy(), e.tamper(), e.illuminance(), e.temperature(), e.battery(), e.battery_voltage()], + exposes: [e.occupancy(), e.tamper(), e.temperature(), e.battery(), e.battery_voltage()], + extend: [m.illuminance()], }, { zigbeeModel: ['SZ-WTD03'], diff --git a/src/devices/shinasystem.ts b/src/devices/shinasystem.ts index 3a095f43303a6..d8a0140cf293f 100644 --- a/src/devices/shinasystem.ts +++ b/src/devices/shinasystem.ts @@ -2,6 +2,7 @@ import fz from '../converters/fromZigbee'; import tz from '../converters/toZigbee'; import * as exposes from '../lib/exposes'; import {deviceEndpoints, electricityMeter, enumLookup, numeric, onOff, temperature} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as globalStore from '../lib/store'; import {DefinitionWithExtend, Fz, Tz} from '../lib/types'; @@ -240,19 +241,19 @@ const definitions: DefinitionWithExtend[] = [ ota: true, description: 'SiHAS multipurpose sensor', meta: {battery: {voltageToPercentage: '3V_2100'}}, - fromZigbee: [fz.battery, fz.temperature, fz.humidity, fz.occupancy, fz.illuminance], + fromZigbee: [fz.battery, fz.temperature, fz.humidity, fz.occupancy], toZigbee: [], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); - const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msRelativeHumidity', 'msOccupancySensing']; + const binds = ['genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity', 'msOccupancySensing']; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.batteryVoltage(endpoint, {min: 30, max: 21600, change: 1}); await reporting.occupancy(endpoint, {min: 1, max: 600, change: 1}); await reporting.temperature(endpoint, {min: 20, max: 300, change: 10}); await reporting.humidity(endpoint, {min: 20, max: 300, change: 40}); - await reporting.illuminance(endpoint, {min: 20, max: 3600, change: 10}); }, - exposes: [e.battery(), e.battery_voltage(), e.temperature(), e.humidity(), e.occupancy(), e.illuminance()], + exposes: [e.battery(), e.battery_voltage(), e.temperature(), e.humidity(), e.occupancy()], + extend: [m.illuminance()], }, { zigbeeModel: ['SBM300Z1'], diff --git a/src/devices/terncy.ts b/src/devices/terncy.ts index 91789b498955e..76171bb0b9f83 100644 --- a/src/devices/terncy.ts +++ b/src/devices/terncy.ts @@ -2,6 +2,7 @@ import fz from '../converters/fromZigbee'; import tz from '../converters/toZigbee'; import * as exposes from '../lib/exposes'; import {deviceEndpoints, light, onOff} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend} from '../lib/types'; @@ -38,10 +39,11 @@ const definitions: DefinitionWithExtend[] = [ model: 'TERNCY-PP01', vendor: 'TERNCY', description: 'Awareness switch', - fromZigbee: [fz.terncy_temperature, fz.occupancy_with_timeout, fz.illuminance, fz.terncy_raw, fz.battery], - exposes: [e.temperature(), e.occupancy(), e.illuminance(), e.action(['single', 'double', 'triple', 'quadruple'])], + fromZigbee: [fz.terncy_temperature, fz.occupancy_with_timeout, fz.terncy_raw, fz.battery], + exposes: [e.temperature(), e.occupancy(), e.action(['single', 'double', 'triple', 'quadruple'])], toZigbee: [], meta: {battery: {dontDividePercentage: true}}, + extend: [m.illuminance()], }, { zigbeeModel: ['TERNCY-SD01'], diff --git a/src/devices/third_reality.ts b/src/devices/third_reality.ts index 0620bf709d38c..c490fcd8bcaab 100644 --- a/src/devices/third_reality.ts +++ b/src/devices/third_reality.ts @@ -14,6 +14,7 @@ import { onOff, temperature, } from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend, Fz, KeyValue} from '../lib/types'; @@ -477,9 +478,10 @@ const definitions: DefinitionWithExtend[] = [ commands: {}, commandsResponse: {}, }), + m.illuminance(), ], - fromZigbee: [fzLocal.thirdreality_private_motion_sensor, fz.illuminance, fz.ias_occupancy_alarm_1_report], - exposes: [e.occupancy(), e.illuminance()], + fromZigbee: [fzLocal.thirdreality_private_motion_sensor, fz.ias_occupancy_alarm_1_report], + exposes: [e.occupancy()], configure: async (device, coordinatorEndpoint) => { device.powerSource = 'Mains (single phase)'; device.save(); diff --git a/src/devices/tplink.ts b/src/devices/tplink.ts index 9671553132d8f..2b8a90f76825a 100644 --- a/src/devices/tplink.ts +++ b/src/devices/tplink.ts @@ -1,5 +1,6 @@ import fz from '../converters/fromZigbee'; import * as exposes from '../lib/exposes'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend} from '../lib/types'; @@ -11,19 +12,17 @@ const definitions: DefinitionWithExtend[] = [ model: 'MS100', vendor: 'TP-Link', description: 'Smart motion sensor', - fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.illuminance], + fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery], toZigbee: [], - exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(), e.illuminance()], + exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery()], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); - const endpoint2 = device.getEndpoint(2); await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']); await reporting.batteryPercentageRemaining(endpoint); - await reporting.bind(endpoint2, coordinatorEndpoint, ['msIlluminanceMeasurement']); - await reporting.illuminance(endpoint2); device.powerSource = 'Battery'; device.save(); }, + extend: [m.illuminance()], }, { zigbeeModel: ['CS100'], diff --git a/src/devices/tuya.ts b/src/devices/tuya.ts index 352e2d4deedf8..166aa5e45508e 100644 --- a/src/devices/tuya.ts +++ b/src/devices/tuya.ts @@ -21,6 +21,7 @@ import { temperature, windowCovering, } from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import * as globalStore from '../lib/store'; import * as tuya from '../lib/tuya'; @@ -1733,11 +1734,12 @@ const definitions: DefinitionWithExtend[] = [ model: 'TS0202_3', vendor: 'Tuya', description: 'Motion detector with illuminance', - fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1_report, fz.illuminance], + fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1_report], toZigbee: [], onEvent: tuya.onEventSetTime, configure: tuya.configureMagicPacket, - exposes: [e.occupancy(), e.battery_low(), e.battery(), e.tamper(), e.illuminance()], + exposes: [e.occupancy(), e.battery_low(), e.battery(), e.tamper()], + extend: [m.illuminance()], }, { fingerprint: tuya.fingerprint('TS0202', ['_TZ3210_cwamkvua']), @@ -7229,32 +7231,35 @@ const definitions: DefinitionWithExtend[] = [ model: 'TS0222_temperature_humidity', vendor: 'Tuya', description: 'Temperature & humidity sensor', - fromZigbee: [fzLocal.TS0222_humidity, fz.battery, fz.temperature, fz.illuminance], + fromZigbee: [fzLocal.TS0222_humidity, fz.battery, fz.temperature], toZigbee: [], configure: tuya.configureMagicPacket, - exposes: [e.battery(), e.temperature(), e.humidity(), e.illuminance()], + exposes: [e.battery(), e.temperature(), e.humidity()], whiteLabel: [tuya.whitelabel('Tuya', 'QT-07S', 'Soil sensor', ['_TZE204_myd45weu'])], + extend: [m.illuminance()], }, { fingerprint: tuya.fingerprint('TS0222', ['_TZ3000_8uxxzz4b', '_TZ3000_hy6ncvmw', '_TZ3000_9kbbfeho', '_TZ3000_l6rsaipj']), model: 'TS0222_light', vendor: 'Tuya', description: 'Light sensor', - fromZigbee: [fz.battery, fz.illuminance], + fromZigbee: [fz.battery], toZigbee: [], configure: tuya.configureMagicPacket, whiteLabel: [tuya.whitelabel('Moes', 'ZSS-QT-LS-C', 'Light sensor', ['_TZ3000_9kbbfeho'])], - exposes: [e.battery(), e.illuminance()], + exposes: [e.battery()], + extend: [m.illuminance()], }, { fingerprint: tuya.fingerprint('TS0222', ['_TZ3000_t9qqxn70']), model: 'THE01860A', vendor: 'Tuya', description: 'Temp & humidity flower sensor with illuminance', - fromZigbee: [fz.humidity, fz.battery, fz.temperature, fz.illuminance], + fromZigbee: [fz.humidity, fz.battery, fz.temperature], toZigbee: [], configure: tuya.configureMagicPacket, - exposes: [e.battery(), e.temperature(), e.humidity(), e.illuminance()], + exposes: [e.battery(), e.temperature(), e.humidity()], + extend: [m.illuminance()], }, { fingerprint: [ @@ -7265,10 +7270,11 @@ const definitions: DefinitionWithExtend[] = [ model: 'TS0222', vendor: 'Tuya', description: 'Light intensity sensor', - fromZigbee: [fz.battery, fz.illuminance, legacy.fromZigbee.TS0222], + fromZigbee: [fz.battery, legacy.fromZigbee.TS0222], toZigbee: [], - exposes: [e.battery(), e.illuminance()], + exposes: [e.battery()], configure: tuya.configureMagicPacket, + extend: [m.illuminance()], }, { zigbeeModel: ['TS0210'], @@ -7537,7 +7543,7 @@ const definitions: DefinitionWithExtend[] = [ model: 'LCZ030', vendor: 'Tuya', description: 'Temperature & humidity & illuminance sensor with display', - fromZigbee: [fz.battery, fz.illuminance, fz.temperature, fz.humidity, fz.ts0201_temperature_humidity_alarm], + fromZigbee: [fz.battery, fz.temperature, fz.humidity, fz.ts0201_temperature_humidity_alarm], toZigbee: [tz.ts0201_temperature_humidity_alarm], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); @@ -7547,7 +7553,6 @@ const definitions: DefinitionWithExtend[] = [ 'genBasic', 'genPowerCfg', 'msTemperatureMeasurement', - 'msIlluminanceMeasurement', 'msRelativeHumidity', 'manuSpecificTuya_2', ]); @@ -7556,7 +7561,6 @@ const definitions: DefinitionWithExtend[] = [ e.temperature(), e.humidity(), e.battery(), - e.illuminance(), e .numeric('alarm_temperature_max', ea.STATE_SET) .withUnit('°C') @@ -7574,6 +7578,7 @@ const definitions: DefinitionWithExtend[] = [ e.enum('alarm_humidity', ea.STATE, ['below_min_humdity', 'over_humidity', 'off']).withDescription('Alarm humidity status'), e.enum('alarm_temperature', ea.STATE, ['below_min_temperature', 'over_temperature', 'off']).withDescription('Alarm temperature status'), ], + extend: [m.illuminance()], }, { fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_auin8mzr'}], diff --git a/src/devices/wirenboard.ts b/src/devices/wirenboard.ts index 56c8bcbb42c85..1f0dbe84ba9d3 100644 --- a/src/devices/wirenboard.ts +++ b/src/devices/wirenboard.ts @@ -3,6 +3,7 @@ import tz from '../converters/toZigbee'; import * as constants from '../lib/constants'; import * as exposes from '../lib/exposes'; import * as modernExtend from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import * as reporting from '../lib/reporting'; import {Configure, DefinitionWithExtend, Fz, KeyValueAny, ModernExtend, Tz} from '../lib/types'; import {assertString, getFromLookup, getOptions, toNumber} from '../lib/utils'; @@ -462,7 +463,6 @@ const definitions: DefinitionWithExtend[] = [ description: 'Wall-mounted multi sensor', fromZigbee: [ fzLocal.temperature, - fz.illuminance, fz.humidity, fz.occupancy, fzLocal.occupancy_level, @@ -491,7 +491,6 @@ const definitions: DefinitionWithExtend[] = [ ], exposes: [ e.temperature(), - e.illuminance(), e.humidity(), e.occupancy(), e.occupancy_level(), @@ -561,7 +560,6 @@ const definitions: DefinitionWithExtend[] = [ const binds = [ 'genBasic', 'msTemperatureMeasurement', - 'msIlluminanceMeasurement', 'msRelativeHumidity', 'msOccupancySensing', 'msCO2', @@ -574,7 +572,6 @@ const definitions: DefinitionWithExtend[] = [ // report configuration await reporting.temperature(endpoint1); - await reporting.illuminance(endpoint1); await reporting.humidity(endpoint1); await reporting.occupancy(endpoint1); @@ -598,6 +595,7 @@ const definitions: DefinitionWithExtend[] = [ }, meta: {multiEndpoint: true, multiEndpointSkip: ['humidity']}, ota: true, + extend: [m.illuminance()], }, { zigbeeModel: ['WBMSW4'], diff --git a/src/lib/modernExtend.ts b/src/lib/modernExtend.ts index f6e7d43ef189b..54ebf27bc3ce7 100644 --- a/src/lib/modernExtend.ts +++ b/src/lib/modernExtend.ts @@ -2082,7 +2082,7 @@ export interface NumericArgs { access?: 'STATE' | 'STATE_GET' | 'STATE_SET' | 'SET' | 'ALL'; unit?: string; endpointNames?: string[]; - reporting?: ReportingConfigWithoutAttribute; + reporting?: false | ReportingConfigWithoutAttribute; valueMin?: number; valueMax?: number; valueStep?: number; @@ -2196,7 +2196,10 @@ export function numeric(args: NumericArgs): ModernExtend { }, ]; - const configure: Configure[] = [setupConfigureForReporting(cluster, attribute, reporting, access, endpoints)]; + const configure: Configure[] = []; + if (reporting) { + configure.push(setupConfigureForReporting(cluster, attribute, reporting, access, endpoints)); + } return {exposes, fromZigbee, toZigbee, configure, isModernExtend: true}; } From 4e8e6de806e867e380a7cd98387d4b71acb52c92 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Sun, 12 Jan 2025 20:41:41 +0100 Subject: [PATCH 5/8] u --- src/converters/fromZigbee.ts | 10 ------ src/devices/philips.ts | 61 ++++++++---------------------------- 2 files changed, 13 insertions(+), 58 deletions(-) diff --git a/src/converters/fromZigbee.ts b/src/converters/fromZigbee.ts index c04efd4068944..1fc6c9e03897a 100644 --- a/src/converters/fromZigbee.ts +++ b/src/converters/fromZigbee.ts @@ -485,16 +485,6 @@ const converters1 = { return {soil_moisture: soilMoisture}; }, } satisfies Fz.Converter, - illuminance: { - cluster: 'msIlluminanceMeasurement', - type: ['attributeReport', 'readResponse'], - options: [exposes.options.illuminance_raw()], - convert: (model, msg, publish, options, meta) => { - const illuminance = msg.data['measuredValue']; - const illuminanceLux = illuminance === 0 ? 0 : Math.pow(10, (illuminance - 1) / 10000); - return {illuminance: illuminanceLux, ...(options.illuminance_raw ? {illuminance_raw: illuminance} : {})}; - }, - } satisfies Fz.Converter, pressure: { cluster: 'msPressureMeasurement', type: ['attributeReport', 'readResponse'], diff --git a/src/devices/philips.ts b/src/devices/philips.ts index fb3cd6c18d490..a38fd1d797ca3 100644 --- a/src/devices/philips.ts +++ b/src/devices/philips.ts @@ -4,6 +4,7 @@ import fz from '../converters/fromZigbee'; import tz from '../converters/toZigbee'; import * as exposes from '../lib/exposes'; import {deviceEndpoints, identify, quirkCheckinInterval} from '../lib/modernExtend'; +import * as m from '../lib/modernExtend'; import {philipsFz, philipsLight, philipsOnOff, philipsTwilightOnOff, philipsTz} from '../lib/philips'; import * as reporting from '../lib/reporting'; import {DefinitionWithExtend} from '../lib/types'; @@ -2461,36 +2462,27 @@ const definitions: DefinitionWithExtend[] = [ model: '9290012607', vendor: 'Philips', description: 'Hue motion sensor', - fromZigbee: [ - fz.battery, - fz.occupancy, - fz.temperature, - fz.occupancy_timeout, - fz.illuminance, - fz.hue_motion_sensitivity, - fz.hue_motion_led_indication, - ], + fromZigbee: [fz.battery, fz.occupancy, fz.temperature, fz.occupancy_timeout, fz.hue_motion_sensitivity, fz.hue_motion_led_indication], exposes: [ e.temperature(), e.occupancy(), e.battery(), - e.illuminance(), e.motion_sensitivity_select(['low', 'medium', 'high']), e.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'), e.numeric('occupancy_timeout', ea.ALL).withUnit('s').withValueMin(0).withValueMax(65535), ], + extend: [m.illuminance()], toZigbee: [tz.occupancy_timeout, philipsTz.hue_motion_sensitivity, philipsTz.hue_motion_led_indication], endpoint: (device) => { return {default: 2, ep1: 1, ep2: 2}; }, configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(2); - const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing']; + const binds = ['genPowerCfg', 'msTemperatureMeasurement', 'msOccupancySensing']; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.batteryPercentageRemaining(endpoint); await reporting.occupancy(endpoint); await reporting.temperature(endpoint); - await reporting.illuminance(endpoint); // read occupancy_timeout and motion_sensitivity await endpoint.read('msOccupancySensing', ['pirOToUDelay']); await endpoint.read('msOccupancySensing', [48], {manufacturerCode: Zcl.ManufacturerCode.SIGNIFY_NETHERLANDS_B_V}); @@ -2502,36 +2494,27 @@ const definitions: DefinitionWithExtend[] = [ model: '9290019758', vendor: 'Philips', description: 'Hue motion outdoor sensor', - fromZigbee: [ - fz.battery, - fz.occupancy, - fz.temperature, - fz.illuminance, - fz.occupancy_timeout, - fz.hue_motion_sensitivity, - fz.hue_motion_led_indication, - ], + fromZigbee: [fz.battery, fz.occupancy, fz.temperature, fz.occupancy_timeout, fz.hue_motion_sensitivity, fz.hue_motion_led_indication], exposes: [ e.temperature(), e.occupancy(), e.battery(), - e.illuminance(), e.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']), e.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'), e.numeric('occupancy_timeout', ea.ALL).withUnit('s').withValueMin(0).withValueMax(65535), ], + extend: [m.illuminance()], toZigbee: [tz.occupancy_timeout, philipsTz.hue_motion_sensitivity, philipsTz.hue_motion_led_indication], endpoint: (device) => { return {default: 2, ep1: 1, ep2: 2}; }, configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(2); - const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing']; + const binds = ['genPowerCfg', 'msTemperatureMeasurement', 'msOccupancySensing']; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.batteryPercentageRemaining(endpoint); await reporting.occupancy(endpoint); await reporting.temperature(endpoint); - await reporting.illuminance(endpoint); // read occupancy_timeout and motion_sensitivity await endpoint.read('msOccupancySensing', ['pirOToUDelay']); await endpoint.read('msOccupancySensing', [48], {manufacturerCode: Zcl.ManufacturerCode.SIGNIFY_NETHERLANDS_B_V}); @@ -2592,33 +2575,24 @@ const definitions: DefinitionWithExtend[] = [ model: '9290030675', vendor: 'Philips', description: 'Hue motion sensor', - fromZigbee: [ - fz.battery, - fz.occupancy, - fz.temperature, - fz.occupancy_timeout, - fz.illuminance, - fz.hue_motion_sensitivity, - fz.hue_motion_led_indication, - ], + fromZigbee: [fz.battery, fz.occupancy, fz.temperature, fz.occupancy_timeout, fz.hue_motion_sensitivity, fz.hue_motion_led_indication], exposes: [ e.temperature(), e.occupancy(), e.battery(), - e.illuminance(), e.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high', 'very_high', 'max']), e.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'), e.numeric('occupancy_timeout', ea.ALL).withUnit('s').withValueMin(0).withValueMax(65535), ], + extend: [m.illuminance()], toZigbee: [tz.occupancy_timeout, philipsTz.hue_motion_sensitivity, philipsTz.hue_motion_led_indication], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(2); - const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing']; + const binds = ['genPowerCfg', 'msTemperatureMeasurement', 'msOccupancySensing']; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.batteryPercentageRemaining(endpoint); await reporting.occupancy(endpoint); await reporting.temperature(endpoint); - await reporting.illuminance(endpoint); // read occupancy_timeout and motion_sensitivity await endpoint.read('msOccupancySensing', ['pirOToUDelay']); await endpoint.read('msOccupancySensing', [48], {manufacturerCode: Zcl.ManufacturerCode.SIGNIFY_NETHERLANDS_B_V}); @@ -2629,33 +2603,24 @@ const definitions: DefinitionWithExtend[] = [ model: '9290030674', vendor: 'Philips', description: 'Hue motion outdoor sensor', - fromZigbee: [ - fz.battery, - fz.occupancy, - fz.temperature, - fz.illuminance, - fz.occupancy_timeout, - fz.hue_motion_sensitivity, - fz.hue_motion_led_indication, - ], + fromZigbee: [fz.battery, fz.occupancy, fz.temperature, fz.occupancy_timeout, fz.hue_motion_sensitivity, fz.hue_motion_led_indication], exposes: [ e.temperature(), e.occupancy(), e.battery(), - e.illuminance(), e.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high', 'very_high', 'max']), e.binary('led_indication', ea.ALL, true, false).withDescription('Blink green LED on motion detection'), e.numeric('occupancy_timeout', ea.ALL).withUnit('s').withValueMin(0).withValueMax(65535), ], + extend: [m.illuminance()], toZigbee: [tz.occupancy_timeout, philipsTz.hue_motion_sensitivity, philipsTz.hue_motion_led_indication], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(2); - const binds = ['genPowerCfg', 'msIlluminanceMeasurement', 'msTemperatureMeasurement', 'msOccupancySensing']; + const binds = ['genPowerCfg', 'msTemperatureMeasurement', 'msOccupancySensing']; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.batteryPercentageRemaining(endpoint); await reporting.occupancy(endpoint); await reporting.temperature(endpoint); - await reporting.illuminance(endpoint); // read occupancy_timeout and motion_sensitivity await endpoint.read('msOccupancySensing', ['pirOToUDelay']); await endpoint.read('msOccupancySensing', [48], {manufacturerCode: Zcl.ManufacturerCode.SIGNIFY_NETHERLANDS_B_V}); From 87e582bd91f8616cffd61e1a62b310947526d3c2 Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Sun, 12 Jan 2025 20:42:58 +0100 Subject: [PATCH 6/8] u --- src/converters/toZigbee.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/converters/toZigbee.ts b/src/converters/toZigbee.ts index 97b21582eb9ee..0b66135ed2875 100644 --- a/src/converters/toZigbee.ts +++ b/src/converters/toZigbee.ts @@ -1893,12 +1893,6 @@ const converters2 = { await entity.read('msRelativeHumidity', ['measuredValue']); }, } satisfies Tz.Converter, - illuminance: { - key: ['illuminance', 'illuminance_raw'], - convertGet: async (entity, key, meta) => { - await entity.read('msIlluminanceMeasurement', ['measuredValue']); - }, - } satisfies Tz.Converter, // #endregion // #region Non-generic converters From fd376664db428bf219351f177902ee21916ddb7d Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Sun, 12 Jan 2025 21:43:01 +0100 Subject: [PATCH 7/8] u --- src/lib/exposes.ts | 1 + src/lib/modernExtend.ts | 21 ++++++++++++++++++++- test/index.test.js | 4 +++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/lib/exposes.ts b/src/lib/exposes.ts index f72d3ad4a975a..0ab5e80e0901d 100644 --- a/src/lib/exposes.ts +++ b/src/lib/exposes.ts @@ -1021,6 +1021,7 @@ export const presets = { new Numeric('holiday_temperature', access.STATE_SET).withUnit('°C').withDescription('Holiday temperature').withValueMin(0).withValueMax(30), humidity: () => new Numeric('humidity', access.STATE).withUnit('%').withDescription('Measured relative humidity'), illuminance: () => new Numeric('illuminance', access.STATE).withDescription('Measured illuminance').withUnit('lx'), + illuminance_raw: () => new Numeric('illuminance_raw', access.STATE).withDescription('Raw measured illuminance'), brightness_state: () => new Enum('brightness_state', access.STATE, ['low', 'middle', 'high', 'strong']).withDescription('Brightness state'), keypad_lockout: () => new Enum('keypad_lockout', access.ALL, ['unlock', 'lock1', 'lock2']).withDescription('Enables/disables physical input on the device'), diff --git a/src/lib/modernExtend.ts b/src/lib/modernExtend.ts index 54ebf27bc3ce7..17dc0dc5d6dcc 100644 --- a/src/lib/modernExtend.ts +++ b/src/lib/modernExtend.ts @@ -12,6 +12,7 @@ import { BatteryLinearVoltage, BatteryNonLinearVoltage, Configure, + DefinitionExposes, DefinitionExposesFunction, DefinitionMeta, Expose, @@ -651,7 +652,7 @@ export function illuminance(args?: Partial): ModernExtend { return result; }; - return numeric({ + const result = numeric({ name: 'illuminance', cluster: 'msIlluminanceMeasurement', attribute: 'measuredValue', @@ -662,6 +663,24 @@ export function illuminance(args?: Partial): ModernExtend { access: 'STATE_GET', ...args, }); + + const fzIlluminanceRaw = { + cluster: 'msIlluminanceMeasurement', + type: ['attributeReport', 'readResponse'], + options: [opt.illuminance_raw()], + convert: (model, msg, publish, options, meta) => { + if (options.illuminance_raw) { + return {illuminance_raw: msg.data['measuredValue']}; + } + }, + } satisfies Fz.Converter; + result.fromZigbee.push(fzIlluminanceRaw); + const exposeIlluminanceRaw: DefinitionExposes = (device, options) => { + return options?.illuminance_raw ? [e.illuminance_raw()] : []; + }; + result.exposes.push(exposeIlluminanceRaw); + + return result; } export function temperature(args?: Partial) { diff --git a/test/index.test.js b/test/index.test.js index 0cdf0b0eae560..1ca9dd42a5c40 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -570,7 +570,9 @@ describe('index.js', () => { it('Function exposes should have linkquality sensor', () => { definitions.forEach((definition) => { if (typeof definition.exposes == 'function') { - expect(definition.exposes().find((e) => e.property === 'linkquality')).not.toBeUndefined(); + if (!definition.exposes().find((e) => e.property === 'linkquality')) { + throw new Error(`e.linkquality() is missing for '${definition.model}'`); + } } }); }); From 451ed6557fc0154d8210a70c6973969b1338a7ff Mon Sep 17 00:00:00 2001 From: Koen Kanters Date: Sun, 12 Jan 2025 22:04:20 +0100 Subject: [PATCH 8/8] u --- src/devices/custom_devices_diy.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/devices/custom_devices_diy.ts b/src/devices/custom_devices_diy.ts index fedfaeeeb48c5..193a2be575fa9 100644 --- a/src/devices/custom_devices_diy.ts +++ b/src/devices/custom_devices_diy.ts @@ -100,15 +100,13 @@ const fzLocal = { illuminance2: { cluster: 'msIlluminanceMeasurement', type: ['attributeReport', 'readResponse'], - options: [exposes.options.illuminance_raw()], convert: (model, msg, publish, options, meta) => { // multi-endpoint version based on the stastard onverter 'fz.illuminance' const illuminance = msg.data['measuredValue']; const illuminanceLux = illuminance === 0 ? 0 : Math.pow(10, (illuminance - 1) / 10000); const multiEndpoint = model.meta && model.meta.multiEndpoint !== undefined && model.meta.multiEndpoint; const property1 = multiEndpoint ? postfixWithEndpointName('illuminance', msg, model, meta) : 'illuminance'; - const property2 = multiEndpoint ? postfixWithEndpointName('illuminance_raw', msg, model, meta) : 'illuminance_raw'; - return {[property1]: illuminanceLux, ...(options.illuminance_raw ? {[property2]: illuminance} : {})}; + return {[property1]: illuminanceLux}; }, } satisfies Fz.Converter, pressure2: {