Skip to content

Commit

Permalink
fix: Obey stateChangeResponse time for PriorityQueuePolling. Change t…
Browse files Browse the repository at this point in the history
…o constants as well
  • Loading branch information
ztalbot2000 committed Apr 26, 2021
1 parent a901a69 commit eb94eeb
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 45 deletions.
45 changes: 32 additions & 13 deletions Cmd4Accessory.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ class Cmd4Accessory

// Bring the parent config variables forward.
// If they do not exist, they would still be undefined.
this.stateChangeResponseTime = ( parentInfo && parentInfo.stateChangeResponseTime ) ? parentInfo.stateChangeResponseTime : constants.DEFAULT_INTERVAL;
// For stateChangeResponseTime, if not the parentInfo, then
// it gets defined by the accessoryType devicesStateChangeDefaultTime
if ( parentInfo && parentInfo.stateChangeResponseTime )
this.stateChangeResponseTime = parentInfo.stateChangeResponseTime;

this.interval = ( parentInfo && parentInfo.interval ) ? parentInfo.interval : constants.DEFAULT_INTERVAL;
this.timeout = ( parentInfo && parentInfo.timeout ) ? parentInfo.timeout : constants.DEFAULT_TIMEOUT;
this.statusMsg = ( parentInfo && parentInfo.statusMsg ) ? parentInfo.statusMsg : constants.DEFAULT_STATUSMSG;
Expand Down Expand Up @@ -142,7 +146,7 @@ class Cmd4Accessory
// number or MAC address.
let UUID = getAccessoryUUID( config, this.api.hap.uuid );

let existingData = this.STORED_DATA_ARRAY.find( data => data[constants.UUID] === UUID );
let existingData = this.STORED_DATA_ARRAY.find( data => data[ constants.UUID ] === UUID );
if ( existingData )
{
this.log.debug(`Cmd4Accessory: found existingData for ${ this.displayName }` );
Expand All @@ -159,8 +163,8 @@ class Cmd4Accessory
// restarts.
this.storedValuesPerCharacteristic = new Array( CMD4_ACC_TYPE_ENUM.EOL ).fill( null );

this.STORED_DATA_ARRAY.push( { [constants.UUID]: UUID,
[constants.storedValuesPerCharacteristic]: this.storedValuesPerCharacteristic
this.STORED_DATA_ARRAY.push( { [ constants.UUID ]: UUID,
[ constants.storedValuesPerCharacteristic ]: this.storedValuesPerCharacteristic
}
);
}
Expand Down Expand Up @@ -641,7 +645,7 @@ class Cmd4Accessory

let characteristicString = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type;

var transposed = { "value": value, "rc": true, "msg": "" };
var transposed = { [ constants.VALUE_lv ]: value, [ constants.RC_lv ]: true, [ constants.MSG_lv ]: "" };
if ( self.outputConstants == true )
{
transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, value );
Expand Down Expand Up @@ -751,7 +755,7 @@ class Cmd4Accessory
// a Constant to its valid value.
// I can't see this happening, but who knows between upgrades
// or restarts.
var transposed = { "value": storedValue, "rc": true, "msg": "" };
var transposed = { [ constants.VALUE_lv ]: storedValue, [ constants.RC_lv ]: true, [ constants.MSG_lv ]: "" };
transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, storedValue );
if ( transposed.rc == false )
self.log.warn( `${ self.displayName }: ${ transposed.msg }`);
Expand Down Expand Up @@ -1017,7 +1021,7 @@ class Cmd4Accessory

// Even if outputConsts is not set, just in case, transpose
// it anyway.
var transposed = { "value": unQuotedReply, "rc": true, "msg": "" };
var transposed = { [ constants.VALUE_lv ]: unQuotedReply, [ constants.RC_lv ]: true, [ constants.MSG_lv ]: "" };
transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, unQuotedReply )
if ( transposed.rc == false )
self.log.warn( `${ self.displayName }: ${ transposed.msg }`);
Expand Down Expand Up @@ -1778,7 +1782,7 @@ class Cmd4Accessory
if ( Object.keys( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].validValues ).length > 0 )
{
// Even if outputConsts is not set, just in case, transpose it anyway.
var transposed = { "value": value, "rc": true, "msg": "" };
var transposed = { [ constants.VALUE_lv ]: value, [ constants.RC_lv ]: true, [ constants.MSG_lv ]: "" };
transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, value ) ;

