First work in progress app

This commit is contained in:
Martijn de Boer 2017-12-12 20:41:32 +01:00
parent 3df0fbae83
commit f93a20a627
12 changed files with 11778 additions and 0 deletions

0
CONTRIBUTING.md Normal file
View File

7
LICENSE.md Normal file
View File

@ -0,0 +1,7 @@
Copyright (C) 2014 Martijn de Boer
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

9
README.md Normal file
View File

@ -0,0 +1,9 @@
NEEDS BETTER README!
npm install
node pixdisp.js
http://localhost:8080/
Matrix driver & Unicorn Hat HD driver inspired by https://github.com/vesteraas/node-unicornhathd

129
drivers/driver.js Normal file
View File

@ -0,0 +1,129 @@
"use strict";
/**
* Basic matrix driver which every implementation can derive from
*/
class Driver {
constructor() {
// Some sane-ish defaults
this.setSize( 16, 16 );
this.setBrightness( 1 );
}
/**
* Sets the display size
*/
setSize( w, h ) {
this.width = w;
this.height = h;
this.createMatrix();
}
/**
* Return an object containing the width and height
*/
getSize() {
return {
width: this.width,
height: this.height
};
}
/**
* Sets brightness between 0.0f and 1.0f
*/
setBrightness( v ) {
this.brightness = v;
}
/**
* Gets the current brightness
*/
getBrightness() {
return this.brightness;
}
/**
* CLear the matrix with the following color, from 0..255
*/
clear( r = 0, g = 0, b = 0) {
for ( let x = 0; x < this.width; x++ ) {
for ( let y = 0; y < this.height; y++) {
this.matrix[x][y].r = r;
this.matrix[x][y].g = g;
this.matrix[x][y].b = b;
}
}
}
/**
* Set pixel color
*/
setPixel( x, y, r = 0, g = 0, b = 0 ) {
this.matrix[x][y].r = r;
this.matrix[x][y].g = g;
this.matrix[x][y].b = b;
}
/**
* Return the pixel color
*/
getPixel( x, y ) {
return {
r: this.matrix[x][y].r,
g: this.matrix[x][y].g,
b: this.matrix[x][y].b,
}
}
/**
* Get the buffer for writing
* @return {Buffer}
*/
getBuffer() {
let buffer = new Buffer( this.width * this.height * 3 );
let size = this.getSize();
// @TODO: for now this only supports square displays!
for ( let y = 0; y < size.height; y++ ) {
for ( let x = 0; x < size.width; x++ ) {
buffer[ y * size.height * 3 + x * 3 + 0 ] = this.matrix[ x ][ y ].r * this.brightness;
buffer[ y * size.height * 3 + x * 3 + 1 ] = this.matrix[ x ][ y ].g * this.brightness;
buffer[ y * size.height * 3 + x * 3 + 2 ] = this.matrix[ x ][ y ].b * this.brightness;
}
}
return buffer;
}
write( buffer ) {
console.log( 'Driver should implement this' );
}
/**
* Create the internal frame
*/
createMatrix() {
this.matrix = [];
let size = this.getSize();
for ( let y = 0; y < size.height; y++ ) {
this.matrix.push( [] );
for ( let x = 0; x < size.width; x++ ) {
this.matrix[ y ].push( {
r: 0,
g: 0,
b: 0
} );
}
}
}
}
exports.Driver = Driver;

29
drivers/unicornhathd.js Normal file
View File

@ -0,0 +1,29 @@
"use strict";
let { Driver } = require( './driver' );
class UnicornHatHD extends Driver {
constructor() {
super();
let SPI = require( 'pi-spi' );
this.spi = SPI.initialize( '/dev/spidev0.0' );
}
write( buffer ) {
this.spi.write(
Buffer.concat(
[ new Buffer( [ 0x72 ] ),
buffer ]
),
function ( err ) {
if ( err ) {
throw 'Failed writing buffer';
}
}
);
}
}
exports.UnicornHatHD = UnicornHatHD;

706
package-lock.json generated Normal file
View File

