Skip to content

Commit

Permalink
feat: Make 6735/6736/6737 state poll interval configurable and defaul…
Browse files Browse the repository at this point in the history
…t to 60 seconds #7733
  • Loading branch information
Koenkk committed Jul 9, 2024
1 parent 2cd4283 commit 6f5707b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 44 deletions.
34 changes: 18 additions & 16 deletions src/devices/busch_jaeger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import {onOff} from '../lib/modernExtend';
import * as reporting from '../lib/reporting';
import * as globalStore from '../lib/store';
import {Definition} from '../lib/types';
import * as utils from '../lib/utils';

const e = exposes.presets;
const ea = exposes.access;

const definitions: Definition[] = [
{
Expand Down Expand Up @@ -141,29 +143,29 @@ const definitions: Definition[] = [
legacy.fz.RM01_down_hold,
legacy.fz.RM01_stop,
],
options: [
e
.numeric('state_poll_interval', ea.SET)
.withValueMin(-1)
.withDescription(
`This device does not support state reporting so it is polled instead. The default poll interval is 60 seconds, set to -1 to disable.`,
),
],
toZigbee: [tz.RM01_light_onoff_brightness, tz.RM01_light_brightness_step, tz.RM01_light_brightness_move],
onEvent: async (type, data, device) => {
onEvent: async (type, data, device, options) => {
const switchEndpoint = device.getEndpoint(0x12);
if (switchEndpoint == null) {
return;
}
// This device doesn't support reporting.
// Therefore we read the on/off state every 5 seconds.
// Therefore we read the on/off state every 60 seconds.
// This is the same way as the Hue bridge does it.
if (type === 'stop') {
clearInterval(globalStore.getValue(device, 'interval'));
globalStore.clearValue(device, 'interval');
} else if (!globalStore.hasValue(device, 'interval')) {
const interval = setInterval(async () => {
try {
await switchEndpoint.read('genOnOff', ['onOff']);
await switchEndpoint.read('genLevelCtrl', ['currentLevel']);
} catch (error) {
// Do nothing
}
}, 5000);
globalStore.putValue(device, 'interval', interval);
}
const poll = async () => {
await switchEndpoint.read('genOnOff', ['onOff']);
await switchEndpoint.read('genLevelCtrl', ['currentLevel']);
};

utils.onEventPoll(type, data, device, options, 'state', 60, poll);
},
},
];
Expand Down
37 changes: 10 additions & 27 deletions src/lib/tuya.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,33 +170,16 @@ export async function onEventMeasurementPoll(
metering = false,
) {
const endpoint = device.getEndpoint(1);
if (type === 'stop') {
clearTimeout(globalStore.getValue(device, 'measurement_poll'));
globalStore.clearValue(device, 'measurement_poll');
} else if (!globalStore.hasValue(device, 'measurement_poll')) {
const seconds = utils.toNumber(
options && options.measurement_poll_interval ? options.measurement_poll_interval : 60,
'measurement_poll_interval',
);
if (seconds === -1) return;
const setTimer = () => {
const timer = setTimeout(async () => {
try {
if (electricalMeasurement) {
await endpoint.read('haElectricalMeasurement', ['rmsVoltage', 'rmsCurrent', 'activePower']);
}
if (metering) {
await endpoint.read('seMetering', ['currentSummDelivered']);
}
} catch (error) {
/* Do nothing*/
}
setTimer();
}, seconds * 1000);
globalStore.putValue(device, 'measurement_poll', timer);
};
setTimer();
}
const poll = async () => {
if (electricalMeasurement) {
await endpoint.read('haElectricalMeasurement', ['rmsVoltage', 'rmsCurrent', 'activePower']);
}
if (metering) {
await endpoint.read('seMetering', ['currentSummDelivered']);
}
};

utils.onEventPoll(type, data, device, options, 'measurement', 60, poll);
}

export async function onEventSetTime(type: OnEventType, data: KeyValue, device: Zh.Device) {
Expand Down
37 changes: 36 additions & 1 deletion src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,49 @@ import {Zcl} from 'zigbee-herdsman';
import {Feature, Light, Numeric} from './exposes';
import {logger} from './logger';
import * as globalStore from './store';
import {Definition, Expose, Fz, KeyValue, KeyValueAny, Publish, Tz, Zh} from './types';
import {Definition, Expose, Fz, KeyValue, KeyValueAny, OnEventData, OnEventType, Publish, Tz, Zh} from './types';

const NS = 'zhc:utils';

export function isLegacyEnabled(options: KeyValue) {
return !options.hasOwnProperty('legacy') || options.legacy;
}

export function onEventPoll(
type: OnEventType,
data: OnEventData,
device: Zh.Device,
options: KeyValue,
key: string,
defaultIntervalSeconds: number,
poll: () => Promise<void>,
) {
if (type === 'stop') {
clearTimeout(globalStore.getValue(device, key));
globalStore.clearValue(device, key);
} else if (!globalStore.hasValue(device, key)) {
const optionsKey = `${key}_poll_interval`;
const seconds = toNumber(options[optionsKey] ?? defaultIntervalSeconds, optionsKey);
if (seconds <= 0) {
logger.debug(`Not polling '${key}' for '${device.ieeeAddr}' since poll interval is <= 0 (got ${seconds})`, NS);
} else {
logger.debug(`Polling '${key}' for '${device.ieeeAddr}' at an interval of ${seconds}`, NS);
const setTimer = () => {
const timer = setTimeout(async () => {
try {
await poll();
} catch (error) {
/* Do nothing*/
}
setTimer();
}, seconds * 1000);
globalStore.putValue(device, key, timer);
};
setTimer();
}
}
}

export function precisionRound(number: number, precision: number): number {
if (typeof precision === 'number') {
const factor = Math.pow(10, precision);
Expand Down

0 comments on commit 6f5707b

Please sign in to comment.