building a better dock light

Hi all, So I have a house on spirit lake in Iowa, and I have to admit I have a problem. I needed a decent way to control the dock lights. I needed it to work over the internet and I needed it to have an app…. Since my lake house has media com for internet a NAT wouldn’t be sufficient.

First let me get this out of the way…

53231748

Anyways onwards and upwards… I chose nodes for this project, mostly because it’s bad ass. The client uses a raspberry pi, along with it’s GPIO, also 3 relays were used to power 3 different sets of lights…

The code at the server listened for connections front the client. and acted not he messages.

Here is the dock lighthouse master source code!

var io = require('socket.io').listen(3000);
 
var iolocal = require('socket.io').listen(3001);
 
var mysql      = require('mysql');
var light;
var connection = mysql.createConnection({
	host     : 'localhost',
	user     : 'docklighthouse',
	password : 'docklighthouse!',
	socketPath : '/var/run/mysqld/mysqld.sock',
	database : 'docklighthouse'
});
 
connection.connect();
 
 
function addlight(id,serial,light,sock) {
	connection.query("DELETE from lights where userid=\""+id+"\" and serial=\""+serial+"\" and lightid=\""+light.id+"\"", function(err, rows) {
		if(err) {
			throw err;
		} else {
			connection.query("INSERT into lights (userid,serial,lightid,name,socket) values (\""+id+"\",\""+serial+"\",\""+light.id+"\",\""+light.name+"\",\""+sock+"\")",function(err,rows) {
				if (err) {
					throw err;
				} else {
					setLightStatus(id,serial,light,sock);
				}
			});
		}
	});
}
 
function setLightStatus(id,serial,light,sock) {
	connection.query("UPDATE lights set status=\""+light.status+"\",socket=\""+sock+"\" where userid=\""+id+"\" and serial=\""+serial+"\" and lightid=\""+light.id+"\"",function(err,rows) {
		if (err) {
			throw err;
		}
	});
}
 
function checkLight(light,serial,id,sock) {
	connection.query("select count(*) as count from lights where userid=\""+id+"\" and serial=\""+serial+"\" and lightid=\""+light.id+"\" and name=\""+light.name+"\"", function(err, rows) {
		if (err) {
			throw err;
		} else {
			if (rows[0].count == 0) {
				//insert it
				addlight(id,serial,light,sock);
			} else {
				setLightStatus(id,serial,light,sock);
			}
		}
	});
}
 
 
function checkLights(id,serial,lights,sock) {
	for (var i = 0; i < lights.length; i++) {
		light = lights[i];
		checkLight(light,serial,id,sock);
	}
}
 
function getUsernameForLights(username,password,serial,lights,sock) {
	var id = 0;
	connection.query("SELECT id from users where username=\""+username+"\" and password=password(\""+password+"\")", function(err, rows) {
		if(err)	{
 			throw err;
		}else{
			id = rows[0].id;
			checkLights(id,serial,lights,sock);
		}
	});
}
 
function addLights(username,password,serial,lights,sock) {
	getUsernameForLights(username,password,serial,lights,sock);
}
 
function setLightStatusUpdate(sock,lightid,status) {
	connection.query("UPDATE lights set status=\""+status+"\" where socket=\""+sock+"\" and lightid=\""+lightid+"\"", function(err, rows) {
		if(err)	{
 			throw err;
		}else{
		}
	});	
}
 
io.sockets.on('connection', function (socket) {
	socket.on('lights', function (data) {
		var json = JSON.parse(data);
		var username = json.username;
		var password = json.password;
		var serial = json.serial;
		var lights = json.lights;
		addLights (username,password,serial,lights,socket.id);
	});
 
	socket.on('setLightStatus',function(data) {
		var json = JSON.parse(data);
		setLightStatusUpdate(json.socket,json.lightid,json.status);
	});
});
 
iolocal.sockets.on('connection', function (socketlocal) {
	socketlocal.on('togglelight', function (data) {
		var json = JSON.parse(data);
		io.sockets.socket(json.socket).emit("togglelight",data);
	});
});

The client looks like

var db = dblite('/home/dock/dock.db');
var io = require('socket.io-client');
var socket = io.connect('http://x.x.x.x:3000');
var fs = require('fs');
var serial = "";
var username = "";
var password = "";
 
start();
 
 
 
 
function start() {
	db.query('SELECT username,password from userinfo',function (err, rows) {
		username = rows[0][0];
		password = rows[0][1];
		getSerial();
	});
}
 
 
 
