Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retry when the device is offline #59

Merged
merged 24 commits into from
Dec 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions accessories/accessory.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class BroadlinkRMAccessory extends HomebridgeAccessory {
// Itterate through each hex config in the array
for (let index = 0; index < data.length; index++) {
const { pause } = data[index];

await this.performRepeatSend(data[index], actionCallback);

if (pause) {
Expand All @@ -65,7 +64,7 @@ class BroadlinkRMAccessory extends HomebridgeAccessory {
async performRepeatSend (parentData, actionCallback) {
const { host, log, name, debug } = this;
let { data, interval, sendCount } = parentData;

sendCount = sendCount || 1
if (sendCount > 1) interval = interval || 0.1;

Expand Down
4 changes: 2 additions & 2 deletions accessories/aircon.js
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,8 @@ class AirConAccessory extends BroadlinkRMAccessory {
// If the device is no longer available, use previous tempeature
const device = getDevice({ host, log });

if (!device || device.state === 'inactive') {
if (device && device.state === 'inactive') {
if (!device || device.state !== 'active') {
if (device && device.state !== 'active') {
log(`${name} addTemperatureCallbackToQueue (device no longer active, using existing temperature)`);
}

Expand Down
2 changes: 1 addition & 1 deletion accessories/switch.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class SwitchAccessory extends BroadlinkRMAccessory {
const { data, host, log, name, debug } = this;
this.stateChangeInProgress = true;
this.reset();

if (hexData) await this.performSend(hexData);

this.checkAutoOnOff();
Expand Down
43 changes: 23 additions & 20 deletions helpers/getDevice.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ const broadlink = require('./broadlink')
const delayForDuration = require('./delayForDuration')

const pingFrequency = 5000;
const pingTimeout = 5;
const pingTimeout = 3;
const pingRetries = 3;

const startPing = (device, log) => {
device.state = 'unknown';
var retryCount = 1;
var retryCount = 0;

setInterval(() => {
try {
Expand All @@ -17,24 +18,26 @@ const startPing = (device, log) => {
active = false;
}

if (!active && device.state === 'active' && retryCount === 2) {
log(`\x1b[31m[ERROR] \x1b[0m Broadlink RM device at ${device.host.address} (${device.host.macAddress || ''}) is no longer reachable after three attempts.`);

device.state = 'inactive';
retryCount = 0;
} else if (!active && device.state === 'active') {
if(broadlink.debug) log(`Broadlink RM device at ${device.host.address} (${device.host.macAddress || ''}) is no longer reachable. (attempt ${retryCount})`);

retryCount += 1;
} else if (active && device.state !== 'active') {
if (device.state === 'inactive') log(`Broadlink RM device at ${device.host.address} (${device.host.macAddress || ''}) has been re-discovered.`);

device.state = 'active';
retryCount = 0;
} else if (active && retryCount !== 0 ) {
//Acive - reset retry counter
retryCount = 0;
}
if(active){
if(device.state !== 'active') {
if (device.state === 'offline') log(`Broadlink RM device at ${device.host.address} (${device.host.macAddress || ''}) has been re-discovered.`);
device.state = 'active';
retryCount = 0;
}
}else{
if(retryCount > pingRetries && device.state !== 'offline'){
//Last attempt, mark offline
log(`\x1b[31m[ERROR] \x1b[0m Broadlink RM device at ${device.host.address} (${device.host.macAddress || ''}) is no longer reachable after three attempts.`);

device.state = 'offline';
}else if(retryCount <= pingRetries){
//Inital Attempts
if(broadlink.debug) log(`Broadlink RM device at ${device.host.address} (${device.host.macAddress || ''}) is no longer reachable. (attempt ${retryCount})`);

device.state = 'inactive';
retryCount += 1;
}
}
}, {timeout: pingTimeout})
} catch (err) {
log(`\x1b[31m[ERROR] \x1b[0m Error pinging Broadlink RM device at ${device.host.address} (${device.host.macAddress || ''}): ${err}`);
Expand Down
77 changes: 66 additions & 11 deletions helpers/sendData.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,88 @@ const assert = require('assert')
const { getDevice } = require('./getDevice');
const convertProntoCode = require('./convertProntoCode')

module.exports = ({ host, hexData, log, name, debug }) => {
const retryInterval = 3000;
const retryCount = 6;

const sendData = async ({host, hexData, log, name, debug}) => {
// Will return true on sucess and flase on failure
assert(hexData && typeof hexData === 'string', `\x1b[31m[ERROR]: \x1b[0m${name} sendData (HEX value is missing)`);

// Check for pronto code
if (hexData.substring(0, 4) === '0000') {
if (debug) log(`\x1b[33m[DEBUG]\x1b[0m ${name} sendHex (Converting Pronto code "${hexData}" to Broadlink code)`);
hexData = convertProntoCode(hexData)
hexData = convertProntoCode(hexData);
if (debug) log(`\x1b[33m[DEBUG]\x1b[0m ${name} sendHex (Pronto code successfuly converted: "${hexData}")`);

if (!hexData) return log(`\x1b[31m[ERROR] \x1b[0m${name} sendData (A Pronto code was detected however its conversion to a Broadlink code failed.)`);

if (!hexData) {
log(`\x1b[31m[ERROR] \x1b[0m${name} sendData (A Pronto code was detected however its conversion to a Broadlink code failed.)`);
return false;
}

}

// Get the Broadlink device
const device = getDevice({ host, log });

if (!device) {
if (!host) return log(`\x1b[31m[ERROR] \x1b[0m${name} sendData (no device found)`);
if (!host) {
log(`\x1b[31m[ERROR] \x1b[0m${name} sendData (no device found)`);
return false;
}

log(`\x1b[31m[ERROR] \x1b[0m${name} sendData (no device found at ${host})`);
return false;
}

return log(`\x1b[31m[ERROR] \x1b[0m${name} sendData (no device found at ${host})`);
if (!device.sendData) {
log(`\x1b[31m[ERROR] \x1b[0mThe device at ${device.host.address} (${device.host.macAddress}) doesn't support the sending of IR or RF codes.`);
return false;
}
if (hexData.includes('5aa5aa555')) {
log(`\x1b[31m[ERROR] \x1b[0mThis type of hex code (5aa5aa555...) is no longer valid. Use the included "Learn Code" accessory to find new (decrypted) codes.`);
return false;
}

if (!device.sendData) return log(`\x1b[31m[ERROR] \x1b[0mThe device at ${device.host.address} (${device.host.macAddress}) doesn't support the sending of IR or RF codes.`);
if (hexData.includes('5aa5aa555')) return log(`\x1b[31m[ERROR] \x1b[0mThis type of hex code (5aa5aa555...) is no longer valid. Use the included "Learn Code" accessory to find new (decrypted) codes.`);
waitForDevice(device, name, log, debug)
.then(() => {
const hexDataBuffer = new Buffer(hexData, 'hex');
device.sendData(hexDataBuffer, debug, hexData);
log(`${name} sendHex (${device.host.address}; ${device.host.macAddress}) ${hexData}`);
return true;
})
.catch(() => {
log(`\x1b[31m[ERROR] \x1b[0mThe device at ${device.host.address} (${device.host.macAddress}) is not available.`);
return false;
});

return false;
}

const waitForDevice = (device, name, log, debug) => {
return new Promise(async (res, rej) => {
let count = 0;

while (device.state !== 'active' && count < retryCount ) {
if(debug) log(`\x1b[33m[DEBUG]\x1b[0m ${name} Device ${device.state}, pausing (attempt ${count+1})...`);
count++;

await wait(retryInterval);
}

const hexDataBuffer = new Buffer(hexData, 'hex');
device.sendData(hexDataBuffer, debug, hexData);
if (count >= retryCount) {
rej();
}

log(`${name} sendHex (${device.host.address}; ${device.host.macAddress}) ${hexData}`);
res();
});
}

const wait = delay => {
return new Promise(res => {
setTimeout(() => {
res();
}, delay);
});
}

module.exports = sendData
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "homebridge-broadlink-rm-tv",
"version": "4.0.3",
"version": "4.0.4",
"description": "Broadlink RM plugin (including the mini and pro) for homebridge: https://github.com/nfarina/homebridge",
"license": "ISC",
"scripts": {
Expand Down