Improved Livolo extension (#1016)

* Improved Livolo extension (pause polling after 3 unsuccessful attempts)

* Added: queuing of all Zigbee messages

* Fixed problem with .startsWith
This commit is contained in:
ptvo
2019-02-04 16:55:44 +01:00
committed by Koen Kanters
parent 6d16875a37
commit c0a87ff520
+91 -28
View File
@@ -18,6 +18,31 @@ class PollLivoloSwitch {
this.startTimer();
}
_resetDeviceState(ieeeAddr) {
this.configured[ieeeAddr] = {
stage: 0,
retry: 0,
waitresp: false,
};
}
onZigbeeMessage(message, device, mappedDevice) {
if (!device) {
return;
}
if ((message.type == 'devInterview') ||
(message.type == 'devIncoming') ||
(message.type == 'endDeviceAnnce') ||
(message.type == 'devStatus')) {
if (this.configured.hasOwnProperty(device.ieeeAddr)) {
logger.info(`LIVOLO ${device.ieeeAddr}. (Re)joins in the network (after power off?)`);
this._resetDeviceState(device.ieeeAddr);
}
return;
}
}
startTimer() {
this.clearTimer();
this.timer = setInterval(() => this.handleInterval(), interval);
@@ -35,21 +60,32 @@ class PollLivoloSwitch {
}
_handleCommandRespSimple(err, rsp) {
this.ext.configured[this.ieeeAddr].waitresp = false;
if (err) {
logger.error(this.cid + '.' + this.ctype, 'response error:', err);
if (this.cid === 'toggle') {
this.ext.configured[this.ieeeAddr] = 0;
if (this.ctype === 'toggle') {
logger.debug(`LIVOLO ${this.ieeeAddr}. Toggle command error:`, err.message);
}
} else {
this.ext.configured[this.ieeeAddr] = 2; // sucessfully send command
logger.debug(`LIVOLO ${this.ieeeAddr}. Sucessfully configured`, rsp);
this.ext.configured[this.ieeeAddr].stage = 1; // sucessfully send command
this.ext.configured[this.ieeeAddr].retry = 0;
this.device.status = 'online';
}
}
_handleCommandRespWithData(err, rsp) {
this.ext.configured[this.ieeeAddr].waitresp = false;
if (err) {
logger.info(this.cid + '.' + this.ctype, 'response error:', err);
logger.info(`LIVOLO ${this.ieeeAddr}. ${this.cid}.${this.ctype} response error:`, err.message);
if (this.ext.configured[this.ieeeAddr].retry >= 3) {
// errors in three sequental reads, stop polling, wait for a device message
this.device.status = 'offline';
logger.info(`LIVOLO ${this.ieeeAddr}. Stopped polling after 3 unsuccessful attempts`);
}
} else {
this.ext.configured[this.ieeeAddr].retry = 0;
this.device.status = 'online';
if (this.ext.zigbee) {
this.ext.zigbee.shepherd.emit('ind:reported', this.ep, this.cid, rsp, this.ep.last_af_msg);
@@ -64,6 +100,40 @@ class PollLivoloSwitch {
ep.last_af_msg = msg;
}
_sendToggle(zdev, ieeeAddr, ep, retry) {
this.zigbee.queue.push((queueCallback) => {
const cfg = {};
logger.debug(`LIVOLO ${ieeeAddr}. Sending the 'toggle' command. Retry: ${retry}`);
ep.functional('genOnOff', 'toggle', [cfg], foundationCfg,
this._handleCommandRespSimple.bind({
device: zdev,
ieeeAddr: ieeeAddr,
cid: 'genOnOff',
ctype: 'toggle',
ext: this,
}));
queueCallback();
});
}
_sendPoll(zdev, ieeeAddr, ep, retry) {
this.zigbee.queue.push((queueCallback) => {
ep.foundation('genOnOff', 'read', [{
attrId: 0, // onOff
}], this._handleCommandRespWithData.bind({
device: zdev,
ieeeAddr: ieeeAddr,
ep: ep,
cid: 'genOnOff',
ctype: 'read',
ext: this,
}));
queueCallback();
});
}
handleInterval() {
this.zigbee.getAllClients()
.filter((d) => d.manufName && d.manufName.startsWith('LIVOLO')) // LIVOLO
@@ -84,31 +154,24 @@ class PollLivoloSwitch {
ep.onAfIncomingMsg = this._handleAfMessage;
if (!this.configured.hasOwnProperty(d.ieeeAddr)) {
this.configured[d.ieeeAddr] = 0;
this._resetDeviceState(d.ieeeAddr);
}
if (!this.configured[d.ieeeAddr]) {
const cfg = {};
// logger.info('=====>Send toggle');
this.configured[d.ieeeAddr] = 1; // command sent, wait a result
ep.functional('genOnOff', 'toggle', [cfg], foundationCfg,
this._handleCommandRespSimple.bind({
device: zdev,
ieeeAddr: d.ieeeAddr,
cid: 'genOnOff',
ctype: 'toggle',
ext: this,
}));
} else if (this.configured[d.ieeeAddr] === 2) {
ep.foundation('genOnOff', 'read', [{
attrId: 0, // onOff
}], this._handleCommandRespWithData.bind({
device: zdev,
ep: ep,
cid: 'genOnOff',
ctype: 'read',
ext: this,
}));
const state = this.configured[d.ieeeAddr];
if (state.waitresp) {
return;
}
if (state.retry < 3) {
if (state.stage === 0) {
state.retry += 1;
state.waitresp = true;
this._sendToggle(zdev, d.ieeeAddr, ep, state.retry);
} else if (state.stage === 1) {
state.retry += 1;
state.waitresp = true;
this._sendPoll(zdev, d.ieeeAddr, ep, state.retry);
}
}
}
}