Skip to content

Instantly share code, notes, and snippets.

@danasf
Last active August 29, 2015 13:57
Show Gist options
  • Select an option

  • Save danasf/9592316 to your computer and use it in GitHub Desktop.

Select an option

Save danasf/9592316 to your computer and use it in GitHub Desktop.
Web socket LED control
Experimenting with web sockets to control LEDs over a serial connection.
index.html - Client
server.js - Server
SerCmdLED.ino - arduino code, we can treat this like a black box, here is the interface:
set all to:
RED
GREEN
BLUE
OFF
set to rgb color:
SET r g b
set pix i to color:
PIX i r g b
HEX i RRGGBB
REFRESH (used after setting relevant pixels)
Returns strings like:
OK,SET RED
ERR,UNKNOWN COMMAND
Console output is like:
Serial port is open!
HTTP server is running.
New web socket connection!
From browser: GREEN
From serial: OK,SET GREEN
From browser: RED
From serial: OK,SET RED
From browser: BLUE
From serial: OK,SET BLUE
From browser: OFF
From serial: OK,OFF
Web socket closed. CODE 1001
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Web Socket Control</title>
<style type="text/css">
.cmdBtn { font-size: 32px; padding:20px; border:1px solid #000; }
.cmdBtn:hover { background:#000; color:#fff; }
#colorBlock { width:100px; height:50px; background:#000; border:1px solid #000; }
input { height:50px; width: 250px; font-size: 2em; }
#pickerWidget { width:250px; margin-bottom: 30px; }
#picker { width: 200px; height: 200px; float:left; }
#slide { width: 30px; height: 200px; float:right ;}
</style>
</head>
<body>
<h1>Web Socket Light Switch</h1>
<div id="incoming">
<h3>Latest Message</h3>
<p id="sockStatus">Unknown</p>
</div>
<div id="colorBlock"></div>
<div id="presets">
<h3>Preset colors</h3>
<button class="cmdBtn" id="redBtn">RED</button>
<button class="cmdBtn" id="greenBtn">GREEN</button>
<button class="cmdBtn" id="blueBtn">BLUE</button>
<button class="cmdBtn" id="offBtn">OFF</button>
</div>
<div id="setcolor">
<h3>Send a color</h3>
<div id="pickerWidget">
<div id="picker"></div>
<div id="slide"></div>
</div>
<p><input type="text" class="basic" id="sendColor" value="#000000"/></p>
<p><button class="cmdBtn" id="sendColorBtn">Send a color</button></p>
</div>
<div id="serial">
<h3>Toggle serial</h3>
<button id="serToggle" class="cmdBtn">Toggle Serial</button>
</div>
</body>
<script type="text/javascript" src="http://cdn.jsdelivr.net/flexicolorpicker/0.1/colorpicker.min.js"></script>
<script>
window.onload=function(){
if(!window.WebSocket) {
alert("I'm sorry, either your browser does not support web sockets, or something went terribly awry, this page will not work as intended!");
}
var sock = new WebSocket('ws://localhost:5000');
var sockStatus = document.getElementById('sockStatus');
var colorBlock = document.getElementById('colorBlock');
var redBtn = document.getElementById('redBtn');
var greenBtn = document.getElementById('greenBtn');
var blueBtn = document.getElementById('blueBtn');
var off = document.getElementById('offBtn');
var sendColorBtn = document.getElementById('sendColorBtn');
var serToggle = document.getElementById('serToggle');
sock.onopen = function () {
sockStatus.innerHTML = 'Connected';
}
sock.onmessage = function (evt) {
console.log("Incoming Data %s",evt.data);
sockStatus.innerHTML = evt.data;
}
sock.onerror = function (err) {
sockStatus.innerHTML = err;
}
sock.onclose = function (evt) {
//console.log(evt);
sockStatus.innerHTML = "Socket Closed "+evt.reason;
}
sock.sendMessage = function (type,message) {
var data = {
header: type,
message: message
}
sock.send(JSON.stringify(data));
}
redBtn.addEventListener('click',function() {
colorBlock.setColor("#ff0000");
sock.sendMessage("literal","RED");
});
greenBtn.addEventListener('click',function() {
colorBlock.setColor("#00ff00");
sock.sendMessage("literal","GREEN");
});
blueBtn.addEventListener('click',function() {
colorBlock.setColor("#0000ff");
sock.sendMessage("literal","BLUE");
});
off.addEventListener('click',function() {
colorBlock.setColor("#000000");
sock.sendMessage("literal","OFF");
});
serToggle.addEventListener('click',function() {
sock.sendMessage("serial","toggle");
});
sendColorBtn.addEventListener('click',function() {
colorBlock.setColor(document.getElementById("sendColor").value);
sock.sendMessage("color",document.getElementById("sendColor").value);
});
colorBlock.setColor = function(color) {
colorBlock.style.backgroundColor=color;
}
ColorPicker(
document.getElementById('slide'),
document.getElementById('picker'),
function(hex, hsv, rgb) {
colorBlock.setColor(hex);
document.getElementById("sendColor").value = hex;
});
}
</script>
</html>
{
"name": "websocketlight",
"version": "0.0.1",
"description": "Control Arduino connected LED via web socket interface",
"main": "server.js",
"dependencies": {
"ws": "~0.4.31",
"serialport": "~1.3.1"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"keywords": [
"led",
"websockets",
"arduino"
],
"author": "dana",
"license": "MIT"
}
/*
Serial control of LED strip
Requires Adafruit_NeoPixel and SerialCommand libraries
https://github.com/adafruit/Adafruit_NeoPixel
https://github.com/scogswell/ArduinoSerialCommand
*/
#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h> // We need this even if we're not using a SoftwareSerial object
#include <SerialCommand.h>
SerialCommand SCmd;
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(15, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(57600);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
strip.setBrightness(150);
SCmd.addCommand("RED",setRed);
SCmd.addCommand("GREEN",setGreen);
SCmd.addCommand("BLUE",setBlue);
SCmd.addCommand("OFF",setOff);
SCmd.addCommand("SET",setStrip);
SCmd.addCommand("PIX",setPix);
SCmd.addCommand("HEX",setHex);
SCmd.addCommand("REFRESH",refreshStrip);
SCmd.addDefaultHandler(unrecognized); // Handler for command that isn't matched
Serial.println("OK,READY");
colorWipe(strip.Color(200, 0, 0), 30); // Red
}
void loop() {
SCmd.readSerial();
}
void setRed() {
colorQuick(strip.Color(255, 0, 0), 0);
Serial.println("OK,SET RED");
}
void setGreen() {
colorQuick(strip.Color(0, 255, 0), 0);
Serial.println("OK,SET GREEN");
}
void setBlue() {
colorQuick(strip.Color(0, 0, 255), 0);
Serial.println("OK,SET BLUE");
}
void setOff() {
colorWipe(0x000000, 0);
Serial.println("OK,OFF");
}
void setStrip() {
uint8_t cnt=0;
uint8_t color[3];
char *arg;
arg = SCmd.next();
if(arg != NULL) {
color[cnt++] = atoi(arg);
}
arg = SCmd.next();
if(arg != NULL) {
color[cnt++] = atoi(arg);
}
arg = SCmd.next();
if(arg != NULL) {
color[cnt++] = atoi(arg);
}
colorQuick(strip.Color(color[0], color[1], color[2]), 0);
Serial.println("OK,SET STRIP");
}
void setHex() {
char *arg;
int pix=0;
arg = SCmd.next();
if(arg != NULL) {
pix = atoi(arg);
}
arg = SCmd.next();
if(arg != NULL) {
strip.setPixelColor(pix,strtol(arg, NULL, 16));
}
Serial.print("OK,SET HEX");
Serial.println(pix);
}
void setPix() {
uint8_t cnt=0;
int pix =0;
uint8_t color[3];
char *arg;
arg = SCmd.next();
if(arg != NULL) {
pix = atoi(arg);
}
arg = SCmd.next();
if(arg != NULL) {
color[cnt++] = atoi(arg);
}
arg = SCmd.next();
if(arg != NULL) {
color[cnt++] = atoi(arg);
}
arg = SCmd.next();
if(arg != NULL) {
color[cnt++] = atoi(arg);
}
strip.setPixelColor(pix, strip.Color(color[0], color[1], color[2]));
Serial.print("OK,SET PIXEL");
Serial.println(pix);
}
void refreshStrip() {
strip.show();
Serial.println("OK,STRIP REFRESH");
}
void unrecognized()
{
Serial.println("ERR,UNKNOWN COMMAND");
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void colorQuick(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
}
strip.show();
delay(wait);
}
/**
* Controlling lights with web socket
**/
// require various modules
var http = require('http');
var WebSocketServer = require('ws').Server;
var serPort = require('serialport');
var fs = require('fs');
// setup http server
var server = http.createServer(function(req,res) {
console.log("HTTP server is running.");
fs.readFile("index.html", function(error,data) {
if(error) {
res.end("Error loading page!");
}
res.end(data);
});
});
server.listen(5000);
// deal with web socket
// web socket server
var wsock = new WebSocketServer({ server: server });
// on new socket conn
wsock.on('connection', function(ws) {
console.log("New web socket connection!");
ws.send("Hello, browser, you're connected!");
ws.on('open',function() {
});
// on message from browser
ws.on('message',function(data) {
var incomingData = JSON.parse(data);
console.log("From browser: %j",incomingData);
if(incomingData.header == "literal") {
ser.write(incomingData.message+"\r",function(err,res) { if(err) { console.log("Ser write err %s",err); } });
}
else if (incomingData.header == "color") {
var parts = incomingData.message.match(/#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})/i);
console.log(parts);
var r = parseInt(parts[1],16);
var g = parseInt(parts[2],16);
var b = parseInt(parts[3],16);
var buildStr = "SET "+r+" "+g+" "+b+"\r";
console.log(buildStr);
ser.write(buildStr,function(err,res) { if(err) { console.log("Ser write err %s",err); } });
}
else if (incomingData.header == "serial") {
ser.toggleState();
}
else {
console.log("I didn't understand that!");
}
});
ws.on('error', function(err) {
console.log("Web socket error: %s",err);
});
ws.on('close',function(code,message) {
console.log("Web socket closed. CODE %d",code);
ws.terminate();
});
// !! wait until web socket websocket.readyState is open
if(ws.OPEN) {
wsock.broadcast();
}
});
wsock.on('error',function(err) {
console.log(err);
});
// deal with serial data event
wsock.broadcast = function () {
ser.on('data', function(data) {
console.log("From serial: %s",data);
for (var i in wsock.clients) {
wsock.clients[i].send(data);
}
});
}
// serial port
var ser = new serPort.SerialPort("/dev/tty.usbserial-A6004oQI",{ baudrate:9600, parser: serPort.parsers.readline("\n")},
function(err) {
if(err) { console.log(err); process.exit(); }
});
ser.on('open', function(error) {
if(error) {
console.log(error);
}
ser.ACTIVE=true;
console.log("Serial port is open!");
});
ser.on('error', function(error) {
console.log(error);
});
ser.on('close',function(error) {
ser.ACTIVE=false;
console.log("Serial port is closed.");
});
// toggle serial state
ser.toggleState = function() {
if(ser.ACTIVE) {
ser.close();
}
else {
ser.open();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment