zigbee2mqtt/lib/extension/deviceReport.js
Koen Kanters d83085ea7f
Zigbee-herdsman (#1945)
* Update zigbee-herdsman and zigbee-shepherd-converters.

* Force Aqara S2 Lock endvices (#1764)

* Start on zigbee-herdsman controller refactor.

* More updates.

* Cleanup zapp.

* updates.

* Propagate adapter disconnected event.

* Updates.

* Initial refactor to zigbee-herdsman.

* Refactor deviceReceive to zigbee-herdsman.

* Rename

* Refactor deviceConfigure.

* Finish bridge config.

* Refactor availability.

* Active homeassistant extension and more refactors.

* Refactor groups.

* Enable soft reset.

* Activate group membership

* Start on tests.

* Enable reporting.

* Add more controller tests.

* Add more tests

* Fix linting error.

* Data en deviceReceive tests.

* Move to zigbee-herdsman-converters.

* More device publish tests.

* Cleanup dependencies.

* Bring device publish coverage to 100.

* Bring home assistant test coverage to 100.

* Device configure tests.

* Attempt to fix tests.

* Another attempt.

* Another one.

* Another one.

* Another.

* Add wait.

* Longer wait.

* Debug.

* Update dependencies.

* Another.

* Begin on availability tests.

* Improve availability tests.

* Complete deviceAvailability tests.

* Device bind tests.

* More tests.

* Begin networkmap refactors.

* start on networkmap tests.

* Network map tests.

* Add utils tests.

* Logger tests.

* Settings and logger tests.

* Ignore some stuff for coverage and add todos.

* Add remaining missing tests.

* Enforce 100% test coverage.

* Start on groups test and refactor entityPublish to resolveEntity

* Remove joinPathStorage, not used anymore as group information is stored into zigbee-herdsman database.

* Fix linting issues.

* Improve tests.

* Add groups.

* fix group membership.

* Group: log names.

* Convert MQTT message to string by default.

* Fix group name.

* Updates.

* Revert configuration.yaml.

* Add new line.

* Fixes.

* Updates.

* Fix tests.

* Ignore soft reset extension.
2019-09-09 19:48:09 +02:00

104 lines
3.9 KiB
JavaScript

const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
const logger = require('../util/logger');
const CC2530Router = zigbeeHerdsmanConverters.devices.find((d) => d.model === 'CC2530.ROUTER');
const utils = require('../util/utils');
const defaultConfiguration = {
minimumReportInterval: 3, maximumReportInterval: 300, reportableChange: 0,
};
const reportKey = 1;
const clusters = {
'genOnOff': [
{attribute: 'onOff', ...defaultConfiguration, minimumReportInterval: 0, reportableChange: 0},
],
'genLevelCtrl': [
{attribute: 'currentLevel', ...defaultConfiguration},
],
'lightingColorCtrl': [
{attribute: 'colorTemperature', ...defaultConfiguration},
{attribute: 'currentX', ...defaultConfiguration},
{attribute: 'currentY', ...defaultConfiguration},
],
'closuresWindowCovering': [
{attribute: 'currentPositionLiftPercentage', ...defaultConfiguration},
{attribute: 'currentPositionTiltPercentage', ...defaultConfiguration},
],
};
class DeviceReport {
constructor(zigbee, mqtt, state, publishEntityState) {
this.zigbee = zigbee;
this.mqtt = mqtt;
this.state = state;
this.publishEntityState = publishEntityState;
this.configuring = new Set();
}
async setupReporting(device) {
if (this.configuring.has(device.ieeeAddr)) return;
this.configuring.add(device.ieeeAddr);
try {
for (const endpoint of device.endpoints) {
for (const [cluster, configuration] of Object.entries(clusters)) {
if (endpoint.supportsInputCluster(cluster)) {
logger.debug(`Setup reporting for '${device.ieeeAddr}' - ${endpoint.ID} - ${cluster}`);
await endpoint.bind(cluster, this.coordinatorEndpoint);
await endpoint.configureReporting(cluster, configuration);
logger.info(
`Succesfully setup reporting for '${device.ieeeAddr}' - ${endpoint.ID} - ${cluster}`
);
}
}
}
// eslint-disable-next-line
device.meta.reporting = reportKey;
} catch (error) {
logger.error(
`Failed to setup reporting for '${device.ieeeAddr}' - ${error}`
);
}
await device.save();
this.configuring.delete(device.ieeeAddr);
}
shouldSetupReporting(mappedDevice, device, messageType) {
if (!device) return false;
// Handle messages of type endDeviceAnnce and devIncoming.
// This message is typically send when a device comes online after being powered off
// Ikea TRADFRI tend to forget their reporting after powered off.
// Re-setup reporting.
// https://github.com/Koenkk/zigbee2mqtt/issues/966
if (messageType === 'deviceAnnounce' && utils.isIkeaTradfriDevice(device)) return true;
if (device.meta.hasOwnProperty('reporting') && device.meta.reporting === reportKey) return false;
if (!utils.isRouter(device) || utils.isBatteryPowered(device)) return false;
if (mappedDevice === CC2530Router) return false;
return true;
}
async onZigbeeStarted() {
this.coordinatorEndpoint = (await this.zigbee.getDevice({type: 'Coordinator'})).endpoints[0];
for (const device of await this.zigbee.getClients()) {
const mappedDevice = zigbeeHerdsmanConverters.findByZigbeeModel(device.modelID);
if (this.shouldSetupReporting(mappedDevice, device, null)) {
this.setupReporting(device);
}
}
}
onZigbeeEvent(type, data, mappedDevice, settingsDevice) {
if (this.shouldSetupReporting(mappedDevice, data.device, type)) {
this.setupReporting(data.device);
}
}
}
module.exports = DeviceReport;