Provide the source code of a microcontroller or tiny computer in JavaScript. Node.js-based computers are supported. Require f3js
package and use its API to design the device enclosure.
var dirPath = '/home/root/camera'
, f3js = require('f3js')
, Grove = require('jsupm_grove')
, CircularLED = require('jsupm_my9221').GroveCircularLED
, level = 0;
//, Twitter = require('twitter'); // FIXME
function execute(cmd, args, onEnd) {
var spawn = require('child_process').spawn
, child = spawn(cmd, args)
, me = this;
me.stdout = '';
me.stderr = '';
child.stdout.on('data', function (data) { me.stdout += data.toString(); });
child.stderr.on('data', function (data) { me.stderr += data.toString(); });
child.stdout.on('end', function () { if (onEnd) { onEnd(me); } });
}
function takePicture(callback) {
var filePath = dirPath + '/picture.jpg';
circularLED.setLevel(24);
new execute(
'fswebcam'
, ['--no-banner', '-r', '1920x1080', '-S', '30', filePath]
, function (me) {
circularLED.setLevel(level);
callback(filePath);
});
}
var thickness = 2 // thickness [1, 5]
, depth = 45
, button = new Grove.GroveButton(3)
, circularLED = new CircularLED(5, 4)
, oc = f3js.cc() // offset container
, front = oc.cc()
, rect = front.jrc(0, 0, 130, 77);
oc.x = 5;
oc.y = 5;
oc.add(front);
rect.jointWidth = 10;
rect.jointHeight = thickness;
front.add(circularLED, rect.width/2, rect.height/2 + 10);
front.rc(rect.width/2 - 10, 10, 20, 10);
var planes = rect.extrude(depth);
planes[4].x = 0;
planes[4].y = rect.height;
oc.add(planes[4]);
planes[0].x = 0;
planes[0].y = rect.height * 2;
oc.add(planes[0]);
planes[2].x = 0;
planes[2].y = rect.height * 2 + depth;
oc.add(planes[2]);
planes[1].x = 0;
planes[1].y = rect.height * 2 + depth * 2;
oc.add(planes[1]);
planes[3].x = rect.height - thickness;
planes[3].y = rect.height * 2 + depth * 2;
oc.add(planes[3]);
planes[0].c(rect.width / 2 - 15, 10, 4);
planes[0].c(rect.width / 2 + 15, 10, 4);
var cableHoleOffset = 2;
planes[1].rc(
5, depth - 10 - thickness * 2 - cableHoleOffset,
rect.height - 10, 10);
var bc = planes[1].add(button, 20, 15);
bc.rotation = 90;
var isTakingPicture = false;
function checkButtonPress() {
if (button.value() <= 0 || isTakingPicture) return;
console.log('take a picture via hardware request');
isTakingPicture = true;
takePicture(function (filePath) {
console.log('took a picture:', filePath);
isTakingPicture = false;
});
}
var http = require('http')
, url = require('url')
, path = require('path')
, fs = require('fs')
, mimeTypes = {
"html": "text/html"
, "jpeg": "image/jpeg"
, "jpg": "image/jpeg"
, "png": "image/png"
, "js": "text/javascript"
, "css": "text/css"};
function handleRequest(req, res){
var uri = url.parse(req.url).pathname
, filePath = path.join(dirPath, uri)
, stats;
if (uri.toLowerCase() === '/shoot') {
if (isTakingPicture) {
busy();
return;
}
console.log('take a picture via HTTP request');
takePicture(function (filePath) {
console.log('took a picture:', filePath);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('200 OK: took a picture\n');
res.end();
isTakingPicture = false;
});
return;
}
var setLevel = /\/set\/brightness\/([0-9]+)/.exec(uri);
if (setLevel) {
var l = parseInt(setLevel[1]);
if (l >= 0 && l <= 24) {
circularLED.setLevel(l);
level = l;
}
console.log('set level:', level);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('200 OK: set level to ' + level + '\n');
res.end();
return;
}
try {
stats = fs.lstatSync(filePath); // throws if path doesn't exist
} catch (e) {
return notFound();
}
if (stats.isFile()) {
var mimeType = mimeTypes[path.extname(filePath).split('.').reverse()[0]];
res.writeHead(200, { 'Content-Type': mimeType });
var fileStream = fs.createReadStream(filePath);
fileStream.pipe(res);
return;
}
return notFound();
function notFound() {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('404 Not Found: ' + filePath + '\n');
res.end();
}
function busy() {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('503 Service Unavailable\n');
res.end();
}
}
var server = http.createServer(handleRequest);
server.listen(8080, function(){
console.log('http server ready: listening on http://localhost:8080');
});
var handler = setInterval(checkButtonPress, 100);
console.log('camera ready: press the button to take a picture');