khanhhs
Published © GPL3+

Arduino - Web-Based Keypad

Remotely controlling Arduino by using web-based keypad.

BeginnerFull instructions provided11,228

Things used in this project

Story

Read more

Schematics

wiring_SLhmifR38E.png

Code

Arduino Code

Arduino
#include "SPI.h"
#include "Phpoc.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

PhpocServer server(80);
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();

void setup() {
	Serial.begin(9600);
	while(!Serial)
		;

	Phpoc.begin(PF_LOG_SPI | PF_LOG_NET);
	//Phpoc.begin();

	server.beginWebSocket("remote_keypad");

	Serial.print("WebSocket server address : ");
	Serial.println(Phpoc.localIP());
	
	matrix.begin(0x70);	// pass in the address
	matrix.setRotation(3);
	matrix.setTextColor(LED_RED);
 
}

void loop() {
	// wait for a new client:
	PhpocClient client = server.available();

	if (client) {
		if (client.available() > 0) {
			// read the bytes incoming from the client:
			char thisChar = client.read();
			
			matrix.clear();
			matrix.setCursor(1,0);
			matrix.print(thisChar);
			matrix.writeDisplay();
		}
	}
}

User Interface (remote_keypad.php)

PHP
<!DOCTYPE html>
<html>
<head>
<title>PHPoC Shield - Web Remote Control for Arduino</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<style>
body { text-align: center; }
h1 { font-weight: bold; font-size: 25pt; }
h2 { font-weight: bold; font-size: 15pt; }
button { font-weight: bold; font-size: 15pt; }
</style>
<script>
var BOX_WIDTH = 120;
var BOX_HEIGHT = 120;
var KEY_WIDTH = 85;
var KEY_HEIGHT = 85;
var OFFSET_X = 65;
var OFFSET_Y = 40;
var canvas_width, canvas_height;
var push_info = [];
var push_text = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#" ];
var push_font = "bold 50px Arial";
var ws;

function init()
{
	var remote = document.getElementById("remote");
	
	remote.width = canvas_width = BOX_WIDTH * 3 + OFFSET_X * 2;
	remote.height = canvas_height = BOX_HEIGHT * 4 + OFFSET_Y * 2;
	
	var ctx = remote.getContext("2d");
	ctx.strokeStyle = "white";
	ctx.lineJoin = "round";

	for(var push_id = 0; push_id < 12; push_id++)
	{
		if(push_id == 9 || push_id == 11)
			push_info[push_id] = {state:false, identifier:null, font:push_font, text:push_text[push_id], color_1:"Crimson", color_2:"Red"};
		else
			push_info[push_id] = {state:false, identifier:null, font:push_font, text:push_text[push_id], color_1:"#1E90FF", color_2:"Aqua"};
	}
	
	update_view();
	
	remote.addEventListener("touchstart", mouse_down);
	remote.addEventListener("touchend", mouse_up);
	remote.addEventListener("touchmove", mouse_move);

	remote.addEventListener("mousedown", mouse_down);
	remote.addEventListener("mouseup", mouse_up);
	remote.addEventListener("mousemove", mouse_move);
	remote.addEventListener("mouseout", mouse_up);
}
function connect_onclick()
{
	if(ws == null)
	{
		var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
		var debug = document.getElementById("debug");

		if((navigator.platform.indexOf("Win") != -1) && (ws_host_addr.charAt(0) == "["))
		{
			// network resource identifier to UNC path name conversion
			ws_host_addr = ws_host_addr.replace(/[\[\]]/g, '');
			ws_host_addr = ws_host_addr.replace(/:/g, "-");
			ws_host_addr += ".ipv6-literal.net";
		}
		
		ws = new WebSocket("ws://" + ws_host_addr + "/remote_keypad", "text.phpoc");

		document.getElementById("ws_state").innerHTML = "CONNECTING";

		ws.onopen = ws_onopen;
		ws.onclose = ws_onclose;
		ws.onmessage = ws_onmessage;
	}
	else
		ws.close();
}
function ws_onopen()
{
	document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>";
	document.getElementById("bt_connect").innerHTML = "Disconnect";

	for(var push_id = 0; push_id < 12; push_id++)
		push_info[push_id].state = false;
		
	update_view();
}
function ws_onclose()
{
	document.getElementById("ws_state").innerHTML = "<font color='gray'>CLOSED</font>";
	document.getElementById("bt_connect").innerHTML = "Connect";

	ws.onopen = null;
	ws.onclose = null;
	ws.onmessage = null;
	ws = null;

	for(var push_id = 0; push_id < 12; push_id++)
		push_info[push_id].state = false;
		
	update_view();
}
function ws_onmessage(e_msg)
{
	e_msg = e_msg || window.event; // MessageEvent

	alert("msg : " + e_msg.data);
}
function update_view()
{
	var remote = document.getElementById("remote");
	var ctx = remote.getContext("2d");
	var cx, cy, x, y;
	
	ctx.clearRect(0, 0, canvas_width, canvas_height);
	ctx.lineWidth = 4;
	ctx.fillStyle = "black";
	ctx.shadowBlur = 0;
	
	var margin, radius;
	for(var i = 0; i < 3; i++)
	{
		if(i == 0)
			margin = 0;
		else if(i == 1)
			margin = 20;
		else
			margin = 28;
		
		radius = 45 - margin;
		
		ctx.beginPath(); 
		ctx.arc(margin + radius, margin + radius, radius, Math.PI, 1.5*Math.PI);
		ctx.lineTo(margin + radius, margin);
		ctx.lineTo(canvas_width - margin - radius, margin);
		ctx.arc(canvas_width - margin - radius, margin + radius, radius, 1.5*Math.PI, 0);
		ctx.lineTo(canvas_width - margin, canvas_height - margin - radius);
		ctx.arc(canvas_width - margin - radius, canvas_height - margin - radius, radius, 0, 0.5*Math.PI);
		ctx.lineTo(margin + radius, canvas_height - margin);
		ctx.arc(margin + radius, canvas_height - margin - radius, radius, 0.5*Math.PI, Math.PI);
		ctx.closePath();
		
		if(i == 0)
			ctx.fill();
		else
			ctx.stroke();
	}
	
	ctx.translate(OFFSET_X, OFFSET_Y);
	
	for(var push_id = 0; push_id < 12; push_id++)
	{
		var push = push_info[push_id];
		var state = push.state;
		
		if(state)
		{
			ctx.fillStyle = push.color_2;
			ctx.shadowBlur = 80;
			ctx.shadowColor = push.color_2;
		}
		else
		{
			ctx.shadowBlur = 0;
			ctx.fillStyle = push.color_1;
		}
		
		cx = BOX_WIDTH * (push_id % 3) + BOX_WIDTH / 2;
		cy = BOX_HEIGHT * parseInt(push_id / 3) + BOX_HEIGHT / 2;
		x = cx - KEY_WIDTH / 2;
		y = cy - KEY_HEIGHT / 2;
		
		ctx.beginPath();
		ctx.lineWidth = 7;
		ctx.rect(x, y, KEY_WIDTH, KEY_HEIGHT);
		ctx.fill();
		ctx.stroke();

		ctx.font = push.font;
		ctx.textAlign = "center";
		ctx.textBaseline = "middle";
		ctx.fillStyle = "white";
		ctx.fillText(push.text, cx, cy);

		if(!state)
			push.identifier = null;
	}
	
	ctx.translate(-OFFSET_X, -OFFSET_Y);
}

