From aa5bbfc9fdbda23362b7e7def92c1626e18472c9 Mon Sep 17 00:00:00 2001 From: mmcwilliams Date: Mon, 4 Mar 2019 22:09:12 -0500 Subject: [PATCH] Port shared modules to typescript. Migrate shared modules first, then look at individual needs of sub-projects. --- app/lib/arduino/index.js.map | 1 + lib/arduino/Readme.md | 82 ++++++ lib/arduino/index.js | 372 ++++++++++++++++++++++++ lib/arduino/index.js.map | 1 + lib/arduino/package.json | 11 + lib/mscript/Readme.md | 186 ++++++++++++ lib/mscript/TODO.md | 13 + lib/mscript/index.js | 545 +++++++++++++++++++++++++++++++++++ lib/mscript/index.old.js | 476 ++++++++++++++++++++++++++++++ lib/mscript/package.json | 11 + package-lock.json | 20 ++ package.json | 28 ++ scripts/build.sh | 7 + scripts/docs.sh | 8 + src/arduino/index.ts | 375 ++++++++++++++++++++++++ src/mscript/index.js | 545 +++++++++++++++++++++++++++++++++++ tsconfig.json | 14 + 17 files changed, 2695 insertions(+) create mode 100644 app/lib/arduino/index.js.map create mode 100644 lib/arduino/Readme.md create mode 100644 lib/arduino/index.js create mode 100644 lib/arduino/index.js.map create mode 100644 lib/arduino/package.json create mode 100644 lib/mscript/Readme.md create mode 100644 lib/mscript/TODO.md create mode 100644 lib/mscript/index.js create mode 100644 lib/mscript/index.old.js create mode 100644 lib/mscript/package.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 scripts/build.sh create mode 100644 scripts/docs.sh create mode 100644 src/arduino/index.ts create mode 100644 src/mscript/index.js create mode 100644 tsconfig.json diff --git a/app/lib/arduino/index.js.map b/app/lib/arduino/index.js.map new file mode 100644 index 0000000..8e9c98c --- /dev/null +++ b/app/lib/arduino/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/arduino/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/arduino/Readme.md b/lib/arduino/Readme.md new file mode 100644 index 0000000..498f041 --- /dev/null +++ b/lib/arduino/Readme.md @@ -0,0 +1,82 @@ +## Functions + +
+
delay(ms)Promise
+

Pause the process for X milliseconds in async/await functions

+
+
send(device, cmd)Promise
+

Send a command to an Arduino using async/await

+
+
write(device, str)Promise
+

Send a string to an Arduino using async/await

+
+
open(device)Promise
+

Connect to an Arduino using async/await

+
+
close(device)Promise
+

Close a connection to an Arduino using async/await

