From b307567a51acda5bebbf3ac8a17b18626223f8e9 Mon Sep 17 00:00:00 2001 From: mmcw-dev Date: Mon, 23 Oct 2017 12:58:37 -0400 Subject: [PATCH] Persist device state with node-persist. This allows multiple controllers to share state, and for device to maintain settings between shutdowns. --- .gitignore | 3 +- app/www/index.html | 7 ++-- lib/intval/index.js | 81 ++++++++++++++++++++++++++++++++++++--------- package-lock.json | 50 ++++++++++++++++++++++++++++ package.json | 1 + 5 files changed, 123 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 947371b..dd23eb4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -run_dev.sh \ No newline at end of file +run_dev.sh +state \ No newline at end of file diff --git a/app/www/index.html b/app/www/index.html index 4d0bf98..2839aeb 100644 --- a/app/www/index.html +++ b/app/www/index.html @@ -265,12 +265,15 @@ +

BLUETOOTH

+ +

WIFI

-
Wifi SSID
-
Wifi Password
diff --git a/lib/intval/index.js b/lib/intval/index.js index 57400cd..9699508 100644 --- a/lib/intval/index.js +++ b/lib/intval/index.js @@ -1,10 +1,12 @@ 'use strict' const log = require('../log')('intval') +const storage = require('node-persist') +const fs = require('fs') let Gpio try { - Gpio = require('onoff').Gpio + //Gpio = require('onoff').Gpio } catch (e) { log.warn('Failed including Gpio, using sim') Gpio = require('../../lib/onoffsim').Gpio @@ -36,7 +38,53 @@ const PINS = { const intval = {} intval.init = function () { + if (!fs.existsSync('./state')) fs.mkdirSync('./state') + storage.init({ + dir: './state', + stringify: JSON.stringify, + parse: JSON.parse, + encoding: 'utf8', + logging: false, // can also be custom logging function + continuous: true, // continously persist to disk + interval: false, // milliseconds, persist to disk on an interval + 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((res) => { + //console.dir(res) + storage.getItem('_state', 'test').then(intval._setState).catch((err) => { + intval._setState(undefined) + log.error('init', err) + }) + }).catch((err) => { + log.error('init', err) + }) + + intval._frame = { + open : 250, //delay before pausing frame in open state + openBwd : 400, + closed : 100, //time that frame actually remains closed for + expected : 630 //expected length of frame, in ms + } + intval._release = { + min : 20, + seq : 1000 + } + intval._microDelay = 10 // delay after stop signal before stopping motors intval._pin = {} + + intval._declarePins() + process.on('SIGINT', intval._undeclarePins) + process.on('uncaughtException', intval._undeclarePins) +} + +intval._setState = function (data) { + if (typeof data !== 'undefined') { + intval._state = data + intval._state.frame.cb = () => {} + log.info('_setState', 'Restored intval state from disk') + return true + } intval._state = { frame : { dir : true, //forward @@ -57,22 +105,17 @@ intval.init = function () { }, counter : 0 } - intval._frame = { - open : 250, //delay before pausing frame in open state - openBwd : 400, - closed : 100, //time that frame actually remains closed for - expected : 630 //expected length of frame, in ms - } - intval._release = { - min : 20, - seq : 1000 - } - intval._microDelay = 10 // delay after stop signal before stopping motors - - intval._declarePins() - process.on('SIGINT', intval._undeclarePins) - process.on('uncaughtException', intval._undeclarePins) + intval._storeState() } + +intval._storeState = function () { + setItem('_state', intval._state) + .then(() => {}) + .catch((err) => { + log.error('_storeState', err) + }) +} + /** * (internal function) Declares all Gpio pins that will be used * @@ -253,20 +296,24 @@ intval.setDir = function (val = true) { return log.warn('Direction must be represented as either true or false') } intval._state.frame.dir = val + intval._storeState() log.info('setDir', { direction : val ? 'forward' : 'backward' }) } intval.setExposure = function (val = 0) { intval._state.frame.exposure = val + intval._storeState() log.info('setExposure', { exposure : val }) } intval.setDelay = function (val = 0) { intval._state.frame.delay = val + intval._storeState() log.info('setDelay', { delay : val }) } intval.setCounter = function (val = 0) { intval._state.counter = val + intval._storeState() log.info('setCounter', { counter : val }) } /** @@ -321,11 +368,13 @@ intval.frame = function (dir = null, time = null, cb = () => {}) { if (dir) { intval._state.frame.cb = (len) => { intval._state.counter++ + intval._storeState() cb(len) } } else { intval._state.frame.cb = (len) => { intval._state.counter-- + intval._storeState() cb(len) } } diff --git a/package-lock.json b/package-lock.json index e8de43b..f791a08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -607,16 +607,46 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, "is-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "requires": { + "is-unc-path": "0.1.2" + } + }, "is-supported-regexp-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz", "integrity": "sha1-i1IMhfrnolM4LUsCZS4EVXbhO7g=" }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -888,6 +918,16 @@ "js-queue": "2.0.0" } }, + "node-persist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-2.1.0.tgz", + "integrity": "sha1-5lK784haBNrWo1PXQXYXfIORRwc=", + "requires": { + "is-absolute": "0.2.6", + "mkdirp": "0.5.1", + "q": "1.1.2" + } + }, "object-get": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.0.tgz", @@ -946,6 +986,11 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, + "q": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz", + "integrity": "sha1-Y1fikSBnAdmfGXq4TlforRlvKok=" + }, "qs": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", @@ -1312,6 +1357,11 @@ } } }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + }, "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", diff --git a/package.json b/package.json index d1b2e33..56894c3 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "cron": "^1.2.1", "gpio": "^0.2.7", "node-ipc": "^9.1.0", + "node-persist": "^2.1.0", "onoff": "^1.1.5", "restify": "^5.2.0", "uuid": "^3.1.0",