function find_push_id(x, y)
{
	var cx, cy, push_id;
	
	x -= OFFSET_X;
	y -= OFFSET_Y;
	
	if((x < 0) || (x >= BOX_WIDTH * 3))
		return 12;

	if((y < 0) || (y >= BOX_HEIGHT * 4))
		return 12;

	push_id = parseInt(x / BOX_WIDTH);
	push_id += 3 * parseInt(y / BOX_WIDTH);

	cx = BOX_WIDTH * (push_id % 3) + BOX_WIDTH / 2;
	cy = BOX_HEIGHT * parseInt(push_id / 3) + BOX_HEIGHT / 2;

	if( Math.abs(x - cx) < KEY_WIDTH && Math.abs(y - cy) < KEY_HEIGHT)
		return push_id;
	else
		return 12;
}
function mouse_down(event)
{
	var debug = document.getElementById("debug");
	var x, y, push_id;

	if(event.changedTouches)
	{
		for(var touch_id = 0; touch_id < event.changedTouches.length; touch_id++)
		{
			var touch = event.changedTouches[touch_id];

			x = touch.pageX - touch.target.offsetLeft;
			y = touch.pageY - touch.target.offsetTop;

			push_id = find_push_id(x, y);

			if(push_id < 12)
			{
				var push = push_info[push_id];

				if(push.state == false)
				{
					var key = push_info[push_id].text;
					send_key(key);
					push_info[push_id].state = true;
					update_view();
					push.identifier = touch.identifier;
				}
			}
		}
	}
	else
	{
		x = event.offsetX;
		y = event.offsetY;

		push_id = find_push_id(x, y);

		if(push_id < 12)
		{
			var key = push_info[push_id].text;
			send_key(key);
			push_info[push_id].state = true;
			update_view();
		}
	}

	event.preventDefault();
}
function mouse_up(event)
{
	var debug = document.getElementById("debug");
	var push_id;

	if(event.changedTouches)
	{
		for(var touch_id = 0; touch_id < event.changedTouches.length; touch_id++)
		{
			var touch = event.changedTouches[touch_id];

			for(var push_id = 0; push_id < 12; push_id++)
			{
				if(touch.identifier == push_info[push_id].identifier)
					break;
			}

			if(push_id < 12)
			{
				push_info[push_id].state = false;
				update_view();
			}
		}
	}
	else
	{
		for(var push_id = 0; push_id < 12; push_id++)
		{
			if(push_info[push_id].state)
			{
				push_info[push_id].state = false;
				update_view();
				break;
			}
		}
	}

	event.preventDefault();
}
function mouse_move(event)
{
	event.preventDefault();
}
function send_key(key)
{
	if(ws && (ws.readyState == 1))
		ws.send(key);
}
window.onload = init;
</script>
</head>

<body>

<p>
<h1>Web-based Remote Keypad</h1>
</p>

<canvas id="remote"></canvas><br>

<h2>WebSocket <font id="ws_state" color="gray">CLOSED</font></h2>
<button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button>
<span id="debug"></span>

</body>
</html>

Credits

khanhhs

khanhhs

0 projects • 56 followers

Comments