Refactor receive

This commit is contained in:
Koen Kanters committed 2020-04-15 22:34:59 +02:00
1 parent 67151fba04
commit 07dc837b76
5 files changed
+43 -43

No files matched your search

+4 -4
View File
@@ -9,7 +9,7 @@ const utils = require('./util/utils');
// Extensions
const ExtensionEntityPublish = require('./extension/entityPublish');
const ExtensionDeviceReceive = require('./extension/deviceReceive');
const ExtensionReceive = require('./extension/receive');
const ExtensionNetworkMap = require('./extension/networkMap');
const ExtensionSoftReset = require('./extension/legacy/softReset');
const ExtensionHomeAssistant = require('./extension/homeassistant');
@@ -37,7 +37,7 @@ class Controller {
const args = [this.zigbee, this.mqtt, this.state, this.publishEntityState, this.eventBus];
this.extensions = [
new ExtensionEntityPublish(...args),
new ExtensionDeviceReceive(...args),
new ExtensionReceive(...args),
new ExtensionDeviceGroupMembership(...args),
new ExtensionConfigure(...args),
new ExtensionNetworkMap(...args),
@@ -289,8 +289,6 @@ class Controller {
resolvedEntity.settings.filtered_attributes.forEach((a) => delete messagePayload[a]);
}
this.eventBus.emit('publishEntityState', {payload: messagePayload, entity: resolvedEntity});
if (Object.entries(messagePayload).length) {
if (settings.get().experimental.output === 'attribute_and_json') {
await this.mqtt.publish(resolvedEntity.name, JSON.stringify(messagePayload), options);
@@ -304,6 +302,8 @@ class Controller {
}
}
}
this.eventBus.emit('publishEntityState', {payload: messagePayload, entity: resolvedEntity});
}
async iteratePayloadAttributeOutput(topicRoot, payload, options) {
+12
View File
@@ -1623,6 +1623,18 @@ class HomeAssistant extends Extension {
}
}
/**
* Publish an empty value for click and action payload, in this way Home Assistant
* can use Home Assistant entities in automations.
* https://github.com/Koenkk/zigbee2mqtt/issues/959#issuecomment-480341347
*/
if (settings.get().advanced.homeassistant_legacy_triggers) {
const key = ['action', 'click'].find((k) => data.payload.hasOwnProperty(k) && data.payload[k] !== '');
if (key) {
this.publishEntityState(data.entity.device.ieeeAddr, {[key]: ''});
}
}
/**
* Implements the MQTT device trigger (https://www.home-assistant.io/integrations/device_trigger.mqtt/)
* The MQTT device trigger does not support JSON parsing, so it cannot listen to zigbee2mqtt/my_device
@@ -4,10 +4,9 @@ const utils = require('../util/utils');
const debounce = require('debounce');
const Extension = require('./extension');
class DeviceReceive extends Extension {
class Receive extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
super(zigbee, mqtt, state, publishEntityState, eventBus);
this.coordinator = null;
this.elapsed = {};
this.debouncers = {};
}
@@ -54,7 +53,7 @@ class DeviceReceive extends Extension {
return result;
}
canHandleEvent(type, data, resolvedEntity) {
shouldProcess(type, data, resolvedEntity) {
if (type !== 'message' || !resolvedEntity) {
return false;
}
@@ -98,7 +97,7 @@ class DeviceReceive extends Extension {
}
onZigbeeEvent(type, data, resolvedEntity) {
if (!this.canHandleEvent(type, data, resolvedEntity)) {
if (!this.shouldProcess(type, data, resolvedEntity)) {
return;
}
@@ -144,21 +143,6 @@ class DeviceReceive extends Extension {
this.publishDebounce(data.device.ieeeAddr, payload, debounce, debounceIgnore);
} else {
this.publishEntityState(data.device.ieeeAddr, payload);
if (settings.get().homeassistant && settings.get().advanced.homeassistant_legacy_triggers) {
/**
* Publish an empty value for click and action payload, in this way Home Assistant
* can use Home Assistant entities in automations.
* https://github.com/Koenkk/zigbee2mqtt/issues/959#issuecomment-480341347
*/
Object.keys(payload).forEach((key) => {
if (['action', 'click'].includes(key)) {
const counterPayload = {};
counterPayload[key] = '';
this.publishEntityState(data.device.ieeeAddr, counterPayload);
}
});
}
}
};
@@ -178,4 +162,4 @@ class DeviceReceive extends Extension {
}
}
module.exports = DeviceReceive;
module.exports = Receive;
+22 -1
View File
@@ -517,7 +517,7 @@ describe('HomeAssistant extension', () => {
MQTT.publish.mockClear();
await zigbeeHerdsman.events.message(payload);
await flushPromises();
// 1 publish is the publish from deviceReceive
// 1 publish is the publish from receive
expect(MQTT.publish).toHaveBeenCalledTimes(1);
});
@@ -939,4 +939,25 @@ describe('HomeAssistant extension', () => {
await flushPromises();
expect(logger.error).toHaveBeenCalledTimes(0);
});
it('Should counter an action/click payload with an empty payload', async () => {
controller = new Controller(false);
await controller.start();
await flushPromises();
MQTT.publish.mockClear();
const device = zigbeeHerdsman.devices.WXKG11LM;
const data = {onOff: 1}
const payload = {data, cluster: 'genOnOff', device, endpoint: device.getEndpoint(1), type: 'attributeReport', linkquality: 10};
await zigbeeHerdsman.events.message(payload);
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(4);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({click: 'single', linkquality: 10});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
expect(MQTT.publish.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/button');
expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({click: '', linkquality: 10});
expect(MQTT.publish.mock.calls[1][2]).toStrictEqual({"qos": 0, "retain": false});
expect(MQTT.publish.mock.calls[2][0]).toStrictEqual('homeassistant/device_automation/0x0017880104e45520/click_single/config');
expect(MQTT.publish.mock.calls[3][0]).toStrictEqual('zigbee2mqtt/button/click');
});
});
@@ -8,7 +8,7 @@ const flushPromises = () => new Promise(setImmediate);
const mocksClear = [MQTT.publish, logger.warn, logger.debug];
describe('Device receive', () => {
describe('Receive', () => {
let controller;
beforeEach(async () => {
@@ -33,23 +33,6 @@ describe('Device receive', () => {
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
});
it('Should handle a zigbee message and counter it when Home Assistant integration is enabled', async () => {
settings.set(['homeassistant'], true);
const device = zigbeeHerdsman.devices.WXKG11LM;
const data = {onOff: 1}
const payload = {data, cluster: 'genOnOff', device, endpoint: device.getEndpoint(1), type: 'attributeReport', linkquality: 10};
await zigbeeHerdsman.events.message(payload);
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledTimes(2);
expect(MQTT.publish.mock.calls[0][0]).toStrictEqual('zigbee2mqtt/button');
expect(JSON.parse(MQTT.publish.mock.calls[0][1])).toStrictEqual({click: 'single', linkquality: 10});
expect(MQTT.publish.mock.calls[0][2]).toStrictEqual({"qos": 0, "retain": false});
expect(MQTT.publish.mock.calls[1][0]).toStrictEqual('zigbee2mqtt/button');
expect(JSON.parse(MQTT.publish.mock.calls[1][1])).toStrictEqual({click: '', linkquality: 10});
expect(MQTT.publish.mock.calls[1][2]).toStrictEqual({"qos": 0, "retain": false});
});
it('Should handle a zigbee message which uses ep (left)', async () => {
const device = zigbeeHerdsman.devices.WXKG02LM;
const data = {onOff: 1}