@ -0,0 +1,706 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"pi-spi": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pi-spi/-/pi-spi-1.0.2.tgz",
"integrity": "sha1-EGGeoufh+EJbiFq++2J8JzkDDcY=",
"requires": {
"nan": "2.8.0"
},
"dependencies": {
"nan": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
"integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo="
}
}
},
"restify": {
"version": "6.3.4",
"resolved": "https://registry.npmjs.org/restify/-/restify-6.3.4.tgz",
"integrity": "sha1-CXmQsiukDwKgdKfUyxwnaQdZ4og=",
"requires": {
"assert-plus": "1.0.0",
"bunyan": "1.8.12",
"clone-regexp": "1.0.0",
"csv": "1.2.1",
"dtrace-provider": "0.8.5",
"escape-regexp-component": "1.0.2",
"ewma": "2.0.1",
"formidable": "1.1.1",
"http-signature": "1.2.0",
"lodash": "4.17.4",
"lru-cache": "4.1.1",
"mime": "1.6.0",
"negotiator": "0.6.1",
"once": "1.4.0",
"pidusage": "1.2.0",
"qs": "6.5.1",
"restify-errors": "5.0.0",
"semver": "5.4.1",
"spdy": "3.4.7",
"uuid": "3.1.0",
"vasync": "1.6.4",
"verror": "1.10.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"bunyan": {
"version": "1.8.12",
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz",
"integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=",
"requires": {
"dtrace-provider": "0.8.5",
"moment": "2.19.4",
"mv": "2.1.1",
"safe-json-stringify": "1.0.4"
},
"dependencies": {
"moment": {
"version": "2.19.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.19.4.tgz",
"integrity": "sha1-F+XixurYgZyOz62DoKzMsxLpRoI=",
"optional": true
},
"mv": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
"integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=",
"optional": true,
"requires": {
"mkdirp": "0.5.1",
"ncp": "2.0.0",
"rimraf": "2.4.5"
},
"dependencies": {
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"optional": true,
"requires": {
"minimist": "0.0.8"
},
"dependencies": {
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"optional": true
}
}
},
"ncp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
"optional": true
},
"rimraf": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
"optional": true,
"requires": {
"glob": "6.0.4"
},
"dependencies": {
"glob": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
"integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
"optional": true,
"requires": {
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
},
"dependencies": {
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"optional": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
},
"dependencies": {
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"optional": true
}
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"optional": true
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"optional": true,
"requires": {
"brace-expansion": "1.1.8"
},
"dependencies": {
"brace-expansion": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
"optional": true,
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
},
"dependencies": {
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"optional": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"optional": true
}
}
}
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"optional": true
}
}
}
}
}
}
},
"safe-json-stringify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz",
"integrity": "sha1-gaCY9Efku8P/MxKiQ1IbwGDvWRE=",
"optional": true
}
}
},
"clone-regexp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.0.tgz",
"integrity": "sha1-6uCiQT9VwJQvgYwin+/OhF1/Oxw=",
"requires": {
"is-regexp": "1.0.0",
"is-supported-regexp-flag": "1.0.0"
},
"dependencies": {
"is-regexp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
"integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk="
},
"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="
}
}
},
"csv": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/csv/-/csv-1.2.1.tgz",
"integrity": "sha1-UjHt/BxxUlEuxFeBB2p6l/9SXAw=",
"requires": {
"csv-generate": "1.1.2",
"csv-parse": "1.3.3",
"csv-stringify": "1.1.2",
"stream-transform": "0.2.2"
},
"dependencies": {
"csv-generate": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-1.1.2.tgz",
"integrity": "sha1-7GsA7a7W5ZrZwgWC9MNk4osUYkA="
},
"csv-parse": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.3.3.tgz",
"integrity": "sha1-0c/YdDwvhJoKuy/VRNtWaV0ZpJA="
},
"csv-stringify": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-1.1.2.tgz",
"integrity": "sha1-d6QVJlgbzjOA8SsA18W7rHDIK1g=",
"requires": {
"lodash.get": "4.4.2"
},
"dependencies": {
"lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
}
}
},
"stream-transform": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-0.2.2.tgz",
"integrity": "sha1-dYZ0h/SVKPi/HYJJllh1PQLfeDg="
}
}
},
"dtrace-provider": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.5.tgz",
"integrity": "sha1-mOu6Ihr6xG4cOf02hY2Pk2dSS5I=",
"optional": true,
"requires": {
"nan": "2.8.0"
},
"dependencies": {
"nan": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
"integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=",
"optional": true
}
}
},
"escape-regexp-component": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/escape-regexp-component/-/escape-regexp-component-1.0.2.tgz",
"integrity": "sha1-nGO20LJf8qiMOtvRjFthrMO5+qI="
},
"ewma": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ewma/-/ewma-2.0.1.tgz",
"integrity": "sha1-mHbBxJGsVzPIZmABo5YaBMl88eg=",
"requires": {
"assert-plus": "1.0.0"
}
},
"formidable": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz",
"integrity": "sha1-lriIb3w8NQi5Mta9cMTTqI818ak="
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "1.0.0",
"jsprim": "1.4.1",
"sshpk": "1.13.1"
},
"dependencies": {
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
},
"dependencies": {
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
}
}
},
"sshpk": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
"requires": {
"asn1": "0.2.3",
"assert-plus": "1.0.0",
"bcrypt-pbkdf": "1.0.1",
"dashdash": "1.14.1",
"ecc-jsbn": "0.1.1",
"getpass": "0.1.7",
"jsbn": "0.1.1",
"tweetnacl": "0.14.5"
},
"dependencies": {
"asn1": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "1.0.0"
}
},
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "1.0.0"
}
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
}
}
}
}
},
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
},
"lru-cache": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
"integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=",
"requires": {
"pseudomap": "1.0.2",
"yallist": "2.1.2"
},
"dependencies": {
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
}
}
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE="
},
"negotiator": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1.0.2"
},
"dependencies": {
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
}
},
"pidusage": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pidusage/-/pidusage-1.2.0.tgz",
"integrity": "sha1-Ze6WrOTgikzT+SQJlshbNnFx7pI="
},
"qs": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
"integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg="
},
"restify-errors": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/restify-errors/-/restify-errors-5.0.0.tgz",
"integrity": "sha1-ZocX4QBoPuxs4NUV+J/x2+wlSo0=",
"requires": {
"assert-plus": "1.0.0",
"lodash": "4.17.4",
"safe-json-stringify": "1.0.4",
"verror": "1.10.0"
},
"dependencies": {
"safe-json-stringify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz",
"integrity": "sha1-gaCY9Efku8P/MxKiQ1IbwGDvWRE=",
"optional": true
}
}
},
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4="
},
"spdy": {
"version": "3.4.7",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz",
"integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=",
"requires": {
"debug": "2.6.9",
"handle-thing": "1.2.5",
"http-deceiver": "1.2.7",
"safe-buffer": "5.1.1",
"select-hose": "2.0.0",
"spdy-transport": "2.0.20"
},
"dependencies": {
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"requires": {
"ms": "2.0.0"
},
"dependencies": {
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"handle-thing": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
"integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ="
},
"http-deceiver": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
"integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc="
},
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
},
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
"integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
},
"spdy-transport": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz",
"integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=",
"requires": {
"debug": "2.6.9",
"detect-node": "2.0.3",
"hpack.js": "2.1.6",
"obuf": "1.1.1",
"readable-stream": "2.3.3",
"safe-buffer": "5.1.1",
"wbuf": "1.7.2"
},
"dependencies": {
"detect-node": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz",
"integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc="
},
"hpack.js": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
"integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
"requires": {
"inherits": "2.0.3",
"obuf": "1.1.1",
"readable-stream": "2.3.3",
"wbuf": "1.7.2"
},
"dependencies": {
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}
}
},
"obuf": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz",
"integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4="
},
"readable-stream": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
"integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"safe-buffer": "5.1.1",
"string_decoder": "1.0.3",
"util-deprecate": "1.0.2"
},
"dependencies": {
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
"requires": {
"safe-buffer": "5.1.1"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
}
}
},
"wbuf": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz",
"integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=",
"requires": {
"minimalistic-assert": "1.0.0"
},
"dependencies": {
"minimalistic-assert": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
"integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M="
}
}
}
}
}
}
},
"uuid": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
"integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ="
},
"vasync": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz",
"integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=",
"requires": {
"verror": "1.6.0"
},
"dependencies": {
"verror": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz",
"integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=",
"requires": {
"extsprintf": "1.2.0"
},
"dependencies": {
"extsprintf": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz",
"integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk="
}
}
}
}
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "1.4.0"
},
"dependencies": {
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"extsprintf": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz",
"integrity": "sha1-4mifjzVvrWLMplo6kcXfX5VRaS8="
}
}
}
}
}
}
}

