Ready to try re-write in prototype

This commit is contained in:
mmcwilliams 2019-10-30 22:32:52 -04:00
parent ac986e874f
commit 26116303cc
10 changed files with 355 additions and 405 deletions

View File

@ -7,7 +7,8 @@ const { exec } = require('child_process')
const BLE = require('./lib/ble') const BLE = require('./lib/ble')
const intval = require('./lib/intval') const intval = require('./lib/intval')
const sequence = require('./lib/sequence') const Sequence = require('./lib/sequence')
const sequence = new Sequence(intval)
const PACKAGE = require('./package.json') const PACKAGE = require('./package.json')
const PORT = process.env.PORT || 6699 const PORT = process.env.PORT || 6699
@ -183,7 +184,7 @@ function rCounter (req, res, next) {
return next() return next()
} }
function rFrame (req, res, next) { async function rFrame (req, res, next) {
let dir = true let dir = true
let exposure = 0 let exposure = 0
if (intval._state.frame.dir !== true) { if (intval._state.frame.dir !== true) {
@ -235,10 +236,14 @@ function rFrame (req, res, next) {
} }
} }
log.info('/frame', { method : req.method, dir : dir, exposure : exposure }) log.info('/frame', { method : req.method, dir : dir, exposure : exposure })
intval.frame(dir, exposure, (len) => {
res.send({ dir : dir, len : len}) if (exposure < 30000) {
await intval.frame(dir, exposure)
} else {
intval.frame(dir, exposure)
res.send({ dir : dir, len : exposure, delaying : true })
return next() return next()
}) }
} }
function rStatus (req, res, next) { function rStatus (req, res, next) {
@ -247,7 +252,7 @@ function rStatus (req, res, next) {
return next() return next()
} }
function rSequence (req, res, next) { async function rSequence (req, res, next) {
let dir = true let dir = true
let exposure = 0 let exposure = 0
let delay = 0 let delay = 0
@ -304,33 +309,17 @@ function rSequence (req, res, next) {
delay = req.body.delay delay = req.body.delay
} }
} }
if (intval._state.sequence && sequence._state.active) { if (intval._state.sequence && sequence.active) {
sequence.setStop()
intval._state.sequence = false intval._state.sequence = false
sequence.stop()
res.send({ stopped : true }) res.send({ stopped : true })
return next()
} else {
console.time('sequence time')
intval._state.sequence = true
let seq_id = sequence.start({
loop : [ (next) => {
intval.frame(dir, exposure, (len) => {
next()
})
}, (next) => {
setTimeout(() => {
next()
}, delay)
}]
}, (seq) => {
console.timeEnd('sequence time')
})
if (seq_id === false) { return next()
res.send({ started : false })
} else { } else {
res.send({ started : true , id : seq_id }) intval._state.sequence = true
} sequence.start()
res.send({ started : true })
return next() return next()
} }
@ -374,10 +363,14 @@ function rRestart (req, res, next) {
//Ble functions //Ble functions
function bFrame (obj, cb) { async function bFrame (obj, cb) {
let dir = true let dir = true
let exposure = 0 let exposure = 0
if (sequence.active) {
return cb()
}
if (intval._state.frame.dir !== true) { if (intval._state.frame.dir !== true) {
dir = false dir = false
} }
@ -401,11 +394,10 @@ function bFrame (obj, cb) {
log.info('frame', { method : 'ble', dir : dir, exposure : exposure }) log.info('frame', { method : 'ble', dir : dir, exposure : exposure })
if (exposure < 5000) { if (exposure < 5000) {
intval.frame(dir, exposure, (len) => { await intval.frame(dir, exposure)
return cb() return cb()
})
} else { } else {
intval.frame(dir, exposure, (len) => {}) intval.frame(dir, exposure)
return cb() return cb()
} }
@ -502,29 +494,14 @@ function bSequence (obj, cb) {
} }
if (intval._state.sequence && sequence._state.active) { if (intval._state.sequence && sequence._state.active) {
//should not occur with single client //should not occur with single client
sequence.setStop()
intval._state.sequence = false intval._state.sequence = false
sequence.stop()
log.info('sequence stop', { method : 'ble' }) log.info('sequence stop', { method : 'ble' })
return cb() return cb()
} else { } else {
console.time('sequence time')
intval._state.sequence = true intval._state.sequence = true
let seq_id = sequence.start({ sequence.start()
loop : [ (next) => { log.info('sequence start', { method : 'ble' })
intval.frame(dir, exposure, (len) => {
next()
})
}, (next) => {
setTimeout(() => {
next()
}, delay)
}]
}, (seq) => {
console.timeEnd('sequence time')
})
if (seq_id !== false) {
log.info('sequence start', { method : 'ble', id : seq_id })
}
return cb() return cb()
} }
} }
@ -558,6 +535,7 @@ function bUpdate (obj, cb) {
}, 20) }, 20)
}) })
} }
function bRestart (obj, cb) { function bRestart (obj, cb) {
log.info('restart', { method : 'ble' }) log.info('restart', { method : 'ble' })
cb() cb()
@ -607,7 +585,6 @@ function index (req, res, next) {
} }
function init () { function init () {
intval.init()
intval.sequence = seq intval.sequence = seq
createServer() createServer()
createBLE() createBLE()

View File

@ -12,6 +12,7 @@ function delay(ms) {
return setTimeout(resolve, ms); return setTimeout(resolve, ms);
}); });
} }
exports.delay = delay;
module.exports.delay = delay; module.exports.delay = delay;
exports.default = delay; exports.default = delay;
//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/delay/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;;;;;IAMI;AAEJ,SAAS,KAAK,CAAE,EAAW;IAC1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAa,EAAE,EAAE;QACpC,OAAO,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;AAE7B,kBAAe,KAAK,CAAC"} {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/delay/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;;;;;IAMI;AAEJ,SAAgB,KAAK,CAAE,EAAW;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAa,EAAE,EAAE;QACpC,OAAO,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACJ,CAAC;AAJD,sBAIC;AAED,MAAM,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;AAE7B,kBAAe,KAAK,CAAC"}

