plasticrake / tplink-smarthome-api

TP-Link Smarthome WiFi API
MIT License
1.02k stars 141 forks source link

TCP timeout; no handling of PromiseRejection #60

Closed NorwegianSailor closed 5 years ago

NorwegianSailor commented 5 years ago

It might be a problem in my code, but I do not believe so since I have used your code examples and get the same error message. At timeout at TCP timeout there is no handling of PromiseRejection. Here is the print out from my console window. TCP Timeout [Hanse385] device.send() Error: TCP Timeout (node:21555) UnhandledPromiseRejectionWarning: Error: TCP Timeout at Timeout.setTimeout [as _onTimeout] (/home/pi/baatserver2/node_modules/tplink-smarthome-api/lib/client.js:225:20) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:21555) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. TCP Timeout [Hanse385] device.send() Error: TCP Timeout (node:21555) UnhandledPromiseRejectionWarning: Error: TCP Timeout at Timeout.setTimeout [as _onTimeout] (/home/pi/baatserver2/node_modules/tplink-smarthome-api/lib/client.js:225:20) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2) TCP Timeout [Hanse385] device.send() Error: TCP Timeout (node:21555) UnhandledPromiseRejectionWarning: Error: TCP Timeout at Timeout.setTimeout [as _onTimeout] (/home/pi/baatserver2/node_modules/tplink-smarthome-api/lib/client.js:225:20) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3) TCP Timeout [Hanse385] device.send() Error: TCP Timeout (node:21555) UnhandledPromiseRejectionWarning: Error: TCP Timeout at Timeout.setTimeout [as _onTimeout] (/home/pi/baatserver2/node_modules/tplink-smarthome-api/lib/client.js:225:20) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4) TCP Timeout [Hanse385] device.send() Error: TCP Timeout (node:21555) UnhandledPromiseRejectionWarning: Error: TCP Timeout at Timeout.setTimeout [as _onTimeout] (/home/pi/baatserver2/node_modules/tplink-smarthome-api/lib/client.js:225:20) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 5) TCP Timeout [Hanse385] device.send() Error: TCP Timeout (node:21555) UnhandledPromiseRejectionWarning: Error: TCP Timeout at Timeout.setTimeout [as _onTimeout] (/home/pi/baatserver2/node_modules/tplink-smarthome-api/lib/client.js:225:20) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 6) TCP Timeout [Hanse385] device.send() Error: TCP Timeout (node:21555) UnhandledPromiseRejectionWarning: Error: TCP Timeout at Timeout.setTimeout [as _onTimeout] (/home/pi/baatserver2/node_modules/tplink-smarthome-api/lib/client.js:225:20) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 7) TCP Timeout [Hanse385] device.send() Error: TCP Timeout (node:21555) UnhandledPromiseRejectionWarning: Error: TCP Timeout at Timeout.setTimeout [as _onTimeout] (/home/pi/baatserver2/node_modules/tplink-smarthome-api/lib/client.js:225:20) at ontimeout (timers.js:498:11) at tryOnTimeout (timers.js:323:5) at Timer.listOnTimeout (timers.js:290:5) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 8) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 9) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 10) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 11) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 12) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 13) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 14) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 15) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 16) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 17) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 18) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 19) [Hanse385] device.send() Error: connect EHOSTUNREACH 192.168.1.103:9999 (node:21555) UnhandledPromiseRejectionWarning: Error: connect EHOSTUNREACH 192.168.1.103:9999 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1191:14) (node:21555) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 20) A client connected and the IP address is: 66.102.9.23

Kind regards Svein Thorstensen A retired R&D manager. Have not worked as a SW engineer since late 80's and today a real beginner in javascript ..........on hobby basis and refreshing my C and C++ knowledge

plasticrake commented 5 years ago

