andig / pimatic-fritz

Pimatic plugin for Fritz!Box SmartHome and FritzDect!200 Node
GNU General Public License v2.0
8 stars 6 forks source link

error [pimatic-fritz]: Cannot access undefined: undefined #15

Closed mwittig closed 8 years ago

mwittig commented 8 years ago

If my Fritz-DECT is not plugged-in I get the following error: error [pimatic-fritz]: Cannot access undefined: undefined. Apparently the frtz function does not return an error object as expected. Supposedly this is a bug in smartfritz-promise. I have tested with pimatic-fritz 0.3.0 plus patch published in PR #14

andig commented 8 years ago

Smartfritz always returns a promise. Could you give a line number for the error message, possibly using development mode?

mwittig commented 8 years ago

I have slightly modified the log outut locally to get the name of the fritzFunction. You should be able to reproduce the error by simply unplugging a registered DECT200.

18:29:49.135 [pimatic-fritz] Cannot access undefined while calling getThermostatList: undefined
Unhandled rejection TypeError: Object #<Object> has no method 'filter'
    at c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\smartfritz-promise\smartfritz.js:350:35
    at tryCatcher (c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\bluebird\js\release\util.js:11:23)
    at Promise._settlePromiseFromHandler (c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\bluebird\js\release\promise.js:488:31)
    at Promise._settlePromise (c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\bluebird\js\release\promise.js:545:18)
    at Promise._settlePromise0 (c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\bluebird\js\release\promise.js:590:10)
    at Promise._settlePromises (c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\bluebird\js\release\promise.js:673:18)
    at Async._drainQueue (c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\bluebird\js\release\async.js:125:16)
    at Async._drainQueues (c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\bluebird\js\release\async.js:135:10)
    at Async.drainQueues (c:\Users\marcus\Documents\Devel\pimatic-dev\node_modules\pimatic-fritz\node_modules\bluebird\js\release\async.js:16:14)
    at process._tickDomainCallback (node.js:492:13)
andig commented 8 years ago

Ok, this seems to happen here: https://github.com/andig/smartfritz/blob/master/smartfritz.js#L350

I assume you have the FritzBox running but not a single device attached? Need to look into that constellation.

Could you provide some debug output for me:

    env.logger.error(parser.toJson(devicelistinfo, {object:true}));
    env.logger.error(parser.toJson(devicelistinfo, {object:true, arrayNotation:true}));

right before that line?

mwittig commented 8 years ago

Yes, exactly. I only have a single smart plug to play with

andig commented 8 years ago

Please see update above. I've also added a testing branch for you, see https://github.com/andig/smartfritz/blob/fix-no-devices/smartfritz.js

mwittig commented 8 years ago

Regarding the requested log output I had use console.log as I placed the statement inside the getDeviceListInfoArray. Btw, I notice the exception orccurred regardless of whether or not DECT 200 was plugged in.

console.log("1", util.inspect(parser.toJson(devicelistinfo, {object:true}), { colors: true, depth: 4 }));
console.log("2", util.inspect(parser.toJson(devicelistinfo, {object:true, arrayNotation:true}), { colors: true, depth: 4}));
#
# DECT 200 plugged
#
1 { devicelist: 
   { version: '1',
     device: 
      { identifier: '08761 0183798',
        id: '16',
        functionbitmask: '896',
        fwversion: '03.37',
        manufacturer: 'AVM',
        productname: 'FRITZ!DECT 200',
        present: '1',
        name: 'FRITZ!DECT 200 &#35;1',
        switch: 
         { state: '0',
           mode: 'manuell',
           lock: '0' },
        powermeter: { power: '0', energy: '4251' },
        temperature: { celsius: '223', offset: '-5' } } } }
2 { devicelist: 
   [ { version: '1',
       device: 
        [ { identifier: '08761 0183798',
            id: '16',
            functionbitmask: '896',
            fwversion: '03.37',
            manufacturer: 'AVM',
            productname: 'FRITZ!DECT 200',
            present: [Object],
            name: [Object],
            switch: [Object],
            powermeter: [Object],
            temperature: [Object] } ] } ] }
#
# DECT 200 unplugged
#
1 { devicelist: 
   { version: '1',
     device: 
      { identifier: '08761 0183798',
        id: '16',
        functionbitmask: '896',
        fwversion: '03.37',
        manufacturer: 'AVM',
        productname: 'FRITZ!DECT 200',
        present: '0',
        name: 'FRITZ!DECT 200 &#35;1',
        switch: { state: {}, mode: {}, lock: {} },
        powermeter: { power: {}, energy: {} },
        temperature: { celsius: {}, offset: {} } } } }
2 { devicelist: 
   [ { version: '1',
       device: 
        [ { identifier: '08761 0183798',
            id: '16',
            functionbitmask: '896',
            fwversion: '03.37',
            manufacturer: 'AVM',
            productname: 'FRITZ!DECT 200',
            present: [Object],
            name: [Object],
            switch: [Object],
            powermeter: [Object],
            temperature: [Object] } ] } ] }
mwittig commented 8 years ago

Another thing I've noticed: If DECT 200 is unplugged and it is switch in pimatic no error message is given. Should I create another issue for this one?

andig commented 8 years ago

Another thing I've noticed: If DECT 200 is unplugged and it is switch in pimatic no error message is given. Should I create another issue for this one?

Yes please. Wondering if it should be an error or just be updated back to its previous state. The latter should already be working.

So what is the status on the issue above? Looking at the debug output I don't think that arrayNotation would be the right thing. When you're saying

Fritz-DECT is not plugged-in

it's still configured in FritzOS, right?

mwittig commented 8 years ago

Wondering if it should be an error or just be updated back to its previous state.

See my comment on the new issue "Switch turns to new state without error if DECT 200 is unplugged".

So what is the status on the issue above? Looking at the debug output I don't think that arrayNotation would be the right thing. When you're saying Fritz-DECT is not plugged-in it's still configured in FritzOS, right?

Yes, it is still configured and thus, the devicelist alway contain one device in my setup. Please also note in this context (as mentioned earlier), the exception is always thrown (without arrayNotation) regardless of whether or not the DECT 200 is plugged in. So you may be able to reproduce the problem if you only have a single device registered with your fritzbox.

As using arrayNotation will also turn the device itself into an array it is not the right way to go. Obviously, the devicelist must be an array because otherwise you cannot use "filter". I think the problem is due to the XML structure an object is returned if there is only a single device. I was struggling with the same problem when I tried to use the getDeviceListInfo method to obtain all device properties with a single call. See https://github.com/mwittig/pimatic-fritz/blob/master/fritz.coffee#L228-L235. A pragmatic solution would be to check the JSON result if devicelist contains an object to transform into an array.

andig commented 8 years ago

A pragmatic solution would be to check the JSON result if devicelist contains an object to transform into an array.

Exactly. I'll build a testcase and fix.

andig commented 8 years ago

Fixed via https://github.com/andig/smartfritz/commit/1dfafef8f45b2c9ca75a45116da284b67537db44 in 0.4.2 of smartfritz.