Skip re-transmitted Xiaomi messages. #1238

This commit is contained in:
Koenkk
2019-03-18 17:59:36 +01:00
committed by Koen Kanters
parent 36bba0154d
commit bee722c9c4
4 changed files with 38 additions and 2 deletions
+19
View File
@@ -80,6 +80,25 @@ class DeviceReceive {
return;
}
/**
* Don't handle re-transmitted Xiaomi messages.
* https://github.com/Koenkk/zigbee2mqtt/issues/1238
*
* Some Xiaomi router devices re-transmit messages from Xiaomi end devices.
* The source address of these message is set to the one of the Xiaomi router.
* Therefore it looks like if the message came from the Xiaomi router, while in
* fact it came from the end device.
* Handling these message would result in false state updates.
* The group ID attribute of these message defines the source address of the end device.
* As the same message is also received directly from the end device, it makes no sense
* to handle these messages.
*/
const hasGroupID = message.hasOwnProperty('groupid') && message.groupid != 0;
if (utils.isXiaomiDevice(device) && utils.isRouter(device) && hasGroupID) {
logger.debug('Skipping re-transmitted Xiaomi message');
return;
}
// Find a conveter for this message.
const cid = message.data.cid;
const cmdId = message.data.cmdId;
+1
View File
@@ -94,6 +94,7 @@ module.exports = {
secondsToMilliseconds: (seconds) => seconds * 1000,
isXiaomiDevice: (device) => xiaomiManufacturerID.includes(device.manufId),
isIkeaTradfriDevice: (device) => ikeaTradfriManufacturerID.includes(device.manufId),
isRouter: (device) => device.type === 'Router',
isNumeric: (string) => /^\d+$/.test(string),
toLocalISOString: (dDate) => toLocalISOString(dDate),
getPostfixes: () => postfixes,
+16
View File
@@ -10,6 +10,7 @@ const WXKG11LM = devices.find((d) => d.model === 'WXKG11LM');
const WXKG02LM = devices.find((d) => d.model === 'WXKG02LM');
const WSDCGQ11LM = devices.find((d) => d.model === 'WSDCGQ11LM');
const RTCGQ11LM = devices.find((d) => d.model === 'RTCGQ11LM');
const ZNCZ02LM = devices.find((d) => d.model === 'ZNCZ02LM');
const mqtt = {
log: () => {},
@@ -248,5 +249,20 @@ describe('DeviceReceive', () => {
expect(publishEntityState).toHaveBeenCalledTimes(1);
expect(typeof publishEntityState.mock.calls[0][1].last_seen).toBe('string');
});
it('Should not handle messages forwarded Xiaomi messages', () => {
const device = {ieeeAddr: '0x12345678', manufId: 4151, type: 'Router'};
const message = utils.zigbeeMessage(device, 'genOnOff', 'attReport', {onOff: 1}, 1, 599);
deviceReceive.onZigbeeMessage(message, device, ZNCZ02LM);
expect(publishEntityState).toHaveBeenCalledTimes(0);
});
it('Should handle messages from Xiaomi router devices', () => {
const device = {ieeeAddr: '0x12345678', manufId: 4151, type: 'Router'};
const message = utils.zigbeeMessage(device, 'genOnOff', 'attReport', {onOff: 1});
deviceReceive.onZigbeeMessage(message, device, ZNCZ02LM);
expect(publishEntityState).toHaveBeenCalledTimes(1);
expect(publishEntityState.mock.calls[0][1]).toStrictEqual({state: 'ON'});
});
});
});
+2 -2
View File
@@ -7,7 +7,7 @@ module.exports = {
jest.spyOn(logger, 'debug').mockReturnValue(undefined);
jest.spyOn(logger, 'error').mockReturnValue(undefined);
},
zigbeeMessage: (device, cid, type, data, epId) => {
return {data: {cid, data}, type, endpoints: [{device, epId}]};
zigbeeMessage: (device, cid, type, data, epId, groupid=0) => {
return {data: {cid, data}, type, groupid, endpoints: [{device, epId}]};
},
};