Set state of stateless properties to ‘idle’ after publish. #959

This commit is contained in:
Koen Kanters
2019-02-05 17:41:47 +01:00
parent 7642b295e1
commit 0826db07d0
2 changed files with 21 additions and 8 deletions
+13 -3
View File
@@ -1,7 +1,7 @@
const settings = require('../util/settings');
const logger = require('../util/logger');
const dontCacheProperties = ['action', 'button', 'button_left', 'button_right', 'click', 'forgotten', 'keyerror'];
const statelessProperties = ['action', 'button', 'button_left', 'button_right', 'click', 'forgotten', 'keyerror'];
/**
* This extensions handles messages received from devices.
@@ -100,11 +100,18 @@ class DeviceReceive {
// - If NO payload is returned do nothing. This is for non-standard behaviour
// for e.g. click switches where we need to count number of clicks and detect long presses.
const publish = (payload) => {
// Don't cache messages with following properties:
// Don't cache messages with stateless properties.
// After a stateless property is send we need to clear it.
// Otherwise the state of the device is incorrect.
// E.g. when a button is pressed a payload like {"click": "single"}
// is produced, afterwards we want to clear this with {"click": "idle"}
// https://github.com/Koenkk/zigbee2mqtt/issues/959
let cache = true;
dontCacheProperties.forEach((property) => {
const clearStatePayload = {};
statelessProperties.forEach((property) => {
if (payload.hasOwnProperty(property)) {
cache = false;
clearStatePayload[property] = 'idle';
}
});
@@ -133,6 +140,9 @@ class DeviceReceive {
}
this.publishEntityState(device.ieeeAddr, payload, cache);
if (Object.keys(clearStatePayload).length > 0) {
this.publishEntityState(device.ieeeAddr, clearStatePayload, false);
}
};
let payload = {};
+8 -5
View File
@@ -36,24 +36,27 @@ describe('DeviceReceive', () => {
const device = {ieeeAddr: '0x12345678'};
const message = utils.zigbeeMessage(device, 'genOnOff', 'attReport', {onOff: 1}, 1);
deviceReceive.onZigbeeMessage(message, device, WXKG11LM);
chai.assert.isTrue(publishEntityState.calledOnce);
chai.assert.isTrue(publishEntityState.calledTwice);
chai.assert.deepEqual(publishEntityState.getCall(0).args[1], {click: 'single'});
chai.assert.deepEqual(publishEntityState.getCall(1).args[1], {click: 'idle'});
});
it('Should handle a zigbee message which uses ep (left)', () => {
const device = {ieeeAddr: '0x12345678'};
const message = utils.zigbeeMessage(device, 'genOnOff', 'attReport', {onOff: 1}, 1);
deviceReceive.onZigbeeMessage(message, device, WXKG02LM);
chai.assert.isTrue(publishEntityState.calledOnce);
chai.assert.isTrue(publishEntityState.calledTwice);
chai.assert.deepEqual(publishEntityState.getCall(0).args[1], {click: 'left'});
chai.assert.deepEqual(publishEntityState.getCall(1).args[1], {click: 'idle'});
});
it('Should handle a zigbee message which uses ep (right)', () => {
const device = {ieeeAddr: '0x12345678'};
const message = utils.zigbeeMessage(device, 'genOnOff', 'attReport', {onOff: 1}, 2);
deviceReceive.onZigbeeMessage(message, device, WXKG02LM);
chai.assert.isTrue(publishEntityState.calledOnce);
chai.assert.isTrue(publishEntityState.calledTwice);
chai.assert.deepEqual(publishEntityState.getCall(0).args[1], {click: 'right'});
chai.assert.deepEqual(publishEntityState.getCall(1).args[1], {click: 'idle'});
});
it('Should handle a zigbee message with default precision', () => {
@@ -207,7 +210,7 @@ describe('DeviceReceive', () => {
};
});
deviceReceive.onZigbeeMessage(message, device, WXKG02LM);
chai.assert.isTrue(publishEntityState.calledOnce);
chai.assert.isTrue(publishEntityState.calledTwice);
chai.assert.equal(typeof publishEntityState.getCall(0).args[1].last_seen, 'number');
});
@@ -222,7 +225,7 @@ describe('DeviceReceive', () => {
};
});
deviceReceive.onZigbeeMessage(message, device, WXKG02LM);
chai.assert.isTrue(publishEntityState.calledOnce);
chai.assert.isTrue(publishEntityState.calledTwice);
chai.assert.equal(typeof publishEntityState.getCall(0).args[1].last_seen, 'string');
});
});