more work on the specification and functionality of base classes, added StateUpdateManager utility, to simplify partial state updates
This commit is contained in:
parent
58891b99f4
commit
5d58715922
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
||||
@ -10,6 +10,10 @@ class HCColorlamp extends HCControlBase {
|
||||
return "colorlamp";
|
||||
}
|
||||
|
||||
get effects() {
|
||||
return [];
|
||||
}
|
||||
|
||||
turnOn() {
|
||||
return Promise.reject();
|
||||
}
|
||||
@ -26,7 +30,19 @@ class HCColorlamp extends HCControlBase {
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
changeColor(hue, sat, light) {
|
||||
/**
|
||||
* Sets the color to the values given in the colors object
|
||||
* Also accepts partial values (only update hue and sat for example)
|
||||
* @param {Object} color
|
||||
* @param {Number} color.hue Hue
|
||||
* @param {Number} color.sat Saturation
|
||||
* @param {Number} color.l Lightness
|
||||
*/
|
||||
changeColor(color) {
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
setEffect(id) {
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,8 +9,12 @@ class HCControlBase extends EventEmitter {
|
||||
constructor(configuration, state) {
|
||||
super();
|
||||
|
||||
if (!configuration.name) throw new Error("Device name is missing");
|
||||
|
||||
this._configuration = configuration;
|
||||
this._state = state;
|
||||
|
||||
this._name = this._configuration.name;
|
||||
}
|
||||
|
||||
get state() {
|
||||
@ -21,6 +25,10 @@ class HCControlBase extends EventEmitter {
|
||||
return "none";
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state by polling the controlled device
|
||||
* @returns A promise which resolves when the state has been pulled
|
||||
|
||||
92
StateUpdateManager.js
Normal file
92
StateUpdateManager.js
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Optional utility classes can use when states need to be partially updated
|
||||
*/
|
||||
|
||||
class StateUpdateManager {
|
||||
constructor(initialState) {
|
||||
this._highestConfirmedId = 0;
|
||||
this._currentId = 0;
|
||||
this._nextId = 1;
|
||||
|
||||
this._updateHistory = [{ id: 0, state: initialState }];
|
||||
}
|
||||
|
||||
get highestConfirmedId() {
|
||||
return this._highestConfirmedId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest (unconfirmed state)
|
||||
*/
|
||||
get state() {
|
||||
return this._updateHistory.find(su => su.id == this._currentId).state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest confirmed state
|
||||
*/
|
||||
get confirmedState() {
|
||||
return this._updateHistory.find(su => su.id == this._highestConfirmedId).state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the potential update of the state
|
||||
* @param {Object} state
|
||||
* @returns {Number} id which is used to confirm or reject the update later
|
||||
*/
|
||||
registerUpdate(state) {
|
||||
let updateId = this._nextId;
|
||||
this._nextId += 1;
|
||||
this._currentId = updateId; // until rejected, this is the most recent id
|
||||
|
||||
this._updateHistory.push({
|
||||
id: updateId,
|
||||
state
|
||||
});
|
||||
|
||||
return updateId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new state and instantly confirm it
|
||||
* @param {Object} state
|
||||
*/
|
||||
insertConfirmedState(state) {
|
||||
let suid = this.registerUpdate();
|
||||
this.confirmUpdate(suid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the update with the specified id
|
||||
* Also remove all updates with lower ids, as these are now confirmed to be outdated
|
||||
* @param {Number} uid
|
||||
*/
|
||||
confirmUpdate(uid) {
|
||||
if (uid < this._highestConfirmedId) return; // already outdated
|
||||
|
||||
this._highestConfirmedId = uid;
|
||||
|
||||
// remove history entries with lower ids
|
||||
this._updateHistory = this._updateHistory.filter(su => su.id >= this._highestConfirmedId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejects the update with the specified id
|
||||
* If the id is outdated it is ignored
|
||||
* Otherwise it is thrown out, and the currentId decremented if required
|
||||
* @param {Number} uid
|
||||
*/
|
||||
rejectUpdate(uid) {
|
||||
if (uid < this._highestConfirmedId) return; // already outdated
|
||||
|
||||
// remove element from history
|
||||
this._updateHistory = this._updateHistory.filter(su => su.id != uid);
|
||||
|
||||
if (this._currentId == uid) {
|
||||
// set current id to highest known uid
|
||||
this._currentId = this._updateHistory.reduce((highest, su) => (su.id > highest) ? su.id : highest, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StateUpdateManager;
|
||||
1
index.js
1
index.js
@ -1,4 +1,5 @@
|
||||
module.exports = {
|
||||
HCColorLamp: require('./ColorlampBase'),
|
||||
HCSwitch: require('./SwitchBase'),
|
||||
StateUpdateManager: require('./StateUpdateManager'),
|
||||
};
|
||||
5
package-lock.json
generated
5
package-lock.json
generated
@ -16,6 +16,11 @@
|
||||
"requires": {
|
||||
"is-plain-obj": "1.1.0"
|
||||
}
|
||||
},
|
||||
"node-object-hash": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.4.1.tgz",
|
||||
"integrity": "sha512-JQVqSM5/mOaUoUhCYR0t1vgm8RFo7qpJtPvnoFCLeqQh1xrfmr3BCD3nGBnACzpIEF7F7EVgqGD3O4lao/BY/A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"author": "Jan Scheiper",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"merge-options": "^1.0.1"
|
||||
"merge-options": "^1.0.1",
|
||||
"node-object-hash": "^1.4.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
const objectHash = require('node-object-hash');
|
||||
|
||||
class BaseState {
|
||||
constructor(cloneObj) {
|
||||
}
|
||||
@ -6,12 +8,16 @@ class BaseState {
|
||||
return {};
|
||||
}
|
||||
|
||||
get hash() {
|
||||
return objectHash(this.asObj);
|
||||
}
|
||||
|
||||
static get default() {
|
||||
return {};
|
||||
}
|
||||
|
||||
clone() {
|
||||
return this(this.asObj);
|
||||
return new this.constructor(this.asObj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ class ColorlampState extends BaseState {
|
||||
sat: cloneState.color.sat,
|
||||
l: cloneState.color.l
|
||||
};
|
||||
this.effect = cloneState.effect;
|
||||
}
|
||||
|
||||
static get default() {
|
||||
@ -23,7 +24,8 @@ class ColorlampState extends BaseState {
|
||||
hue: 0,
|
||||
sat: 0,
|
||||
l: 0
|
||||
}
|
||||
},
|
||||
effect: "none"
|
||||
};
|
||||
}
|
||||
|
||||
@ -35,7 +37,8 @@ class ColorlampState extends BaseState {
|
||||
hue: this.color.hue,
|
||||
sat: this.color.sat,
|
||||
l: this.color.l
|
||||
}
|
||||
},
|
||||
effect: this.effect
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user