6
package.json Normal file
View File

@ -0,0 +1,6 @@
{
"dependencies": {
"pi-spi": "^1.0.2",
"restify": "^6.3.4"
}
}

48
pixdisp.js Normal file
View File

@ -0,0 +1,48 @@
'use strict';
let { UnicornHatHD } = require( './drivers/unicornhathd' );
let restify = require( 'restify' );
let bindAddr = '0.0.0.0';
let bindPort = 8080;
let server = restify.createServer( {
handleUpgrades: true
} );
server.use( restify.plugins.queryParser() );
server.use( restify.plugins.bodyParser() );
server.use( restify.plugins.jsonp() );
server.use( restify.plugins.gzipResponse() );
server.use( restify.plugins.throttle(
{
burst: 50,
rate: 30,
ip: true
}
));
server.get(/.*/, restify.plugins.serveStatic({
'directory': 'www',
'default': 'index.html'
}));
server.pre( restify.pre.userAgentConnection() );
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 );
});

12
www/css/app.css Normal file
View File

@ -0,0 +1,12 @@
#artboard {
border: 1px solid #00d1b2;
width: 100%;
}
.paletteBox {
border: 1px solid whitesmoke;
width: 10%;
height: 10%;
float: left;
margin: 0 1% 1% 0;
}

