Last active
August 29, 2015 13:57
-
-
Save danasf/9592316 to your computer and use it in GitHub Desktop.
Web socket LED control
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "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" | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| 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); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * 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