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 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 PORT = process.env.PORT || 6699
@ -183,7 +184,7 @@ function rCounter (req, res, next) {
return next()
}
function rFrame (req, res, next) {
async function rFrame (req, res, next) {
let dir = true
let exposure = 0
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 })
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()
})
}
}
function rStatus (req, res, next) {
@ -247,7 +252,7 @@ function rStatus (req, res, next) {
return next()
}
function rSequence (req, res, next) {
async function rSequence (req, res, next) {
let dir = true
let exposure = 0
let delay = 0
@ -304,33 +309,17 @@ function rSequence (req, res, next) {
delay = req.body.delay
}
}
if (intval._state.sequence && sequence._state.active) {
sequence.setStop()
if (intval._state.sequence && sequence.active) {
intval._state.sequence = false
sequence.stop()
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) {
res.send({ started : false })
} else {
res.send({ started : true , id : seq_id })
}
return next()
} else {
intval._state.sequence = true
sequence.start()
res.send({ started : true })
return next()
}
@ -374,9 +363,13 @@ function rRestart (req, res, next) {
//Ble functions
function bFrame (obj, cb) {
async function bFrame (obj, cb) {
let dir = true
let exposure = 0
if (sequence.active) {
return cb()
}
if (intval._state.frame.dir !== true) {
dir = false
@ -401,11 +394,10 @@ function bFrame (obj, cb) {
log.info('frame', { method : 'ble', dir : dir, exposure : exposure })
if (exposure < 5000) {
intval.frame(dir, exposure, (len) => {
return cb()
})
await intval.frame(dir, exposure)
return cb()
} else {
intval.frame(dir, exposure, (len) => {})
intval.frame(dir, exposure)
return cb()
}
@ -502,29 +494,14 @@ function bSequence (obj, cb) {
}
if (intval._state.sequence && sequence._state.active) {
//should not occur with single client
sequence.setStop()
intval._state.sequence = false
sequence.stop()
log.info('sequence stop', { method : 'ble' })
return cb()
} 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) {
log.info('sequence start', { method : 'ble', id : seq_id })
}
sequence.start()
log.info('sequence start', { method : 'ble' })
return cb()
}
}
@ -558,6 +535,7 @@ function bUpdate (obj, cb) {
}, 20)
})
}
function bRestart (obj, cb) {
log.info('restart', { method : 'ble' })
cb()
@ -607,7 +585,6 @@ function index (req, res, next) {
}
function init () {
intval.init()
intval.sequence = seq
createServer()
createBLE()

View File

@ -12,6 +12,7 @@ function delay(ms) {
return setTimeout(resolve, ms);
});
}
exports.delay = delay;
module.exports.delay = delay;
exports.default = delay;
//# 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 storage = __importStar(require("node-persist"));
const fs_extra_1 = require("fs-extra");
require("../delay");
const delay_1 = require("../delay");
let Gpio;
try {
Gpio = require('onoff').Gpio;
@ -52,9 +52,15 @@ class Intval {
};
this._release = {
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._state = {};
this._init();
@ -64,21 +70,7 @@ class Intval {
*/
async _init() {
let dirExists;
try {
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({
const storateOptions = {
dir: this.STATE_DIR,
stringify: JSON.stringify,
parse: JSON.parse,
@ -87,22 +79,56 @@ class Intval {
continuous: true,
interval: 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._declarePins();
});
process.on('SIGINT', this._undeclarePins);
process.on('uncaughtException', this._undeclarePins);
}
process.on('SIGINT', this._undeclarePins.bind(this));
process.on('uncaughtException', this._undeclarePins.bind(this));
}
/**
* Restore the state from the storage object
*/
_restoreState() {
storage.getItem('_state', 'test').then(this._setState).catch((err) => {
this._setState();
async _restoreState() {
let data;
try {
data = await storage.getItem('_state');
}
catch (err) {
log.error('_restoreState', err);
});
}
try {
this._setState(data);
}
catch (err) {
log.error('_restoreState', err);
this._setState();
}
this._declarePins();
}
/**
@ -127,14 +153,6 @@ class Intval {
current: {},
cb: () => { }
},
release: {
time: 0,
active: false //is pressed
},
micro: {
time: 0,
primed: false //is ready to stop frame
},
counter: 0,
sequence: false
};
@ -144,11 +162,12 @@ class Intval {
* Store the state object.
*/
_storeState() {
storage.setItem('_state', this._state)
.then(() => { })
.catch((err) => {
try {
storage.setItem('_state', this._state);
}
catch (err) {
log.error('_storeState', err);
});
}
}
/**
* (internal function) Declares all Gpio pins that will be used.
@ -247,7 +266,7 @@ class Intval {
* @param {integer} val Current value of the pin
*
*/
_watchMicro(err, val) {
async _watchMicro(err, val) {
const now = +new Date();
if (err) {
log.error('_watchMicro', err);
@ -255,9 +274,9 @@ class Intval {
//log.info(`Microswitch val: ${val}`)
//determine when to stop
if (val === 0 && this._state.frame.active) {
if (!this._state.micro.primed) {
this._state.micro.primed = true;
this._state.micro.time = now;
if (!this._micro.primed) {
this._micro.primed = true;
this._micro.time = now;
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) {
this._state.micro.primed = false;
this._state.micro.time = 0;
setTimeout(() => {
this._stop();
}, this._microDelay);
await delay_1.delay(this._micro.delay);
this._stop();
}
}
}
@ -277,7 +295,7 @@ class Intval {
*
* 1) If closed, start timer.
* 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
*
* Button + 10K ohm resistor
@ -298,34 +316,39 @@ class Intval {
if (val === 0) {
//closed
if (this._releaseClosedState(now)) {
this._state.release.time = now;
this._state.release.active = true; //maybe unncecessary
this._release.time = now;
this._release.active = true; //maybe unncecessary
}
}
else if (val === 1) {
//opened
if (this._state.release.active) {
press = now - this._state.release.time;
if (this._release.active) {
press = now - this._release.time;
if (press > this._release.min && press < this._release.seq) {
this.frame();
}
else if (press >= this._release.seq) {
this.sequence();
this._sequence();
}
//log.info(`Release closed for ${press}ms`)
this._state.release.time = 0;
this._state.release.active = false;
this._release.time = 0;
this._release.active = false;
}
}
}
_sequence() {
if (this.sequence) {
this._state.sequence = this.sequence();
}
}
/**
*
*/
_releaseClosedState(now) {
if (!this._state.release.active && this._state.release.time === 0) {
if (!this._release.active && this._release.time === 0) {
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 false;
@ -389,7 +412,7 @@ class Intval {
* @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)) {
dir = true;
}
@ -402,10 +425,12 @@ class Intval {
else if (exposure === null) {
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.active = true;
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) {
this._startFwd();
}
@ -415,47 +440,40 @@ class Intval {
if (exposure !== 0) {
this._state.frame.paused = true;
if (dir) {
setTimeout(this._pause, this._frame.open);
//log.info('frame', { pausing : time + this._frame.open })
setTimeout(() => {
this._state.frame.paused = false;
this._startFwd();
}, exposure + this._frame.closed);
await delay_1.delay(this._frame.open);
this._pause();
await delay_1.delay(exposure + this._frame.closed);
this._state.frame.paused = false;
this._startFwd();
}
else {
setTimeout(this._pause, this._frame.openBwd);
setTimeout(() => {
//log.info('frame', 'restarting')
this._state.frame.paused = false;
this._startBwd();
}, exposure + this._frame.closed);
await delay_1.delay(this._frame.openBwd);
this._pause();
await delay_1.delay(exposure + this._frame.closed);
this._state.frame.paused = false;
this._startBwd();
}
}
if (dir) {
this._state.frame.cb = (len) => {
this._state.counter++;
this._storeState();
cb(len);
};
}
else {
this._state.frame.cb = (len) => {
this._state.counter--;
this._storeState();
cb(len);
};
}
this._state.frame.current = {
dir: dir,
exposure: exposure
};
}
/**
*
* Returns the state of the
*/
status() {
return this._state;
}
}
module.exports = new Intval();
exports.default = Intval;
module.exports = Intval;
//# 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 });
const v4_1 = __importDefault(require("uuid/v4"));
const log = require('../log')('seq');
require("../delay");
const delay_1 = require("../delay");
const MAX_INTEGER = 2147483647;
/** Object sequence features */
class Sequence {
constructor() {
this._state = {
arr: []
};
/**
* @constructor
*
* Create a sequencer object from class
**/
constructor(intval) {
this.active = false;
this.paused = false;
this.frame = false;
this.delay = false;
this.delay = 0;
this.count = 0;
this._stop = null;
this._loop = {
arr: [],
count: 0,
max: 0
};
/**
* Stop a running sequence and reset counter and delay
**/
this.stop = function () {
this.active = false;
this.count = 0;
this._state.arr = [];
this._loop.count = 0;
this._loop.max = 0;
this._loop.arr = [];
if (this._stop)
this._stop();
this._stop = null;
this.delay = 0;
};
this.intval = intval;
this.intval.sequence = function () {
if (this.active) {
this.stop();
return false;
}
else {
this.start();
return true;
}
};
}
/**
* Start running a "sequence" of frames. Shoots a continuous sequence
* of single frames with a delay in between each one.
**/
start(options, cb) {
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();
async start(options) {
let len = typeof options.len !== 'undefined' ? options.len : MAX_INTEGER;
let multiple = typeof options.multiple !== 'undefined' ? options.multiple : 1;
this.id = v4_1.default();
return this.id;
}
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.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++;
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();
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) {
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 });
}
this.stop();
}
}
module.exports = new Sequence();
exports.Sequence = Sequence;
module.exports = Sequence;
//# 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
**/
function delay (ms : number) {
export function delay (ms : number) {
return new Promise((resolve : any) => {
return setTimeout(resolve, ms);
});

View File

@ -3,8 +3,8 @@
const db = require('../db');
const log = require('../log')('intval');
import * as storage from 'node-persist';
import { exists, mkdir } from 'fs-extra';
import '../delay';
import { pathExists, mkdir } from 'fs-extra';
import { delay } from '../delay';
let Gpio : any
try {
@ -15,7 +15,7 @@ try {
}
const PINS = {
const PINS : any = {
fwd : {
pin : 13,
dir : 'out'
@ -51,7 +51,8 @@ interface Entry {
}
/** class representing the intval3 features */
class Intval {
export default class Intval {
private STATE_DIR : string = '~/state';
private _frame : any = {
@ -62,12 +63,21 @@ class Intval {
}
private _release : any = {
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 _state : any = {};
public sequence : any;
constructor() {
this._init();
@ -79,22 +89,7 @@ class Intval {
private async _init () {
let dirExists : boolean;
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({
const storateOptions = {
dir: this.STATE_DIR,
stringify: JSON.stringify,
parse: JSON.parse,
@ -105,25 +100,60 @@ class Intval {
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
//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._declarePins();
})
}
process.on('SIGINT', this._undeclarePins);
process.on('uncaughtException', this._undeclarePins);
process.on('SIGINT', this._undeclarePins.bind(this));
process.on('uncaughtException', this._undeclarePins.bind(this));
}
/**
* Restore the state from the storage object
*/
private _restoreState () {
storage.getItem('_state', 'test').then(this._setState).catch((err) => {
this._setState();
private async _restoreState () {
let data : any;
try {
data = await storage.getItem('_state');
} catch (err) {
log.error('_restoreState', err);
})
}
try {
this._setState(data);
} catch (err) {
log.error('_restoreState', err);
this._setState();
}
this._declarePins();
}
@ -150,14 +180,6 @@ class Intval {
current : {}, //current settings
cb : () => {}
},
release : {
time: 0,
active : false //is pressed
},
micro : {
time : 0,
primed : false //is ready to stop frame
},
counter : 0,
sequence : false
}
@ -169,11 +191,11 @@ class Intval {
*/
private _storeState () {
storage.setItem('_state', this._state)
.then(() => {})
.catch((err) => {
log.error('_storeState', err);
})
try {
storage.setItem('_state', this._state);
} catch (err) {
log.error('_storeState', err);
}
}
/**
@ -181,7 +203,7 @@ class Intval {
*/
private _declarePins () {
let pin;
let pin : any;
for (let p in PINS) {
pin = PINS[p];
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();
if (err) {
log.error('_watchMicro', err);
@ -298,18 +320,17 @@ class Intval {
//log.info(`Microswitch val: ${val}`)
//determine when to stop
if (val === 0 && this._state.frame.active) {
if (!this._state.micro.primed) {
this._state.micro.primed = true;
this._state.micro.time = now;
if (!this._micro.primed) {
this._micro.primed = true;
this._micro.time = now;
log.info('Microswitch primed to stop motor');
}
} 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) {
this._state.micro.primed = false;
this._state.micro.time = 0;
setTimeout( () => {
this._stop();
}, this._microDelay);
await delay(this._micro.delay)
this._stop();
}
}
}
@ -320,7 +341,7 @@ class Intval {
*
* 1) If closed, start timer.
* 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
*
* Button + 10K ohm resistor
@ -342,34 +363,40 @@ class Intval {
if (val === 0) {
//closed
if (this._releaseClosedState(now)) {
this._state.release.time = now;
this._state.release.active = true; //maybe unncecessary
this._release.time = now;
this._release.active = true; //maybe unncecessary
}
} else if (val === 1) {
//opened
if (this._state.release.active) {
press = now - this._state.release.time;
if (this._release.active) {
press = now - this._release.time;
if (press > this._release.min && press < this._release.seq) {
this.frame();
} else if (press >= this._release.seq) {
this.sequence();
this._sequence();
}
//log.info(`Release closed for ${press}ms`)
this._state.release.time = 0;
this._state.release.active = false;
this._release.time = 0;
this._release.active = false;
}
}
}
private _sequence () {
if (this.sequence) {
this._state.sequence = this.sequence()
}
}
/**
*
*/
private _releaseClosedState (now : number) {
if (!this._state.release.active && this._state.release.time === 0) {
if (!this._release.active && this._release.time === 0) {
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 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) ) {
dir = true;
} else {
@ -465,42 +492,46 @@ class Intval {
this._state.frame.active = true;
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) {
this._startFwd();
} else {
this._startBwd();
}
if (exposure !== 0) {
this._state.frame.paused = true;
if (dir) {
setTimeout(this._pause, this._frame.open);
//log.info('frame', { pausing : time + this._frame.open })
setTimeout( () => {
this._state.frame.paused = false;
this._startFwd();
}, exposure + this._frame.closed);
await delay(this._frame.open)
this._pause()
await delay(exposure + this._frame.closed)
this._state.frame.paused = false
this._startFwd()
} else {
setTimeout(this._pause, this._frame.openBwd);
setTimeout( () => {
//log.info('frame', 'restarting')
this._state.frame.paused = false;
this._startBwd();
}, exposure + this._frame.closed);
await delay(this._frame.openBwd)
this._pause()
await delay(exposure + this._frame.closed)
this._state.frame.paused = false;
this._startBwd()
}
}
if (dir) {
this._state.frame.cb = (len : number) => {
this._state.counter++;
this._storeState();
cb(len);
}
} else {
this._state.frame.cb = (len : number) => {
this._state.counter--;
this._storeState();
cb(len);
}
}
}
@ -514,6 +545,4 @@ class Intval {
}
}
module.exports = new Intval();
export default Intval;
module.exports = Intval

View File

@ -2,135 +2,99 @@
import uuid from 'uuid/v4';
const log = require('../log')('seq');
import '../delay';
import { delay } from '../delay';
const MAX_INTEGER = 2147483647;
interface Options {
len? : number;
multiple? : number;
delay? : number;
}
interface Loop {
count : number;
max : number;
delay : number;
}
/** Object sequence features */
class Sequence {
public _state : any = {
arr : []
}
private id : string;
export class Sequence {
private id : string
private active : boolean = false;
private paused : boolean = false;
private active : boolean = false
private frame : boolean = false;
private delay : boolean = false;
private count : number = 0;
private delay : number = 0
private count : number = 0
private _stop : Function = null;
private intval : any
public _loop : any = {
arr : [],
count : 0,
max : 0
/**
* @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
}
}
}
constructor (intval : Intval) {
}
/**
* Start running a "sequence" of frames. Shoots a continuous sequence
* 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) {
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++
}
if (this.delay > 0) {
await delay(this.delay)
}
if (!this.active) {
break
}
}
this.stop()
}
public setStop () {
this.active = false
}
/**
* Stop a running sequence and reset counter and delay
**/
public stop = function () {
this.active = false
this.count = 0
this._state.arr = []
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 })
}
this.delay = 0
}
}
module.exports = new Sequence();
module.exports = Sequence