View File

@ -11,7 +11,7 @@ const db = require('../db');
const log = require('../log')('intval'); const log = require('../log')('intval');
const storage = __importStar(require("node-persist")); const storage = __importStar(require("node-persist"));
const fs_extra_1 = require("fs-extra"); const fs_extra_1 = require("fs-extra");
require("../delay"); const delay_1 = require("../delay");
let Gpio; let Gpio;
try { try {
Gpio = require('onoff').Gpio; Gpio = require('onoff').Gpio;
@ -52,9 +52,15 @@ class Intval {
}; };
this._release = { this._release = {
min: 20, min: 20,
seq: 1000 seq: 1000,
time: 0,
active: false
};
this._micro = {
time: 0,
primed: false,
delay: 10 // delay after stop signal before stopping motors
}; };
this._microDelay = 10; // delay after stop signal before stopping motors
this._pin = {}; this._pin = {};
this._state = {}; this._state = {};
this._init(); this._init();
@ -64,21 +70,7 @@ class Intval {
*/ */
async _init() { async _init() {
let dirExists; let dirExists;
try { const storateOptions = {
dirExists = await fs_extra_1.exists(this.STATE_DIR);
}
catch (err) {
log.error('init', `Error locating state directory ${this.STATE_DIR}`);
}
if (!dirExists) {
try {
await fs_extra_1.mkdir(this.STATE_DIR);
}
catch (err) {
log.error('init', `Error creating state directory ${this.STATE_DIR}`);
}
}
storage.init({
dir: this.STATE_DIR, dir: this.STATE_DIR,
stringify: JSON.stringify, stringify: JSON.stringify,
parse: JSON.parse, parse: JSON.parse,
@ -87,22 +79,56 @@ class Intval {
continuous: true, continuous: true,
interval: false, interval: false,
ttl: false, ttl: false,
}).then(this._restoreState).catch((err) => { };
log.warn('init', err); try {
dirExists = await fs_extra_1.pathExists(this.STATE_DIR);
}
catch (err) {
log.error('_init', `Error locating state directory ${this.STATE_DIR}`);
}
if (!dirExists) {
try {
await fs_extra_1.mkdir(this.STATE_DIR);
}
catch (err) {
log.error('_init', `Error creating state directory ${this.STATE_DIR}`);
}
}
try {
await storage.init(storateOptions);
}
catch (err) {
log.error('_init', err);
}
try {
await this._restoreState();
}
catch (err) {
log.warn('_init', err);
this.reset(); this.reset();
this._declarePins(); this._declarePins();
}); }
process.on('SIGINT', this._undeclarePins); process.on('SIGINT', this._undeclarePins.bind(this));
process.on('uncaughtException', this._undeclarePins); process.on('uncaughtException', this._undeclarePins.bind(this));
} }
/** /**
* Restore the state from the storage object * Restore the state from the storage object
*/ */
_restoreState() { async _restoreState() {
storage.getItem('_state', 'test').then(this._setState).catch((err) => { let data;
this._setState(); try {
data = await storage.getItem('_state');
}
catch (err) {
log.error('_restoreState', err); log.error('_restoreState', err);
}); }
try {
this._setState(data);
}
catch (err) {
log.error('_restoreState', err);
this._setState();
}
this._declarePins(); this._declarePins();
} }
/** /**
@ -127,14 +153,6 @@ class Intval {
current: {}, current: {},
cb: () => { } cb: () => { }
}, },
release: {
time: 0,
active: false //is pressed
},
micro: {
time: 0,
primed: false //is ready to stop frame
},
counter: 0, counter: 0,
sequence: false sequence: false
}; };
@ -144,11 +162,12 @@ class Intval {
* Store the state object. * Store the state object.
*/ */
_storeState() { _storeState() {
storage.setItem('_state', this._state) try {
.then(() => { }) storage.setItem('_state', this._state);
.catch((err) => { }
catch (err) {
log.error('_storeState', err); log.error('_storeState', err);
}); }
} }
/** /**
* (internal function) Declares all Gpio pins that will be used. * (internal function) Declares all Gpio pins that will be used.
@ -247,7 +266,7 @@ class Intval {
* @param {integer} val Current value of the pin * @param {integer} val Current value of the pin
* *
*/ */
_watchMicro(err, val) { async _watchMicro(err, val) {
const now = +new Date(); const now = +new Date();
if (err) { if (err) {
log.error('_watchMicro', err); log.error('_watchMicro', err);
@ -255,9 +274,9 @@ class Intval {
//log.info(`Microswitch val: ${val}`) //log.info(`Microswitch val: ${val}`)
//determine when to stop //determine when to stop
if (val === 0 && this._state.frame.active) { if (val === 0 && this._state.frame.active) {
if (!this._state.micro.primed) { if (!this._micro.primed) {
this._state.micro.primed = true; this._micro.primed = true;
this._state.micro.time = now; this._micro.time = now;
log.info('Microswitch primed to stop motor'); log.info('Microswitch primed to stop motor');
} }
} }
@ -265,9 +284,8 @@ class Intval {
if (this._state.micro.primed && !this._state.micro.paused && (now - this._state.frame.start) > this._frame.open) { if (this._state.micro.primed && !this._state.micro.paused && (now - this._state.frame.start) > this._frame.open) {
this._state.micro.primed = false; this._state.micro.primed = false;
this._state.micro.time = 0; this._state.micro.time = 0;
setTimeout(() => { await delay_1.delay(this._micro.delay);
this._stop(); this._stop();
}, this._microDelay);
} }
} }
} }
@ -277,7 +295,7 @@ class Intval {
* *
* 1) If closed, start timer. * 1) If closed, start timer.
* 2) If opened, check timer AND * 2) If opened, check timer AND
* 3) If `press` (`now - this._state.release.time`) greater than minimum and less than `this._release.seq`, start frame * 3) If `press` (`now - this._release.time`) greater than minimum and less than `this._release.seq`, start frame
* 4) If `press` greater than `this._release.seq`, start sequence * 4) If `press` greater than `this._release.seq`, start sequence
* *
* Button + 10K ohm resistor * Button + 10K ohm resistor
@ -298,34 +316,39 @@ class Intval {
if (val === 0) { if (val === 0) {
//closed //closed
if (this._releaseClosedState(now)) { if (this._releaseClosedState(now)) {
this._state.release.time = now; this._release.time = now;
this._state.release.active = true; //maybe unncecessary this._release.active = true; //maybe unncecessary
} }
} }
else if (val === 1) { else if (val === 1) {
//opened //opened
if (this._state.release.active) { if (this._release.active) {
press = now - this._state.release.time; press = now - this._release.time;
if (press > this._release.min && press < this._release.seq) { if (press > this._release.min && press < this._release.seq) {
this.frame(); this.frame();
} }
else if (press >= this._release.seq) { else if (press >= this._release.seq) {
this.sequence(); this._sequence();
} }
//log.info(`Release closed for ${press}ms`) //log.info(`Release closed for ${press}ms`)
this._state.release.time = 0; this._release.time = 0;
this._state.release.active = false; this._release.active = false;
} }
} }
} }
_sequence() {
if (this.sequence) {
this._state.sequence = this.sequence();
}
}
/** /**
* *
*/ */
_releaseClosedState(now) { _releaseClosedState(now) {
if (!this._state.release.active && this._state.release.time === 0) { if (!this._release.active && this._release.time === 0) {
return true; return true;
} }
if (this._state.release.active && (now - this._state.release.time) > (this._release.seq * 10)) { if (this._release.active && (now - this._release.time) > (this._release.seq * 10)) {
return true; return true;
} }
return false; return false;
@ -389,7 +412,7 @@ class Intval {
* @param {?integer} [exposure="null"] (optional) Exposure time, 0 = minimum * @param {?integer} [exposure="null"] (optional) Exposure time, 0 = minimum
* *
*/ */
frame(dir = null, exposure = null, cb = () => { }) { async frame(dir = null, exposure = null) {
if (dir === true || (dir === null && this._state.frame.dir === true)) { if (dir === true || (dir === null && this._state.frame.dir === true)) {
dir = true; dir = true;
} }
@ -402,10 +425,12 @@ class Intval {
else if (exposure === null) { else if (exposure === null) {
exposure = 0; //default speed exposure = 0; //default speed
} }
this._state.frame.current.exposure = exposure;
this._state.frame.current.dir = dir;
this._state.frame.start = +new Date(); this._state.frame.start = +new Date();
this._state.frame.active = true; this._state.frame.active = true;
this._pin.micro.watch(this._watchMicro); this._pin.micro.watch(this._watchMicro);
log.info('frame', { dir: dir ? 'forward' : 'backward', exposure: exposure }); log.info('frame', { dir: dir ? 'forward' : 'backward', exposure });
if (dir) { if (dir) {
this._startFwd(); this._startFwd();
} }
@ -415,47 +440,40 @@ class Intval {
if (exposure !== 0) { if (exposure !== 0) {
this._state.frame.paused = true; this._state.frame.paused = true;
if (dir) { if (dir) {
setTimeout(this._pause, this._frame.open); await delay_1.delay(this._frame.open);
//log.info('frame', { pausing : time + this._frame.open }) this._pause();
setTimeout(() => { await delay_1.delay(exposure + this._frame.closed);
this._state.frame.paused = false; this._state.frame.paused = false;
this._startFwd(); this._startFwd();
}, exposure + this._frame.closed);
} }
else { else {
setTimeout(this._pause, this._frame.openBwd); await delay_1.delay(this._frame.openBwd);
setTimeout(() => { this._pause();
//log.info('frame', 'restarting') await delay_1.delay(exposure + this._frame.closed);
this._state.frame.paused = false; this._state.frame.paused = false;
this._startBwd(); this._startBwd();
}, exposure + this._frame.closed);
} }
} }
if (dir) { if (dir) {
this._state.frame.cb = (len) => { this._state.frame.cb = (len) => {
this._state.counter++; this._state.counter++;
this._storeState(); this._storeState();
cb(len);
}; };
} }
else { else {
this._state.frame.cb = (len) => { this._state.frame.cb = (len) => {
this._state.counter--; this._state.counter--;
this._storeState(); this._storeState();
cb(len);
}; };
} }
this._state.frame.current = {
dir: dir,
exposure: exposure
};
} }
/** /**
* * Returns the state of the
*/ */
status() { status() {
return this._state; return this._state;
} }
} }
module.exports = new Intval(); exports.default = Intval;
module.exports = Intval;
//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -5,111 +5,72 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
const v4_1 = __importDefault(require("uuid/v4")); const v4_1 = __importDefault(require("uuid/v4"));
const log = require('../log')('seq'); const log = require('../log')('seq');
require("../delay"); const delay_1 = require("../delay");
const MAX_INTEGER = 2147483647;
/** Object sequence features */ /** Object sequence features */
class Sequence { class Sequence {
constructor() { /**
this._state = { * @constructor
arr: [] *
}; * Create a sequencer object from class
**/
constructor(intval) {
this.active = false; this.active = false;
this.paused = false; this.delay = 0;
this.frame = false;
this.delay = false;
this.count = 0; this.count = 0;
this._stop = null; /**
this._loop = { * Stop a running sequence and reset counter and delay
arr: [], **/
count: 0,
max: 0
};
this.stop = function () { this.stop = function () {
this.active = false; this.active = false;
this.count = 0; this.count = 0;
this._state.arr = []; this.delay = 0;
this._loop.count = 0; };
this._loop.max = 0; this.intval = intval;
this._loop.arr = []; this.intval.sequence = function () {
if (this._stop) if (this.active) {
this._stop(); this.stop();
this._stop = null; return false;
}
else {
this.start();
return true;
}
}; };
} }
/** /**
* Start running a "sequence" of frames. Shoots a continuous sequence * Start running a "sequence" of frames. Shoots a continuous sequence
* of single frames with a delay in between each one. * of single frames with a delay in between each one.
**/ **/
start(options, cb) { async start(options) {
if (this._state.active) { let len = typeof options.len !== 'undefined' ? options.len : MAX_INTEGER;
return false; let multiple = typeof options.multiple !== 'undefined' ? options.multiple : 1;
}
this.active = true;
this.count = 0;
if (options.arr) {
this._state.arr = options.arr;
}
if (options.loop) {
this._loop.arr = options.loop;
this._loop.count = 0;
}
if (options.maxLoop) {
this._loop.max = options.maxLoop;
}
else {
this._loop.max = 0;
}
this._stop = cb;
this.step();
this.id = v4_1.default(); this.id = v4_1.default();
return this.id; this.delay = typeof options.delay !== 'undefined' ? options.delay : 0;
}
setStop() {
this.active = false;
}
pause() {
this.paused = true;
}
resume() {
this.paused = false;
this.step();
}
step() {
if (this.active && !this.paused) {
if (this._state.arr.length > 0) {
if (this.count > this._state.arr.length - 1) {
return this.stop();
}
log.info('step', { count: this.count, id: this._state.id });
return this._state.arr[this.count](() => {
this.count++;
this.step();
});
}
else if (this._loop.arr.length > 0) {
if (this.count > this._loop.arr.length - 1) {
this.count = 0; this.count = 0;
this._loop.count++; for (let i = 0; i < len; i++) {
} if (multiple > 1) {
if (this._loop.max > 0 && this._loop.count > this._loop.max) { for (let x = 0; x < multiple; x++) {
return this.stop(); await this.intval.frame();
} log.info({ id: this.id, count: this.count });
log.info('step', { count: this.count, id: this.id });
return this._loop.arr[this.count](() => {
this.count++; this.count++;
this.step(); }
});
} }
else { else {
return this.stop(); await this.intval.frame();
log.info({ id: this.id, count: this.count });
this.count++;
}
if (this.delay > 0) {
await delay_1.delay(this.delay);
}
if (!this.active) {
break;
} }
} }
else if (this.paused) { this.stop();
log.info('step', 'Sequence paused', { loop: this._loop.count, count: this.count });
}
else if (!this.active) {
log.info('step', 'Sequence stopped', { loop: this._loop.count, count: this.count });
}
} }
} }
module.exports = new Sequence(); exports.Sequence = Sequence;
module.exports = Sequence;
//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sequence/index.ts"],"names":[],"mappings":"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"} {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sequence/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;;;;AAEZ,iDAA2B;AAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;AACrC,oCAAiC;AAEjC,MAAM,WAAW,GAAG,UAAU,CAAC;AAc/B,+BAA+B;AAC/B,MAAa,QAAQ;IAUpB;;;;QAII;IAEJ,YAAa,MAAY;QAbjB,WAAM,GAAa,KAAK,CAAA;QAExB,UAAK,GAAY,CAAC,CAAA;QAClB,UAAK,GAAY,CAAC,CAAA;QA6D1B;;YAEI;QACG,SAAI,GAAG;YACb,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;YACnB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;YACd,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;QACf,CAAC,CAAA;QAzDA,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG;YACtB,IAAI,IAAI,CAAC,MAAM,EAAE;gBAChB,IAAI,CAAC,IAAI,EAAE,CAAA;gBACX,OAAO,KAAK,CAAA;aACZ;iBAAM;gBACN,IAAI,CAAC,KAAK,EAAE,CAAA;gBACZ,OAAO,IAAI,CAAA;aACX;QACF,CAAC,CAAA;IACF,CAAC;IAED;;;QAGI;IAEG,KAAK,CAAC,KAAK,CAAE,OAAiB;QACpC,IAAI,GAAG,GAAY,OAAO,OAAO,CAAC,GAAG,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAA;QACjF,IAAI,QAAQ,GAAY,OAAO,OAAO,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QAEtF,IAAI,CAAC,EAAE,GAAG,YAAI,EAAE,CAAA;QAChB,IAAI,CAAC,KAAK,GAAG,OAAO,OAAO,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QACrE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;QAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE;YAC7B,IAAI,QAAQ,GAAG,CAAC,EAAE;gBACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE,EAAE;oBAClC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;oBACzB,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;oBAC9C,IAAI,CAAC,KAAK,EAAE,CAAA;iBACZ;aACD;iBAAM;gBACN,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;gBACzB,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;gBAC9C,IAAI,CAAC,KAAK,EAAE,CAAA;aACZ;YAED,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE;gBACnB,MAAM,aAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;aACvB;YAED,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;gBACjB,MAAK;aACL;SACD;QAED,IAAI,CAAC,IAAI,EAAE,CAAA;IACZ,CAAC;CAUD;AA3ED,4BA2EC;AAED,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAA"}

View File

@ -8,7 +8,7 @@
* @returns {Promise} Promise to resolve after timeout * @returns {Promise} Promise to resolve after timeout
**/ **/
function delay (ms : number) { export function delay (ms : number) {
return new Promise((resolve : any) => { return new Promise((resolve : any) => {
return setTimeout(resolve, ms); return setTimeout(resolve, ms);
}); });

View File

@ -3,8 +3,8 @@
const db = require('../db'); const db = require('../db');
const log = require('../log')('intval'); const log = require('../log')('intval');
import * as storage from 'node-persist'; import * as storage from 'node-persist';
import { exists, mkdir } from 'fs-extra'; import { pathExists, mkdir } from 'fs-extra';
import '../delay'; import { delay } from '../delay';
let Gpio : any let Gpio : any
try { try {
@ -15,7 +15,7 @@ try {
} }
const PINS = { const PINS : any = {
fwd : { fwd : {
pin : 13, pin : 13,
dir : 'out' dir : 'out'
@ -51,7 +51,8 @@ interface Entry {
} }
/** class representing the intval3 features */ /** class representing the intval3 features */
class Intval { export default class Intval {
private STATE_DIR : string = '~/state'; private STATE_DIR : string = '~/state';
private _frame : any = { private _frame : any = {
@ -62,12 +63,21 @@ class Intval {
} }
private _release : any = { private _release : any = {
min : 20, min : 20,
seq : 1000 seq : 1000,
time : 0,
active : false
} }
private _microDelay : number = 10; // delay after stop signal before stopping motors
private _micro : any = {
time : 0,
primed : false, //is ready to stop frame
delay : 10// delay after stop signal before stopping motors
}
private _pin : any = {}; private _pin : any = {};
private _state : any = {}; private _state : any = {};
public sequence : any;
constructor() { constructor() {
this._init(); this._init();
@ -79,22 +89,7 @@ class Intval {
private async _init () { private async _init () {
let dirExists : boolean; let dirExists : boolean;
const storateOptions = {
try {
dirExists = await exists(this.STATE_DIR);
} catch (err) {
log.error('init', `Error locating state directory ${this.STATE_DIR}`);
}
if (!dirExists) {
try {
await mkdir(this.STATE_DIR);
} catch (err) {
log.error('init', `Error creating state directory ${this.STATE_DIR}`)
}
}
storage.init({
dir: this.STATE_DIR, dir: this.STATE_DIR,
stringify: JSON.stringify, stringify: JSON.stringify,
parse: JSON.parse, parse: JSON.parse,
@ -105,25 +100,60 @@ class Intval {
ttl: false, // ttl* [NEW], can be true for 24h default or a number in MILLISECONDS ttl: false, // ttl* [NEW], can be true for 24h default or a number in MILLISECONDS
//expiredInterval: 2 * 60 * 1000, // [NEW] every 2 minutes the process will clean-up the expired cache //expiredInterval: 2 * 60 * 1000, // [NEW] every 2 minutes the process will clean-up the expired cache
//forgiveParseErrors: false // [NEW] //forgiveParseErrors: false // [NEW]
}).then(this._restoreState).catch((err) => { }
log.warn('init', err)
try {
dirExists = await pathExists(this.STATE_DIR);
} catch (err) {
log.error('_init', `Error locating state directory ${this.STATE_DIR}`);
}
if (!dirExists) {
try {
await mkdir(this.STATE_DIR);
} catch (err) {
log.error('_init', `Error creating state directory ${this.STATE_DIR}`);
}
}
try {
await storage.init(storateOptions);
} catch (err) {
log.error('_init', err);
}
try {
await this._restoreState();
} catch (err) {
log.warn('_init', err) ;
this.reset(); this.reset();
this._declarePins(); this._declarePins();
}) }
process.on('SIGINT', this._undeclarePins); process.on('SIGINT', this._undeclarePins.bind(this));
process.on('uncaughtException', this._undeclarePins); process.on('uncaughtException', this._undeclarePins.bind(this));
} }
/** /**
* Restore the state from the storage object * Restore the state from the storage object
*/ */
private _restoreState () { private async _restoreState () {
storage.getItem('_state', 'test').then(this._setState).catch((err) => { let data : any;
this._setState();
try {
data = await storage.getItem('_state');
} catch (err) {
log.error('_restoreState', err); log.error('_restoreState', err);
}) }
try {
this._setState(data);
} catch (err) {
log.error('_restoreState', err);
this._setState();
}
this._declarePins(); this._declarePins();
} }
@ -150,14 +180,6 @@ class Intval {
current : {}, //current settings current : {}, //current settings
cb : () => {} cb : () => {}
}, },
release : {
time: 0,
active : false //is pressed
},
micro : {
time : 0,
primed : false //is ready to stop frame
},
counter : 0, counter : 0,
sequence : false sequence : false
} }
@ -169,11 +191,11 @@ class Intval {
*/ */
private _storeState () { private _storeState () {
storage.setItem('_state', this._state) try {
.then(() => {}) storage.setItem('_state', this._state);
.catch((err) => { } catch (err) {
log.error('_storeState', err); log.error('_storeState', err);
}) }
} }
/** /**
@ -181,7 +203,7 @@ class Intval {
*/ */
private _declarePins () { private _declarePins () {
let pin; let pin : any;
for (let p in PINS) { for (let p in PINS) {
pin = PINS[p]; pin = PINS[p];
if (pin.edge) this._pin[p] = new Gpio(pin.pin, pin.dir, pin.edge); if (pin.edge) this._pin[p] = new Gpio(pin.pin, pin.dir, pin.edge);
@ -290,7 +312,7 @@ class Intval {
* *
*/ */
private _watchMicro (err : Error, val : number) { private async _watchMicro (err : Error, val : number) {
const now : number = +new Date(); const now : number = +new Date();
if (err) { if (err) {
log.error('_watchMicro', err); log.error('_watchMicro', err);
@ -298,18 +320,17 @@ class Intval {
//log.info(`Microswitch val: ${val}`) //log.info(`Microswitch val: ${val}`)
//determine when to stop //determine when to stop
if (val === 0 && this._state.frame.active) { if (val === 0 && this._state.frame.active) {
if (!this._state.micro.primed) { if (!this._micro.primed) {
this._state.micro.primed = true; this._micro.primed = true;
this._state.micro.time = now; this._micro.time = now;
log.info('Microswitch primed to stop motor'); log.info('Microswitch primed to stop motor');
} }
} else if (val === 1 && this._state.frame.active) { } else if (val === 1 && this._state.frame.active) {
if (this._state.micro.primed && !this._state.micro.paused && (now - this._state.frame.start) > this._frame.open) { if (this._state.micro.primed && !this._state.micro.paused && (now - this._state.frame.start) > this._frame.open) {
this._state.micro.primed = false; this._state.micro.primed = false;
this._state.micro.time = 0; this._state.micro.time = 0;
setTimeout( () => { await delay(this._micro.delay)
this._stop(); this._stop();
}, this._microDelay);
} }
} }
} }
@ -320,7 +341,7 @@ class Intval {
* *
* 1) If closed, start timer. * 1) If closed, start timer.
* 2) If opened, check timer AND * 2) If opened, check timer AND
* 3) If `press` (`now - this._state.release.time`) greater than minimum and less than `this._release.seq`, start frame * 3) If `press` (`now - this._release.time`) greater than minimum and less than `this._release.seq`, start frame
* 4) If `press` greater than `this._release.seq`, start sequence * 4) If `press` greater than `this._release.seq`, start sequence
* *
* Button + 10K ohm resistor * Button + 10K ohm resistor
@ -342,34 +363,40 @@ class Intval {
if (val === 0) { if (val === 0) {
//closed //closed
if (this._releaseClosedState(now)) { if (this._releaseClosedState(now)) {
this._state.release.time = now; this._release.time = now;
this._state.release.active = true; //maybe unncecessary this._release.active = true; //maybe unncecessary
} }
} else if (val === 1) { } else if (val === 1) {
//opened //opened
if (this._state.release.active) { if (this._release.active) {
press = now - this._state.release.time; press = now - this._release.time;
if (press > this._release.min && press < this._release.seq) { if (press > this._release.min && press < this._release.seq) {
this.frame(); this.frame();
} else if (press >= this._release.seq) { } else if (press >= this._release.seq) {
this.sequence(); this._sequence();
} }
//log.info(`Release closed for ${press}ms`) //log.info(`Release closed for ${press}ms`)
this._state.release.time = 0; this._release.time = 0;
this._state.release.active = false; this._release.active = false;
} }
} }
} }
private _sequence () {
if (this.sequence) {
this._state.sequence = this.sequence()
}
}
/** /**
* *
*/ */
private _releaseClosedState (now : number) { private _releaseClosedState (now : number) {
if (!this._state.release.active && this._state.release.time === 0) { if (!this._release.active && this._release.time === 0) {
return true; return true;
} }
if (this._state.release.active && (now - this._state.release.time) > (this._release.seq * 10)) { if (this._release.active && (now - this._release.time) > (this._release.seq * 10)) {
return true; return true;
} }
return false; return false;
@ -445,7 +472,7 @@ class Intval {
* *
*/ */
public frame (dir : boolean = null, exposure : number = null, cb : Function = () => {}) { public async frame (dir : boolean = null, exposure : number = null) {
if (dir === true || (dir === null && this._state.frame.dir === true) ) { if (dir === true || (dir === null && this._state.frame.dir === true) ) {
dir = true; dir = true;
} else { } else {
@ -465,42 +492,46 @@ class Intval {
this._state.frame.active = true; this._state.frame.active = true;
this._pin.micro.watch(this._watchMicro); this._pin.micro.watch(this._watchMicro);
log.info('frame', {dir : dir ? 'forward' : 'backward', exposure : exposure}); log.info('frame', {dir : dir ? 'forward' : 'backward', exposure });
if (dir) { if (dir) {
this._startFwd(); this._startFwd();
} else { } else {
this._startBwd(); this._startBwd();
} }
if (exposure !== 0) { if (exposure !== 0) {
this._state.frame.paused = true; this._state.frame.paused = true;
if (dir) { if (dir) {
setTimeout(this._pause, this._frame.open); await delay(this._frame.open)
//log.info('frame', { pausing : time + this._frame.open })
setTimeout( () => { this._pause()
this._state.frame.paused = false;
this._startFwd(); await delay(exposure + this._frame.closed)
}, exposure + this._frame.closed);
this._state.frame.paused = false
this._startFwd()
} else { } else {
setTimeout(this._pause, this._frame.openBwd);
setTimeout( () => { await delay(this._frame.openBwd)
//log.info('frame', 'restarting')
this._pause()
await delay(exposure + this._frame.closed)
this._state.frame.paused = false; this._state.frame.paused = false;
this._startBwd(); this._startBwd()
}, exposure + this._frame.closed);
} }
} }
if (dir) { if (dir) {
this._state.frame.cb = (len : number) => { this._state.frame.cb = (len : number) => {
this._state.counter++; this._state.counter++;
this._storeState(); this._storeState();
cb(len);
} }
} else { } else {
this._state.frame.cb = (len : number) => { this._state.frame.cb = (len : number) => {
this._state.counter--; this._state.counter--;
this._storeState(); this._storeState();
cb(len);
} }
} }
} }
@ -514,6 +545,4 @@ class Intval {
} }
} }
module.exports = new Intval(); module.exports = Intval
export default Intval;

View File

@ -2,135 +2,99 @@
import uuid from 'uuid/v4'; import uuid from 'uuid/v4';
const log = require('../log')('seq'); const log = require('../log')('seq');
import '../delay'; import { delay } from '../delay';
const MAX_INTEGER = 2147483647; const MAX_INTEGER = 2147483647;
interface Options { interface Options {
len? : number; len? : number;
multiple? : number;
delay? : number;
}
interface Loop {
count : number;
max : number;
delay : number;
} }
/** Object sequence features */ /** Object sequence features */
class Sequence { export class Sequence {
public _state : any = { private id : string
arr : []
private active : boolean = false
private delay : number = 0
private count : number = 0
private intval : any
/**
* @constructor
*
* Create a sequencer object from class
**/
constructor (intval : any) {
this.intval = intval
this.intval.sequence = function () {
if (this.active) {
this.stop()
return false
} else {
this.start()
return true
}
} }
private id : string;
private active : boolean = false;
private paused : boolean = false;
private frame : boolean = false;
private delay : boolean = false;
private count : number = 0;
private _stop : Function = null;
public _loop : any = {
arr : [],
count : 0,
max : 0
} }
constructor (intval : Intval) {
}
/** /**
* Start running a "sequence" of frames. Shoots a continuous sequence * Start running a "sequence" of frames. Shoots a continuous sequence
* of single frames with a delay in between each one. * of single frames with a delay in between each one.
**/ **/
public startOld (options : any, cb : Function) {
if (this._state.active) {
return false
}
this.active = true
this.count = 0
if (options.arr) {
this._state.arr = options.arr
}
if (options.loop) {
this._loop.arr = options.loop
this._loop.count = 0
}
if (options.maxLoop) {
this._loop.max = options.maxLoop
} else {
this._loop.max = 0
}
this._stop = cb
this.step()
this.id = uuid()
return this.id
}
public async start (options : Options) { public async start (options : Options) {
let len : number = typeof options.len !== 'undefined' ? options.len : MAX_INTEGER
let multiple : number = typeof options.multiple !== 'undefined' ? options.multiple : 1
this.id = uuid()
this.delay = typeof options.delay !== 'undefined' ? options.delay : 0
this.count = 0
for (let i = 0; i < len; i++) {
if (multiple > 1) {
for (let x = 0; x < multiple; x++) {
await this.intval.frame()
log.info({ id : this.id, count : this.count })
this.count++
}
} else {
await this.intval.frame()
log.info({ id : this.id, count : this.count })
this.count++
} }
public setStop () { if (this.delay > 0) {
this.active = false await delay(this.delay)
} }
if (!this.active) {
break
}
}
this.stop()
}
/**
* Stop a running sequence and reset counter and delay
**/
public stop = function () { public stop = function () {
this.active = false this.active = false
this.count = 0 this.count = 0
this._state.arr = [] this.delay = 0
this._loop.count = 0
this._loop.max = 0
this._loop.arr = []
if (this._stop) this._stop()
this._stop = null
}
public pause () {
this.paused = true
}
public resume () {
this.paused = false
this.step()
}
public step () {
if (this.active && !this.paused) {
if (this._state.arr.length > 0) {
if (this.count > this._state.arr.length - 1) {
return this.stop()
}
log.info('step', { count : this.count, id : this._state.id })
return this._state.arr[this.count](() => {
this.count++
this.step()
})
} else if (this._loop.arr.length > 0) {
if (this.count > this._loop.arr.length - 1) {
this.count = 0
this._loop.count++
}
if (this._loop.max > 0 && this._loop.count > this._loop.max) {
return this.stop()
}
log.info('step', { count : this.count, id : this.id })
return this._loop.arr[this.count](() => {
this.count++
this.step()
})
} else{
return this.stop()
}
} else if (this.paused) {
log.info('step', 'Sequence paused', { loop : this._loop.count, count : this.count })
} else if (!this.active) {
log.info('step', 'Sequence stopped', { loop : this._loop.count, count : this.count })
}
} }
} }
module.exports = new Sequence(); module.exports = Sequence