10663
www/css/bulma.css vendored Normal file

File diff suppressed because it is too large Load Diff

46
www/index.html Normal file
View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>Pixel Display</title>
<link rel="stylesheet" type="text/css" href="css/bulma.css">
<link rel="stylesheet" type="text/css" href="css/app.css">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name=viewport content="width=device-width, initial-scale=1">
<script src="js/app.js" type="module" async></script>
</head>
<body>
<section class="hero is-primary">
<div class="hero-body">
<div class="container">
<h1 class="title">Pixel Display</h1>
<h2 class="subtitle">Leave a little bit of art, and please keep it clean!</h2>
</div>
</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>
<br /><br />
<div class="columns">
<div class="column is-half" id="canvasHolder">
</div>
<div class="column" id="paletteHolder">
</div>
</div>
</section>
<footer class="footer">
<div class="container">
<div class="content has-text-centered">
<p>
<strong>Pixel Display</strong> (pixdisp). The source code is licensed <a href="http://opensource.org/licenses/mit-license.php">MIT</a>. Fork, patch, contribute at Github.
</p>
</div>
</div>
</footer>
</body>
</html>

123
www/js/app.js Normal file
View File

@ -0,0 +1,123 @@
'use strict';
class App
{
constructor() {
this.createCanvas(16,16);
this.createPalette();
}
createCanvas( width, height ) {
let holder = document.querySelector( '#canvasHolder' );
let canvas = document.createElement( 'canvas' );
canvas.id = 'artboard';
canvas.width = width;
canvas.height = height;
holder.appendChild( canvas );
canvas.addEventListener( 'click', this.handleCanvas );
this.canvas = canvas;
this.context = canvas.getContext( '2d' );
this.context.imageSmoothingEnabled = false;
this.context.fillStyle = 'black';
this.context.fillRect( 0, 0, width, height );
}
createPalette() {
let paletteItBe = [
"0 0 0",
"20 12 28",
"68 36 52",
"48 52 109",
"78 74 78",
"133 76 48",
"52 101 36",
"208 70 72",
"117 113 97",
"89 125 206",
"210 125 44",
"133 149 161",
"109 170 44",
"210 170 153",
"109 194 202",
"218 212 94",
"222 238 214",
"0 71 189",
"2 136 217",
"7 185 252",
"0 149 67",
"0 171 56",
"154 240 0",
"255 179 0",
"255 206 0",
"255 239 59",
"255 206 0",
"255 230 59",
"234 0 52",
"253 71 3",
"255 139 42",
"130 0 172",
"182 16 191",
"204 114 245"
];
let holder = document.querySelector( '#paletteHolder' );
for ( let i = 0 ; i < paletteItBe.length; i++ ) {
let paletteStr = paletteItBe[ i ];
let colorValues = paletteStr.split( ' ' );
let element = document.createElement( 'div' );
element.className = 'paletteBox column';
element.dataset.colorR = colorValues[ 0 ];
element.dataset.colorG = colorValues[ 1 ];
element.dataset.colorB = colorValues[ 2 ];
element.style.backgroundColor = `rgba(${colorValues[ 0 ]}, ${colorValues[ 1 ]}, ${colorValues[ 2 ]}, 1)`;
holder.appendChild( element );
element.addEventListener( 'click', this.handlePalette );
}
let colorValues = paletteItBe[ paletteItBe.length - 1 ].split( ' ' );
this.selectedR = colorValues[ 0 ];
this.selectedG = colorValues[ 1 ];
this.selectedB = colorValues[ 2 ];
}
handlePalette( ev ) {
if ( ev.preventDefault ) {
ev.preventDefault();
}
app.selectedR = this.dataset.colorR;
app.selectedG = this.dataset.colorG;
app.selectedB = this.dataset.colorB;
}
handleCanvas( ev ) {
if ( ev.preventDefault ) {
ev.preventDefault();
}
let rect = app.canvas.getBoundingClientRect(),
scale = app.canvas.width / rect.width;
let mouseX = Math.floor( ( ev.clientX - rect.left ) * scale ),
mouseY = Math.floor( ( ev.clientY - rect.top ) * scale );
app.context.fillStyle = `rgba(${app.selectedR}, ${app.selectedG}, ${app.selectedB}, 1)`;
app.context.fillRect( mouseX, mouseY, 1, 1 );
}
}
let app = new App();