mirror of
https://github.com/sexybiggetje/pixdisp.git
synced 2024-11-24 13:01:01 +01:00
Working implementation of drivers, and drawing application. Things light up!
This commit is contained in:
parent
f93a20a627
commit
7c212e22ee
11 changed files with 236 additions and 25 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,3 +1,6 @@
|
|||
# Application data
|
||||
config.json
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
NEEDS BETTER README!
|
||||
|
||||
Make sure you are on a recent nodejs version. Raspbian has old version. Use nodesource ;).
|
||||
|
||||
npm install
|
||||
|
||||
node pixdisp.js
|
||||
|
|
14
config.example.json
Normal file
14
config.example.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"bindAddr": "0.0.0.0",
|
||||
"bindPort": 8080,
|
||||
|
||||
"driver": "dummy",
|
||||
|
||||
"matrix": {
|
||||
"width": 16,
|
||||
"height": 16,
|
||||
"brightness": 1,
|
||||
"flipHorizontal": false,
|
||||
"flipVertical": false
|
||||
}
|
||||
}
|
67
controllers/apicontroller.js
Normal file
67
controllers/apicontroller.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
"use strict";
|
||||
|
||||
class ApiController {
|
||||
|
||||
constructor( server, driver ) {
|
||||
|
||||
this.server = server;
|
||||
this.driver = driver;
|
||||
|
||||
this.server.post( { path: '/api/writecanvas' }, this.writecanvas.bind( this ) );
|
||||
this.server.get( { path: '/api/write' }, this.write.bind( this ) );
|
||||
this.server.get( { path: '/api/setpixel/:x/:y/:r/:g/:b' }, this.setPixel.bind( this ) );
|
||||
|
||||
}
|
||||
|
||||
writecanvas( request, resource, next ) {
|
||||
|
||||
this.driver.clearMatrix();
|
||||
|
||||
resource.setHeader( 'Access-Control-Allow-Origin', '*' );
|
||||
|
||||
let data = JSON.parse( request.params.data );
|
||||
|
||||
for ( let obj of data) {
|
||||
this.driver.setPixel( obj.y, obj.x, obj.r, obj.g, obj.b );
|
||||
}
|
||||
|
||||
let buffer = this.driver.getBuffer();
|
||||
this.driver.write( buffer );
|
||||
|
||||
resource.json( 200, { 'msg': 'Ok' } );
|
||||
return next();
|
||||
|
||||
}
|
||||
|
||||
write( request, resource, next ) {
|
||||
|
||||
resource.setHeader( 'Access-Control-Allow-Origin', '*' );
|
||||
|
||||
let buffer = this.driver.getBuffer();
|
||||
this.driver.write( buffer );
|
||||
|
||||
resource.json( 200, { 'msg': 'Ok' } );
|
||||
return next();
|
||||
|
||||
}
|
||||
|
||||
setPixel( request, resource, next ) {
|
||||
|
||||
resource.setHeader( 'Access-Control-Allow-Origin', '*' );
|
||||
|
||||
this.driver.setPixel(
|
||||
request.params.x,
|
||||
request.params.y,
|
||||
request.params.r,
|
||||
request.params.g,
|
||||
request.params.b
|
||||
);
|
||||
|
||||
resource.json( 200, { 'msg': 'Ok' } );
|
||||
return next();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.ApiController = ApiController;
|
|
@ -10,6 +10,9 @@ class Driver {
|
|||
this.setSize( 16, 16 );
|
||||
this.setBrightness( 1 );
|
||||
|
||||
this.flipHorizontal = false;
|
||||
this.flipVertical = false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,7 +22,7 @@ class Driver {
|
|||
this.width = w;
|
||||
this.height = h;
|
||||
|
||||
this.createMatrix();
|
||||
this.clearMatrix();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,6 +87,8 @@ class Driver {
|
|||
* @return {Buffer}
|
||||
*/
|
||||
getBuffer() {
|
||||
this.flipMatrix( this.flipHorizontal, this.flipVertical );
|
||||
|
||||
let buffer = new Buffer( this.width * this.height * 3 );
|
||||
|
||||
let size = this.getSize();
|
||||
|
@ -100,22 +105,38 @@ class Driver {
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write output to the device. Implement at driver level.
|
||||
*/
|
||||
write( buffer ) {
|
||||
console.log( 'Driver should implement this' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the matrix along it's axis.
|
||||
*/
|
||||
flipMatrix( horizontal, vertical ) {
|
||||
if ( horizontal === true ) {
|
||||
for ( let i = 0; i < this.matrix.length; i++ ) {
|
||||
this.matrix[ i ].reverse();
|
||||
}
|
||||
}
|
||||
|
||||
if ( vertical === true ) {
|
||||
this.matrix.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the internal frame
|
||||
*/
|
||||
createMatrix() {
|
||||
clearMatrix() {
|
||||
this.matrix = [];
|
||||
|
||||
let size = this.getSize();
|
||||
|
||||
for ( let y = 0; y < size.height; y++ ) {
|
||||
for ( let y = 0; y < this.height; y++ ) {
|
||||
this.matrix.push( [] );
|
||||
|
||||
for ( let x = 0; x < size.width; x++ ) {
|
||||
for ( let x = 0; x < this.width; x++ ) {
|
||||
this.matrix[ y ].push( {
|
||||
r: 0,
|
||||
g: 0,
|
||||
|
|
40
drivers/driverfactory.js
Normal file
40
drivers/driverfactory.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
"use strict";
|
||||
|
||||
class DriverFactory {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
createFromConfig( config ) {
|
||||
|
||||
let driver;
|
||||
|
||||
switch ( config.driver.toLowerCase() ) {
|
||||
|
||||
default:
|
||||
console.warn( "Unknown driver defaulting to Dummy" );
|
||||
|
||||
case "dummy":
|
||||
let { Dummy } = require( './dummy' );
|
||||
driver = new Dummy();
|
||||
break;
|
||||
|
||||
case "pimoroniunicorn":
|
||||
let { PimoroniUnicorn } = require( './pimoroniunicorn' );
|
||||
driver = new PimoroniUnicorn();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
driver.setSize( config.matrix.width, config.matrix.height );
|
||||
driver.setBrightness( config.matrix.brightness );
|
||||
|
||||
driver.flipHorizontal = config.matrix.flipHorizontal;
|
||||
driver.flipVertical = config.matrix.flipVertical;
|
||||
|
||||
return driver;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.DriverFactory = DriverFactory;
|
15
drivers/dummy.js
Normal file
15
drivers/dummy.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
"use strict";
|
||||
|
||||
let { Driver } = require( './driver' );
|
||||
|
||||
class Dummy extends Driver {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
write( buffer ) {
|
||||
console.log( buffer );
|
||||
}
|
||||
}
|
||||
|
||||
exports.Dummy = Dummy;
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
let { Driver } = require( './driver' );
|
||||
|
||||
class UnicornHatHD extends Driver {
|
||||
class PimoroniUnicorn extends Driver {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
|
@ -26,4 +26,4 @@ class UnicornHatHD extends Driver {
|
|||
}
|
||||
}
|
||||
|
||||
exports.UnicornHatHD = UnicornHatHD;
|
||||
exports.PimoroniUnicorn = PimoroniUnicorn;
|
39
pixdisp.js
39
pixdisp.js
|
@ -1,18 +1,36 @@
|
|||
'use strict';
|
||||
|
||||
let { UnicornHatHD } = require( './drivers/unicornhathd' );
|
||||
let fs = require( 'fs' );
|
||||
let config;
|
||||
let api;
|
||||
|
||||
if ( fs.existsSync( 'config.json' ) ) {
|
||||
let contents = fs.readFileSync( 'config.json' );
|
||||
config = JSON.parse( contents );
|
||||
} else {
|
||||
let contents = fs.readFileSync( 'config.example.json' );
|
||||
config = JSON.parse( contents );
|
||||
}
|
||||
|
||||
let driver;
|
||||
let { DriverFactory } = require( './drivers/driverfactory' );
|
||||
let driverFactory = new DriverFactory();
|
||||
|
||||
let { ApiController } = require( './controllers/apicontroller' );
|
||||
|
||||
let restify = require( 'restify' );
|
||||
|
||||
let bindAddr = '0.0.0.0';
|
||||
let bindPort = 8080;
|
||||
let bindAddr = config.bindAddr;
|
||||
let bindPort = config.bindPort;
|
||||
|
||||
let server = restify.createServer( {
|
||||
handleUpgrades: true
|
||||
} );
|
||||
|
||||
server.use( restify.plugins.queryParser() );
|
||||
server.use( restify.plugins.bodyParser() );
|
||||
server.use( restify.plugins.bodyParser( {
|
||||
mapParams: true
|
||||
} ) );
|
||||
server.use( restify.plugins.jsonp() );
|
||||
server.use( restify.plugins.gzipResponse() );
|
||||
server.use( restify.plugins.throttle(
|
||||
|
@ -23,6 +41,11 @@ server.use( restify.plugins.throttle(
|
|||
}
|
||||
));
|
||||
|
||||
driver = driverFactory.createFromConfig( config );
|
||||
driver.write( driver.getBuffer() );
|
||||
|
||||
api = new ApiController( server, driver );
|
||||
|
||||
server.get(/.*/, restify.plugins.serveStatic({
|
||||
|
||||
'directory': 'www',
|
||||
|
@ -37,12 +60,4 @@ server.listen( bindPort, bindAddr, function() {
|
|||
console.log( '%s listening at %s ', server.name , server.url );
|
||||
console.log( 'Ready.' );
|
||||
|
||||
// Some test code
|
||||
let driver = new UnicornHatHD();
|
||||
driver.setPixel( 1, 1, 255, 0, 0 );
|
||||
driver.setPixel( 5, 5, 255, 0, 255 );
|
||||
|
||||
let buffer = driver.getBuffer();
|
||||
driver.write( buffer );
|
||||
|
||||
});
|
|
@ -19,10 +19,7 @@
|
|||
</div>
|
||||
</section>
|
||||
<section class="section view">
|
||||
<a class="button is-small is-link">Load current</a>
|
||||
<a class="button is-small is-link">Capture camera</a>
|
||||
<a class="button is-small is-link">Browse history</a>
|
||||
<a class="button is-small is-success">Submit</a>
|
||||
<a class="button is-small is-success" id="submitImage">Submit</a>
|
||||
<br /><br />
|
||||
<div class="columns">
|
||||
<div class="column is-half" id="canvasHolder">
|
||||
|
|
|
@ -18,6 +18,7 @@ class App
|
|||
holder.appendChild( canvas );
|
||||
|
||||
canvas.addEventListener( 'click', this.handleCanvas );
|
||||
document.getElementById( 'submitImage' ).addEventListener( 'click', this.submitCanvas );
|
||||
|
||||
this.canvas = canvas;
|
||||
this.context = canvas.getContext( '2d' );
|
||||
|
@ -118,6 +119,42 @@ class App
|
|||
|
||||
}
|
||||
|
||||
submitCanvas( ev ) {
|
||||
|
||||
if ( ev.preventDefault ) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
let imageData = app.context.getImageData( 0, 0, app.canvas.width, app.canvas.height );
|
||||
let request = new XMLHttpRequest();
|
||||
|
||||
request.open( 'POST', '/api/writecanvas', true );
|
||||
request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8' );
|
||||
|
||||
let obj = [];
|
||||
for ( let x = 0; x < app.canvas.width; x++ ) {
|
||||
for ( let y = 0; y < app.canvas.height; y++ ) {
|
||||
let index = ( y * app.canvas.width + x ) * 4;
|
||||
let r = imageData.data[ index ];
|
||||
let g = imageData.data[ index + 1 ];
|
||||
let b = imageData.data[ index + 2 ];
|
||||
|
||||
if ( r > 0 || g > 0 || b > 0 ) {
|
||||
obj.push( {
|
||||
x: x,
|
||||
y: y,
|
||||
r: r,
|
||||
g: g,
|
||||
b: b
|
||||
} )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obj = encodeURI( 'data=' + JSON.stringify( obj ) );
|
||||
request.send( obj );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let app = new App();
|
Loading…
Reference in a new issue