if ( transposed.rc == false )
Expand Down Expand Up @@ -2267,7 +2271,7 @@ class Cmd4Accessory
if ( this.CMD4 == constants.PLATFORM && ( ! this.publishExternally || ! this.category ) ||
this.CMD4 == constants.STANDALONE )
{
this.log.warn( 'Televisions should be Platform Accessories with "publishExternally": true, "category": "TELEVISION"' );
this.log.warn( `Televisions should be Platform Accessories with "${ constants.PUBLISHEXTERNALLY }": true, "${ constants.CATEGORY }": "TELEVISION"` );
}
if ( this.CMD4 == constants.PLATFORM && ! this.publishExternally && ( numberOfTVsPerBridge += 1 ) > 1 )
{
Expand Down Expand Up @@ -2333,6 +2337,10 @@ class Cmd4Accessory
// Heirarchy is first the default
let timeout = constants.DEFAULT_TIMEOUT;
let interval = constants.DEFAULT_INTERVAL;
let stateChangeResponseTime = constants.DEFAULT_STATE_CHANGE_RESPONSE_TIME;
if ( ! accessory.stateChangeResponseTime )
stateChangeResponseTime = CMD4_DEVICE_TYPE_ENUM.properties[ accessory.typeIndex ].devicesStateChangeDefaultTime;

let queueName = constants.DEFAULT_QUEUE_NAME;

// Secondly the accessories definition
Expand All @@ -2354,11 +2362,13 @@ class Cmd4Accessory
timeout = pollingEntrys[0].timeout;
if ( pollingEntrys[0].interval )
interval = pollingEntrys[0].interval;
if ( pollingEntrys[0].stateChangeResponseTime )
stateChangeResponseTime = pollingEntrys[0].stateChangeResponseTime;
if ( pollingEntrys[0].queueName )
queueName = pollingEntrys[0].queueName;
}

return { "timeout": timeout, "interval": interval, "queueName": queueName };
return { [ constants.TIMEOUT_lv ]: timeout, [ constants.INTERVAL_lv ]: interval, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: stateChangeResponseTime, [ constants.QUEUE_NAME_lv ]: queueName };

}

Expand Down Expand Up @@ -2390,14 +2400,18 @@ class Cmd4Accessory
let jsonPollingConfig = accessory.polling[ jsonIndex ];
queueName = constants.DEFAULT_QUEUE_NAME;

// The default timeout is defined frist by the accessory, and if not defined,
// The default timeout is defined first by the accessory, and if not defined,
// then the default 1 minute. Timeouts are in milliseconds
let timeout = ( this.timeout ) ? this.timeout : constants.DEFAULT_TIMEOUT;

// The default interval is defined first by the accessory, and if not defined,
// then the default 1 minute interval. Intervals are in seconds
let interval = ( this.interval ) ? this.interval : constants.DEFAULT_INTERVAL;

// The default stateChangeResponseTime is defined first by the accessory, and if not defined,
// then the default 3 seconds. stateChangeResponseTime is in seconds
let stateChangeResponseTime = ( this.stateChangeResponseTime ) ? this.stateChangeResponseTime : constants.DEFAULT_STATE_CHANGE_RESPONSE_TIME;

let value;
let accTypeEnumIndex = -1;

Expand All @@ -2419,6 +2433,11 @@ class Cmd4Accessory
case constants.INTERVAL:
// Intervals are in seconds
interval = parseInt( value, 10 ) * 1000;
break;
case constants.STATECHANGERESPONSETIME:
// respnse time is in seconds
stateChangeResponseTime = value * 1000;

