Add preliminary support for writing sandboxed javascript for animation purposes. Renders a single frame now.

This commit is contained in:
Martijn de Boer 2018-01-07 16:18:58 +01:00
parent 485c34bbdc
commit b755b5dbb3
8 changed files with 117 additions and 14 deletions

View File

@ -2,15 +2,19 @@
class ApiController {
constructor( server, driver ) {
constructor( server, driver, vmcontroller ) {
this.server = server;
this.driver = driver;
this.vmcontroller = vmcontroller;
this.server.post( { path: '/api/writecanvas' }, this.writeCanvas.bind( this ) );
this.server.post( { path: '/api/runcode' }, this.runCode.bind( this ) );
this.server.get( { path: '/api/write' }, this.write.bind( this ) );
this.server.get( { path: '/api/getdisplaysize' }, this.getDisplaySize.bind( this ) );
this.server.get( { path: '/api/setpixel/:x/:y/:r/:g/:b' }, this.setPixel.bind( this ) );
this.server.get( { path: '/api/getcode' }, this.getCode.bind( this ) );
}
@ -18,8 +22,6 @@ class ApiController {
this.driver.clearMatrix();
resource.setHeader( 'Access-Control-Allow-Origin', '*' );
let data = JSON.parse( request.params.data );
for ( let obj of data) {
@ -36,8 +38,6 @@ class ApiController {
write( request, resource, next ) {
resource.setHeader( 'Access-Control-Allow-Origin', '*' );
let buffer = this.driver.getBuffer();
this.driver.write( buffer );
@ -48,8 +48,6 @@ class ApiController {
getDisplaySize( request, resource, next ) {
resource.setHeader( 'Access-Control-Allow-Origin', '*' );
resource.json( 200, this.driver.getSize() );
return next();
@ -57,8 +55,6 @@ class ApiController {
setPixel( request, resource, next ) {
resource.setHeader( 'Access-Control-Allow-Origin', '*' );
this.driver.setPixel(
request.params.x,
request.params.y,
@ -72,6 +68,25 @@ class ApiController {
}
getCode( request, resource, next ) {
resource.send( this.vmcontroller.runningCode );
return next();
}
runCode( request, resource, next ) {
this.runningCode = request.params.code;
this.vmcontroller.compileScript( this.runningCode );
this.vmcontroller.runScript();
resource.json( 200, { 'msg': 'Ok' } );
return next();
}
}
exports.ApiController = ApiController;

View File

@ -0,0 +1,75 @@
'use strict';
class VMController
{
constructor( driver ) {
this.driver = driver;
this.runningCode = ';';
this.runningVmScript = false;
this.previousTime = 0;
this.delta = 0;
this.sandbox = {};
this.vm = null;
}
getRunningCode() {
return this.runningCode;
}
compileScript( script ) {
let { NodeVM, VMScript } = require( 'vm2' );
this.resetSandbox();
this.runningCode = script;
this.vm = new NodeVM( {
'console': 'inherit',
'sandbox': this.sandbox
} );
this.runningVmScript = new VMScript( this.runningCode );
}
resetSandbox() {
this.sandbox = {
'matrix': this.driver,
'delta': this.getDelta.bind( this )
};
}
runScript( ) {
let delta = 0;
let tmd = this.getTimeData();
if ( this.previousTime === 0 ) {
this.previousTime = tmd;
} else {
delta = tmd - this.previousTime;
this.previousTime = tmd;
}
this.delta = delta;
this.vm.run( this.runningVmScript, 'pixdisp-sandbox.js' );
}
getTimeData() {
let hrTime = process.hrtime();
return hrTime[ 0 ] * 1000000 + hrTime[ 1 ] / 1000;
}
getDriver() {
return this.driver;
}
getDelta() {
return this.delta;
}
}
exports.VMController = VMController;

View File

@ -202,7 +202,7 @@ class Driver {
/**
* Write output to the device. Implement at driver level.
*/
write( buffer ) { //eslint-disable-line no-unused-vars
write( buffer = false ) { //eslint-disable-line no-unused-vars
console.log( 'Driver should implement this' );
}

View File

@ -9,7 +9,7 @@ class Dummy extends Driver {
this.silence = false;
}
write( buffer ) {
write( buffer = false ) {
if ( this.silence !== true ) {
console.log( buffer );
}

View File

@ -11,7 +11,7 @@ class PimoroniUnicorn extends Driver {
this.spi = false;
}
write( buffer ) {
write( buffer = false ) {
if ( this.spi === false) {
if ( fs.existsSync( '/dev/spidev0.0' ) ) {
let SPI = require( 'pi-spi' );
@ -22,6 +22,10 @@ class PimoroniUnicorn extends Driver {
}
}
if ( buffer === false ) {
buffer = this.getBuffer();
}
this.spi.write(
Buffer.concat(
[

5
package-lock.json generated
View File

@ -5385,6 +5385,11 @@
"extsprintf": "1.3.0"
}
},
"vm2": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/vm2/-/vm2-3.5.2.tgz",
"integrity": "sha512-imsgTODim0/3fSDA0g4SeYBF9oAuJnYXpILnA6GJ7rglNPLOv1s+CfgE7pqzOHFEKrJsogIxupE5fW2DI65rIg=="
},
"walker": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz",

View File

@ -8,7 +8,8 @@
"license": "MIT",
"dependencies": {
"pi-spi": "^1.0.2",
"restify": "^6.3.4"
"restify": "^6.3.4",
"vm2": "^3.5.2"
},
"devDependencies": {
"eslint": "^4.15.0",

View File

@ -4,6 +4,7 @@ let fs = require( 'fs' );
let os = require( 'os' );
let config,
vmcontroller,
api,
contents;
@ -29,6 +30,7 @@ let driver;
let { DriverFactory } = require( './drivers/driverfactory' );
let driverFactory = new DriverFactory();
let { VMController } = require( './controllers/vmcontroller' );
let { ApiController } = require( './controllers/apicontroller' );
let restify = require( 'restify' );
@ -57,7 +59,8 @@ server.use( restify.plugins.throttle(
driver = driverFactory.createFromConfig( config );
driver.write( driver.getBuffer() );
api = new ApiController( server, driver );
vmcontroller = new VMController( driver );
api = new ApiController( server, driver, vmcontroller );
server.get(/.*/, restify.plugins.serveStatic({