If you can provide the code it would be helpful. Also try wrapping your code and errors with ``` https://help.github.com/articles/creating-and-highlighting-code-blocks/

NorwegianSailor commented 5 years ago

Hi, Attached is my code. I have used the example found in the example folder.

'use strict';
const util = require('util');
const { Client } = require('tplink-smarthome-api');
const client = new Client();
var io;

exports.startPollingPowerPlug = function(socket,callback){
    io=socket;

// Client events `device-*` also have `bulb-*` and `plug-*` counterparts.
// Use those if you want only events for those types and not all devices.
client.on('device-new', (device) => {
    device.startPolling(5000);
    if (device.alias === 'Hanse385'){
        callback('Polling is startet on device '+device.alias, device);
    }

  // Device (Common) Events
    device.on('emeter-realtime-update', (emeterRealtime) => {
        if (device.alias === 'Hanse385'){
        io.emit('landstromdata',emeterRealtime);
        }
    });

    //Plug Events
    /** 
    device.on('power-on', () => { logEvent('power-on', device); });
    device.on('power-off', () => { logEvent('power-off', device); });
    device.on('in-use', () => { logEvent('in-use', device); });
    device.on('not-in-use', () => { logEvent('not-in-use', device); });
    device.on('in-use-update', (inUse) => { logEvent('in-use-update', device, inUse); });
**/

  // Bulb Events
  /**
  device.on('lightstate-on', (lightstate) => { logEvent('lightstate-on', device, lightstate); });
  device.on('lightstate-off', (lightstate) => { logEvent('lightstate-off', device, lightstate); });
  device.on('lightstate-change', (lightstate) => { logEvent('lightstate-change', device, lightstate); });
  device.on('lightstate-update', (lightstate) => { logEvent('lightstate-update', device, lightstate); });
  * **/
});
//client.on('device-online', (device) => { logEvent('device-online', device); });
//client.on('device-offline', (device) => { logEvent('device-offline', device); });

console.log('Starting Device Discovery');
client.startDiscovery({
    deviceTypes: ['plug'],
    discoveryTimeout: 20000
});

}
plasticrake commented 5 years ago

Hi @NorwegianSailor, I wrapped your code with ``` to make it more readable, please format it appropriately. https://help.github.com/articles/creating-and-highlighting-code-blocks/

I think the issue may be with device.startPolling(5000). It is a function that I don't use myself and haven't put much work into, I really just made it for the examples.

  startPolling (interval) {
    // TODO
    this.pollingTimer = setInterval(() => {
      this.getInfo();
    }, interval);
    return this;
  }

I think the getInfo call is where the unhandled exception is coming from. I recommend you try implementing your own version of startPolling yourself instead of calling startPolling

I'll leave this issue open so maybe I can revisit this function to improve it.

hufftheweevil commented 5 years ago

I'm having the same issue. I, too, suspected it was the getInfo call.

At first I thought this would do the trick and also match your other methods:

  startPolling(interval) {
    return new Promise((resolve, reject) => {
      this.pollingTimer = setInterval(() => {
        this.getInfo()
          .then(resolve)
          .catch(reject);
      }, interval);
    })
  }

But then I realized that a promise only ever resolves/rejects once.

An alternate way to do it (although not as pretty):

  startPolling(interval, errorHandler) {
    if (typeof errorHandler !== 'function') errorHandler = () => {}
    this.pollingTimer = setInterval(() => {
      this.getInfo().catch(errorHandler);
    }, interval);
    return this;
  }

So that's the way I'm doing it for now. I can create a PR if you want.

Side question: what's the difference between the two TP Link commands get_info() and get_sysInfo()?

plasticrake commented 5 years ago

Thanks @hufftheweevil, i will have to take a look at this more in depth. I think I'd lean on emitting an error event over a callback.

Depends on which getInfo() you're taking about, from the plug.getInfo() docs:

plug.getInfo([sendOptions]) ⇒ Promise.<Object, Error>

Requests common Plug status details in a single request.

    system.get_sysinfo
    cloud.get_sysinfo
    emeter.get_realtime
    schedule.get_next_action

It sends this command:

this.sendCommand('{"emeter":{"get_realtime":{}},"schedule":{"get_next_action":{}},"system":{"get_sysinfo":{}},"cnCloud":{"get_info":{}}}', this.childId, sendOptions);
hufftheweevil commented 5 years ago

That sounds like a good way to handle it too.

Disregard my question about those get functions - I was confusing myself. I was thinking the getInfo() call inside startPolling() was referring to the one in shared/cloud.js, but now I realize that it's using the one in plug/index.js and bulb/index.js.