break;
case constants.QUEUE:
{
Expand Down Expand Up @@ -2492,7 +2511,7 @@ class Cmd4Accessory

log.debug( `Setting up accessory: ${ accessory.displayName } for polling of: ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type } timeout: ${ timeout } interval: ${ interval }` );

settings.arrayOfPollingCharacteristics.push( {"accessory": accessory, "accTypeEnumIndex": accTypeEnumIndex, "interval": interval, "timeout": timeout, "queueName": queueName } );
settings.arrayOfPollingCharacteristics.push( { [ constants.ACCESSORY_lv ]: accessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: accTypeEnumIndex, [ constants.INTERVAL_lv ]: interval, [ constants.TIMEOUT_lv ]: timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: stateChangeResponseTime, [ constants.QUEUE_NAME_lv ]: queueName } );

}
break;
Expand All @@ -2511,7 +2530,7 @@ class Cmd4Accessory
// Make sure the defined characteristics will be polled
CMD4_DEVICE_TYPE_ENUM.properties[ accessory.typeIndex ].defaultPollingCharacteristics.forEach( defaultPollingAccTypeEnumIndex =>
{
settings.arrayOfPollingCharacteristics.push( {"accessory": accessory, "accTypeEnumIndex": defaultPollingAccTypeEnumIndex, "timeout": accessory.timeout } );
settings.arrayOfPollingCharacteristics.push( { [ constants.ACCESSORY_lv ]: accessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: defaultPollingAccTypeEnumIndex, [ constants.INTERVAL_lv ]: accessory.interval, [ constants.TIMEOUT_lv ]: accessory.timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: constants.DEFAULT_STATE_CHANGE_RESPONSE_TIME, [ constants.QUEUE_NAME_lv ]: constants.DEFAULT_QUEUE_NAME } );
});

}
Expand Down
12 changes: 6 additions & 6 deletions Cmd4Platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -778,16 +778,16 @@ class Cmd4Platform
let details = self.lookupDetailsForPollingCharacteristic( self, accTypeEnumIndex );
let specificQueue = settings.listOfCreatedPriorityQueues[ details.queueName ];
// Add To Top of priority queue
// ( isSet, isPolled, accessory, accTypeEnumIndex, interval, timeout, callback, value )
specificQueue.addQueueEntry( false, false, self, accTypeEnumIndex, details.interval, details.timeout, callback, null );
// ( isSet, isPolled, accessory, accTypeEnumIndex, interval, timeout, stateChangeResponseTime, callback, value )
specificQueue.addQueueEntry( false, false, self, accTypeEnumIndex, details.interval, details.timeout, details.stateChangeResponseTime, callback, null );
}
prioritySetValue( accTypeEnumIndex, value, callback )
{
let self = this;
let details = self.lookupDetailsForPollingCharacteristic( self, accTypeEnumIndex );
let specificQueue = settings.listOfCreatedPriorityQueues[ details.queueName ];
//specificQueue.addQueueEntry( isSet, isPolled, accessory, accTypeEnumIndex, interval, timeout, callback, value )
specificQueue.addQueueEntry( true, false, self, accTypeEnumIndex, details.interval, details.timeout, callback, value )
//specificQueue.addQueueEntry( isSet, isPolled, accessory, accTypeEnumIndex, interval, timeout, stateChangeResponseTime, callback, value )
specificQueue.addQueueEntry( true, false, self, accTypeEnumIndex, details.interval, details.timeout, details.stateChangeResponseTime, callback, value )
// todo if ( relatedCharacteristic )
// todo AddToTopOfQueueBehindSet( get
}
Expand Down Expand Up @@ -845,8 +845,8 @@ class Cmd4Platform
settings.listOfCreatedPriorityQueues[ elem.queueName ] = queue;
}
this.log.debug( `Adding ${ elem.accessory.displayName } ${ CMD4_ACC_TYPE_ENUM.properties[ elem.accTypeEnumIndex ].type } elem.timeout: ${ elem.timeout } elem.interval: ${ elem.interval } to Polled Queue ${ elem.queueName }` );
// ( isSet, isPolled, accessory, accTypeEnumIndex, interval, timeout, callback, value )
queue.addQueueEntry( false, true, elem.accessory, elem.accTypeEnumIndex, elem.interval, elem.timeout, null, null )
// ( isSet, isPolled, accessory, accTypeEnumIndex, interval, timeout, stateChangeResponseTime, callback, value )
queue.addQueueEntry( false, true, elem.accessory, elem.accTypeEnumIndex, elem.interval, elem.timeout, elem.stateChangeResponseTime, null, null )

});

Expand Down
40 changes: 23 additions & 17 deletions Cmd4PriorityPollingQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ class Cmd4PriorityPollingQueue
this.originalInterval = 0;
this.optimalInterval = 0;
}
addQueueEntry( isSet, isPolled, accessory, accTypeEnumIndex, interval, timeout, callback, value )
addQueueEntry( isSet, isPolled, accessory, accTypeEnumIndex, interval, timeout, stateChangeResponseTime, callback, value )
{
if ( isSet || ! isSet && !isPolled )
{
// A mixture of gets and sets, all from IOS though
this.highPriorityQueue.push( { "isSet": isSet, "isPolled": isPolled, "accessory": accessory, "accTypeEnumIndex": accTypeEnumIndex, "interval": interval, "timeout": timeout, "callback": callback, "value": value } );
this.highPriorityQueue.push( { [ constants.IS_SET_lv ]: isSet, [ constants.IS_POLLED_lv ]: isPolled, [ constants.ACCESSORY_lv ]: accessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: accTypeEnumIndex, [ constants.INTERVAL_lv ]: interval, [ constants.TIMEOUT_lv ]: timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: stateChangeResponseTime, [ constants.CALLBACK_lv ]: callback, [ constants.VALUE_lv ]: value } );
if ( this.queueStarted == true )
{
// We cant have a low priority timer going off starting the queue
Expand All @@ -60,12 +60,12 @@ class Cmd4PriorityPollingQueue
} else
{
// These are all gets from polling
this.lowPriorityQueue.push( { "isSet": isSet, "isPolled": isPolled, "accessory": accessory, "accTypeEnumIndex": accTypeEnumIndex, "interval": interval, "timeout": timeout, "callback": callback, "value": value } );
this.lowPriorityQueue.push( { [ constants.IS_SET_lv ]: isSet, [ constants.IS_POLLED_lv ]: isPolled, [ constants.ACCESSORY_lv ]: accessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: accTypeEnumIndex, [ constants.INTERVAL_lv ]: interval, [ constants.TIMEOUT_lv ]: timeout, [ constants.CALLBACK_lv ]: callback, [ constants.VALUE_lv ]: value } );

if ( this.currentIntervalBeingUsed == 0 )
{
if ( this.queueMsg == true )
this.log.info( `Interval being used for queue: "${ this.queueName }" is from ${ accessory.displayName } ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type } interval: ${ interval }` );
this.log.info( `Interval being used for queue: "${ this.queueName }" is from ${ accessory.displayName } ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type } ${ constants.INTERVAL_lv }: ${ interval }` );
this.currentIntervalBeingUsed = interval;
this.optimalInterval = interval;
this.originalInterval = interval;
Expand All @@ -90,7 +90,7 @@ class Cmd4PriorityPollingQueue
let relatedCurrentAccTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties[ entry.accTypeEnumIndex ].relatedCurrentAccTypeEnumIndex;
if ( relatedCurrentAccTypeEnumIndex != null &&
settings.arrayOfPollingCharacteristics.filter( entry => entry.accessory.UUID == self.UUID &&
entry.accTypeEnumIndex == relatedCurrentAccTypeEnumIndex
entry.accTypeEnumIndex == 999
).length > 0 &&
isRelatedTargetCharacteristicInSameDevice(
self.typeIndex,
Expand All @@ -102,23 +102,29 @@ class Cmd4PriorityPollingQueue
{
let pollingID = Date.now( );
let relatedCharacteristic = CMD4_ACC_TYPE_ENUM.properties[ relatedCurrentAccTypeEnumIndex ].characteristic;
entry.accessory.getValue( relatedCharacteristic, function ( error, properValue, returnedPollingID )
{
// This function should only be called once, noted by the pollingID.
if ( pollingID != returnedPollingID )
let stateChangeResponseTime = entry.stateChangeResponseTime;
if ( stateChangeResponseTime < this.currentIntervalBeingUsed * .5 )
stateChangeResponseTime = this.currentIntervalBeingUsed * .5;

setTimeout(() => {
entry.accessory.getValue( relatedCharacteristic, function ( error, properValue, returnedPollingID )
{
entry.accessory.log.info("More entries for pollingID for related get");
// This function should only be called once, noted by the pollingID.
if ( pollingID != returnedPollingID )
{
entry.accessory.log.info("More entries for pollingID for related get");

return;
}
return;
}

pollingID = -1;
pollingID = -1;

entry.callback( error );
entry.callback( error );

setTimeout( ( ) => { self.processQueue( ); }, 0);
setTimeout( ( ) => { self.processQueue( ); }, 0);

}, pollingID );
}, pollingID );
}, stateChangeResponseTime );
} else {

entry.callback( error );
Expand All @@ -136,7 +142,7 @@ class Cmd4PriorityPollingQueue
// This function should only be called once, noted by the pollingID.
if ( pollingID != returnedPollingID )
{
entry.accessory.log.info(`More entries for pollingID of get error:${error} val:${properValue} returnedPollingID:${returnedPollingID}`);
entry.accessory.log.info(`More entries for pollingID of get error:${error} value:${properValue} returnedPollingID:${returnedPollingID}`);

return;
}
Expand Down
19 changes: 19 additions & 0 deletions cmd4Constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
"use strict";

// Naming convention
// DEFAULT_ => Default values
// _l => Lower Case
// _lv => Lower Case Variable of same name

// Triggers which Array CMD4Accessory will be placed
// Either cmd4Accessories or cmd4StandaloneAccessories
exports.STANDALONE = "Standalone";
Expand All @@ -9,6 +14,7 @@ exports.COLLECTION = "Collection";
// Default intervals
exports.SLOW_STATE_CHANGE_RESPONSE_TIME = 10000; // 10 seconds
exports.MEDIUM_STATE_CHANGE_RESPONSE_TIME = 3000; // 3 seconds
exports.DEFAULT_STATE_CHANGE_RESPONSE_TIME = 3000; // 3 seconds
exports.FAST_STATE_CHANGE_RESPONSE_TIME = 1000; // 1 second

exports.DEFAULT_TIMEOUT = 60000; // 1 minute
Expand Down Expand Up @@ -120,6 +126,19 @@ exports.VALIDVALUES = "ValidValues";
exports.ACCESS = "Access";


// Internal list variables
exports.ACCESSORY_lv = "accessory";
exports.CALLBACK_lv = "callback";
exports.ACC_TYPE_ENUM_INDEX_lv = "accTypeEnumIndex";
exports.INTERVAL_lv = "interval";
exports.IS_SET_lv = "isSet";
exports.IS_POLLED_lv = "isPolled";
exports.QUEUE_lv = "queue";
exports.QUEUE_NAME_lv = "queueName";
exports.RC_lv = "rc";
exports.STATE_CHANGE_RESPONSE_TIME_lv = "stateChangeResponseTime";
exports.TIMEOUT_lv = "timeout";
exports.VALUE_lv = "value";

exports.ERROR_TIMER_EXPIRED = -151;
exports.ERROR_CMD_FAILED_REPLY = -152;
Expand Down
2 changes: 1 addition & 1 deletion test/Cmd4AccessorySetValue.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ describe( "Testing Cmd4Accessory", function( )

new Cmd4Accessory( log, TVConfig, _api, [ ], null );

let expectedPublishedOutput = `Televisions should be Platform Accessories with "publishExternally": true,`;
let expectedPublishedOutput = `Televisions should be Platform Accessories with "PublishExternally": true,`;

assert.include( log.errBuf, expectedPublishedOutput, `Cmd4Accessory output expected: ${ expectedPublishedOutput } received: ${ log.logBuf }` );
assert.equal( 0, log.logLineCount, ` Cmd4Accessory logged lines than one: ${ log.logBuf }` );
Expand Down
Loading

0 comments on commit eb94eeb

Please sign in to comment.