mirror of
https://github.com/Koenkk/zigbee2mqtt.git
synced 2026-08-23 11:09:52 +00:00
Send only 1 MQTT message when last_seen is enabled and Zigbee message is received. https://github.com/Koenkk/zigbee2mqtt/issues/9519
This commit is contained in:
+2
-4
@@ -160,10 +160,8 @@ class Controller {
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.get().advanced.last_seen && settings.get().advanced.last_seen !== 'disable') {
|
||||
this.eventBus.onLastSeenChanged(this, (data) =>
|
||||
this.publishEntityState(data.device, {}, 'lastSeenChanged'));
|
||||
}
|
||||
this.eventBus.onLastSeenChanged(this,
|
||||
(data) => utils.publishLastSeen(data, settings.get(), false, this.publishEntityState));
|
||||
}
|
||||
|
||||
@bind async enableDisableExtension(enable: boolean, name: string): Promise<void> {
|
||||
|
||||
@@ -4,6 +4,7 @@ import debounce from 'debounce';
|
||||
import Extension from './extension';
|
||||
import stringify from 'json-stable-stringify-without-jsonify';
|
||||
import bind from 'bind-decorator';
|
||||
import utils from '../util/utils';
|
||||
|
||||
type DebounceFunction = (() => void) & { clear(): void; } & { flush(): void; };
|
||||
|
||||
@@ -107,7 +108,11 @@ export default class Receive extends Extension {
|
||||
data = {...data, device: this.zigbee.deviceByNetworkAddress(data.groupID)};
|
||||
}
|
||||
|
||||
if (!this.shouldProcess(data)) return;
|
||||
if (!this.shouldProcess(data)) {
|
||||
utils.publishLastSeen({device: data.device, reason: 'messageEmitted'},
|
||||
settings.get(), true, this.publishEntityState);
|
||||
return;
|
||||
}
|
||||
|
||||
const converters = data.device.definition.fromZigbee.filter((c) => {
|
||||
const type = Array.isArray(c.type) ? c.type.includes(data.type) : c.type === data.type;
|
||||
@@ -163,6 +168,9 @@ export default class Receive extends Extension {
|
||||
|
||||
if (Object.keys(payload).length) {
|
||||
publish(payload);
|
||||
} else {
|
||||
utils.publishLastSeen({device: data.device, reason: 'messageEmitted'},
|
||||
settings.get(), true, this.publishEntityState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-1
@@ -136,7 +136,8 @@ declare global {
|
||||
type StateChange = {
|
||||
entity: Device | Group, from: KeyValue, to: KeyValue, reason: string | null, update: KeyValue };
|
||||
type PermitJoinChanged = ZHEvents.PermitJoinChangedPayload;
|
||||
type LastSeenChanged = { device: Device };
|
||||
type LastSeenChanged = { device: Device,
|
||||
reason: 'deviceAnnounce' | 'networkAddress' | 'deviceJoined' | 'messageEmitted' | 'messageNonEmitted'; };
|
||||
type DeviceNetworkAddressChanged = { device: Device };
|
||||
type DeviceAnnounce = { device: Device };
|
||||
type DeviceInterview = { device: Device, status: 'started' | 'successful' | 'failed' };
|
||||
|
||||
+16
-1
@@ -280,11 +280,26 @@ const hours = (hours: number): number => 1000 * 60 * 60 * hours;
|
||||
const minutes = (minutes: number): number => 1000 * 60 * minutes;
|
||||
const seconds = (seconds: number): number => 1000 * seconds;
|
||||
|
||||
function publishLastSeen(data: eventdata.LastSeenChanged, settings: Settings, allowMessageEmitted: boolean,
|
||||
publishEntityState: PublishEntityState): void {
|
||||
/**
|
||||
* Prevent 2 MQTT publishes when 1 message event is received;
|
||||
* - In case reason == messageEmitted, receive.ts will only call this when it did not publish a
|
||||
* message based on the received zigbee message. In this case allowMessageEmitted has to be true.
|
||||
* - In case reason !== messageEmitted, controller.ts will call this based on the zigbee-herdsman
|
||||
* lastSeenChanged event.
|
||||
*/
|
||||
const allow = data.reason !== 'messageEmitted' || (data.reason === 'messageEmitted' && allowMessageEmitted);
|
||||
if (settings.advanced.last_seen && settings.advanced.last_seen !== 'disable' && allow) {
|
||||
publishEntityState(data.device, {}, 'lastSeenChanged');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
endpointNames, capitalize, getZigbee2MQTTVersion, getDependencyVersion, formatDate, objectHasProperties,
|
||||
equalsPartial, getObjectProperty, getResponse, parseJSON, loadModuleFromText, loadModuleFromFile,
|
||||
getExternalConvertersDefinitions, removeNullPropertiesFromObject, toNetworkAddressHex, toSnakeCase,
|
||||
parseEntityID, isEndpoint, isZHGroup, hours, minutes, seconds, validateFriendlyName, sleep,
|
||||
sanitizeImageParameter, isAvailabilityEnabledForDevice,
|
||||
sanitizeImageParameter, isAvailabilityEnabledForDevice, publishLastSeen,
|
||||
};
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ export default class Zigbee {
|
||||
|
||||
this.herdsman.on('adapterDisconnected', () => this.eventBus.emitAdapterDisconnected());
|
||||
this.herdsman.on('lastSeenChanged', (data: ZHEvents.LastSeenChangedPayload) => {
|
||||
this.eventBus.emitLastSeenChanged({device: this.resolveDevice(data.device.ieeeAddr)});
|
||||
this.eventBus.emitLastSeenChanged({device: this.resolveDevice(data.device.ieeeAddr), reason: data.reason});
|
||||
});
|
||||
this.herdsman.on('permitJoinChanged', (data: ZHEvents.PermitJoinChangedPayload) => {
|
||||
this.eventBus.emitPermitJoinChanged(data);
|
||||
|
||||
+11
-1
@@ -644,9 +644,19 @@ describe('Controller', () => {
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
const device = zigbeeHerdsman.devices.remote;
|
||||
await zigbeeHerdsman.events.lastSeenChanged({device});
|
||||
await zigbeeHerdsman.events.lastSeenChanged({device, reason: 'deviceAnnounce'});
|
||||
expect(MQTT.publish).toHaveBeenCalledTimes(1);
|
||||
expect(MQTT.publish).toHaveBeenCalledWith(
|
||||
'zigbee2mqtt/remote', stringify({"brightness":255,"last_seen":1000}), { qos: 0, retain: true }, expect.any(Function));
|
||||
});
|
||||
|
||||
it('Should not publish last seen changes when reason is messageEmitted', async () => {
|
||||
settings.set(['advanced', 'last_seen'], 'epoch');
|
||||
await controller.start();
|
||||
await flushPromises();
|
||||
MQTT.publish.mockClear();
|
||||
const device = zigbeeHerdsman.devices.remote;
|
||||
await zigbeeHerdsman.events.lastSeenChanged({device, reason: 'messageEmitted'});
|
||||
expect(MQTT.publish).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user