-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #325 from OpenHausIO/dev
`v2.2.0` release
- Loading branch information
Showing
17 changed files
with
725 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const { Transform } = require("stream"); | ||
|
||
const logger = require("../system/logger"); | ||
const log = logger.create("adapter/eol"); | ||
|
||
module.exports = (options = {}) => { | ||
|
||
// https://github.com/OpenHausIO/backend/issues/315 | ||
let cr = Buffer.from("\r"); | ||
let lf = Buffer.from("\n"); | ||
//let eol = Buffer.from("\x1A"); | ||
let nl = Buffer.concat([ | ||
cr, | ||
lf | ||
]); | ||
|
||
let encode = new Transform({ | ||
transform(chunk, encoding, cb) { | ||
log.trace("[encode] (%s) %j", encoding, chunk); | ||
cb(null, Buffer.concat([chunk, nl])); | ||
}, | ||
...options | ||
}); | ||
|
||
let decode = new Transform({ | ||
transform(chunk, encoding, cb) { | ||
log.trace("[encode] (%s) %j", encoding, chunk); | ||
cb(null, chunk.subarray(0, nl.length)); | ||
}, | ||
...options | ||
}); | ||
|
||
return { | ||
encode, | ||
decode | ||
}; | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
const Joi = require("joi"); | ||
const mongodb = require("mongodb"); | ||
|
||
const dispatcher = require("../../system/dispatcher"); | ||
//const C_ENDPOINTS = require("../endpoints"); | ||
|
||
/** | ||
* @description | ||
* This is a functions as a state for a endpoint.<br /> | ||
* E.g "Power" state, or "Volume" | ||
* | ||
* @class State | ||
* | ||
* @param {Object} obj Object that matches the item schema. See properties below: | ||
* | ||
* @property {String} [_id=ObjectID] MongoDB ObjectID as String | ||
* @property {String} type Required makro type: trigger `command` or schedule a `timer` or even trigger a other `scene` | ||
* @property {String} [command] When `type=command` ObjectID of command to trigger on endpoint | ||
* @property {String} [endpoint] When `type=command` ObjectID of endpoint | ||
* @property {Number} [value] When `type=timer` Miliseconds to sleep | ||
* @property {String} [scene] When `type=scene` ObjectID of scene | ||
* @property {Object} timestamps Timestamps that are set when added or updated | ||
* @property {Number} [timestamps.created=Date.now()] Set when added | ||
* @property {Number} timestamps.updated Every time set to Date.now() when a value is set | ||
*/ | ||
module.exports = class Makro { | ||
|
||
|
||
constructor(obj) { | ||
|
||
Object.assign(this, obj); | ||
this._id = String(obj._id); | ||
|
||
} | ||
|
||
|
||
/** | ||
* @function | ||
* Executes the makro | ||
* | ||
* @param {Object} result | ||
* @param {AbortionSignal} signal | ||
* | ||
* @returns | ||
*/ | ||
execute(result, signal) { | ||
return new Promise((resolve, reject) => { | ||
try { | ||
if (this.type === "timer") { | ||
|
||
let timeout = setTimeout(() => { | ||
resolve(this._id, signal); | ||
}, this.value); | ||
|
||
signal.addEventListener("abort", () => { | ||
clearTimeout(timeout); | ||
}, { | ||
once: true | ||
}); | ||
|
||
} else if (this.type === "command") { | ||
|
||
dispatcher({ | ||
"component": "endpoints", | ||
"item": this.endpoint, | ||
"method": "trigger", | ||
"args": [this.command] | ||
}); | ||
|
||
resolve(this._id); | ||
|
||
} else if (this.type === "scene") { | ||
|
||
dispatcher({ | ||
"component": "scenes", | ||
"item": this.scene, | ||
"method": "trigger", | ||
"args": [] | ||
}); | ||
|
||
} else { | ||
|
||
reject(`${this.type} is invalid!`); | ||
|
||
} | ||
} catch (err) { | ||
|
||
reject(err); | ||
|
||
} | ||
}); | ||
} | ||
|
||
|
||
/** | ||
* @function schema | ||
* State schema, see properties above. | ||
* | ||
* @static | ||
* | ||
* @returns {Object} Joi Object | ||
* | ||
* @link https://joi.dev/api/?v=17.6.0#anyvalidatevalue-options | ||
*/ | ||
static schema() { | ||
return Joi.object({ | ||
_id: Joi.string().pattern(/^[0-9a-fA-F]{24}$/).default(() => { | ||
return String(new mongodb.ObjectId()); | ||
}), | ||
type: Joi.string().valid("command", "timer", "scene"/*, "state"*/).required(), | ||
timestamps: Joi.object({ | ||
created: Joi.number().allow(null), | ||
updated: Joi.number().allow(null) | ||
}) | ||
}).when(".type", { | ||
switch: [{ | ||
is: "command", | ||
then: Joi.object({ | ||
endpoint: Joi.string().pattern(/^[0-9a-fA-F]{24}$/), | ||
command: Joi.string().pattern(/^[0-9a-fA-F]{24}$/) | ||
}) | ||
}, { | ||
is: "timer", | ||
then: Joi.object({ | ||
value: Joi.number().min(1).max(Number.MAX_SAFE_INTEGER) | ||
}) | ||
}, { | ||
is: "scene", | ||
then: Joi.object({ | ||
scene: Joi.string().pattern(/^[0-9a-fA-F]{24}$/) | ||
}) | ||
}] | ||
}); | ||
} | ||
|
||
|
||
/** | ||
* @function validate | ||
* Validate schema object | ||
* | ||
* @static | ||
* | ||
* @param {Object} obj Input data that matches the schema | ||
* | ||
* @returns {Object} Joi validation object | ||
* | ||
* @link https://joi.dev/api/?v=17.6.0#anyvalidatevalue-options | ||
*/ | ||
static validate(obj) { | ||
return Makro.schema().validate(obj); | ||
} | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
const Makro = require("./class.makro.js"); | ||
|
||
|
||
module.exports = class Scene { | ||
|
||
constructor(obj) { | ||
|
||
Object.assign(this, obj); | ||
this._id = String(obj._id); | ||
|
||
this.makros = obj.makros.map((makro) => { | ||
return new Makro(makro); | ||
}); | ||
|
||
Object.defineProperty(this, "running", { | ||
value: false, | ||
enumerable: false, | ||
configurable: false, | ||
writable: true | ||
}); | ||
|
||
Object.defineProperty(this, "aborted", { | ||
value: false, | ||
enumerable: false, | ||
configurable: false, | ||
writable: true | ||
}); | ||
|
||
Object.defineProperty(this, "index", { | ||
value: 0, | ||
enumerable: false, | ||
configurable: false, | ||
writable: true | ||
}); | ||
|
||
Object.defineProperty(this, "finished", { | ||
value: false, | ||
enumerable: false, | ||
configurable: false, | ||
writable: true | ||
}); | ||
|
||
Object.defineProperty(this, "_ac", { | ||
value: null, | ||
enumerable: false, | ||
configurable: false, | ||
writable: true | ||
}); | ||
|
||
} | ||
|
||
trigger() { | ||
|
||
let ac = new AbortController(); | ||
this._ac = ac; | ||
|
||
let init = this.makros.map((makro) => { | ||
|
||
// bind scope to method | ||
return makro.execute.bind(makro); | ||
|
||
}).reduce((acc, cur, i) => { | ||
return (result) => { | ||
return acc(result, this._ac.signal).then((r) => { | ||
if (this.aborted) { | ||
|
||
return Promise.reject("Aborted!"); | ||
|
||
} else { | ||
|
||
this.index = i; | ||
return cur(r, this._ac.signal); | ||
|
||
} | ||
}).catch((err) => { | ||
console.log("Catched", i, err); | ||
return Promise.reject(err); | ||
}); | ||
}; | ||
}); | ||
|
||
this.running = true; | ||
this.aborted = false; | ||
this.finished = false; | ||
this.index = 0; | ||
|
||
return init(true, this._ac).then((result) => { | ||
console.log("Makro stack done", result); | ||
this.finished = true; | ||
}).catch((err) => { | ||
console.log("Makro stack aborted", err); | ||
this.finished = false; | ||
}).finally(() => { | ||
console.log("Finaly"); | ||
this.running = false; | ||
}); | ||
|
||
} | ||
|
||
|
||
abort() { | ||
|
||
console.log("Aborted called"); | ||
|
||
this._ac.abort(); | ||
this.running = false; | ||
this.aborted = true; | ||
this.finished = false; | ||
|
||
} | ||
|
||
}; |
Oops, something went wrong.