function getSerial() {
	var fileContent = fs.readFileSync('/proc/cpuinfo').toString();
	var lines = fileContent.split("\n");
	for( var i = 0; i < lines.length; ++i ) {
		if (lines[i].indexOf("Serial") > -1) {
			var sp = lines[i].split(":");
			serial = sp[1].trim();
		}
	}
	getLights();
	//sendStatus();
	setInterval(function(){getLights()},5000);
}
 
 
function getLightStatusReal(id) {
	var lightStatus="0";
	if (id == 1 ) {
		lightStatus = fs.readFileSync("/sys/class/gpio/gpio7/value");
	}
	if (id == 2 ) {
		lightStatus = fs.readFileSync("/sys/class/gpio/gpio8/value");
	}
	if (id == 3 ) {
		lightStatus = fs.readFileSync("/sys/class/gpio/gpio25/value");
	}
	lightStatus = lightStatus.toString();
	lightStatus = lightStatus.trim();
	return lightStatus;
 
}
 
function getLights() {
	db.query('SELECT light,name FROM lights',function (err, rows) {
		var i = 0;
		var json = "";
		while (i < rows.length) {
			if (json != "") {
				json += ",";
			}
			var name = rows[i][1];
			name = name.escapeSpecialChars();
			var id = rows[i][0];
			var status = getLightStatusReal(id);
			json += "{\"name\": \""+name+"\",\"id\": \""+rows[i][0]+"\",\"status\":\""+status+"\"}";
			i++;
		}
		json = "{\"username\":\""+username+"\",\"password\":\""+password+"\",\"command\":\"setlights\",\"serial\":\""+serial+"\",\"lights\": ["+json+"]}";
		console.log(json);
		socket.emit("lights",json);
	});
}
 
 
function getLightStatus() {
	db.query('SELECT light,name FROM lights',function (err, rows) {
		var i = 0;
		var json = "";
		while (i < rows.length) {
			if (json != "") {
				json += ",";
			}
			var name = rows[i][1];
			name = name.escapeSpecialChars();
			var id = rows[i][0];
			var status = getLightStatusReal(id);
			json += "{\"name\": \""+name+"\",\"id\": \""+rows[i][0]+"\",\"status\":\""+status+"\"}";
			i++;
		}
		json = "{\"username\":\""+username+"\",\"password\":\""+password+"\",\"command\":\"setlights\",\"serial\":\""+serial+"\",\"lights\": ["+json+"]}";
		//console.log(json);
		socket.emit("lights",json);
	});
}
 
 
function sendStatus() {
	setInterval(function() { getLightStatus(); },5000);
}
 
socket.on('togglelight',function (data) {
	var json = JSON.parse(data);
	var lightid = parseInt(json.lightid);
	var lightStatus="0";
	if (lightid == 1 ) {
		lightStatus = fs.readFileSync("/sys/class/gpio/gpio7/value");
		if (parseInt(lightStatus) == 1) {
			fs.writeFileSync("/sys/class/gpio/gpio7/value","0");			
			socket.emit("setLightStatus",'{"lightid":"'+lightid+'","socket":"'+json.socket+'","status":"0"}');
		} else {
			fs.writeFileSync("/sys/class/gpio/gpio7/value","1");
			socket.emit("setLightStatus",'{"lightid":"'+lightid+'","socket":"'+json.socket+'","status":"1"}');
		}
	}
	if (lightid == 2 ) {
		lightStatus = fs.readFileSync("/sys/class/gpio/gpio8/value");
		if (parseInt(lightStatus) == 1) {
			fs.writeFileSync("/sys/class/gpio/gpio8/value","0");
			socket.emit("setLightStatus",'{"lightid":"'+lightid+'","socket":"'+json.socket+'","status":"0"}');
		} else {
			fs.writeFileSync("/sys/class/gpio/gpio8/value","1");
			socket.emit("setLightStatus",'{"lightid":"'+lightid+'","socket":"'+json.socket+'","status":"1"}');
		}
	}
	if (lightid == 3 ) {
		lightStatus = fs.readFileSync("/sys/class/gpio/gpio25/value");
		if (parseInt(lightStatus) == 1) {
			fs.writeFileSync("/sys/class/gpio/gpio25/value","0");
			socket.emit("setLightStatus",'{"lightid":"'+lightid+'","socket":"'+json.socket+'","status":"0"}');
		} else {
			fs.writeFileSync("/sys/class/gpio/gpio25/value","1");
			socket.emit("setLightStatus",'{"lightid":"'+lightid+'","socket":"'+json.socket+'","status":"1"}');
		}
	}
 
});
 
String.prototype.escapeSpecialChars = function() {
    return this.replace(/\\n/g, "\\n")
               .replace(/\\'/g, "\\'")
               .replace(/\\"/g, '\\"')
               .replace(/\\&/g, "\\&")
               .replace(/\\r/g, "\\r")
               .replace(/\\t/g, "\\t")
               .replace(/\\b/g, "\\b")
               .replace(/\\f/g, "\\f");
};

And that’s it, short of some database and an iPhone app this is what makes up dock lighthouse!!

–John “Let the light Shine on me!” Hass

Leave a Reply

Your email address will not be published. Required fields are marked *