Fix race condition when configuring devices

This commit is contained in:
jbn
2019-02-26 19:33:32 +01:00
committed by Koen Kanters
parent 5a9aef6d3b
commit fdf97180b0
+19 -10
View File
@@ -9,7 +9,7 @@ const Queue = require('queue');
class DeviceConfigure {
constructor(zigbee, mqtt, state, publishEntityState) {
this.zigbee = zigbee;
this.configured = [];
this.configured = {};
this.attempts = {};
this.queue = new Queue();
@@ -22,26 +22,29 @@ class DeviceConfigure {
const mappedDevice = zigbeeShepherdConverters.findByZigbeeModel(device.modelId);
if (mappedDevice) {
this.configure(device, mappedDevice);
this.configure(device, mappedDevice, device.ieeeAddr);
}
});
}
onZigbeeMessage(message, device, mappedDevice) {
if (device && mappedDevice) {
this.configure(device, mappedDevice);
const ieeeAddr = device.ieeeAddr;
if (!this.configured[ieeeAddr]) {
this.configure(device, mappedDevice, ieeeAddr);
}
}
}
configure(device, mappedDevice) {
const ieeeAddr = device.ieeeAddr;
configure(device, mappedDevice, ieeeAddr) {
if (!this.attempts.hasOwnProperty(ieeeAddr)) {
this.attempts[ieeeAddr] = 0;
}
if (!this.configured.includes(ieeeAddr) && mappedDevice.configure) {
if (mappedDevice.configure) {
const friendlyName = settings.getDevice(ieeeAddr) ? settings.getDevice(ieeeAddr).friendly_name : 'unknown';
// mark device as currently being configured to prevent race conditions
this.configured[ieeeAddr]='configuring';
this.queue.push((queueCallback) => {
logger.debug(`Configuring ${friendlyName} (${ieeeAddr}) ...`);
@@ -49,15 +52,18 @@ class DeviceConfigure {
// Call configure function of this device.
mappedDevice.configure(ieeeAddr, this.zigbee.shepherd, this.zigbee.getCoordinator(), (ok, msg) => {
if (ok) {
logger.info(`Successfully configured ${friendlyName} (${ieeeAddr})`);
this.configured.push(ieeeAddr);
logger.info(`Succesfully configured ${friendlyName} (${ieeeAddr})`);
this.configured[ieeeAddr]='configured';
} else {
// If a device is not joined in the network the configure command may fail
// (especially, immediately after zigbee start)
// also, this command may fail if the network is busy or lost data packets
if (this.attempts[ieeeAddr] > 1) {
// Give up after 3 attempts.
this.configured.push(ieeeAddr);
this.configured[ieeeAddr] = 'failed';
} else {
// we're not done yet so mark not busy
delete this.configured[ieeeAddr];
}
logger.warn(
@@ -73,6 +79,9 @@ class DeviceConfigure {
queueCallback();
});
});
} else {
// no need to configure anyting. So just mark as done
this.configured[ieeeAddr]='configured';
}
}
}