Skip to content

Commit

Permalink
Merge pull request #325 from OpenHausIO/dev
Browse files Browse the repository at this point in the history
`v2.2.0` release
  • Loading branch information
mStirner authored Mar 27, 2023
2 parents 2057e70 + 43bcf5d commit 90d39db
Show file tree
Hide file tree
Showing 17 changed files with 725 additions and 86 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"editor.insertSpaces": true,
"editor.detectIndentation": false,
"editor.formatOnSave": true,
"editor.formatOnPaste": true
"editor.formatOnPaste": false
},
"files.exclude": {
"**/.git": false
Expand Down
2 changes: 1 addition & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ module.exports = function (grunt) {

grunt.registerTask("checksum", () => {

let m5f = path.join(PATH_DIST, "./checksums.md5");
let m5f = path.join(PATH_DIST, "./checksums.txt");

fs.rmSync(m5f, { force: true });
let files = fs.readdirSync(PATH_DIST);
Expand Down
38 changes: 38 additions & 0 deletions adapter/eol.js
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
};

};
2 changes: 1 addition & 1 deletion components/devices/class.interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ module.exports = class Interface {
is: "SERIAL",
then: SERIAL
}),
adapter: Joi.array().items("eiscp", "raw").default(["raw"]),
adapter: Joi.array().items("eiscp", "raw", "eol").default(["raw"]),
description: Joi.string().allow(null).default(null)
});

Expand Down
9 changes: 9 additions & 0 deletions components/endpoints/class.endpoint.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const State = require("./class.state.js");
//const Commands = require("./class.commands.js");
//const States = require("./!class.states.js");

const _expose = require("../../helper/expose.js");

/**
* @description
* Endpoint item, stored in the component `.items` Array.
Expand Down Expand Up @@ -49,5 +51,12 @@ module.exports = class Endpoint {
//this.method1 = _expose(this.commands, "method1");
//this.method2 = _expose(this.states, "method2");

Object.defineProperty(this, "trigger", {
value: _expose(this.commands, "trigger"),
enumerable: false,
configurable: false,
writable: false
});

}
};
153 changes: 153 additions & 0 deletions components/scenes/class.makro.js
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);
}

};
112 changes: 112 additions & 0 deletions components/scenes/class.scene.js
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;

}

};
Loading

0 comments on commit 90d39db

Please sign in to comment.