Basic Information

This page allows you to edit the existing project (Web Camera). The edited project will replace the existing entry in the IoT Projects page. If you want to add a new entry based on the project, please fork from it instead.

* Photo URLs that end with any one of .jpg, .jpeg, .png or that are uploaded to the Gyazo web service in the PNG format (e.g.https://gyazo.com/hogehoge) are supported.

{ "dependencies": { "twitter": "latest" } }

* Node.js entry point main: index.js and dependencies to the npm module dependencies: { f3js: (略) } will be automatically added and thus do not need to be in this form.

Card preview
Web Camera
'16/7/8 9:59
arc@dmz

Private Project

This project is already public and cannot be made private.

Source Code

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');
Customization

This content does not allow any customization.

Layout view options
Adding comments to variable declarations in the source code populate various GUI widgets in the "Customization" section depending on their types.

Design Alternatives

Modules

No modules are required for this project.

Layout
Program

Login first to use this feature.