Noisy Polling Results for Switches?

Discussions about Z-Way software and Z-Wave technology in general
Post Reply
markolbert
Posts: 64
Joined: 16 Oct 2014 06:09

Noisy Polling Results for Switches?

Post by markolbert »

I've written a node app which controls various light switches around my home. These are US switches without the ability to notify the controller when they've been manually adjusted. They also don't support the Hail command. So in order to tell what level they're at I poll them periodically.

In doing that polling I'm noticing an odd situation. I'm currently logging every polling instance where the returned level has changed from its earlier value. The log is filled with items like the following:
01/24/2016 09:10:00 AM - info: switch Kitchen (15) level changed from 99 to 0
01/24/2016 09:10:30 AM - info: switch Kitchen (15) level changed from 0 to 99
01/24/2016 09:17:00 AM - info: switch Kitchen (15) level changed from 99 to 0
01/24/2016 09:17:30 AM - info: switch Kitchen (15) level changed from 0 to 99
01/24/2016 09:18:00 AM - info: switch Front Lights (26) level changed from 0 to 99
01/24/2016 09:18:30 AM - info: switch Front Lights (26) level changed from 99 to 0
01/24/2016 09:18:30 AM - info: switch Upstairs Hallway (17) level changed from 0 to 99
01/24/2016 09:19:00 AM - info: switch Kitchen (15) level changed from 99 to 0
01/24/2016 09:19:00 AM - info: switch Upstairs Hallway (17) level changed from 99 to 0
I'm polling about eight switches every 30 seconds (so far as I can tell, it takes less than a second for the z-way server to process all the jobs involved).

The polling code itself is relatively simple (this is in a node module):

Code: Select all

ZWave.prototype.curLevel = function (nodeNumber) {
    var self = this;
    
    return self.pollDevice(nodeNumber).then( function( exists ) {
        return self.getLastLevel( nodeNumber );
    } );
};

ZWave.prototype.getLastLevel = function( nodeNumber ) {
    var self = this;
    
    return self.requestAsync( sprintf( '/Run/devices[%d].instances[0].commandClasses[0x20].data.level.valueOf()', nodeNumber ) )
        .then( function( value ) {
            return value;
        } )
        .catch( function( error ) {
            winston.error( sprintf( 'getLastLevel(%d): %s', nodeNumber, error ) );
        } );
};

ZWave.prototype.pollDevice = function( nodeNumber ) {
    var self = this;
    
    return self.requestAsync( sprintf( '/Run/devices[%d].instances[0].commandClasses[0x20].Get()', nodeNumber ) )
        .then( function( value ) {
            return ( value == 'null' );
        } )
        .catch( function( error ) {
            winston.error( sprintf( 'pollDevice(%d): %s', nodeNumber, error ) );
        } );
};

ZWave.prototype.requestAsync = function (path) {
    var self = this;
    
    return new Promise(function (resolve, reject) {
        var request = http.request({
            hostname: self.server,
            port: self.port,
            path: '/ZWaveAPI/' + path,
            method: 'POST',
        }, function (response) {
            // Bundle the result
            var body = '';
            
            // Build the body
            response.on('data', function (chunk) {
                body += chunk;
            });
            
            // wait until all data received to resolve
            response.on('end', function () {
                resolve(body);
            });
        });
        
        // Handle errors
        request.on('error', function (error) {
            winston.error('Problem with request', error);
            reject(error);
        });
        
        // Must always call .end() even if there is no data being written to the request body
        request.end();
    });
};
In a nutshell, I'm doing a get() against a particular node in pollDevice(), and then doing a separate call to retrieve the value of the device's level in getLastLevel(). The requests are all built around bluebird promises, which simply do a POST against ZWaveAPI and then parse the result.

I'm not currently doing any kind of error checking, and I'm issuing the request for level value immediately after the initial get() against a node. I think that may be the source of the problem -- because it takes time for the z-way server to communicate with the switch -- but I thought the docs say that the pre-existing level value should be unchanged until z-way hears back from the switch, but that the pre-existing level will be marked as invalidated until z-way hears back. Which wouldn't explain why the retrieved value keeps jumping back and forth.

Thoughts on what's going on, and how to fix it/work around it would be most appreciated.
viper384
Posts: 42
Joined: 18 Feb 2015 05:25

Re: Noisy Polling Results for Switches?

Post by viper384 »

Your code seems complex to me, I can't help debugging it, I'm not even sure how to load it. However I do know what you ask for can be easily accomplished with a couple of HTTP requests, maybe that will help?

Poll the switch

Code: Select all

http://$zwaveMeSrv/ZWaveAPI/Run/devices[$1].instances[0].commandClasses[25].Get()
Retrieve the updated value

Code: Select all

http://$zwaveMeSrv/ZWaveAPI/Run/devices[$1].instances[0].commandClasses[0x25].data.level.value
In ZAutomation there is a "Periodic Switch Poller" app, but the lowest interval is 1 minute :(.
Post Reply