+
+
+ + + +## delay(ms) ⇒ Promise +Pause the process for X milliseconds in async/await functions + +**Kind**: global function +**Returns**: Promise - Resolves after wait + +| Param | Type | Description | +| --- | --- | --- | +| ms | integer | milliseconds | + + + +## send(device, cmd) ⇒ Promise +Send a command to an Arduino using async/await + +**Kind**: global function +**Returns**: Promise - Resolves after sending + +| Param | Type | Description | +| --- | --- | --- | +| device | string | Arduino identifier | +| cmd | string | Single character command to send | + + + +## write(device, str) ⇒ Promise +Send a string to an Arduino using async/await + +**Kind**: global function +**Returns**: Promise - Resolves after sending + +| Param | Type | Description | +| --- | --- | --- | +| device | string | Arduino identifier | +| str | string | String to send | + + + +## open(device) ⇒ Promise +Connect to an Arduino using async/await + +**Kind**: global function +**Returns**: Promise - Resolves after opening + +| Param | Type | Description | +| --- | --- | --- | +| device | string | Arduino identifier | + + + +## close(device) ⇒ Promise +Close a connection to an Arduino using async/await + +**Kind**: global function +**Returns**: Promise - Resolves after closing + +| Param | Type | Description | +| --- | --- | --- | +| device | string | Arduino identifier | + diff --git a/lib/arduino/index.js b/lib/arduino/index.js new file mode 100644 index 0000000..992bebe --- /dev/null +++ b/lib/arduino/index.js @@ -0,0 +1,372 @@ +'use strict'; +const SerialPort = require('serialport'); +const Readline = SerialPort.parsers.Readline; +const exec = require('child_process').exec; +const parser = new Readline(''); +const newlineRe = new RegExp('\n', 'g'); +const returnRe = new RegExp('\r', 'g'); +let eventEmitter; +let cfg; +/** + * Pause the process for X milliseconds in async/await functions + * + * @param {integer} ms milliseconds + * + * @returns {Promise} Resolves after wait + **/ +async function delay(ms) { + return new Promise(resolve => { + return setTimeout(resolve, ms); + }); +} +/** + * Send a command to an Arduino using async/await + * + * @param {string} device Arduino identifier + * @param {string} cmd Single character command to send + * + * @returns {Promise} Resolves after sending + **/ +async function send(device, cmd) { + return new Promise((resolve, reject) => { + arduino.queue[cmd] = (ms) => { + return resolve(ms); + }; + return arduino.serial[device].write(cmd, (err, results) => { + if (err) { + //console.error(err) + return reject(err); + } + // + }); + }); +} +/** + * Send a string to an Arduino using async/await + * + * @param {string} device Arduino identifier + * @param {string} str String to send + * + * @returns {Promise} Resolves after sending + **/ +async function write(device, str) { + return new Promise((resolve, reject) => { + arduino.serial[device].write(str, function (err, results) { + if (err) { + return reject(err); + } + //console.log('sent: ' + str) + return resolve(results); + }); + }); +} +/** + * Connect to an Arduino using async/await + * + * @param {string} device Arduino identifier + * + * @returns {Promise} Resolves after opening + **/ +async function openArduino(device) { + return new Promise((resolve, reject) => { + return arduino.serial[device].open(error => { + if (error) { + return reject(error); + } + return resolve(true); + }); + }); +} +/** + * Close a connection to an Arduino using async/await + * + * @param {string} device Arduino identifier + * + * @returns {Promise} Resolves after closing + **/ +async function closeArduino(device) { + return new Promise((resolve, reject) => { + return arduino.serial[device].close((err) => { + if (err) { + return reject(err); + } + return resolve(true); + }); + }); +} +/****** + Arduino handlers +*******/ +const arduino = { + path: {}, + known: [ + '/dev/tty.usbmodem1a161', + '/dev/tty.usbserial-A800f8dk', + '/dev/tty.usbserial-A900cebm', + '/dev/tty.usbmodem1a131', + '/dev/tty.usbserial-a900f6de', + '/dev/tty.usbmodem1a141', + '/dev/ttyACM0', + 'COM3' + ], + alias: {}, + serial: { + connect: {}, + projector: {}, + camera: {}, + light: {} + }, + baud: 57600, + queue: {}, + timer: 0, + lock: false, + locks: {} +}; +arduino.enumerate = async function () { + return new Promise((resolve, reject) => { + return SerialPort.list((err, ports) => { + let matches = []; + if (err) { + return reject(err); + } + ports.forEach(port => { + if (arduino.known.indexOf(port.comName) !== -1) { + matches.push(port.comName); + } + else if ((port.manufacturer + '').toLowerCase().indexOf('arduino') !== -1) { + matches.push(port.comName); + } + else if ((port.comName + '').toLowerCase().indexOf('usbserial') !== -1) { + matches.push(port.comName); + } + else if ((port.comName + '').toLowerCase().indexOf('usbmodem') !== -1) { + matches.push(port.comName); + } + }); + if (matches.length === 0) { + return reject('No USB devices found'); + } + else if (matches.length > 0) { + return resolve(matches); + } + }); + }); +}; +//commands which respond to a sent char +arduino.send = async function (serial, cmd, res) { + const device = arduino.alias[serial]; + let results; + if (arduino.locks[serial]) { + return false; + } + arduino.locks[serial] = true; + await delay(cfg.arduino.serialDelay); + try { + results = await send(device, cmd); + } + catch (e) { + return console.error(e); + } + arduino.locks[serial] = false; + arduino.timer = new Date().getTime(); + return await eventEmitter.emit('arduino_send', cmd); +}; +//send strings, after char triggers firmware to accept +arduino.string = async function (serial, str) { + const device = arduino.alias[serial]; + let writeSuccess; + await delay(cfg.arduino.serialDelay); + if (typeof arduino.serial[device].fake !== 'undefined' + && arduino.serial[device].fake) { + return arduino.serial[device].string(str); + } + else { + try { + writeSuccess = await write(device, str); + } + catch (e) { + return console.error(e); + } + return writeSuccess; + } +}; +//respond with same char over serial when done +arduino.end = async function (serial, data) { + const end = new Date().getTime(); + const ms = end - arduino.timer; + let complete; + if (arduino.queue[data] !== undefined) { + arduino.locks[serial] = false; + //console.log('Command ' + data + ' took ' + ms + 'ms'); + complete = arduino.queue[data](ms); //execute callback + eventEmitter.emit('arduino_end', data); + delete arduino.queue[data]; + } + else { + //console.log('Received stray "' + data + '"'); //silent to user + } + return complete; +}; +arduino.alias = function (serial, device) { + console.log(`Making "${serial}" an alias of ${device}`); + arduino.alias[serial] = device; +}; +arduino.connect = async function (serial, device, confirm) { + return new Promise(async (resolve, reject) => { + let connectSuccess; + arduino.path[serial] = device; + arduino.alias[serial] = device; + arduino.serial[device] = new SerialPort(arduino.path[serial], { + autoOpen: false, + baudRate: cfg.arduino.baud, + parser: parser + }); + arduino.locks[device] = false; + try { + connectSuccess = await openArduino(device); + } + catch (e) { + console.error('failed to open: ' + e); + return reject(e); + } + console.log(`Opened connection with ${arduino.path[serial]} as ${serial}`); + if (!confirm) { + arduino.serial[device].on('data', async (data) => { + let d = data.toString('utf8'); + d = d.replace(newlineRe, '').replace(returnRe, ''); + return await arduino.end(serial, d); + }); + } + else { + arduino.serial[device].on('data', async (data) => { + let d = data.toString('utf8'); + d = d.replace(newlineRe, '').replace(returnRe, ''); + return await arduino.confirmEnd(d); + }); + } + return resolve(arduino.path[serial]); + }); +}; +arduino.confirmExec = {}; +arduino.confirmEnd = function (data) { + //console.dir(data) + if (data === cfg.arduino.cmd.connect + || data === cfg.arduino.cmd.proj_identifier + || data === cfg.arduino.cmd.cam_identifier + || data === cfg.arduino.cmd.light_identifier + || data === cfg.arduino.cmd.proj_light_identifier + || data === cfg.arduino.cmd.proj_cam_light_identifier + || data === cfg.arduino.cmd.proj_cam_identifier) { + arduino.confirmExec(null, data); + arduino.confirmExec = {}; + } +}; +arduino.verify = async function () { + return new Promise(async (resolve, reject) => { + const device = arduino.alias['connect']; + let writeSuccess; + arduino.confirmExec = function (err, data) { + if (data === cfg.arduino.cmd.connect) { + return resolve(true); + } + else { + return reject('Wrong data returned'); + } + }; + await delay(cfg.arduino.serialDelay); + try { + writeSuccess = await send(device, cfg.arduino.cmd.connect); + } + catch (e) { + return reject(e); + } + return resolve(writeSuccess); + }); +}; +arduino.distinguish = async function () { + return new Promise(async (resolve, reject) => { + const device = arduino.alias['connect']; + let writeSuccess; + let type; + arduino.confirmExec = function (err, data) { + if (data === cfg.arduino.cmd.proj_identifier) { + type = 'projector'; + } + else if (data === cfg.arduino.cmd.cam_identifier) { + type = 'camera'; + } + else if (data === cfg.arduino.cmd.light_identifier) { + type = 'light'; + } + else if (data === cfg.arduino.cmd.proj_light_identifier) { + type = 'projector,light'; + } + else if (data === cfg.arduino.cmd.proj_cam_light_identifier) { + type = 'projector,camera,light'; + } + else if (data === cfg.arduino.cmd.proj_cam_identifier) { + type = 'projector,camera'; + } + else if (data === cfg.ardino.cmd.proj_second_identifier) { + type = 'projector_second'; + } + return resolve(type); + }; + await delay(cfg.arduino.serialDelay); + try { + writeSuccess = await send(device, cfg.arduino.cmd.mcopy_identifier); + } + catch (e) { + console.error(e); + return reject(e); + } + }); +}; +arduino.close = async function (callback) { + const device = arduino.alias['connect']; + let closeSuccess; + try { + closeSuccess = await closeArduino(device); + } + catch (e) { + return console.error(e); + } + return closeSuccess; +}; +arduino.fakeConnect = async function (serial) { + //console.log('Connecting to fake arduino...'); + const device = '/dev/fake'; + arduino.alias[serial] = device; + arduino.serial[device] = { + write: function (cmd, cb) { + const t = { + c: cfg.arduino.cam.time + cfg.arduino.cam.delay, + p: cfg.arduino.proj.time + cfg.arduino.proj.delay + }; + let timeout = t[cmd]; + let end; + if (typeof timeout === 'undefined') + timeout = 10; + arduino.timer = +new Date(); + setTimeout(() => { + arduino.end(serial, cmd); + return cb(); + }, timeout); + }, + string: async function (str) { + //do nothing + return true; + }, + fake: true + }; + //console.log('Connected to fake arduino! Not real! Doesn\'t exist!'); + return true; +}; +if (typeof module !== 'undefined' && module.parent) { + module.exports = function (c, ee) { + eventEmitter = ee; + cfg = c; + return arduino; + }; +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/arduino/index.js.map b/lib/arduino/index.js.map new file mode 100644 index 0000000..8e9c98c --- /dev/null +++ b/lib/arduino/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/arduino/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/lib/arduino/package.json b/lib/arduino/package.json new file mode 100644 index 0000000..43708c1 --- /dev/null +++ b/lib/arduino/package.json @@ -0,0 +1,11 @@ +{ + "name": "arduino", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} diff --git a/lib/mscript/Readme.md b/lib/mscript/Readme.md new file mode 100644 index 0000000..3112f09 --- /dev/null +++ b/lib/mscript/Readme.md @@ -0,0 +1,186 @@ + + +## lib/mscript + +* [lib/mscript](#module_lib/mscript) + * [~Mscript](#module_lib/mscript..Mscript) + * [.clear()](#module_lib/mscript..Mscript+clear) + * [.interpret()](#module_lib/mscript..Mscript+interpret) + * [.basic_cmd()](#module_lib/mscript..Mscript+basic_cmd) + * [.new_loop()](#module_lib/mscript..Mscript+new_loop) + * [.end_loop()](#module_lib/mscript..Mscript+end_loop) + * [.move_cam()](#module_lib/mscript..Mscript+move_cam) + * [.move_proj()](#module_lib/mscript..Mscript+move_proj) + * [.set_state()](#module_lib/mscript..Mscript+set_state) + * [.last_loop()](#module_lib/mscript..Mscript+last_loop) + * [.parent_loop()](#module_lib/mscript..Mscript+parent_loop) + * [.loop_count()](#module_lib/mscript..Mscript+loop_count) + * [.fade()](#module_lib/mscript..Mscript+fade) + * [.fade_count()](#module_lib/mscript..Mscript+fade_count) + * [.fade_start()](#module_lib/mscript..Mscript+fade_start) + * [.fade_end()](#module_lib/mscript..Mscript+fade_end) + * [.update()](#module_lib/mscript..Mscript+update) + * [.str_to_arr()](#module_lib/mscript..Mscript+str_to_arr) + * [.light_to_arr()](#module_lib/mscript..Mscript+light_to_arr) + * [.light_state()](#module_lib/mscript..Mscript+light_state) + * [.fail()](#module_lib/mscript..Mscript+fail) + * [~startsWith()](#module_lib/mscript..startsWith) + + + +### lib/mscript~Mscript +class Mscript + +**Kind**: inner class of [lib/mscript](#module_lib/mscript) + +* [~Mscript](#module_lib/mscript..Mscript) + * [.clear()](#module_lib/mscript..Mscript+clear) + * [.interpret()](#module_lib/mscript..Mscript+interpret) + * [.basic_cmd()](#module_lib/mscript..Mscript+basic_cmd) + * [.new_loop()](#module_lib/mscript..Mscript+new_loop) + * [.end_loop()](#module_lib/mscript..Mscript+end_loop) + * [.move_cam()](#module_lib/mscript..Mscript+move_cam) + * [.move_proj()](#module_lib/mscript..Mscript+move_proj) + * [.set_state()](#module_lib/mscript..Mscript+set_state) + * [.last_loop()](#module_lib/mscript..Mscript+last_loop) + * [.parent_loop()](#module_lib/mscript..Mscript+parent_loop) + * [.loop_count()](#module_lib/mscript..Mscript+loop_count) + * [.fade()](#module_lib/mscript..Mscript+fade) + * [.fade_count()](#module_lib/mscript..Mscript+fade_count) + * [.fade_start()](#module_lib/mscript..Mscript+fade_start) + * [.fade_end()](#module_lib/mscript..Mscript+fade_end) + * [.update()](#module_lib/mscript..Mscript+update) + * [.str_to_arr()](#module_lib/mscript..Mscript+str_to_arr) + * [.light_to_arr()](#module_lib/mscript..Mscript+light_to_arr) + * [.light_state()](#module_lib/mscript..Mscript+light_state) + * [.fail()](#module_lib/mscript..Mscript+fail) + + + +#### mscript.clear() +Clear the state of the script + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.interpret() +Main function, accepts multi-line string, parses into lines +and interprets the instructions from the text. Returns an array +of steps to be fed into the mcopy. + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.basic\_cmd() +Apply a basic two character command + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.new\_loop() +Start a new loop + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.end\_loop() +Close the most recent loop + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.move\_cam() +Move camera to explicitly-defined frame + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.move\_proj() +Move projector to explicitly-defined frame + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.set\_state() +Set the state of either the cam or projector + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.last\_loop() +Return the last loop + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.parent\_loop() +Return the second-last loop + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.loop\_count() +Extract the loop count integer from a LOOP cmd + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.fade() +Execute a fade of frame length, from color to another color + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.fade\_count() +Extract the fade length integer from a FADE cmd + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.fade\_start() +Extract the start color from a string + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.fade\_end() +Extract the end color from a string + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.update() +Increase the state of a specific object, such as the camera/projector, +by the value defined in val + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.str\_to\_arr() +Split string on command, extract any integers from string + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.light\_to\_arr() +Split a string on a command to extract data for light array + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.light\_state() +Split a string to extract an rgb color value + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +#### mscript.fail() +Throw an error with specific message + +**Kind**: instance method of [Mscript](#module_lib/mscript..Mscript) + + +### lib/mscript~startsWith() +startswith function from lodash, do not want the entire lib for this + +**Kind**: inner method of [lib/mscript](#module_lib/mscript) diff --git a/lib/mscript/TODO.md b/lib/mscript/TODO.md new file mode 100644 index 0000000..b0f824f --- /dev/null +++ b/lib/mscript/TODO.md @@ -0,0 +1,13 @@ +# TODO - mscript + +* Add variables and simple evaluation +* Add "Light" feature + +Bash-like variables? +Similar to LESS/SASS? +Makes a tokenization easier + +@ is better than $ + +RangeError: Invalid array length + at Mscript.str_to_arr (./mcopy/app/lib/mscript/index.js:474:9) diff --git a/lib/mscript/index.js b/lib/mscript/index.js new file mode 100644 index 0000000..e2fac5e --- /dev/null +++ b/lib/mscript/index.js @@ -0,0 +1,545 @@ +'use strict'; + +/** @module lib/mscript */ + +const BLACK = '0,0,0'; +const WHITE = '255,255,255'; +const CMD = [ + 'CF', + 'PF', + 'BF', + 'CB', + 'PB', + 'BB' +]; +const ALTS = { + 'CF' : ['CAMERA FORWARD', 'CAM FORWARD'], + 'PF' : ['PROJECTOR FORWARD', 'PROJ FORWARD'], + 'BF' : ['BLACK FORWARD', 'BLACK', 'BLANK FORWARD', 'BLANK'], + 'CB' : ['CAMERA BACKWARD', 'CAM BACKWARD', 'CAMERA BACK', 'CAM BACK'], + 'PB' : ['PROJECTOR FORWARD', 'PROJ FORWARD', 'PROJECTOR BACK', 'PROJ BACK'], + 'BB' : ['BLACK BACKWARD', 'BLACK BACK', 'BLANK BACK'], + 'L ' : ['LIGHT', 'COLOR', 'LAMP'], + 'F ' : ['FADE'] +}; + +/** helper functions */ + +/** startswith function from lodash, do not want the entire lib for this */ +function startsWith(string, target, position) { + const { length } = string; + position = position == null ? 0 : position; + if (position < 0) { + position = 0; + } else if (position > length) { + position = length; + } + target = `${target}`; + return string.slice(position, position + target.length) == target; +} + +/** class Mscript */ +class Mscript { + constructor () { + this.output = {}; + } + /** + * Clear the state of the script + */ + clear () { + this.lines = []; + + this.cam = 0; + this.proj = 0; + this.color = ''; + this.loops = []; + this.rec = -1; + + this.two = ''; + this.arr = []; + this.light = []; + this.target = 0; //move to target using CAM # or PROJ # + this.dist = 0; + + this.variables = {}; + + this.output = {}; + } + /** + * Main function, accepts multi-line string, parses into lines + * and interprets the instructions from the text. Returns an array + * of steps to be fed into the mcopy. + */ + interpret (text, callback) { + this.clear() + + if (typeof text === 'undefined') { + return this.fail('No input'); + } + + //split string into lines, each containing a command + this.lines = text.split('\n'); + + this.lines = this.lines.map(line => { + line = line.replace(/\t+/g, ''); //strip tabs + line = line.trim(); //remove excess whitespace before and after command + line = line.toUpperCase(); + return line; + }) + + for (let line of this.lines) { + this.two = line.substring(0, 2); + if (CMD.indexOf(this.two) !== -1) { + this.basic_cmd(line); + } else if (startsWith(line, '@') || line.indexOf('@') !== -1) { + this.variable(line); + } else if (startsWith(line, 'LOOP')) { + this.new_loop(line); + } else if (startsWith(line, 'L ')) { + this.light_state(line); + } else if (startsWith(line, 'F ')) { + this.new_loop(line, true); + } else if (startsWith(line, 'END')) { + this.end_loop(line); + } else if (startsWith(line, 'CAM')) { //directly go to that frame (black?) + this.move_cam(line); + } else if (startsWith(line, 'PROJ')) { //directly go to that frame + this.move_proj(line); + } else if (startsWith(line, 'SET')) { //set that state + this.set_state(line); + } else if (startsWith(line, '#') || startsWith(line, '//')) { + //comments + //ignore while parsing + } + } + + this.output.success = true; + this.output.arr = this.arr; //all instructions + this.output.light = this.light; //all light instructions + this.output.cam = this.cam; + this.output.proj = this.proj; + + if (typeof callback !== 'undefined') { + //should only be invoked by running mscript.tests() + callback(this.output); + } else { + return this.output; + } + } + variable (line) { + let parts = line.split('='); + let key = parts[0]; + let value = parts[1]; + let update = false; + + if (value && value.indexOf('#') !== -1) { + value = value.split('#')[0]; + } + + if (value && value.indexOf('//') !== -1) { + value = value.split('//')[0]; + } + + if (value && value.indexOf('+') !== -1) { + if (value) + update = true; + } + + if (line.indexOf('-') !== -1) { + + update = true; + } + + if (line.indexOf(',') === -1) { //if not color string + try { + value = parseInt(value); + } catch (err) { + //supress parsing error + } + } + //console.dir(parts) + if (!this.variables[key] || update) { + this.variables[key] = value; + } + console.dir(this.variables) + } + variable_replace(line) { + + } + /** + * Apply a basic two character command + */ + basic_cmd (line) { + if (this.rec !== -1) { + //hold generated arr in state loop array + this.loops[this.rec].arr + .push.apply(this.loops[this.rec].arr, + this.str_to_arr(line, + this.two)); + this.loops[this.rec].light + .push.apply(this.loops[this.rec].light, + this.light_to_arr(line, + this.two)); + } else { + this.arr.push.apply(this.arr, this.str_to_arr(line, this.two)); + this.light.push.apply(this.light, this.light_to_arr(line, this.two)) + } + } + /** + * Start a new loop + */ + new_loop (line, fade) { + this.rec++; + this.loops[this.rec] = { + arr : [], + light : [], + cam : 0, + proj : 0, + cmd : line + '' + }; + if (fade) { + this.fade(line); + } + } + /** + * Close the most recent loop + */ + end_loop (line) { + let light_arr; + let start; + let end; + let len; + + for (let x = 0; x < this.loop_count(this.loops[this.rec].cmd); x++) { + light_arr = this.loops[this.rec].light; + if (this.loops[this.rec].fade) { + start = this.loops[this.rec].start; + end = this.loops[this.rec].end; + len = this.loops[this.rec].fade_len; + light_arr = light_arr.map(l => { + return this.fade_rgb(start, end, len, x); + }) + } + if (this.rec === 0) { + this.arr.push.apply(this.arr, this.loops[this.rec].arr); + this.light.push.apply(this.light, light_arr); + } else if (this.rec >= 1) { + this.loops[this.rec - 1].arr + .push.apply(this.loops[this.rec - 1].arr, + this.loops[this.rec].arr); + + this.loops[this.rec - 1].light + .push.apply(this.loops[this.rec - 1].light, + light_arr); + } + } + this.update('END', this.loop_count(this.loops[this.rec].cmd)); + delete this.loops[this.rec]; + this.rec--; + } + /** + * Move camera to explicitly-defined frame + */ + move_cam (line) { + this.target = parseInt(line.split('CAM ')[1]); + if (this.rec !== -1) { + if (this.target > this.cam) { + this.dist = this.target - this.cam; + for (let x = 0; x < this.dist; x++) { + this.loops[this.rec].arr.push('BF'); + this.loops[this.rec].light.push(BLACK); + this.update('BF'); + } + } else { + this.dist = this.cam - this.target; + for (let x = 0; x < this.dist; x++) { + this.loops[this.rec].arr.push('BB'); + this.loops[this.rec].light.push(BLACK); + this.update('BB'); + } + } + } else { + if (target > this.cam) { + this.dist = this.target - this.cam; + for (let x = 0; x < this.dist; x++) { + this.arr.push('BF'); + this.light.push(BLACK); + this.update('BF'); + } + } else { + this.dist = this.cam - this.target; + for (let x = 0; x < this.dist; x++) { + this.arr.push('BB'); + this.light.push(BLACK); + this.update('BB'); + } + } + } + } + /** + * Move projector to explicitly-defined frame + */ + move_proj (line) { + this.target = parseInt(line.split('PROJ ')[1]); + if (this.rec !== -1) { + if (this.target > this.proj) { + this.dist = this.target - this.proj; + for (let x = 0; x < this.dist; x++) { + this.loops[this.rec].arr.push('PF'); + this.loops[this.rec].light.push(''); + this.update('PF'); + } + } else { + this.dist = this.proj - this.target; + for (let x = 0; x < this.dist; x++) { + this.loops[this.rec].arr.push('PB'); + this.loops[this.rec].light.push(''); + this.update('PB'); + } + } + } else { + if (this.target > this.proj) { + this.dist = this.target - this.proj; + for (let x = 0; x < this.dist; x++) { + this.arr.push('PF'); + this.light.push(''); + this.update('PF'); + } + } else { + this.dist = this.proj - this.target; + for (let x = 0; x < this.dist; x++) { + this.arr.push('PB'); + this.light.push(''); + this.update('PB'); + } + } + } + } + /** + * Set the state of either the cam or projector + */ + set_state (line) { + if (startsWith(line, 'SET CAM')) { + this.cam = parseInt(line.split('SET CAM')[1]); + } else if (startsWith(line, 'SET PROJ')) { + this.proj = parseInt(line.split('SET PROJ')[1]); + } + } + /** + * Return the last loop + */ + last_loop () { + return this.loops[this.loops.length - 1]; + } + /** + * Return the second-last loop + */ + parent_loop () { + return this.loops[this.loops.length - 2]; + } + /** + * Extract the loop count integer from a LOOP cmd + */ + loop_count (str) { + return parseInt(str.split(' ')[1]); + } + /** + * Execute a fade of frame length, from color to another color + */ + fade (line) { + let len = this.fade_count(line); + let start = this.fade_start(line); + let end = this.fade_end(line); + + this.loops[this.rec].start = start; + this.loops[this.rec].end = end; + this.loops[this.rec].fade = true; + this.loops[this.rec].fade_count = 0; + this.loops[this.rec].fade_len = len; + } + /** + * Extract the fade length integer from a FADE cmd + */ + fade_count (str) { + return parseInt(str.split(' ')[1]); + } + /** + * Extract the start color from a string + */ + fade_start (str) { + let color = str.split(' ')[2]; + return this.rgb(color.trim()) + } + /** + * Extract the end color from a string + */ + fade_end (str) { + let color = str.split(' ')[3]; + return this.rgb(color.trim()) + } + fade_rgb (start, end, len, x) { + let cur = []; + let diff; + for (let i = 0; i < 3; i++) { + if (x === len - 1) { + cur[i] = end[i]; + } else if (start[i] >= end[i]) { + diff = start[i] - end[i]; + cur[i] = start[i] - Math.round((diff / (len - 1)) * x); + } else { + diff = end[i] - start[i]; + cur[i] = start[i] + Math.round((diff / (len - 1)) * x); + } + } + return this.rgb_str(cur); + + } + rgb (str) { + let rgb = str.split(','); + return rgb.map( char => { + return parseInt(char); + }) + } + rgb_str (arr) { + return arr.join(','); + } + /** + * Increase the state of a specific object, such as the camera/projector, + * by the value defined in val + */ + update (cmd, val = 1) { + if (cmd === 'END') { + //I don't understand this loop + for (let i = 0; i < val; i++) { + if (this.rec === 0) { + this.cam += this.loops[this.rec].cam; + this.proj += this.loops[this.rec].proj; + } else if (this.rec >= 1) { + this.loops[this.rec - 1].cam += this.loops[this.rec].cam; + this.loops[this.rec - 1].proj += this.loops[this.rec].proj; + } + } + } else if (cmd === 'CF') { + if (this.rec === -1) { + this.cam += val; + } else { + this.loops[this.rec].cam += val; + } + } else if (cmd === 'CB') { + if (this.rec === -1) { + this.cam -= val; + } else { + this.loops[this.rec].cam--; + } + } else if (cmd === 'PF') { + if (this.rec === -1) { + this.proj += val; + } else { + this.loops[this.rec].proj += val; + } + } else if (cmd === 'PB') { + if (this.rec === -1) { + this.proj -= val; + } else { + this.loops[this.rec].proj--; + } + } else if (cmd === 'BF') { + if (this.rec === -1) { + this.cam += val; + } else { + this.loops[this.rec].cam += val; + } + } else if (cmd === 'BB') { + if (this.rec === -1) { + this.cam -= val; + } else { + this.loops[this.rec].cam -= val; + } + } else if (cmd === 'L ') { + + } + } + /** + * Split string on command, extract any integers from string + */ + str_to_arr (str, cmd) { + const cnt = str.split(cmd); + let c = parseInt(cnt[1]); + let arr = []; + if (cnt[1] === '') { + c = 1; + } else { + c = parseInt(cnt[1]); + } + arr = new Array(c).fill(cmd); + this.update(cmd, c); + return arr; + } + /** + * Split a string on a command to extract data for light array + */ + light_to_arr (str, cmd) { + const cnt = str.split(cmd); + let c = parseInt(cnt[1]); + let arr = []; + if (cnt[1] === '') { + c = 1; + } else { + c = parseInt(cnt[1]); + } + for (var i = 0; i < c; i++) { + if (cmd === 'CF' + || cmd === 'CB') { + arr.push(this.color); + } else if (cmd === 'BF' + || cmd === 'BB') { + arr.push(BLACK); + } else { + arr.push(''); + } + } + return arr; + } + /** + * Split a string to extract an rgb color value + */ + light_state (str) { + //add parsers for other color spaces + const color = str.replace('L ', '').trim(); + this.color = color; + } + + /** + * Throw an error with specific message + */ + fail (msg) { + throw new Error(msg); + } +} + +module.exports = Mscript; + + +/* + +CAM # - go to camera frame # +PROJ # - go to projector frame # + +SET CAM # - sets camera count to # +SET PROJ # - sets projector count to # + +LOOP # - begin loop, can nest recursively, # times +END LOOP - (or END) closes loop + +L #RGB - sets light to rgb value + +FADE 24 0,0,0 255,255,255 + +CF - Camera forwards +PF - Projector forwards +BF - Black forwards +CB - Camera backwards +PB - Projector backwards +BB - Black backwards + +*/ \ No newline at end of file diff --git a/lib/mscript/index.old.js b/lib/mscript/index.old.js new file mode 100644 index 0000000..65e8d17 --- /dev/null +++ b/lib/mscript/index.old.js @@ -0,0 +1,476 @@ +'use strict'; + +/** @module lib/mscript */ + +let fs; +let input; + +/** object mscript */ +const mscript = {}; + +/** + * Check for the presence of specific arguments in process + * argv + * + * @param {string} shrt Short version of argument or flag + * @param {string} lng Long version of argument or flag + * + * @return {boolean} Is flag present + */ +mscript.arg = function arg (shrt, lng) { + if (process.argv.indexOf(shrt) !== -1 || + process.argv.indexOf(lng) !== -1) { + return true; + } + return false; +}; + +/** + * Check for the position of specific arguments in process + * argv + * + * @param {string} shrt Short version of argument or flag + * @param {string} lng Long version of argument or flag + * + * @return {boolean} Position of arg or flag, for locating input + */ +mscript.arg_pos = function arg_pos (shrt, lng) { + var pos = -1; + pos = process.argv.indexOf(shrt); + if (pos === -1) { + pos = process.argv.indexOf(lng); + } + return pos; +}; + +mscript.black = '0,0,0'; +mscript.cmd = [ + 'CF', + 'PF', + 'BF', + 'CB', + 'PB', + 'BB' +]; +mscript.alts = { + 'CF' : ['CAMERA FORWARD', 'CAM FORWARD'], + 'PF' : ['PROJECTOR FORWARD', 'PROJ FORWARD'], + 'BF' : ['BLACK FORWARD', 'BLACK', 'BLANK FORWARD', 'BLANK'], + 'CB' : ['CAMERA BACKWARD', 'CAM BACKWARD', 'CAMERA BACK', 'CAM BACK'], + 'PB' : ['PROJECTOR FORWARD', 'PROJ FORWARD', 'PROJECTOR BACK', 'PROJ BACK'], + 'BB' : ['BLACK BACKWARD', 'BLACK BACK', 'BLANK BACK'], + 'L ' : ['LIGHT', 'COLOR', 'LAMP'], + 'F ' : ['FADE'] +}; + +mscript.state = {}; + +/** + * Clear the state object + */ +mscript.state_clear = function state_clear () { + mscript.state = { + cam : 0, + proj : 0, + color : '', + loops : [], + rec : -1 + }; +}; +/** + * This is never used and doesn't do anything? + */ +mscript.alts_unique = function alts_unique () { + var ids = Object.keys(mscript.alts), + all = []; + for (var i = 0; i < ids.length; i++) { + if (all.indexOf(ids[i]) === -1) { + all.push(ids[i]); + } else { + mscript.fail("Can't compile"); + } + } +}; +/** + * + */ +mscript.interpret = function interpret (text, callback) { + mscript.state_clear(); + if (typeof text === 'undefined') { + mscript.fail('No input'); + } + var lines = text.split('\n'), + two = '', + arr = [], + light = [], + target = 0, + dist = 0, //? + output = {}; + for (var i = 0; i < lines.length; i++) { + lines[i] = lines[i].replace(/\t+/g, ""); //strip tabs + lines[i] = lines[i].trim(); //remove excess whitespace before and after command + two = lines[i].substring(0, 2); + if (mscript.cmd.indexOf(two) !== -1) { + + if (mscript.state.loops.length > 0) { + //hold generated arr in state loop array + mscript.state.loops[mscript.state.rec].arr + .push.apply(mscript.state.loops[mscript.state.rec].arr, + mscript.str_to_arr(lines[i], + two)); + mscript.state.loops[mscript.state.rec].light + .push.apply(mscript.state.loops[mscript.state.rec].light, + mscript.light_to_arr(lines[i], + two)); + } else { + arr.push.apply(arr, mscript.str_to_arr(lines[i], two)); + light.push.apply(light, mscript.light_to_arr(lines[i], two)) + } + + } else if (lines[i].substring(0, 4) === 'LOOP') { + mscript.state.rec++; + mscript.state.loops[mscript.state.rec] = { + arr : [], + light : [], + cam : 0, + proj : 0, + cmd : lines[i] + '' + }; + } else if (lines[i].substring(0, 2) === 'L ') { + mscript.light_state(lines[i]); + } else if (lines[i].substring(0, 3) === 'END') { + for (var x = 0; x < mscript.loop_count(mscript.state.loops[mscript.state.rec].cmd); x++) { + if (mscript.state.rec === 0) { + arr.push.apply(arr, mscript.state.loops[mscript.state.rec].arr); + light.push.apply(light, mscript.state.loops[mscript.state.rec].light); + } else if (mscript.state.rec >= 1) { + mscript.state.loops[mscript.state.rec - 1].arr + .push.apply(mscript.state.loops[mscript.state.rec - 1].arr, + mscript.state.loops[mscript.state.rec].arr); + mscript.state.loops[mscript.state.rec - 1].light + .push.apply(mscript.state.loops[mscript.state.rec - 1].light, + mscript.state.loops[mscript.state.rec].light); + } + } + mscript.state_update('END', mscript.loop_count(mscript.state.loops[mscript.state.rec].cmd)); + delete mscript.state.loops[mscript.state.rec]; + mscript.state.rec--; + } else if (lines[i].substring(0, 3) === 'CAM') { //directly go to that frame (black?) + target = parseInt(lines[i].split('CAM ')[1]); + if (mscript.state.loops.length > 0) { + if (target > mscript.state.cam) { + dist = target - mscript.state.cam; + for (var x = 0; x < dist; x++) { + mscript.state.loops[mscript.state.rec].arr.push('BF'); + mscript.state.loops[mscript.state.rec].light.push(mscript.black); + mscript.state_update('BF'); + } + } else { + dist = mscript.state.cam - target; + for (var x = 0; x < dist; x++) { + mscript.state.loops[mscript.state.rec].arr.push('BB'); + mscript.state.loops[mscript.state.rec].light.push(mscript.black); + mscript.state_update('BB'); + } + } + } else { + if (target > mscript.state.cam) { + dist = target - mscript.state.cam; + for (var x = 0; x < dist; x++) { + arr.push('BF'); + light.push(mscript.black); + mscript.state_update('BF'); + } + } else { + dist = mscript.state.cam - target; + for (var x = 0; x < dist; x++) { + arr.push('BB'); + light.push(mscript.black); + mscript.state_update('BB'); + } + } + } + } else if (lines[i].substring(0, 4) === 'PROJ') { //directly go to that frame + target = parseInt(lines[i].split('PROJ ')[1]); + if (mscript.state.loops.length > 0) { + if (target > mscript.state.proj) { + dist = target - mscript.state.proj; + for (var x = 0; x < dist; x++) { + mscript.state.loops[mscript.state.rec].arr.push('PF'); + mscript.state.loops[mscript.state.rec].light.push(''); + mscript.state_update('PF'); + } + } else { + dist = mscript.state.proj - target; + for (var x = 0; x < dist; x++) { + mscript.state.loops[mscript.state.rec].arr.push('PB'); + mscript.state.loops[mscript.state.rec].light.push(''); + mscript.state_update('PB'); + } + } + } else { + if (target > mscript.state.proj) { + dist = target - mscript.state.proj; + for (var x = 0; x < dist; x++) { + arr.push('PF'); + light.push(''); + mscript.state_update('PF'); + } + } else { + dist = mscript.state.proj - target; + for (var x = 0; x < dist; x++) { + arr.push('PB'); + light.push(''); + mscript.state_update('PB'); + } + } + } + } else if (lines[i].substring(0, 3) === 'SET') { //set that state + if (lines[i].substring(0, 7) === 'SET CAM') { + mscript.state.cam = parseInt(lines[i].split('SET CAM')[1]); + } else if (lines[i].substring(0, 8) === 'SET PROJ') { + mscript.state.proj = parseInt(lines[i].split('SET PROJ')[1]); + } + } else if (lines[i].substring(0, 1) === '#' || lines[i].substring(0, 2) === '//') { + //comments + //ignore while parsing + } + } + output.success = true; + output.arr = arr; + output.light = light; + output.cam = mscript.state.cam; + output.proj = mscript.state.proj; + if (typeof callback !== 'undefined') { + //should only be invoked by running mscript.tests() + callback(output); + } else { + return mscript.output(output); + } +}; +/** + * + */ +mscript.last_loop = function last_loop () { + return mscript.state.loops[mscript.state.loops.length - 1]; +}; +/** + * + */ +mscript.parent_loop = function parent_loop () { + return mscript.state.loops[mscript.state.loops.length - 2]; +}; +/** + * + */ +mscript.state_update = function state_update (cmd, val) { + if (cmd === 'END') { + for (var i = 0; i < val; i++) { + if (mscript.state.rec === 0) { + mscript.state.cam += mscript.state.loops[mscript.state.rec].cam; + mscript.state.proj += mscript.state.loops[mscript.state.rec].proj; + } else if (mscript.state.rec >= 1) { + mscript.state.loops[mscript.state.rec - 1].cam += mscript.state.loops[mscript.state.rec].cam; + mscript.state.loops[mscript.state.rec - 1].proj += mscript.state.loops[mscript.state.rec].proj; + } + } + } else if (cmd === 'CF') { + if (mscript.state.loops.length < 1) { + mscript.state.cam++; + } else { + mscript.state.loops[mscript.state.rec].cam++; + } + } else if (cmd === 'CB') { + if (mscript.state.loops.length < 1) { + mscript.state.cam--; + } else { + mscript.state.loops[mscript.state.rec].cam--; + } + } else if (cmd === 'PF') { + if (mscript.state.loops.length < 1) { + mscript.state.proj++; + } else { + mscript.state.loops[mscript.state.rec].proj++; + } + } else if (cmd === 'PB') { + if (mscript.state.loops.length < 1) { + mscript.state.proj--; + } else { + mscript.state.loops[mscript.state.rec].proj--; + } + } else if (cmd === 'BF') { + if (mscript.state.loops.length < 1) { + mscript.state.cam++; + } else { + mscript.state.loops[mscript.state.rec].cam++; + } + } else if (cmd === 'BB') { + if (mscript.state.loops.length < 1) { + mscript.state.cam--; + } else { + mscript.state.loops[mscript.state.rec].cam++; + } + } else if (cmd === 'L ') { + + } +}; +/** + * + */ +mscript.str_to_arr = function str_to_arr (str, cmd) { + var cnt = str.split(cmd), + c = parseInt(cnt[1]), + arr = []; + if (cnt[1] === '') { + c = 1; + } else { + c = parseInt(cnt[1]); + } + for (var i = 0; i < c; i++) { + arr.push(cmd); + mscript.state_update(cmd); + } + return arr; +}; +/** + * + */ +mscript.light_state = function light_state (str) { + //add parsers for other color spaces + var color = str.replace('L ', '').trim(); + mscript.state.color = color; +}; +/** + * + */ +mscript.light_to_arr = function light_to_arr (str, cmd) { + var cnt = str.split(cmd), + c = parseInt(cnt[1]), + arr = []; + if (cnt[1] === '') { + c = 1; + } else { + c = parseInt(cnt[1]); + } + for (var i = 0; i < c; i++) { + if (cmd === 'CF' + || cmd === 'CB') { + arr.push(mscript.state.color); + } else if (cmd === 'BF' + || cmd === 'BB') { + arr.push(mscript.black); + } else { + arr.push(''); + } + } + return arr; +}; +/** + * + */ +mscript.loop_count = function loop_count (str) { + return parseInt(str.split(' ')[1]); +}; +mscript.fade_count = function fade_count (str) { + return parseInt(str.split(' ')[1]); +} +/** + * + */ +mscript.fail = function fail (reason) { + console.error(JSON.stringify({success: false, error: true, msg : reason})); + if (process) process.exit(); +}; +/** + * + */ +mscript.output = function output (data) { + var json = true; //default + if (mscript.arg('-j', '--json')) { + json = true; + } + + if (mscript.arg('-t', '--text')) { + json = false; + } + + if (json) { + console.log(JSON.stringify(data)); + } else { + var ids = Object.keys(data); + for (var i = 0; i < ids.length; i++) { + console.log(ids[i] + ': ' + data[ids[i]]); + } + } +}; +/** + * + */ +mscript.init = function init () { + if (mscript.arg('-t', '--tests')) { + return mscript.tests(); + } + + if (mscript.arg('-v', '--verbose')) { + console.time('mscript'); + } + + if (mscript.arg('-c', '--cam')) { + mscript.state.cam = parseInt(process.argv[mscript.arg_pos('-c', '--cam') + 1]); + } + + if (mscript.arg('-p', '--proj')) { + mscript.state.proj = parseInt(process.argv[mscript.arg_pos('-p', '--proj') + 1]); + } + + if (mscript.arg('-f', '--file')) { + input = process.argv[mscript.arg_pos('-f', '--file') + 1]; + mscript.interpret(fs.readFileSync(input, 'utf8')); + } else { + mscript.interpret(input); + } + + if (mscript.arg('-v', '--verbose')) { + console.timeEnd('mscript'); + } +}; + +if (typeof document === 'undefined' + && typeof module !== 'undefined' + && !module.parent) { + //node script + fs = require('fs'); + input = process.argv[2]; + mscript.init(); +} else if (typeof module !== 'undefined' && module.parent) { + //module + fs = require('fs'); + module.exports = mscript; +} else { + //web +} + + +/* + +CAM # - go to camera frame # +PROJ # - go to projector frame # + +SET CAM # - sets camera count to # +SET PROJ # - sets projector count to # + +LOOP # - begin loop, can nest recursively, # times +END LOOP - (or END) closes loop + +L #RGB - sets light to rgb value + +FADE + +CF - Camera forwards +PF - Projector forwards +BF - Black forwards +CB - Camera backwards +PB - Projector backwards +BB - Black backwards + +*/ \ No newline at end of file diff --git a/lib/mscript/package.json b/lib/mscript/package.json new file mode 100644 index 0000000..5453ae8 --- /dev/null +++ b/lib/mscript/package.json @@ -0,0 +1,11 @@ +{ + "name": "mscript", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..3803e3b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "mcopy", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "11.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.10.4.tgz", + "integrity": "sha512-wa09itaLE8L705aXd8F80jnFpxz3Y1/KRHfKsYL2bPc0XF+wEWu8sR9n5bmeu8Ba1N9z2GRNzm/YdHcghLkLKg==", + "dev": true + }, + "typescript": { + "version": "3.3.3333", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3333.tgz", + "integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8e1236d --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "mcopy", + "version": "0.1.0", + "description": "Small gauge film optical printer platform", + "main": "build.js", + "directories": { + "doc": "docs", + "lib": "lib" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "sh ./scripts/build.sh" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/sixteenmillimeter/mcopy.git" + }, + "author": "mmcwilliams", + "license": "MIT", + "bugs": { + "url": "https://github.com/sixteenmillimeter/mcopy/issues" + }, + "homepage": "https://github.com/sixteenmillimeter/mcopy#readme", + "devDependencies": { + "@types/node": "^11.10.4", + "typescript": "^3.3.3333" + } +} diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100644 index 0000000..9e904a4 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +./node_modules/.bin/tsc -p tsconfig.json + +#electron-build fails when local modules are in parent directory +#copy them into lib directory +cp -r ./lib/ ./app/lib \ No newline at end of file diff --git a/scripts/docs.sh b/scripts/docs.sh new file mode 100644 index 0000000..aec64f2 --- /dev/null +++ b/scripts/docs.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +libs="./lib/*" +for l in $libs +do + echo "Generating documentation for $l" + ./node_modules/.bin/jsdoc2md $l/index.js > $l/Readme.md +done \ No newline at end of file diff --git a/src/arduino/index.ts b/src/arduino/index.ts new file mode 100644 index 0000000..9703770 --- /dev/null +++ b/src/arduino/index.ts @@ -0,0 +1,375 @@ +'use strict' + +const SerialPort = require('serialport') +const Readline = SerialPort.parsers.Readline +const exec = require('child_process').exec + +const parser = new Readline('') +const newlineRe : RegExp = new RegExp('\n', 'g') +const returnRe : RegExp = new RegExp('\r', 'g') + +let eventEmitter : any +let cfg : object + +/** + * Pause the process for X milliseconds in async/await functions + * + * @param {integer} ms milliseconds + * + * @returns {Promise} Resolves after wait + **/ +async function delay (ms : number) { + return new Promise(resolve => { + return setTimeout(resolve, ms) + }) +} + +/** + * Send a command to an Arduino using async/await + * + * @param {string} device Arduino identifier + * @param {string} cmd Single character command to send + * + * @returns {Promise} Resolves after sending + **/ +async function send (device : string, cmd : string) { + return new Promise ((resolve, reject) => { + arduino.queue[cmd] = (ms : number) => { + return resolve(ms) + } + return arduino.serial[device].write(cmd, (err : any, results : any) => { + if (err) { + //console.error(err) + return reject(err) + } + // + }) + }) +} + +/** + * Send a string to an Arduino using async/await + * + * @param {string} device Arduino identifier + * @param {string} str String to send + * + * @returns {Promise} Resolves after sending + **/ +async function write (device : string, str : string) { + return new Promise ((resolve, reject) => { + arduino.serial[device].write(str, function (err, results) { + if (err) { + return reject(err) + } + //console.log('sent: ' + str) + return resolve(results) + }) + }) +} + +/** + * Connect to an Arduino using async/await + * + * @param {string} device Arduino identifier + * + * @returns {Promise} Resolves after opening + **/ +async function openArduino (device : string) { + return new Promise((resolve, reject) => { + return arduino.serial[device].open(error => { + if (error) { + return reject(error) + } + return resolve(true) + }) + }) +} + +/** + * Close a connection to an Arduino using async/await + * + * @param {string} device Arduino identifier + * + * @returns {Promise} Resolves after closing + **/ +async function closeArduino (device : string) { + return new Promise((resolve : any, reject : any) => { + return arduino.serial[device].close((err) => { + if (err) { + return reject(err) + } + return resolve(true) + }) + }) +} + +/****** + Arduino handlers +*******/ +const arduino = { + path : {}, + known: [ + '/dev/tty.usbmodem1a161', + '/dev/tty.usbserial-A800f8dk', + '/dev/tty.usbserial-A900cebm', + '/dev/tty.usbmodem1a131', + '/dev/tty.usbserial-a900f6de', + '/dev/tty.usbmodem1a141', + '/dev/ttyACM0', + 'COM3' + ], + alias : { + + }, + serial : { + connect : {}, + projector : {}, + camera : {}, + light : {} + }, + baud : 57600, + queue : {}, + timer : 0, + lock : false, + locks : { + + } +} + +arduino.enumerate = async function () { + return new Promise( (resolve, reject) => { + return SerialPort.list((err, ports) => { + let matches = [] + if (err) { + return reject(err) + } + ports.forEach(port => { + if (arduino.known.indexOf(port.comName) !== -1) { + matches.push(port.comName) + } else if ((port.manufacturer + '').toLowerCase().indexOf('arduino') !== -1) { + matches.push(port.comName) + } else if ((port.comName + '').toLowerCase().indexOf('usbserial') !== -1) { + matches.push(port.comName) + } else if ((port.comName + '').toLowerCase().indexOf('usbmodem') !== -1) { + matches.push(port.comName) + } + }) + if (matches.length === 0) { + return reject('No USB devices found'); + } else if (matches.length > 0) { + return resolve(matches) + } + }) + }) +} + +//commands which respond to a sent char +arduino.send = async function (serial, cmd, res) { + const device = arduino.alias[serial] + let results + if (arduino.locks[serial]) { + return false + } + arduino.locks[serial] = true + await delay(cfg.arduino.serialDelay) + try { + results = await send(device, cmd) + } catch (e) { + return console.error(e) + } + arduino.locks[serial] = false + arduino.timer = new Date().getTime() + return await eventEmitter.emit('arduino_send', cmd) +} + +//send strings, after char triggers firmware to accept +arduino.string = async function (serial, str) { + const device = arduino.alias[serial] + let writeSuccess + await delay(cfg.arduino.serialDelay) + if (typeof arduino.serial[device].fake !== 'undefined' + && arduino.serial[device].fake) { + return arduino.serial[device].string(str) + } else { + try { + writeSuccess = await write(device, str) + } catch (e) { + return console.error(e) + } + return writeSuccess + } +} + +//respond with same char over serial when done +arduino.end = async function (serial, data) { + const end = new Date().getTime() + const ms = end - arduino.timer + let complete + if (arduino.queue[data] !== undefined) { + arduino.locks[serial] = false; + //console.log('Command ' + data + ' took ' + ms + 'ms'); + complete = arduino.queue[data](ms) //execute callback + eventEmitter.emit('arduino_end', data) + delete arduino.queue[data] + } else { + //console.log('Received stray "' + data + '"'); //silent to user + } + return complete +}; +arduino.alias = function (serial, device) { + console.log(`Making "${serial}" an alias of ${device}`) + arduino.alias[serial] = device +} +arduino.connect = async function (serial, device, confirm) { + return new Promise(async (resolve, reject) => { + let connectSuccess + arduino.path[serial] = device; + arduino.alias[serial] = device; + arduino.serial[device] = new SerialPort(arduino.path[serial], { + autoOpen : false, + baudRate: cfg.arduino.baud, + parser: parser + }) + arduino.locks[device] = false + try { + connectSuccess = await openArduino(device) + } catch (e) { + console.error('failed to open: ' + e) + return reject(e) + } + console.log(`Opened connection with ${arduino.path[serial]} as ${serial}`); + if (!confirm) { + arduino.serial[device].on('data', async (data) => { + let d = data.toString('utf8') + d = d.replace(newlineRe, '').replace(returnRe, '') + return await arduino.end(serial, d) + }) + } else { + arduino.serial[device].on('data', async (data) => { + let d = data.toString('utf8') + d = d.replace(newlineRe, '').replace(returnRe, '') + return await arduino.confirmEnd(d) + }) + } + return resolve(arduino.path[serial]) + }) + +} + +arduino.confirmExec = {}; +arduino.confirmEnd = function (data) { + //console.dir(data) + if (data === cfg.arduino.cmd.connect + || data === cfg.arduino.cmd.proj_identifier + || data === cfg.arduino.cmd.cam_identifier + || data === cfg.arduino.cmd.light_identifier + || data === cfg.arduino.cmd.proj_light_identifier + || data === cfg.arduino.cmd.proj_cam_light_identifier + || data === cfg.arduino.cmd.proj_cam_identifier ) { + arduino.confirmExec(null, data); + arduino.confirmExec = {}; + } +} + +arduino.verify = async function () { + return new Promise(async (resolve, reject) => { + const device = arduino.alias['connect'] + let writeSuccess + arduino.confirmExec = function (err, data) { + if (data === cfg.arduino.cmd.connect) { + return resolve(true) + } else { + return reject('Wrong data returned') + } + } + await delay(cfg.arduino.serialDelay) + try { + writeSuccess = await send(device, cfg.arduino.cmd.connect) + } catch (e) { + return reject(e) + } + return resolve(writeSuccess) + }) +} + +arduino.distinguish = async function () { + return new Promise(async (resolve, reject) => { + const device = arduino.alias['connect'] + let writeSuccess + let type + arduino.confirmExec = function (err, data) { + if (data === cfg.arduino.cmd.proj_identifier) { + type = 'projector' + } else if (data === cfg.arduino.cmd.cam_identifier) { + type = 'camera' + } else if (data === cfg.arduino.cmd.light_identifier) { + type = 'light' + } else if (data === cfg.arduino.cmd.proj_light_identifier) { + type = 'projector,light' + } else if (data === cfg.arduino.cmd.proj_cam_light_identifier) { + type = 'projector,camera,light' + } else if (data === cfg.arduino.cmd.proj_cam_identifier) { + type = 'projector,camera' + } else if (data === cfg.ardino.cmd.proj_second_identifier) { + type = 'projector_second' + } + return resolve(type) + } + await delay(cfg.arduino.serialDelay) + try { + writeSuccess = await send(device, cfg.arduino.cmd.mcopy_identifier) + } catch (e) { + console.error(e) + return reject(e) + } + }) +} + +arduino.close = async function (callback) { + const device = arduino.alias['connect'] + let closeSuccess + try { + closeSuccess = await closeArduino(device) + } catch (e) { + return console.error(e) + } + return closeSuccess +}; + +arduino.fakeConnect = async function (serial) { + //console.log('Connecting to fake arduino...'); + const device = '/dev/fake' + arduino.alias[serial] = device + arduino.serial[device] = { + write : function (cmd, cb) { + const t = { + c : cfg.arduino.cam.time + cfg.arduino.cam.delay, + p : cfg.arduino.proj.time + cfg.arduino.proj.delay + } + let timeout = t[cmd] + let end + if (typeof timeout === 'undefined') timeout = 10 + arduino.timer = +new Date() + setTimeout(() => { + arduino.end(serial, cmd) + return cb() + }, timeout) + + }, + string : async function (str) { + //do nothing + return true + }, + fake : true + }; + //console.log('Connected to fake arduino! Not real! Doesn\'t exist!'); + return true +} + +if (typeof module !== 'undefined' && module.parent) { + module.exports = function (c, ee) { + eventEmitter = ee + cfg = c + return arduino + } +} \ No newline at end of file diff --git a/src/mscript/index.js b/src/mscript/index.js new file mode 100644 index 0000000..e2fac5e --- /dev/null +++ b/src/mscript/index.js @@ -0,0 +1,545 @@ +'use strict'; + +/** @module lib/mscript */ + +const BLACK = '0,0,0'; +const WHITE = '255,255,255'; +const CMD = [ + 'CF', + 'PF', + 'BF', + 'CB', + 'PB', + 'BB' +]; +const ALTS = { + 'CF' : ['CAMERA FORWARD', 'CAM FORWARD'], + 'PF' : ['PROJECTOR FORWARD', 'PROJ FORWARD'], + 'BF' : ['BLACK FORWARD', 'BLACK', 'BLANK FORWARD', 'BLANK'], + 'CB' : ['CAMERA BACKWARD', 'CAM BACKWARD', 'CAMERA BACK', 'CAM BACK'], + 'PB' : ['PROJECTOR FORWARD', 'PROJ FORWARD', 'PROJECTOR BACK', 'PROJ BACK'], + 'BB' : ['BLACK BACKWARD', 'BLACK BACK', 'BLANK BACK'], + 'L ' : ['LIGHT', 'COLOR', 'LAMP'], + 'F ' : ['FADE'] +}; + +/** helper functions */ + +/** startswith function from lodash, do not want the entire lib for this */ +function startsWith(string, target, position) { + const { length } = string; + position = position == null ? 0 : position; + if (position < 0) { + position = 0; + } else if (position > length) { + position = length; + } + target = `${target}`; + return string.slice(position, position + target.length) == target; +} + +/** class Mscript */ +class Mscript { + constructor () { + this.output = {}; + } + /** + * Clear the state of the script + */ + clear () { + this.lines = []; + + this.cam = 0; + this.proj = 0; + this.color = ''; + this.loops = []; + this.rec = -1; + + this.two = ''; + this.arr = []; + this.light = []; + this.target = 0; //move to target using CAM # or PROJ # + this.dist = 0; + + this.variables = {}; + + this.output = {}; + } + /** + * Main function, accepts multi-line string, parses into lines + * and interprets the instructions from the text. Returns an array + * of steps to be fed into the mcopy. + */ + interpret (text, callback) { + this.clear() + + if (typeof text === 'undefined') { + return this.fail('No input'); + } + + //split string into lines, each containing a command + this.lines = text.split('\n'); + + this.lines = this.lines.map(line => { + line = line.replace(/\t+/g, ''); //strip tabs + line = line.trim(); //remove excess whitespace before and after command + line = line.toUpperCase(); + return line; + }) + + for (let line of this.lines) { + this.two = line.substring(0, 2); + if (CMD.indexOf(this.two) !== -1) { + this.basic_cmd(line); + } else if (startsWith(line, '@') || line.indexOf('@') !== -1) { + this.variable(line); + } else if (startsWith(line, 'LOOP')) { + this.new_loop(line); + } else if (startsWith(line, 'L ')) { + this.light_state(line); + } else if (startsWith(line, 'F ')) { + this.new_loop(line, true); + } else if (startsWith(line, 'END')) { + this.end_loop(line); + } else if (startsWith(line, 'CAM')) { //directly go to that frame (black?) + this.move_cam(line); + } else if (startsWith(line, 'PROJ')) { //directly go to that frame + this.move_proj(line); + } else if (startsWith(line, 'SET')) { //set that state + this.set_state(line); + } else if (startsWith(line, '#') || startsWith(line, '//')) { + //comments + //ignore while parsing + } + } + + this.output.success = true; + this.output.arr = this.arr; //all instructions + this.output.light = this.light; //all light instructions + this.output.cam = this.cam; + this.output.proj = this.proj; + + if (typeof callback !== 'undefined') { + //should only be invoked by running mscript.tests() + callback(this.output); + } else { + return this.output; + } + } + variable (line) { + let parts = line.split('='); + let key = parts[0]; + let value = parts[1]; + let update = false; + + if (value && value.indexOf('#') !== -1) { + value = value.split('#')[0]; + } + + if (value && value.indexOf('//') !== -1) { + value = value.split('//')[0]; + } + + if (value && value.indexOf('+') !== -1) { + if (value) + update = true; + } + + if (line.indexOf('-') !== -1) { + + update = true; + } + + if (line.indexOf(',') === -1) { //if not color string + try { + value = parseInt(value); + } catch (err) { + //supress parsing error + } + } + //console.dir(parts) + if (!this.variables[key] || update) { + this.variables[key] = value; + } + console.dir(this.variables) + } + variable_replace(line) { + + } + /** + * Apply a basic two character command + */ + basic_cmd (line) { + if (this.rec !== -1) { + //hold generated arr in state loop array + this.loops[this.rec].arr + .push.apply(this.loops[this.rec].arr, + this.str_to_arr(line, + this.two)); + this.loops[this.rec].light + .push.apply(this.loops[this.rec].light, + this.light_to_arr(line, + this.two)); + } else { + this.arr.push.apply(this.arr, this.str_to_arr(line, this.two)); + this.light.push.apply(this.light, this.light_to_arr(line, this.two)) + } + } + /** + * Start a new loop + */ + new_loop (line, fade) { + this.rec++; + this.loops[this.rec] = { + arr : [], + light : [], + cam : 0, + proj : 0, + cmd : line + '' + }; + if (fade) { + this.fade(line); + } + } + /** + * Close the most recent loop + */ + end_loop (line) { + let light_arr; + let start; + let end; + let len; + + for (let x = 0; x < this.loop_count(this.loops[this.rec].cmd); x++) { + light_arr = this.loops[this.rec].light; + if (this.loops[this.rec].fade) { + start = this.loops[this.rec].start; + end = this.loops[this.rec].end; + len = this.loops[this.rec].fade_len; + light_arr = light_arr.map(l => { + return this.fade_rgb(start, end, len, x); + }) + } + if (this.rec === 0) { + this.arr.push.apply(this.arr, this.loops[this.rec].arr); + this.light.push.apply(this.light, light_arr); + } else if (this.rec >= 1) { + this.loops[this.rec - 1].arr + .push.apply(this.loops[this.rec - 1].arr, + this.loops[this.rec].arr); + + this.loops[this.rec - 1].light + .push.apply(this.loops[this.rec - 1].light, + light_arr); + } + } + this.update('END', this.loop_count(this.loops[this.rec].cmd)); + delete this.loops[this.rec]; + this.rec--; + } + /** + * Move camera to explicitly-defined frame + */ + move_cam (line) { + this.target = parseInt(line.split('CAM ')[1]); + if (this.rec !== -1) { + if (this.target > this.cam) { + this.dist = this.target - this.cam; + for (let x = 0; x < this.dist; x++) { + this.loops[this.rec].arr.push('BF'); + this.loops[this.rec].light.push(BLACK); + this.update('BF'); + } + } else { + this.dist = this.cam - this.target; + for (let x = 0; x < this.dist; x++) { + this.loops[this.rec].arr.push('BB'); + this.loops[this.rec].light.push(BLACK); + this.update('BB'); + } + } + } else { + if (target > this.cam) { + this.dist = this.target - this.cam; + for (let x = 0; x < this.dist; x++) { + this.arr.push('BF'); + this.light.push(BLACK); + this.update('BF'); + } + } else { + this.dist = this.cam - this.target; + for (let x = 0; x < this.dist; x++) { + this.arr.push('BB'); + this.light.push(BLACK); + this.update('BB'); + } + } + } + } + /** + * Move projector to explicitly-defined frame + */ + move_proj (line) { + this.target = parseInt(line.split('PROJ ')[1]); + if (this.rec !== -1) { + if (this.target > this.proj) { + this.dist = this.target - this.proj; + for (let x = 0; x < this.dist; x++) { + this.loops[this.rec].arr.push('PF'); + this.loops[this.rec].light.push(''); + this.update('PF'); + } + } else { + this.dist = this.proj - this.target; + for (let x = 0; x < this.dist; x++) { + this.loops[this.rec].arr.push('PB'); + this.loops[this.rec].light.push(''); + this.update('PB'); + } + } + } else { + if (this.target > this.proj) { + this.dist = this.target - this.proj; + for (let x = 0; x < this.dist; x++) { + this.arr.push('PF'); + this.light.push(''); + this.update('PF'); + } + } else { + this.dist = this.proj - this.target; + for (let x = 0; x < this.dist; x++) { + this.arr.push('PB'); + this.light.push(''); + this.update('PB'); + } + } + } + } + /** + * Set the state of either the cam or projector + */ + set_state (line) { + if (startsWith(line, 'SET CAM')) { + this.cam = parseInt(line.split('SET CAM')[1]); + } else if (startsWith(line, 'SET PROJ')) { + this.proj = parseInt(line.split('SET PROJ')[1]); + } + } + /** + * Return the last loop + */ + last_loop () { + return this.loops[this.loops.length - 1]; + } + /** + * Return the second-last loop + */ + parent_loop () { + return this.loops[this.loops.length - 2]; + } + /** + * Extract the loop count integer from a LOOP cmd + */ + loop_count (str) { + return parseInt(str.split(' ')[1]); + } + /** + * Execute a fade of frame length, from color to another color + */ + fade (line) { + let len = this.fade_count(line); + let start = this.fade_start(line); + let end = this.fade_end(line); + + this.loops[this.rec].start = start; + this.loops[this.rec].end = end; + this.loops[this.rec].fade = true; + this.loops[this.rec].fade_count = 0; + this.loops[this.rec].fade_len = len; + } + /** + * Extract the fade length integer from a FADE cmd + */ + fade_count (str) { + return parseInt(str.split(' ')[1]); + } + /** + * Extract the start color from a string + */ + fade_start (str) { + let color = str.split(' ')[2]; + return this.rgb(color.trim()) + } + /** + * Extract the end color from a string + */ + fade_end (str) { + let color = str.split(' ')[3]; + return this.rgb(color.trim()) + } + fade_rgb (start, end, len, x) { + let cur = []; + let diff; + for (let i = 0; i < 3; i++) { + if (x === len - 1) { + cur[i] = end[i]; + } else if (start[i] >= end[i]) { + diff = start[i] - end[i]; + cur[i] = start[i] - Math.round((diff / (len - 1)) * x); + } else { + diff = end[i] - start[i]; + cur[i] = start[i] + Math.round((diff / (len - 1)) * x); + } + } + return this.rgb_str(cur); + + } + rgb (str) { + let rgb = str.split(','); + return rgb.map( char => { + return parseInt(char); + }) + } + rgb_str (arr) { + return arr.join(','); + } + /** + * Increase the state of a specific object, such as the camera/projector, + * by the value defined in val + */ + update (cmd, val = 1) { + if (cmd === 'END') { + //I don't understand this loop + for (let i = 0; i < val; i++) { + if (this.rec === 0) { + this.cam += this.loops[this.rec].cam; + this.proj += this.loops[this.rec].proj; + } else if (this.rec >= 1) { + this.loops[this.rec - 1].cam += this.loops[this.rec].cam; + this.loops[this.rec - 1].proj += this.loops[this.rec].proj; + } + } + } else if (cmd === 'CF') { + if (this.rec === -1) { + this.cam += val; + } else { + this.loops[this.rec].cam += val; + } + } else if (cmd === 'CB') { + if (this.rec === -1) { + this.cam -= val; + } else { + this.loops[this.rec].cam--; + } + } else if (cmd === 'PF') { + if (this.rec === -1) { + this.proj += val; + } else { + this.loops[this.rec].proj += val; + } + } else if (cmd === 'PB') { + if (this.rec === -1) { + this.proj -= val; + } else { + this.loops[this.rec].proj--; + } + } else if (cmd === 'BF') { + if (this.rec === -1) { + this.cam += val; + } else { + this.loops[this.rec].cam += val; + } + } else if (cmd === 'BB') { + if (this.rec === -1) { + this.cam -= val; + } else { + this.loops[this.rec].cam -= val; + } + } else if (cmd === 'L ') { + + } + } + /** + * Split string on command, extract any integers from string + */ + str_to_arr (str, cmd) { + const cnt = str.split(cmd); + let c = parseInt(cnt[1]); + let arr = []; + if (cnt[1] === '') { + c = 1; + } else { + c = parseInt(cnt[1]); + } + arr = new Array(c).fill(cmd); + this.update(cmd, c); + return arr; + } + /** + * Split a string on a command to extract data for light array + */ + light_to_arr (str, cmd) { + const cnt = str.split(cmd); + let c = parseInt(cnt[1]); + let arr = []; + if (cnt[1] === '') { + c = 1; + } else { + c = parseInt(cnt[1]); + } + for (var i = 0; i < c; i++) { + if (cmd === 'CF' + || cmd === 'CB') { + arr.push(this.color); + } else if (cmd === 'BF' + || cmd === 'BB') { + arr.push(BLACK); + } else { + arr.push(''); + } + } + return arr; + } + /** + * Split a string to extract an rgb color value + */ + light_state (str) { + //add parsers for other color spaces + const color = str.replace('L ', '').trim(); + this.color = color; + } + + /** + * Throw an error with specific message + */ + fail (msg) { + throw new Error(msg); + } +} + +module.exports = Mscript; + + +/* + +CAM # - go to camera frame # +PROJ # - go to projector frame # + +SET CAM # - sets camera count to # +SET PROJ # - sets projector count to # + +LOOP # - begin loop, can nest recursively, # times +END LOOP - (or END) closes loop + +L #RGB - sets light to rgb value + +FADE 24 0,0,0 255,255,255 + +CF - Camera forwards +PF - Projector forwards +BF - Black forwards +CB - Camera backwards +PB - Projector backwards +BB - Black backwards + +*/ \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..cd5b18a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "target": "ES2017", + "noImplicitAny": true, + "moduleResolution": "node", + "sourceMap": true, + "removeComments" : false, + "outDir": "./lib/", + "rootDir" : "./src/" + }, + "exclude" : [] +} \ No newline at end of file