RaspberryPi B+でカメラモジュール使ってnode.jsとsocket.ioでストリーミング配信してみる
RaspberryPi B+でカメラモジュール使ってnode.jsとsocket.ioでストリーミング配信してみます。
純正カメラをつなげました。
ついでにネットワークがつながってるので、シリアルログインが不要のためmicroUSBケーブルで接続してます。
カメラの有効化を行います
# sudo raspi-config
下記を参考にさせて頂きます
Raspberry Pi, Camera and Node.js - Live Streaming with Websockets #IoT | The Jackal of Javascript
liveStreamingフォルダを作って、expressをsocket.io付きでinitします。
http://thejackalofjavascript.com/rpi-live-streaming/ pi@raspberrypi ~ $ cd httpd/ pi@raspberrypi ~/httpd $ ls sample pi@raspberrypi ~/httpd $ mkdir liveStreaming && cd liveStreaming pi@raspberrypi ~/httpd/liveStreaming $ ls pi@raspberrypi ~/httpd/liveStreaming $ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sane defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg> --save` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. name: (liveStreaming) liveStreaming version: (0.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC) About to write to /home/pi/httpd/liveStreaming/package.json: { "name": "liveStreaming", "version": "0.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } Is this ok? (yes) pi@raspberrypi ~/httpd/liveStreaming $ npm install express socket.io --save npm WARN package.json liveStreaming@0.0.0 No description npm WARN package.json liveStreaming@0.0.0 No repository field. npm WARN package.json liveStreaming@0.0.0 No README data npm http GET https://registry.npmjs.org/socket.io npm http GET https://registry.npmjs.org/express npm http 200 https://registry.npmjs.org/socket.io npm http 200 https://registry.npmjs.org/express npm http GET https://registry.npmjs.org/socket.io/-/socket.io-1.3.4.tgz npm http 200 https://registry.npmjs.org/socket.io/-/socket.io-1.3.4.tgz npm http GET https://registry.npmjs.org/engine.io npm http GET https://registry.npmjs.org/socket.io-parser npm http GET https://registry.npmjs.org/socket.io-client npm http GET https://registry.npmjs.org/socket.io-adapter npm http GET https://registry.npmjs.org/has-binary-data npm http GET https://registry.npmjs.org/debug npm http 200 https://registry.npmjs.org/has-binary-data npm http 200 https://registry.npmjs.org/debug npm http 200 https://registry.npmjs.org/socket.io-adapter npm http 200 https://registry.npmjs.org/socket.io-parser npm http 200 https://registry.npmjs.org/socket.io-client npm http GET https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.3.tgz npm http GET https://registry.npmjs.org/debug/-/debug-2.1.0.tgz npm http GET https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.3.1.tgz npm http GET https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.3.tgz npm http 200 https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.3.tgz npm http 200 https://registry.npmjs.org/engine.io npm http 200 https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.3.1.tgz npm http 200 https://registry.npmjs.org/debug/-/debug-2.1.0.tgz npm http GET https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.4.tgz npm http 200 https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.3.tgz npm http 200 https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.4.tgz npm http GET https://registry.npmjs.org/engine.io/-/engine.io-1.5.1.tgz npm http 200 https://registry.npmjs.org/engine.io/-/engine.io-1.5.1.tgz npm http GET https://registry.npmjs.org/methods npm http GET https://registry.npmjs.org/fresh npm http GET https://registry.npmjs.org/media-typer npm http GET https://registry.npmjs.org/on-finished npm http GET https://registry.npmjs.org/parseurl npm http GET https://registry.npmjs.org/path-to-regexp npm http GET https://registry.npmjs.org/proxy-addr npm http GET https://registry.npmjs.org/qs npm http GET https://registry.npmjs.org/range-parser npm http GET https://registry.npmjs.org/send npm http GET https://registry.npmjs.org/serve-static npm http GET https://registry.npmjs.org/type-is npm http GET https://registry.npmjs.org/vary npm http GET https://registry.npmjs.org/cookie npm http GET https://registry.npmjs.org/merge-descriptors npm http GET https://registry.npmjs.org/utils-merge npm http GET https://registry.npmjs.org/accepts npm http GET https://registry.npmjs.org/content-disposition npm http GET https://registry.npmjs.org/cookie-signature npm http GET https://registry.npmjs.org/depd npm http GET https://registry.npmjs.org/escape-html npm http GET https://registry.npmjs.org/etag npm http GET https://registry.npmjs.org/finalhandler npm http 304 https://registry.npmjs.org/methods npm http 304 https://registry.npmjs.org/on-finished npm http 304 https://registry.npmjs.org/fresh npm http 304 https://registry.npmjs.org/parseurl npm http 304 https://registry.npmjs.org/path-to-regexp npm http 304 https://registry.npmjs.org/range-parser npm http 200 https://registry.npmjs.org/proxy-addr npm http 200 https://registry.npmjs.org/qs npm http 304 https://registry.npmjs.org/vary npm http 304 https://registry.npmjs.org/media-typer npm http 304 https://registry.npmjs.org/cookie npm http 200 https://registry.npmjs.org/serve-static npm http 200 https://registry.npmjs.org/send npm http GET https://registry.npmjs.org/qs/-/qs-2.3.3.tgz npm http 304 https://registry.npmjs.org/utils-merge npm http 304 https://registry.npmjs.org/merge-descriptors npm http 200 https://registry.npmjs.org/cookie-signature npm http 304 https://registry.npmjs.org/content-disposition npm http 200 https://registry.npmjs.org/accepts npm http 200 https://registry.npmjs.org/qs/-/qs-2.3.3.tgz npm http 200 https://registry.npmjs.org/type-is npm http 304 https://registry.npmjs.org/depd npm http 304 https://registry.npmjs.org/escape-html npm http 304 https://registry.npmjs.org/etag npm http GET https://registry.npmjs.org/send/-/send-0.11.1.tgz npm http 304 https://registry.npmjs.org/finalhandler npm http GET https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz npm http 200 https://registry.npmjs.org/send/-/send-0.11.1.tgz npm http 200 https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz npm http GET https://registry.npmjs.org/accepts/-/accepts-1.2.4.tgz npm http 200 https://registry.npmjs.org/accepts/-/accepts-1.2.4.tgz npm http GET https://registry.npmjs.org/crc npm http GET https://registry.npmjs.org/ee-first npm http GET https://registry.npmjs.org/mime-types npm http GET https://registry.npmjs.org/negotiator npm http GET https://registry.npmjs.org/ipaddr.js npm http GET https://registry.npmjs.org/forwarded npm http 304 https://registry.npmjs.org/ee-first npm http 304 https://registry.npmjs.org/crc npm http 304 https://registry.npmjs.org/forwarded npm http 304 https://registry.npmjs.org/mime-types npm http 200 https://registry.npmjs.org/negotiator npm http 304 https://registry.npmjs.org/ipaddr.js npm http GET https://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz npm http GET https://registry.npmjs.org/object-keys npm http 200 https://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz npm http GET https://registry.npmjs.org/debug npm http GET https://registry.npmjs.org/socket.io-parser npm http GET https://registry.npmjs.org/destroy npm http GET https://registry.npmjs.org/mime npm http GET https://registry.npmjs.org/ms npm http 200 https://registry.npmjs.org/object-keys npm http 304 https://registry.npmjs.org/debug npm http 304 https://registry.npmjs.org/socket.io-parser npm http 304 https://registry.npmjs.org/destroy npm http 304 https://registry.npmjs.org/ms npm http 200 https://registry.npmjs.org/mime npm http GET https://registry.npmjs.org/object-keys/-/object-keys-1.0.1.tgz npm http GET https://registry.npmjs.org/debug/-/debug-1.0.2.tgz npm http GET https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz npm http GET https://registry.npmjs.org/mime/-/mime-1.2.11.tgz npm http 200 https://registry.npmjs.org/object-keys/-/object-keys-1.0.1.tgz npm http 200 https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz npm http 200 https://registry.npmjs.org/mime/-/mime-1.2.11.tgz npm http 200 https://registry.npmjs.org/debug/-/debug-1.0.2.tgz npm http GET https://registry.npmjs.org/json3 npm http GET https://registry.npmjs.org/component-emitter npm http GET https://registry.npmjs.org/isarray npm http GET https://registry.npmjs.org/benchmark npm http 200 https://registry.npmjs.org/isarray npm http GET https://registry.npmjs.org/debug/-/debug-0.7.4.tgz npm http 200 https://registry.npmjs.org/component-emitter npm http GET https://registry.npmjs.org/mime-db npm http 200 https://registry.npmjs.org/json3 npm http 200 https://registry.npmjs.org/benchmark npm http 200 https://registry.npmjs.org/debug/-/debug-0.7.4.tgz npm http 304 https://registry.npmjs.org/mime-db npm http GET https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz npm http GET https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz npm http GET https://registry.npmjs.org/json3/-/json3-3.2.6.tgz npm http GET https://registry.npmjs.org/benchmark/-/benchmark-1.0.0.tgz npm http 200 https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz npm http 200 https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz npm http 200 https://registry.npmjs.org/json3/-/json3-3.2.6.tgz npm http 200 https://registry.npmjs.org/benchmark/-/benchmark-1.0.0.tgz npm http GET https://registry.npmjs.org/ws npm http GET https://registry.npmjs.org/engine.io-parser npm http GET https://registry.npmjs.org/base64id npm http GET https://registry.npmjs.org/debug npm http 304 https://registry.npmjs.org/debug npm http 200 https://registry.npmjs.org/engine.io-parser npm http 200 https://registry.npmjs.org/ws npm http 200 https://registry.npmjs.org/base64id npm http GET https://registry.npmjs.org/debug/-/debug-1.0.3.tgz npm http GET https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz npm http GET https://registry.npmjs.org/ws/-/ws-0.5.0.tgz npm http GET https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz npm http 200 https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz npm http 200 https://registry.npmjs.org/debug/-/debug-1.0.3.tgz npm http 200 https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz npm http 200 https://registry.npmjs.org/ws/-/ws-0.5.0.tgz npm http GET https://registry.npmjs.org/ms npm http 304 https://registry.npmjs.org/ms npm http GET https://registry.npmjs.org/component-emitter npm http GET https://registry.npmjs.org/isarray npm http 304 https://registry.npmjs.org/isarray npm http 304 https://registry.npmjs.org/component-emitter npm http GET https://registry.npmjs.org/engine.io-client npm http GET https://registry.npmjs.org/component-bind npm http GET https://registry.npmjs.org/object-component npm http GET https://registry.npmjs.org/has-binary npm http GET https://registry.npmjs.org/indexof npm http GET https://registry.npmjs.org/parseuri npm http GET https://registry.npmjs.org/to-array npm http GET https://registry.npmjs.org/backo2 npm http GET https://registry.npmjs.org/debug npm http 200 https://registry.npmjs.org/object-component npm http 200 https://registry.npmjs.org/component-bind npm http 200 https://registry.npmjs.org/indexof npm http 200 https://registry.npmjs.org/to-array npm http 200 https://registry.npmjs.org/backo2 npm http 304 https://registry.npmjs.org/debug npm http 200 https://registry.npmjs.org/has-binary npm http 200 https://registry.npmjs.org/parseuri npm http GET https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz npm http GET https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz npm http GET https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz npm http 200 https://registry.npmjs.org/engine.io-client npm http GET https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz npm http GET https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz npm http 200 https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz npm http GET https://registry.npmjs.org/has-binary/-/has-binary-0.1.6.tgz npm http 200 https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz npm http 200 https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz npm http GET https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz npm http 200 https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz npm http 200 https://registry.npmjs.org/has-binary/-/has-binary-0.1.6.tgz npm http 200 https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz npm http GET https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.5.1.tgz npm http 200 https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz npm http 200 https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.5.1.tgz npm http GET https://registry.npmjs.org/ms npm http 304 https://registry.npmjs.org/ms npm http GET https://registry.npmjs.org/arraybuffer.slice npm http GET https://registry.npmjs.org/after npm http GET https://registry.npmjs.org/base64-arraybuffer npm http GET https://registry.npmjs.org/blob npm http GET https://registry.npmjs.org/utf8 npm http GET https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz npm http 200 https://registry.npmjs.org/base64-arraybuffer npm http 200 https://registry.npmjs.org/arraybuffer.slice npm http 200 https://registry.npmjs.org/after npm http 200 https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz npm http GET https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz npm http GET https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz npm http 200 https://registry.npmjs.org/blob npm http GET https://registry.npmjs.org/after/-/after-0.8.1.tgz npm http 200 https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz npm http 200 https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz npm http 200 https://registry.npmjs.org/after/-/after-0.8.1.tgz npm http GET https://registry.npmjs.org/blob/-/blob-0.0.2.tgz npm http 200 https://registry.npmjs.org/utf8 npm http 200 https://registry.npmjs.org/blob/-/blob-0.0.2.tgz npm http GET https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz npm http 200 https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz npm http GET https://registry.npmjs.org/better-assert npm http 200 https://registry.npmjs.org/better-assert npm http GET https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz npm http 200 https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz npm http GET https://registry.npmjs.org/nan npm http GET https://registry.npmjs.org/options npm http GET https://registry.npmjs.org/ultron npm http 200 https://registry.npmjs.org/options npm http GET https://registry.npmjs.org/options/-/options-0.0.6.tgz npm http 200 https://registry.npmjs.org/ultron npm http GET https://registry.npmjs.org/isarray npm http 200 https://registry.npmjs.org/nan npm http 200 https://registry.npmjs.org/options/-/options-0.0.6.tgz npm http 304 https://registry.npmjs.org/isarray npm http GET https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz npm http GET https://registry.npmjs.org/nan/-/nan-1.4.3.tgz npm http 200 https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz npm http 200 https://registry.npmjs.org/nan/-/nan-1.4.3.tgz npm http GET https://registry.npmjs.org/callsite npm http 200 https://registry.npmjs.org/callsite npm http GET https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz npm http 200 https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz npm http GET https://registry.npmjs.org/parsejson npm http GET https://registry.npmjs.org/parseqs npm http GET https://registry.npmjs.org/component-inherit npm http GET https://registry.npmjs.org/has-cors npm http GET https://github.com/rase-/node-XMLHttpRequest/archive/a6b6f2.tar.gz npm http GET https://registry.npmjs.org/ws npm http GET https://registry.npmjs.org/engine.io-parser npm http GET https://registry.npmjs.org/debug npm http GET https://registry.npmjs.org/parseuri npm http 200 https://registry.npmjs.org/has-cors npm http 200 https://registry.npmjs.org/parseqs npm http 304 https://registry.npmjs.org/engine.io-parser npm http 200 https://registry.npmjs.org/parsejson npm http 304 https://registry.npmjs.org/ws npm http 200 https://registry.npmjs.org/component-inherit npm http 304 https://registry.npmjs.org/debug npm http 304 https://registry.npmjs.org/parseuri npm http GET https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz npm http GET https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz npm http GET https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz npm http GET https://registry.npmjs.org/ws/-/ws-0.4.31.tgz npm http GET https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz npm http GET https://registry.npmjs.org/debug/-/debug-1.0.4.tgz npm http GET https://registry.npmjs.org/parseuri/-/parseuri-0.0.4.tgz npm http 200 https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz npm http 200 https://registry.npmjs.org/debug/-/debug-1.0.4.tgz npm http 200 https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz npm http 200 https://registry.npmjs.org/ws/-/ws-0.4.31.tgz npm http 200 https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz npm http 200 https://registry.npmjs.org/parseuri/-/parseuri-0.0.4.tgz npm http 200 https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz npm http 200 https://github.com/rase-/node-XMLHttpRequest/archive/a6b6f2.tar.gz npm http GET https://registry.npmjs.org/isarray npm http 200 https://registry.npmjs.org/nan/-/nan-0.3.2.tgz > ws@0.4.31 install /home/pi/httpd/liveStreaming/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws > (node-gyp rebuild 2> builderror.log) || (exit 0) make: Entering directory '/home/pi/httpd/liveStreaming/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build' CXX(target) Release/obj.target/bufferutil/src/bufferutil.o SOLINK_MODULE(target) Release/obj.target/bufferutil.node SOLINK_MODULE(target) Release/obj.target/bufferutil.node: Finished COPY Release/bufferutil.node CXX(target) Release/obj.target/validation/src/validation.o SOLINK_MODULE(target) Release/obj.target/validation.node SOLINK_MODULE(target) Release/obj.target/validation.node: Finished COPY Release/validation.node make: Leaving directory '/home/pi/httpd/liveStreaming/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build' express@4.11.2 node_modules/express ├── utils-merge@1.0.0 ├── merge-descriptors@0.0.2 ├── methods@1.1.1 ├── fresh@0.2.4 ├── cookie@0.1.2 ├── escape-html@1.0.1 ├── range-parser@1.0.2 ├── cookie-signature@1.0.5 ├── finalhandler@0.3.3 ├── vary@1.0.0 ├── media-typer@0.3.0 ├── parseurl@1.3.0 ├── serve-static@1.8.1 ├── content-disposition@0.5.0 ├── path-to-regexp@0.1.3 ├── depd@1.0.0 ├── on-finished@2.2.0 (ee-first@1.1.0) ├── qs@2.3.3 ├── debug@2.1.1 (ms@0.6.2) ├── proxy-addr@1.0.6 (forwarded@0.1.0, ipaddr.js@0.1.8) ├── etag@1.5.1 (crc@3.2.1) ├── send@0.11.1 (destroy@1.0.3, ms@0.7.0, mime@1.2.11) ├── type-is@1.5.7 (mime-types@2.0.9) └── accepts@1.2.4 (negotiator@0.5.1, mime-types@2.0.9) socket.io@1.3.4 node_modules/socket.io ├── debug@2.1.0 (ms@0.6.2) ├── has-binary-data@0.1.3 (isarray@0.0.1) ├── socket.io-parser@2.2.3 (isarray@0.0.1, debug@0.7.4, component-emitter@1.1.2, benchmark@1.0.0, json3@3.2.6) ├── socket.io-adapter@0.3.1 (object-keys@1.0.1, debug@1.0.2, socket.io-parser@2.2.2) ├── engine.io@1.5.1 (base64id@0.1.0, debug@1.0.3, engine.io-parser@1.2.1, ws@0.5.0) └── socket.io-client@1.3.4 (to-array@0.1.3, indexof@0.0.1, component-bind@1.0.0, debug@0.7.4, backo2@1.0.2, object-component@0.0.3, component-emitter@1.1.2, has-binary@0.1.6, parseuri@0.0.2, engine.io-client@1.5.1)
準備完了したら、
index.js(サーバー側)とindex.html(クライアント側)を作成します。
index.js
var express = require('express'); var app = express(); var http = require('http').Server(app); var io = require('socket.io')(http); var fs = require('fs'); var path = require('path'); var spawn = require('child_process').spawn; var proc; var dateformat = require("dateformat"); app.use('/', express.static(path.join(__dirname, 'stream'))); app.get('/', function(req, res) { res.sendFile(__dirname + '/index.html'); }); var sockets = {}; io.on('connection', function(socket) { sockets[socket.id] = socket; console.log("Total clients connected : ", Object.keys(sockets).length); socket.on('disconnect', function() { delete sockets[socket.id]; // no more sockets, kill the stream if (Object.keys(sockets).length == 0) { app.set('watchingFile', false); if (proc) proc.kill(); fs.unwatchFile('./stream/image_stream.jpg'); } }); socket.on('start-stream', function() { startStreaming(io); }); }); http.listen(3000, function() { console.log('listening on *:3000'); }); function stopStreaming() { if (Object.keys(sockets).length == 0) { app.set('watchingFile', false); if (proc) proc.kill(); fs.unwatchFile('./stream/image_stream.jpg'); } } function startStreaming(io) { if (app.get('watchingFile')) { io.sockets.emit('liveStream', {url:'image_stream.jpg?_t=' + (Math.random() * 100000), time:dateformat(new Date(), "yyyy/mm/dd HH:MM:ss")}); return; } var args = ["-bm", "-w", "320", "-h", "240", "-o", __dirname + "/stream/image_stream.jpg", "-t", "999999999", "-tl", "500", "--nopreview"]; proc = spawn('raspistill', args); console.log('Watching for changes...'); app.set('watchingFile', true); fs.watchFile(__dirname+'/stream/image_stream.jpg', function(current, previous) { console.log('emmit liveStewam'); io.sockets.emit('liveStream', {url:'image_stream.jpg?_t=' + (Math.random() * 100000), time:dateformat(new Date(), "yyyy/mm/dd HH:MM:ss")}); }) proc.stdout.on('data', function(data) { console.log('stdout: ' + data); }) proc.stderr.on('data', function(data) { console.log('stderr: ' + data); }) proc.on('exit', function(code) { console.log('exit code: ' + code); }) }
spawnでraspistillコマンドを実行してストリーミングします。
その後、fs.watchFileで、image_stream.jpgを監視。
変更があったら、io.sockets.emitで画像URLと更新時間を送付します。
proc = spawn('raspistill', args); console.log('Watching for changes...'); app.set('watchingFile', true); fs.watchFile(__dirname+'/stream/image_stream.jpg', function(current, previous) { console.log('emmit liveStewam'); io.sockets.emit('liveStream', {url:'image_stream.jpg?_t=' + (Math.random() * 100000), time:dateformat(new Date(), "yyyy/mm/dd HH:MM:ss")});
raspistillコマンドの - tl 500 は電圧等の関係で値調整が必要ですのでご注意を。
次にindex.html(クライアント側)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>the view from my office </title> <!-- Bootstrap CSS --> <link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"> <style type="text/css"> #stream { height: 99%; margin: 0px auto; display: block; margin-top: 20px; } </style> <!-- jQuery --> <script src="http://code.jquery.com/jquery.js"></script> <!-- Bootstrap JavaScript --> <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script> <script src="/socket.io/socket.io.js"></script> <script> var socket = io(); socket.on('liveStream', function(data) { $('#stream').attr('src', data.url); $('#timetext').text(data.time); $('.start').hide(); }); function startStream() { socket.emit('start-stream'); $('.start').hide(); } </script> </head> <body class="container"> <h1 class="text-center">the view from my office <small>Powered by PI</small> </h1> <hr> <button type="button" id="" class="btn btn-info start" onclick="startStream()">Start Camera</button> <div class="row"> <img src="" id="stream"> </div> <div id="timetext" class="text-center"></div> </body> </html>
最初にstartStreamで、socket.emitで、"start-stream"を送付します。
後は、socket.onで、"liveStream"を受け取り画像と更新時間を再描画。
socket.on('liveStream', function(data) { $('#stream').attr('src', data.url); $('#timetext').text(data.time); $('.start').hide(); }); function startStream() { socket.emit('start-stream'); $('.start').hide();
node.jsってこんなに簡単にコーティング出来る。感動。
nohup node ./httpd/liveStreaming/index.js &
で起動します。
ターミナル閉じたいのでnohup にしました。
startCameraをクリック
オフィスというか僕のデスクからの外の景色です。
ちなみにカメラのびよ~んの奴がうまい事向きを調整できずに逆さカメラになっております
RaspberryPi
気がついたらRaspberryPi2が発売されてましたが、
RaspberryPi B+を購入しました。
RaspberryPi2では、Windows10も提供って事でIoT周りがドンドン盛り上がってきてます。
「Raspberry Pi 2」にWindows 10が無償提供されることが決定 - GIGAZINE
動かすに当たって、RaspberryPi だけではダメで色々と必要です。
・シリアル接続のコード
ディスプレイやキーボードを持ってればいいけど持ってなかったので。普通持ってないよね?
Amazon.co.jp: Raspberry Pi Arduino PL2303HX内蔵USBシリアル変換ケーブル: パソコン・周辺機器
・OSインストール済みSDカード
普通、SDカードが読めるPCって持ってないよね。
Amazon.co.jp: debian OS for Raspberry Pi (Raspbian), OSインストール済み SDカード (microSDHC 32GB Class 6 (SDカードアダプタ付)): パソコン・周辺機器
・wifiアダプター
これも最近、ネットワークケーブルって周りに出てないでしょ
Amazon.co.jp: PLANEX 無線LAN子機 (USBアダプター型) 11n/g/b 150Mbps GW-USNANO2A (FFP): パソコン・周辺機器
って形で色々と揃える必要があります。
写真の様な形で接続して、下記からドライバーをDLしてインストールします。
http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=225&pcid=41
マニュアルに書いてある通り、自動でセットアップされたドライバーを削除して、このドライバーをインストールする必要がありました。
1.telnetで接続です。teratermを使いました。
接続後、シリアルのレートをraspberryPiに合わせて115200に変更します。
無事に接続されます!
こんな小さいのみ普通にLinuxが動いている事に感動です。
2.wifi設定
/etc/network/interfacesを編集
iface wlan0 inet dhcp
#iface wlan0 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
#wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp
/etc/wpa_supplicant/wpa_supplicant.confを編集
network={ ssid="YOUR_NETWORK_NAME" psk="YOUR_NETWORK_PASSWORD" proto=WPA2 key_mgmt=WPA-PSK }
最後に
sudo ifdown wlan0
sudo ifup wlan0
で完了です。
ifconfigでwlan0 のIPを確認して、PCからsshも繋がりました。
3.node.jsを入れてみる
最初にnode.jsのバーション管理のnodebrewを入れます。
pi@raspberrypi:~$ curl -L git.io/nodebrew | perl - setup % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0 100 22630 100 22630 0 0 10503 0 0:00:02 0:00:02 --:--:-- 920k fetching nodebrew... install nodebrew in $HOME/.nodebrew ======================================== Add path: export PATH=$HOME/.nodebrew/current/bin:$PATH ========================================
言われた通り環境変数追加
pi@raspberrypi:~$ vi ~/.bashrc export PATH=$HOME/.nodebrew/current/bin:$PATH pi@raspberrypi:~$ source ~/.bashrc
ということでnode.jsインストール
pi@raspberrypi:~$ nodebrew install-binary 0.10.28 fetch: http://nodejs.org/dist/v0.10.28/node-v0.10.28-linux-arm-pi.tar.gz ######################################################################## 100.0% 36.9% Install successful pi@raspberrypi:~$ nodebrew use 0.10.28 use v0.10.28 pi@raspberrypi:~$ node -v v0.10.28
expressでwebサーバー化
pi@raspberrypi ~ $ npm install -g express-generator npm http GET https://registry.npmjs.org/express-generator npm http 200 https://registry.npmjs.org/express-generator npm http GET https://registry.npmjs.org/express-generator/-/express-generator-4.11.2.tgz npm http 200 https://registry.npmjs.org/express-generator/-/express-generator-4.11.2.tgz npm http GET https://registry.npmjs.org/commander npm http GET https://registry.npmjs.org/mkdirp npm http GET https://registry.npmjs.org/sorted-object npm http 200 https://registry.npmjs.org/mkdirp npm http 200 https://registry.npmjs.org/sorted-object npm http 200 https://registry.npmjs.org/commander npm http GET https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz npm http GET https://registry.npmjs.org/sorted-object/-/sorted-object-1.0.0.tgz npm http GET https://registry.npmjs.org/commander/-/commander-2.6.0.tgz npm http 200 https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz npm http 200 https://registry.npmjs.org/sorted-object/-/sorted-object-1.0.0.tgz npm http 200 https://registry.npmjs.org/commander/-/commander-2.6.0.tgz npm http GET https://registry.npmjs.org/minimist npm http 200 https://registry.npmjs.org/minimist npm http GET https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz npm http 200 https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz /home/pi/.nodebrew/current/bin/express -> /home/pi/.nodebrew/current/lib/node_modules/express-generator/bin/express express-generator@4.11.2 /home/pi/.nodebrew/current/lib/node_modules/express-generator ├── sorted-object@1.0.0 ├── commander@2.6.0 └── mkdirp@0.5.0 (minimist@0.0.8) pi@raspberrypi ~ $ pi@raspberrypi:~$ vi ~/.bashrc 追加 export PATH=$HOME/.nodebrew/current/bin:$PATH export PATH=$HOME/.nodebrew/node/v0.10.28/bin/express:$PATH export NODE_PATH=$HOME/.nodebrew/node/v0.10.28/lib/node_modules pi@raspberrypi:~$ source ~/.bashrc pi@raspberrypi:~$ mkdir httpd pi@raspberrypi:~$ cd httpd pi@raspberrypi ~/httpd $ express -e sample create : sample create : sample/package.json create : sample/app.js create : sample/public create : sample/public/javascripts create : sample/public/images create : sample/public/stylesheets create : sample/public/stylesheets/style.css create : sample/routes create : sample/routes/index.js create : sample/routes/users.js create : sample/views create : sample/views/index.ejs create : sample/views/error.ejs create : sample/bin create : sample/bin/www install dependencies: $ cd sample && npm install run the app: $ DEBUG=sample:* ./bin/www pi@raspberrypi ~/httpd $ pi@raspberrypi ~/httpd $ cd sample && npm install npm http GET https://registry.npmjs.org/body-parser npm http GET https://registry.npmjs.org/cookie-parser npm http GET https://registry.npmjs.org/ejs npm http GET https://registry.npmjs.org/morgan npm http GET https://registry.npmjs.org/serve-favicon npm http GET https://registry.npmjs.org/debug npm http GET https://registry.npmjs.org/express npm http 200 https://registry.npmjs.org/cookie-parser npm http 200 https://registry.npmjs.org/serve-favicon npm http 304 https://registry.npmjs.org/debug npm http 304 https://registry.npmjs.org/express npm http 200 https://registry.npmjs.org/morgan npm http 200 https://registry.npmjs.org/ejs npm http 200 https://registry.npmjs.org/body-parser npm http GET https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.2.0.tgz npm http GET https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.3.tgz npm http GET https://registry.npmjs.org/morgan/-/morgan-1.5.1.tgz npm http 200 https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.2.0.tgz npm http GET https://registry.npmjs.org/ejs/-/ejs-2.2.4.tgz npm http 200 https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.3.tgz npm http GET https://registry.npmjs.org/body-parser/-/body-parser-1.10.2.tgz npm http 200 https://registry.npmjs.org/ejs/-/ejs-2.2.4.tgz npm http 200 https://registry.npmjs.org/morgan/-/morgan-1.5.1.tgz npm http 200 https://registry.npmjs.org/body-parser/-/body-parser-1.10.2.tgz npm http GET https://registry.npmjs.org/etag npm http GET https://registry.npmjs.org/fresh npm http GET https://registry.npmjs.org/ms npm http GET https://registry.npmjs.org/parseurl npm http GET https://registry.npmjs.org/cookie npm http GET https://registry.npmjs.org/cookie-signature npm http 304 https://registry.npmjs.org/fresh npm http 304 https://registry.npmjs.org/etag npm http 304 https://registry.npmjs.org/cookie-signature npm http 304 https://registry.npmjs.org/ms npm http 304 https://registry.npmjs.org/parseurl npm http 304 https://registry.npmjs.org/cookie npm http GET https://registry.npmjs.org/basic-auth npm http GET https://registry.npmjs.org/depd npm http GET https://registry.npmjs.org/on-finished npm http 200 https://registry.npmjs.org/basic-auth npm http 304 https://registry.npmjs.org/on-finished npm http 304 https://registry.npmjs.org/depd npm http GET https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.0.tgz npm http 200 https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.0.tgz npm http GET https://registry.npmjs.org/bytes npm http GET https://registry.npmjs.org/iconv-lite npm http GET https://registry.npmjs.org/raw-body npm http GET https://registry.npmjs.org/media-typer npm http GET https://registry.npmjs.org/qs npm http GET https://registry.npmjs.org/type-is npm http 200 https://registry.npmjs.org/raw-body npm http 200 https://registry.npmjs.org/bytes npm http 304 https://registry.npmjs.org/media-typer npm http 304 https://registry.npmjs.org/type-is npm http 200 https://registry.npmjs.org/iconv-lite npm http 304 https://registry.npmjs.org/qs npm http GET https://registry.npmjs.org/raw-body/-/raw-body-1.3.2.tgz npm http GET https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz npm http GET https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.6.tgz npm http 200 https://registry.npmjs.org/raw-body/-/raw-body-1.3.2.tgz npm http 200 https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz npm http 200 https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.6.tgz npm http GET https://registry.npmjs.org/crc npm http 304 https://registry.npmjs.org/crc npm http GET https://registry.npmjs.org/ee-first npm http 304 https://registry.npmjs.org/ee-first npm http GET https://registry.npmjs.org/on-finished npm http GET https://registry.npmjs.org/parseurl npm http GET https://registry.npmjs.org/methods npm http GET https://registry.npmjs.org/range-parser npm http GET https://registry.npmjs.org/type-is npm http GET https://registry.npmjs.org/send npm http GET https://registry.npmjs.org/cookie npm http GET https://registry.npmjs.org/serve-static npm http GET https://registry.npmjs.org/vary npm http GET https://registry.npmjs.org/merge-descriptors npm http GET https://registry.npmjs.org/utils-merge npm http GET https://registry.npmjs.org/accepts npm http GET https://registry.npmjs.org/cookie-signature npm http GET https://registry.npmjs.org/content-disposition npm http GET https://registry.npmjs.org/depd npm http GET https://registry.npmjs.org/escape-html npm http GET https://registry.npmjs.org/etag npm http GET https://registry.npmjs.org/fresh npm http GET https://registry.npmjs.org/finalhandler npm http GET https://registry.npmjs.org/media-typer npm http GET https://registry.npmjs.org/path-to-regexp npm http GET https://registry.npmjs.org/proxy-addr npm http 304 https://registry.npmjs.org/on-finished npm http 304 https://registry.npmjs.org/parseurl npm http 304 https://registry.npmjs.org/send npm http 304 https://registry.npmjs.org/methods npm http 304 https://registry.npmjs.org/cookie npm http 304 https://registry.npmjs.org/range-parser npm http 304 https://registry.npmjs.org/vary npm http 304 https://registry.npmjs.org/serve-static npm http 304 https://registry.npmjs.org/merge-descriptors npm http 304 https://registry.npmjs.org/utils-merge npm http 304 https://registry.npmjs.org/type-is npm http 304 https://registry.npmjs.org/accepts npm http 304 https://registry.npmjs.org/cookie-signature npm http 304 https://registry.npmjs.org/content-disposition npm http 304 https://registry.npmjs.org/depd npm http 304 https://registry.npmjs.org/escape-html npm http 304 https://registry.npmjs.org/etag npm http 304 https://registry.npmjs.org/fresh npm http 304 https://registry.npmjs.org/finalhandler npm http 304 https://registry.npmjs.org/media-typer npm http 304 https://registry.npmjs.org/path-to-regexp npm http 304 https://registry.npmjs.org/proxy-addr npm http GET https://registry.npmjs.org/crc npm http GET https://registry.npmjs.org/ee-first npm http GET https://registry.npmjs.org/mime-types npm http GET https://registry.npmjs.org/negotiator npm http GET https://registry.npmjs.org/mime-types npm http GET https://registry.npmjs.org/forwarded npm http GET https://registry.npmjs.org/ipaddr.js npm http 304 https://registry.npmjs.org/crc npm http 304 https://registry.npmjs.org/forwarded npm http 304 https://registry.npmjs.org/ee-first npm http 304 https://registry.npmjs.org/ipaddr.js npm http 304 https://registry.npmjs.org/mime-types npm http 304 https://registry.npmjs.org/negotiator npm http 304 https://registry.npmjs.org/mime-types npm http GET https://registry.npmjs.org/destroy npm http GET https://registry.npmjs.org/ms npm http GET https://registry.npmjs.org/mime npm http 304 https://registry.npmjs.org/ms npm http 304 https://registry.npmjs.org/destroy npm http 304 https://registry.npmjs.org/mime npm http GET https://registry.npmjs.org/mime-db npm http 304 https://registry.npmjs.org/mime-db npm http GET https://registry.npmjs.org/ee-first npm http GET https://registry.npmjs.org/mime-types npm http 304 https://registry.npmjs.org/ee-first npm http 304 https://registry.npmjs.org/mime-types cookie-parser@1.3.3 node_modules/cookie-parser ├── cookie@0.1.2 └── cookie-signature@1.0.5 debug@2.1.1 node_modules/debug └── ms@0.6.2 morgan@1.5.1 node_modules/morgan ├── basic-auth@1.0.0 ├── depd@1.0.0 └── on-finished@2.2.0 (ee-first@1.1.0) serve-favicon@2.2.0 node_modules/serve-favicon ├── fresh@0.2.4 ├── ms@0.7.0 ├── parseurl@1.3.0 └── etag@1.5.1 (crc@3.2.1) ejs@2.2.4 node_modules/ejs express@4.11.2 node_modules/express ├── merge-descriptors@0.0.2 ├── utils-merge@1.0.0 ├── methods@1.1.1 ├── cookie@0.1.2 ├── fresh@0.2.4 ├── escape-html@1.0.1 ├── range-parser@1.0.2 ├── cookie-signature@1.0.5 ├── finalhandler@0.3.3 ├── vary@1.0.0 ├── media-typer@0.3.0 ├── parseurl@1.3.0 ├── serve-static@1.8.1 ├── content-disposition@0.5.0 ├── path-to-regexp@0.1.3 ├── depd@1.0.0 ├── on-finished@2.2.0 (ee-first@1.1.0) ├── qs@2.3.3 ├── proxy-addr@1.0.6 (forwarded@0.1.0, ipaddr.js@0.1.8) ├── etag@1.5.1 (crc@3.2.1) ├── send@0.11.1 (destroy@1.0.3, ms@0.7.0, mime@1.2.11) ├── accepts@1.2.3 (negotiator@0.5.0, mime-types@2.0.9) └── type-is@1.5.7 (mime-types@2.0.9) body-parser@1.10.2 node_modules/body-parser ├── media-typer@0.3.0 ├── bytes@1.0.0 ├── raw-body@1.3.2 ├── depd@1.0.0 ├── on-finished@2.2.0 (ee-first@1.1.0) ├── qs@2.3.3 ├── type-is@1.5.7 (mime-types@2.0.9) └── iconv-lite@0.4.6 pi@raspberrypi ~/httpd/sample $ pi@raspberrypi ~/httpd/sample $ node app 依存モジュールを入れる pi@raspberrypi ~/httpd/sample $ express -V 4.11.2 pi@raspberrypi ~/httpd/sample $ npm start > sample@0.0.0 start /home/pi/httpd/sample > node ./bin/www
無事動いた。パチパチ。
この後色々とやってみます。楽しみ。
VBAでWinHttp.WinHttpRequestで画面引き継ぐには、Keep-Aliveが必要だった
Web上のログイン画面とか色々とexcelVBAでちょちょいと調べたりする事あるじゃないですか。
で、WEBAPIを叩いてたですが、
1番目のapiでcodeを取得して、そのcodeで
2番目のapiを叩くみたいな処理をexcelVBAで作ってたら、何故かエラー。
Dim url As String Const app_id = "AAA" Const secret = "BBB" url = "https://hoge.com/v1/oauth?app_id=" & app_id Dim xmlhttp As Object Dim xNode As Object Dim xNode2 As Object Dim retCd As String Dim xdoc As Object Dim code As String Dim AccessToken As String Set xmlhttp = CreateObject("WinHttp.WinHttpRequest.5.1") xmlhttp.Open "GET", url, False xmlhttp.send (Null) retCd = xmlhttp.Status '結果コード取得 If retCd <> 200 Then Debug.Print "error:" & retCd Exit Sub Else Debug.Print xmlhttp.getAllResponseHeaders() 'Debug.Print StrConv(xmlhttp.responsebody, vbUnicode) code = getValueFromXml(StrConv(xmlhttp.responsebody, vbUnicode), "Code") End If url = "https://hoge.com/v1/token" xmlhttp.Open "POST", url, False xmlhttp.SetRequestHeader "Content-Type", "application/x-www-form-urlencoded" Dim postData As Variant postData = "grant_type=oauth_code&app_id=" & app_id & "&secret=" & secret & "&code=" & code xmlhttp.send ("grant_type=oauth_code&app_id=" & app_id & "&secret=" & secret & "&code=" & code)
全くうまく行かない。
ブラウザでやるとうまくいきます。
最初cookieと思って、レスポンスヘッダーを調べてみたら何も入ってない!
なんだ!
と色々と悩んだ結果、Keep-Aliveを設定したら動いたというオチ。
xmlhttp.SetRequestHeader "Connection", "Keep-Alive"
こんな事あるんだ。
2時間返せ
Unimedia モンゴルアプリコンテスト2014!
1月24日にUnimedia モンゴルアプリコンテスト2014!の決勝戦を行いました。
■Service/Tool部門
1-位 iLamp(D.Amartuvshin)
buletoothでLEDとスマフォを繋いでコントロールするアプリです。
日本でもスピーカー付きが7000円とかで発売されてますが、安価に開発出来ればニーズはありそうです。
なにより自分でマイクロチップ使って、LEDと配線してるのを見て感動しました。
2-位 Happy Baby2.0(Happy Baby)
この二人は昨年も応募してくれてて、しかも去年と同じくお子さんを授かってました。モンゴル人数増加で国安泰ですね(w
赤ちゃんの成長を記録するアプリです。
googleのmaterial designでUIが作られてて非常に綺麗でした。
3-位 Smart Hand Driver(S.Khangal)
こちらは、入力が難しいモンゴルのキリル文字の入力アプリです。
タイプではなくてドラッグして文字入力できるアプリです。
■Game部門
1-位 Spelling Sheep(Batkholboo)
タイピングゲーム。スペルを間違えたり、タイピングが遅かったら、フェンスの中の可愛い羊たちが狼にとらわれるゲーム。
キャラクターを写真から起こしてるという事で非常に綺麗なグラフィックでした。
2-位 Pill heals(Pill heals)
薬が患部へ到着させる事をコンセプトにしたジャイロゲームです。途中さまざまなウィルスが邪魔をします。
結構はまります(w
3-位 Apipo(Usukhbayar)
VR技術を使ったゲーム。画面から出てきた色に対して、同色の色のリアルカードで対応させます。
最後に記念撮影
IoTでbluetoothだったり、VR、3Dゲームや、material design等のアプリが沢山応募ありました。
昨年よりも格段レベルが高くなってきてます。
この中から幾つが製品化される物も出ると思います。今後も楽しみです。
次回は今年の11月頃を予定してますが、次回は大学でのunimediaラボからも応募が来ると思うので更にレベルアップが期待出来そうです。
littleBit
IoTという事でlittleBit入手しました。
磁石でブロックを組み立てる感じで出来るのが売りです。
Arduinoの様な配線は必要ありません。
サイトも用意されてます。
littleBits Cloud Control
ここでセットアップする事ができます。
アプリ名を入力
ランプが点灯するまで待ちます。
littleBitはLinuxが入ってるので起動まで時間が掛かります。
次にwifiでlittleBitに接続します。wifiまで最初から実装って凄いですね。
つなぐとwifi設定画面に移行します。
これでlittleBit自体がwifi接続可能になります。
完了すると管理画面みたいなのに遷移します。
これからテストです
次にボタンを繋ぎます。単純に磁石でくっつけるだけです。
その後グリーンになるまで待ちます
次は、LEDをつないで、同じでグリーンになるまで待ちます。
ここでWEB側でボタンを押すとLEDが点灯します!
littleBitがサイトにアクセスしてボタンの状態を取得してる様ですね。
次は、ボタン状態がメーター表示される。
押すとバーが動きました
これで一通り完了です。
IFTTTと連携出来るんですね。
littleBitチャンネルがあって沢山のアプリがあります。
最後に完成写真です。
littleBitはプログラミングは出来ないみたいですが、
IFTTT経由だったり、Arudinoもモジュールも発売されてます。
米ドル為替チェックアプリ作成! by ArduinoとProcessing
昨年買ったArduinoで米ドル為替チェックアプリ作成してみました。
先ずはProcessingを入手します。
https://processing.org/download/
最新版は、processing-2.2.1でした。
これでproccesingがネット情報のデータを取得して、シリアルポート経由でArduinoと通信できる訳です。
proccesingはjavaで書けます。
シリアルポートの通信もこんな感じです。
port = new Serial(this, arduinoPort, 9600); // connect to Arduino
yahooからUSDJPYのデータを取得して、その後パースします。
String url = "http://info.finance.yahoo.co.jp/fx/detail/?code=USDJPY=FX"; String[] lines = loadStrings(url); // Turn array into one long String String xml = join(lines, "" );
以下全ソースコード
import processing.serial.*; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.StringTokenizer; import processing.serial.*; int interval = 10; // retrieve feed every 60 seconds; int lastTime; // the last time we fetched the content int light = 0; // light level measured by the lamp Serial port; color c; String cs; String doll; String doll_old; String buffer = ""; // Accumulates characters coming from Arduino PFont font; void setup() { size(640, 480); frameRate(10); // we don't need fast updates font = loadFont("HelveticaNeue-Bold-32.vlw"); fill(255); textFont(font, 32); // IMPORTANT NOTE: // The first serial port retrieved by Serial.list() // should be your Arduino. If not, uncomment the next // line by deleting the // before it, and re-run the // sketch to see a list of serial ports. Then, change // the 0 in between [ and ] to the number of the port // that your Arduino is connected to. //println(Serial.list()); String arduinoPort = Serial.list()[0]; port = new Serial(this, arduinoPort, 9600); // connect to Arduino lastTime = 0; fetchData(); } void draw() { background( c ); int n = (interval - ((millis()-lastTime)/1000)); int up=0; int stay=0; int down=0; if(Float.parseFloat(doll) > Float.parseFloat(doll_old)){ up = 255; }else if(Float.parseFloat(doll) < Float.parseFloat(doll_old)){ down = 255; }else{ stay = 255; } // Build a colour based on the 3 values c = color(up, stay, down); cs = "#" + hex(c, 6); // Prepare a string to be sent to Arduino text("Arduino Networked Lamp", 10, 40); text("Reading $doll:", 10, 100); text(doll, 10, 140); text("Next update in "+ n + " seconds", 10, 450); text("up", 10, 200); text(" " + up, 130, 200); rect(200, 172, up, 28); text("down ", 10, 240); text(" " + down, 130, 240); rect(200, 212, down, 28); text("stay ", 10, 280); text(" " + stay, 130, 280); rect(200, 252, stay, 28); // write the colour string to the screen text("sending", 10, 340); text(cs, 200, 340); text("light level", 10, 380); rect(200, 352, light/10.23, 28); // this turns 1023 into 100 if (n <= 0) { fetchData(); lastTime = millis(); } port.write(cs); // send data to Arduino if (port.available() > 0) { // check if there is data waiting int inByte = port.read(); // read one byte if (inByte != 10) { // if byte is not newline buffer = buffer + char(inByte); // just add it to the buffer } else { // newline reached, let's process the data if (buffer.length() > 1) { // make sure there is enough data // chop off the last character, it's a carriage return // (a carriage return is the character at the end of a // line of text) buffer = buffer.substring(0, buffer.length() -1); // turn the buffer from string into an integer number light = int(buffer); // clean the buffer for the next read cycle buffer = ""; // We're likely falling behind in taking readings // from Arduino. So let's clear the backlog of // incoming sensor readings so the next reading is // up-to-date. port.clear(); } } } } void fetchData() { try { doll_old = doll; // Get all the HTML/XML source code into an array of strings // (each line is one element in the array) String url = "http://info.finance.yahoo.co.jp/fx/detail/?code=USDJPY=FX"; String[] lines = loadStrings(url); // Turn array into one long String String xml = join(lines, "" ); String lookfor = "<dd id=\"USDJPY_detail_bid\">"; String end = "</span>"; doll = giveMeTextBetween(xml,lookfor,end); doll = doll.replace("<span class=\"large\">", ""); if(doll_old==null) doll_old = doll; System.out.println(doll); } catch(Exception e){ e.printStackTrace(); System.out.println("ERROR: "+e.getMessage()); } } // A function that returns a substring between two substrings String giveMeTextBetween(String s, String before, String after) { String found = ""; int start = s.indexOf(before); // Find the index of the beginning tag if (start == - 1) return""; // If we don't find anything, send back a blank String start += before.length(); // Move to the end of the beginning tag int end = s.indexOf(after,start); // Find the index of the end tag if (end == -1) return""; // If we don't find the end tag, send back a blank String return s.substring(start,end); // Return the text in between }
こちらは、Arduino側です。「Arduinoをはじめよう」のサンプルそのままです。
const int SENSOR = 0; const int R_LED = 9; const int G_LED = 10; const int B_LED = 11; const int BUTTON = 7; int val = 0; // variable to store the value coming from the sensor int btn = LOW; int old_btn = LOW; int state = 0; char buffer[7] ; int pointer = 0; byte inByte = 0; byte r = 0; byte g = 0; byte b = 0; void setup() { Serial.begin(9600); // open the serial port pinMode(BUTTON, INPUT); } void loop() { val = analogRead(SENSOR); // read the value from the sensor Serial.println(val); // print the value to // the serial port if (Serial.available() >0) { // read the incoming byte: inByte = Serial.read(); // If the marker's found, next 6 characters are the colour if (inByte == '#') { while (pointer < 6) { // accumulate 6 chars buffer[pointer] = Serial.read(); // store in the buffer pointer++; // move the pointer forward by 1 } // now we have the 3 numbers stored as hex numbers // we need to decode them into 3 bytes r, g and b r = hex2dec(buffer[1]) + hex2dec(buffer[0]) * 16; g = hex2dec(buffer[3]) + hex2dec(buffer[2]) * 16; b = hex2dec(buffer[5]) + hex2dec(buffer[4]) * 16; pointer = 0; // reset the pointer so we can reuse the buffer } } btn = digitalRead(BUTTON); // read input value and store it // Check if there was a transition if ((btn == HIGH) && (old_btn == LOW)){ state = 1 - state; } old_btn = btn; // val is now old, let's store it if (state == 1) { // if the lamp is on analogWrite(R_LED, r); // turn the leds on analogWrite(G_LED, g); // at the colour analogWrite(B_LED, b); // sent by the computer } else { analogWrite(R_LED, 0); // otherwise turn off analogWrite(G_LED, 0); analogWrite(B_LED, 0); } delay(100); // wait 100ms between each send } int hex2dec(byte c) { // converts one HEX character into a number if (c >= '0' && c <= '9') { return c - '0'; } else if (c >= 'A' && c <= 'F') { return c - 'A' + 10; } }
後は、Arduinoを配線して完了です。
上昇したら赤、同じなら青、下がったら黄色が点灯します。
これは、processingの画面です。
これで安心して仕事が出来ますね(w
githubにソースを公開しときました!
k1morikawa/arduino_processing · GitHub
2015あけましておめでとうございます!!
昨年末、モンゴルでユニメディアのラボを設立しました!
モンゴル科学技術大学、モンゴル国立大学でオープニングセレモニーを行いました。
人生初の白手袋はめてリボンカットを行いました!!!
atモンゴル科学技術大学
モンゴル科学技術大学サイトhttp://www.sict.edu.mn/content/News/NewsDetail.aspx?m=1&newsID=298
atモンゴル国立大学
モンゴル国立大学サイトhttp://news.num.edu.mn/?p=22037
Google Glass、AndroidWearでGalaxy Gear2、iBeaconでStickFind、IoTでCloudBit等の研究開発を始めます!
モンゴルから世界へ未来へ!!
今年は1月24日には、モンゴルで2回目のアプリコンテストも行います!
ガートナーの2014ハイプ・サイクルの中で僕なりにポイント絞った戦略です。
http://www.gartner.co.jp/press/html/pr20140903-01.html
やったります!ので!
2015もよろしくお願い致します!
森川敬一