Initial checkin.
This commit is contained in:
commit
bc7a1a8315
|
@ -0,0 +1,4 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
*.sublime-workspace
|
||||
public/css/style.css
|
|
@ -0,0 +1,29 @@
|
|||
##[Node-LEDS](http://www.quietless.com/kitchen/controlling-24-leds-with-node-js-and-a-raspberry-pi/)
|
||||
|
||||
This was a quick project to see how difficult it would be to control an Arduino microcontroller over a local network with a Raspberry PI.
|
||||
|
||||
To build the project you'll need to setup Node.js. [ideally on a PI if you want to build the project to spec.](http://www.quietless.com/kitchen/how-to-setup-node-js-on-a-raspberry-pi/)
|
||||
|
||||
Materials used in this project:
|
||||
|
||||
* [Raspberry PI Model B](http://www.raspberrypi.org/)
|
||||
* [Arduino Leonardo](https://www.sparkfun.com/products/11286)
|
||||
* [2x 400 tie pt Breadboards](https://www.sparkfun.com/products/9567)
|
||||
* [1x Full Length Breadboard](https://www.sparkfun.com/products/112)
|
||||
* [4x74HC595 Shift Registers](https://www.sparkfun.com/products/733)
|
||||
* [7-Segment Display - 4-Digit](https://www.sparkfun.com/products/9481)
|
||||
* [24 Leds](http://www.amazon.com/microtivity-IL188-Assorted-Resistors-Colors/dp/B0060FGA8A)
|
||||
* [Bunch of Jumper Wires](http://www.amazon.com/Breadboard-jumper-wire-75pcs-pack/dp/B0040DEI9M)
|
||||
|
||||
Installation:
|
||||
|
||||
1. [Follow the schematic to wire everything up](http://quietless.com/docs/node-leds/node-leds.pdf)
|
||||
2. Flash the sketch at /arduino/node-led/node-led.ino onto your Arduino
|
||||
3. Connect the Arduino to your PI
|
||||
4. Fire up the Node server by running the app via > node app
|
||||
5. Point a web browser at the IP address of the PI e.g. 192.168.2.1:8080
|
||||
|
||||
Any questions, comments, suggestions open an issue or [post a comment on my blog.](http://www.quietless.com/kitchen/controlling-24-leds-with-node-js-and-a-raspberry-pi/)
|
||||
|
||||
|
||||
![Node-LEDS-schematic](http://quietless.com/docs/node-leds/node-leds.png "Node-LEDS-schematic")
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
/**
|
||||
* Node-Serial
|
||||
* Author: flabbergast
|
||||
* based on node-leds by Stephen Braitsch (https://github.com/braitsch/node-leds)
|
||||
*/
|
||||
|
||||
var express = require('express')
|
||||
, http = require('http')
|
||||
, port = require('./modules/serial_node')
|
||||
, socket = require('./modules/socket_server');
|
||||
|
||||
var app = express();
|
||||
|
||||
app.configure(function(){
|
||||
app.set('port', 8080);
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade');
|
||||
app.locals.pretty = true;
|
||||
app.use(express.bodyParser());
|
||||
app.use(express.cookieParser());
|
||||
app.use(express.session({ secret: 'super-duper-secret-secret' }));
|
||||
app.use(express.methodOverride());
|
||||
app.use(require("stylus").middleware({
|
||||
compress: true,
|
||||
src: __dirname + "/public"
|
||||
}));
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
});
|
||||
|
||||
app.configure('development', function(){
|
||||
app.use(express.errorHandler());
|
||||
});
|
||||
|
||||
/* ROUTES */
|
||||
|
||||
app.get('/', function(req, res){
|
||||
res.render('index');
|
||||
});
|
||||
|
||||
/* start the node server & initialize socket-io */
|
||||
var server = http.createServer(app).listen(app.get('port'), function(){
|
||||
socket.init(require('socket.io').listen(server));
|
||||
console.log("Express server listening at", server.address());
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": "/Users/js/Documents/Programming/Node/llap"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Public API
|
||||
*/
|
||||
|
||||
exports.writeNumber = function(n)
|
||||
{
|
||||
// parse number into multiplier and remainder //
|
||||
var m = Math.floor(n/255);
|
||||
var r = n%255;
|
||||
var data = [1, m, r];
|
||||
console.log('sending over serial ::', data);
|
||||
sendDataOverSerial(new Buffer(data));
|
||||
}
|
||||
|
||||
exports.getPath = function()
|
||||
{
|
||||
if(serport) {
|
||||
return serport.path;
|
||||
} else {
|
||||
return "not connected";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Private Methods
|
||||
*/
|
||||
|
||||
var serport;
|
||||
var socket = require('./socket_server');
|
||||
var serialport = require('serialport');
|
||||
var exec = require('child_process').exec;
|
||||
|
||||
/*
|
||||
Attempt to connect to a serial port
|
||||
*/
|
||||
|
||||
var detectSerialOnOSX = function()
|
||||
{
|
||||
var port;
|
||||
console.log('* attempting to detect a serial port on mac osx *');
|
||||
exec('ls /dev/tty.*', function(error, stdout, stderr){
|
||||
if (stdout){
|
||||
var ports = stdout.split('\n');
|
||||
for (var i = ports.length - 1; i >= 0; i--){
|
||||
if (ports[i].search('usbmodem') != -1 || ports[i].search('usbserial') != -1) port = ports[i];
|
||||
}
|
||||
}
|
||||
if (port){
|
||||
attemptConnection(port);
|
||||
} else{
|
||||
detectSerialOnRaspberryPI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var detectSerialOnRaspberryPI = function()
|
||||
{
|
||||
var port;
|
||||
console.log('* attempting to connect to a serial port on raspberry pi *');
|
||||
serialport.list(function (e, ports) {
|
||||
ports.forEach(function(obj) {
|
||||
if (obj.hasOwnProperty('pnpId')){
|
||||
// FTDI captures the duemilanove //
|
||||
// Arduino captures the leonardo //
|
||||
if (obj.pnpId.search('FTDI') != -1 || obj.pnpId.search('Arduino') != -1) {
|
||||
port = obj.comName;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (port){
|
||||
attemptConnection(port);
|
||||
} else{
|
||||
console.log('* failed to find a serial port : please check your connections *');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var attemptConnection = function(port)
|
||||
{
|
||||
console.log('* attempting to connect to serial at :', port, ' *');
|
||||
serport = new serialport.SerialPort(port, { baudrate: 9600, parser: serialport.parsers.readline("\n") });
|
||||
serport.on("open", function () {
|
||||
console.log('* connection to a serial port successful ! *');
|
||||
serport.on('data', function(data){
|
||||
// send incoming data from serport out to the socket server //
|
||||
socket.onDataOverSerial(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var sendDataOverSerial = function(buffer)
|
||||
{
|
||||
// calling write if an serport is not connected will crash the server! //
|
||||
if (serport){
|
||||
serport.write(buffer, function(e, results) {
|
||||
if (e) {
|
||||
console.log('error :: ' + e);
|
||||
} else{
|
||||
// console.log('message successfully sent');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
detectSerialOnOSX();
|
|
@ -0,0 +1,41 @@
|
|||
var sockets;
|
||||
var serport = require('./serial_node');
|
||||
var activeUser;
|
||||
|
||||
/*
|
||||
TODO - need to store the current animation & autoMode setting on the server
|
||||
*/
|
||||
|
||||
exports.init = function(io){
|
||||
|
||||
sockets = io.sockets;
|
||||
io.set('log level', 1);
|
||||
sockets.on('connection', function (socket) {
|
||||
// only allow the most recent connected user to interact with serial //
|
||||
activeUser = socket;
|
||||
// tell client they have successfully connected to the server and wait for their response //
|
||||
socket.emit('connected-to-server', {
|
||||
// transmit current status
|
||||
});
|
||||
// listen for the client to tell us who they are //
|
||||
socket.on('connected-client-response', function(data){
|
||||
socket.user = data;
|
||||
onUserConnected(socket);
|
||||
});
|
||||
// transmit info about the server on request
|
||||
socket.on('request-server-info', function (data) {
|
||||
socket.emit('server-info-response', { serialPort: serport.getPath() });
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.onDataOverSerial = function(data){
|
||||
console.log('onDataOverSerial', data);
|
||||
// process data received
|
||||
};
|
||||
|
||||
var onUserConnected = function(socket)
|
||||
{
|
||||
serport.writeNumber(socket.user.id);
|
||||
// here comes socket.on('something-happens', ...)
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "node-led",
|
||||
"version": "0.0.1",
|
||||
"author": {
|
||||
"name": "Stephen Braitsch",
|
||||
"email": "stephen@fuseproject.com"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:fuseproject/node-led.git"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"express": "3.1.0",
|
||||
"jade": "0.28.1",
|
||||
"stylus": "0.32.0",
|
||||
"socket.io": "0.9.12",
|
||||
"serialport": "https://github.com/voodootikigod/node-serialport/tarball/master"
|
||||
},
|
||||
"engines": {
|
||||
"node": "0.8.18",
|
||||
"npm": "1.2.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
raiseText()
|
||||
color grey
|
||||
text-shadow: -1px 1px 0 white
|
||||
-moz-text-shadow: -1px 1px 0 white
|
||||
-webkit-text-shadow: -1px 1px 0 white
|
||||
|
||||
html, body
|
||||
margin 0
|
||||
padding 0
|
||||
|
||||
body
|
||||
height 100%
|
||||
background-color #EEE
|
||||
|
||||
.navbar-inner
|
||||
padding 0
|
||||
|
||||
.navbar-inner .brand
|
||||
width 100%
|
||||
margin 0
|
||||
text-align center
|
||||
|
||||
.navbar .brand
|
||||
padding 10px 0 10px 0
|
||||
|
||||
#wrapper
|
||||
padding 15px 50px 0 50px
|
||||
margin auto
|
||||
|
||||
footer
|
||||
text-align center
|
||||
padding 30px 0
|
||||
margin-top 70px
|
||||
border-top 1px solid #e5e5e5
|
||||
background-color #f5f5f5
|
||||
|
||||
.footer p
|
||||
margin-bottom 0
|
||||
color #777
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
$(document).ready(function(){
|
||||
|
||||
$('#wrapper #serialtalk #serialtalk-btn').click(function(e){
|
||||
// handle the button press
|
||||
/* useful fns: $(e.target).attr('id') .addClass('btn-warning')
|
||||
if (socket && socket_connected){
|
||||
socket.emit('animation-selected', { id:n });
|
||||
}
|
||||
*/
|
||||
});
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
var socket = io.connect('/');
|
||||
var socket_connected = false;
|
||||
var autoMode;
|
||||
|
||||
socket.on('connected-to-server', function (data) {
|
||||
|
||||
// update the view based with the current server settings //
|
||||
|
||||
// generate a random id for this newly connected user //
|
||||
var id = Math.floor(Math.random()*9999);
|
||||
$('#user-id').html('Connected : <span style="color:blue">'+id+'</span>');
|
||||
socket_connected = true;
|
||||
socket.emit('connected-client-response', { id:id });
|
||||
socket.emit('request-server-info', {});
|
||||
});
|
||||
|
||||
socket.on('server-info-response', function (data) {
|
||||
$('footer #serial-port-elt').html('<span>'+data.serialPort+'</span>');
|
||||
});
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,27 @@
|
|||
extends layout
|
||||
|
||||
block content
|
||||
.navbar
|
||||
.navbar-inner
|
||||
#user-id.brand
|
||||
#wrapper
|
||||
#serialtalk(style="text-align: center;")
|
||||
//form.form-inline
|
||||
.input-append
|
||||
input#serialtalk-text.span2(type="text", placeholder="LLAP message")
|
||||
button#serialtalk-btn.btn Send
|
||||
p Last response:
|
||||
span#serialtalk-resp nothing yet
|
||||
|
||||
block footer
|
||||
p <strong>Server info:</strong>
|
||||
| #{process.title}:[#{process.version}]
|
||||
| serial-port:[
|
||||
span#serial-port-elt
|
||||
|]
|
||||
|
||||
|
||||
block scripts
|
||||
script(src='/js/index.js')
|
||||
script(src="/socket.io/socket.io.js")
|
||||
script(src='/js/socket_client.js')
|
|
@ -0,0 +1,17 @@
|
|||
!!! 5
|
||||
html
|
||||
head
|
||||
title Node LED
|
||||
link(rel='stylesheet', href='/vendor/bootstrap.min.css')
|
||||
link(rel='stylesheet', href='/css/style.css')
|
||||
meta(http-equiv="cache-control", content="no-cache")
|
||||
meta(name="apple-touch-fullscreen", content="yes")
|
||||
meta(name="apple-mobile-web-app-capable", content="yes")
|
||||
meta(name="apple-mobile-web-app-status-bar-style", content="black")
|
||||
meta(name="viewport", content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0")
|
||||
body
|
||||
block content
|
||||
footer.footer
|
||||
block footer
|
||||
script(src='/vendor/jquery-1.9.0.min.js')
|
||||
block scripts
|
Loading…
Reference in New Issue