Fabulous Car
This is an attempt to make it easy to control motors with a remote control over wifi using the ESP8266 board.
// CODE FOR REMOTE CONTROLLED CAR USING 2 SERVOS | |
#include <Arduino.h> | |
#include <ESP8266WiFi.h> | |
#include <ESP8266WiFiMulti.h> | |
#include <WebSocketsServer.h> | |
#include <ESP8266WebServer.h> | |
#include <ESP8266mDNS.h> | |
#include <Hash.h> | |
#include <Servo.h> | |
#define USE_SERIAL Serial | |
#define PIN1 4 | |
#define PIN2 5 | |
Servo servo1, servo2; | |
ESP8266WebServer server (80); | |
ESP8266WiFiMulti WiFiMulti; | |
const char *ssid = "fabulouscar"; | |
const char *password = "bananabanana"; | |
WebSocketsServer webSocket = WebSocketsServer(81); | |
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { | |
switch(type) { | |
case WStype_DISCONNECTED: | |
USE_SERIAL.printf("[%u] Disconnected!\n", num); | |
break; | |
case WStype_CONNECTED: { | |
IPAddress ip = webSocket.remoteIP(num); | |
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); | |
// send message to client | |
webSocket.sendTXT(num, "Connected"); | |
} | |
break; | |
case WStype_TEXT: | |
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); | |
String str((char*)payload); | |
parse_instructions(str); | |
break; | |
} | |
} | |
void parse_instructions(String str) | |
{ | |
int delimiter_pos = str.indexOf(" "); | |
String command = str.substring(0, delimiter_pos); // command | |
String params = str.substring(delimiter_pos+1); // parameter | |
if(command.equals("m1f")) { | |
// Motor 1 forward | |
servo1.attach(PIN1); | |
servo1.write(180); | |
} | |
if(command.equals("m1b")) { | |
// Motor 1 backward | |
servo1.attach(PIN1); | |
servo1.write(0); | |
} | |
if(command.equals("m1s")) { | |
// Motor 1 stop | |
servo1.detach(); | |
} | |
if(command.equals("m2f")) { | |
// Motor 2 forward | |
servo2.attach(PIN2); | |
servo2.write(0); | |
} | |
if(command.equals("m2b")) { | |
// Motor 2 backward | |
servo2.attach(PIN2); | |
servo2.write(180); | |
} | |
if(command.equals("m2s")) { | |
// Motor 2 stop | |
servo2.detach(); | |
} | |
if(command.equals("m1p")) { | |
// Motor 1 pwm | |
servo1.attach(PIN1); | |
servo1.write(params.toInt()); | |
} | |
if(command.equals("m2p")) { | |
// Motor 2 pwm | |
servo2.attach(PIN2); | |
servo2.write(params.toInt()); | |
} | |
} | |
void setup() { | |
//USE_SERIAL.begin(921600); | |
USE_SERIAL.begin(115200); | |
pinMode(PIN1, OUTPUT); | |
pinMode(PIN2, OUTPUT); | |
// servo1.attach(PIN1); | |
// servo2.attach(PIN2); | |
USE_SERIAL.setDebugOutput(true); | |
USE_SERIAL.println(); | |
USE_SERIAL.println(); | |
USE_SERIAL.println(); | |
for(uint8_t t = 4; t > 0; t--) { | |
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); | |
USE_SERIAL.flush(); | |
delay(1000); | |
} | |
// WiFiMulti.addAP("SSID", "XXX"); | |
// while(WiFiMulti.run() != WL_CONNECTED) { | |
// delay(100); | |
// } | |
USE_SERIAL.print("Setting soft-AP ... "); | |
WiFi.softAP(ssid, password); | |
IPAddress myIP = WiFi.softAPIP(); | |
USE_SERIAL.print("AP IP address: "); | |
USE_SERIAL.println(myIP); | |
// start webSocket server | |
webSocket.begin(); | |
webSocket.onEvent(webSocketEvent); | |
if(MDNS.begin("fabulouscar")) { | |
USE_SERIAL.println("MDNS responder started"); | |
} | |
// handle index | |
server.on("/", []() { | |
// send index.html | |
server.send(200, "text/html", "<meta charset=utf-8><title>Remote Control</title><meta content='width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no'name=viewport><style>.pad{width:50%;height:50%;position:absolute}</style><div style=width:100vw><div style=top:0;left:0;background:#6686b7 class=pad id=m1f></div><div style=top:50%;left:0;background:#54c1de class=pad id=m1b></div><div style=top:0;right:0;background:#ff5e63 class=pad id=m2f></div><div style=top:50%;right:0;background:#fcba55 class=pad id=m2b></div></div><script>window.onload=function(){boardPath=location.hash?location.hash.substring(1):location.hostname,connection=new WebSocket('ws://'+boardPath+':81/',['arduino']),connection.onopen=function(){connection.send('Connect '+new Date)},connection.onerror=function(e){console.log('WebSocket Error ',e)},connection.onmessage=function(e){console.log('Server: ',e.data)},createEvent=function(e){return function(t){console.log(e),t.preventDefault(),connection.send(e)}},registerEvents=function(e){forwardButton=document.getElementById('m'+e+'f'),backwardButton=document.getElementById('m'+e+'b'),forwardButton.addEventListener('touchstart',createEvent('m'+e+'f')),forwardButton.addEventListener('mousedown',createEvent('m'+e+'f')),forwardButton.addEventListener('touchend',createEvent('m'+e+'s')),forwardButton.addEventListener('mouseup',createEvent('m'+e+'s')),backwardButton.addEventListener('touchstart',createEvent('m'+e+'b')),backwardButton.addEventListener('mousedown',createEvent('m'+e+'b')),backwardButton.addEventListener('touchend',createEvent('m'+e+'s')),backwardButton.addEventListener('mouseup',createEvent('m'+e+'s'))},registerEvents(1),registerEvents(2)}</script>');"); | |
}); | |
server.begin(); | |
// Add service to MDNS | |
MDNS.addService("http", "tcp", 80); | |
MDNS.addService("ws", "tcp", 81); | |
} | |
void loop() { | |
webSocket.loop(); | |
server.handleClient(); | |
} |
// CODE FOR REMOTE CONTROLLED CAR USING DC MOTOR WITH H-BRIDGE (DRIVER) | |
// AND THE MOST REGULAR TOWER SERVO | |
#include <Arduino.h> | |
#include <ESP8266WiFi.h> | |
#include <ESP8266WiFiMulti.h> | |
#include <WebSocketsServer.h> | |
#include <ESP8266WebServer.h> | |
#include <ESP8266mDNS.h> | |
#include <Hash.h> | |
#include <Servo.h> | |
#define USE_SERIAL Serial | |
Servo servo; | |
int servoPin = 12; | |
int forwardPin = 5; | |
int backwardPin = 4; | |
ESP8266WiFiMulti WiFiMulti; | |
ESP8266WebServer server = ESP8266WebServer(80); | |
WebSocketsServer webSocket = WebSocketsServer(81); | |
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { | |
switch(type) { | |
case WStype_DISCONNECTED: | |
USE_SERIAL.printf("[%u] Disconnected!\n", num); | |
break; | |
case WStype_CONNECTED: { | |
IPAddress ip = webSocket.remoteIP(num); | |
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); | |
// send message to client | |
webSocket.sendTXT(num, "Connected"); | |
} | |
break; | |
case WStype_TEXT: | |
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); | |
String str((char*)payload); | |
parse_instructions(str); | |
break; | |
} | |
} | |
void parse_instructions(String str) | |
{ | |
int delimiter_pos = str.indexOf(" "); | |
String command = str.substring(0, delimiter_pos); // command | |
String params = str.substring(delimiter_pos+1); // parameter | |
if(command.equals("l")) { | |
// left | |
servo.write(180); | |
} | |
if(command.equals("c")) { | |
// center | |
servo.write(90); | |
} | |
if(command.equals("r")) { | |
// right | |
servo.write(0); | |
} | |
if(command.equals("f")) { | |
// forward | |
digitalWrite(forwardPin, LOW); | |
digitalWrite(backwardPin, HIGH); | |
} | |
if(command.equals("b")) { | |
// forward | |
digitalWrite(forwardPin, HIGH); | |
digitalWrite(backwardPin, LOW); | |
} | |
if(command.equals("s")) { | |
// stop | |
digitalWrite(forwardPin, HIGH); | |
digitalWrite(backwardPin, HIGH); | |
} | |
} | |
void setup() { | |
//USE_SERIAL.begin(921600); | |
USE_SERIAL.begin(115200); | |
servo.attach(servoPin); | |
pinMode(forwardPin, OUTPUT); | |
pinMode(backwardPin, OUTPUT); | |
digitalWrite(forwardPin, HIGH); | |
digitalWrite(backwardPin, HIGH); | |
USE_SERIAL.setDebugOutput(true); | |
USE_SERIAL.println(); | |
USE_SERIAL.println(); | |
USE_SERIAL.println(); | |
for(uint8_t t = 4; t > 0; t--) { | |
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); | |
USE_SERIAL.flush(); | |
delay(1000); | |
} | |
WiFiMulti.addAP("xxx", "xxx"); | |
while(WiFiMulti.run() != WL_CONNECTED) { | |
delay(100); | |
} | |
// start webSocket server | |
webSocket.begin(); | |
webSocket.onEvent(webSocketEvent); | |
if(MDNS.begin("speed2")) { | |
USE_SERIAL.println("MDNS responder started"); | |
} | |
// handle index | |
server.on("/", []() { | |
// send index.html | |
server.send(200, "text/html", "<html> <head> <meta charset='utf-8'> <title>Remote Control</title> <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'/> <style>.pad{width:50%; height:50%; position:absolute}</style> </head> <body> <div style='width:100vw;height100vh;'> <div id='f' class='pad' style='top:0;left:0;background:#6686b7'></div><div id='s' class='pad' style='top:50%;left:0;background:#54c1de'></div><div id='l' class='pad' style='top:0;right:0;background:#ff5e63'></div><div id='r' class='pad' style='top:50%;right:0;background:#fcba55'></div></div><script type='text/javascript'> window.onload=function (){boardPath=location.hash ? location.hash.substring(1) : location.hostname; connection=new WebSocket('ws://'+boardPath+':81/', ['arduino']); connection.onopen=function (){connection.send('Connect ' + new Date());}; connection.onerror=function (error){console.log('WebSocket Error ', error);}; connection.onmessage=function (e){console.log('Server: ', e.data);}; createEvent=function (n){return function (e){console.log(n); e.preventDefault(); connection.send(n);};}; forwardButton=document.getElementById('f'); backwardButton=document.getElementById('s'); leftButton=document.getElementById('l'); rightButton=document.getElementById('r'); forwardButton.addEventListener('touchstart', createEvent('f')); forwardButton.addEventListener('mousedown', createEvent('f')); forwardButton.addEventListener('touchend', createEvent('s')); forwardButton.addEventListener('mouseup', createEvent('s')); backwardButton.addEventListener('touchstart', createEvent('b')); backwardButton.addEventListener('mousedown', createEvent('b')); backwardButton.addEventListener('touchend', createEvent('s')); backwardButton.addEventListener('mouseup', createEvent('s')); leftButton.addEventListener('touchstart', createEvent('l')); leftButton.addEventListener('mousedown', createEvent('l')); leftButton.addEventListener('touchend', createEvent('c')); leftButton.addEventListener('mouseup', createEvent('c')); rightButton.addEventListener('touchstart', createEvent('r')); rightButton.addEventListener('mousedown', createEvent('r')); rightButton.addEventListener('touchend', createEvent('c')); rightButton.addEventListener('mouseup', createEvent('c'));}; </script> </body></html>"); | |
}); | |
server.begin(); | |
// Add service to MDNS | |
MDNS.addService("http", "tcp", 80); | |
MDNS.addService("ws", "tcp", 81); | |
} | |
void loop() { | |
webSocket.loop(); | |
server.handleClient(); | |
} |
print('Booting...') | |
import network | |
import utime | |
import webrepl | |
SSID = 'WIFI NETWORK NAME' | |
PASSWORD = 'WIFI NETWORK PASSWORD' | |
sta = network.WLAN(network.STA_IF) | |
sta.active(True) | |
sta.connect(SSID, PASSWORD) | |
timeout = 50 | |
while not sta.isconnected(): | |
utime.sleep_ms(100) | |
timeout -= 1 | |
if timeout == 0: | |
print('Could not connect to wifi network') | |
break | |
if sta.isconnected(): | |
print('connected', sta.ifconfig()) | |
webrepl.start(password=123456) | |
else: | |
print('not connected') |
from machine import Pin, PWM | |
class Motor(): | |
def __init__(self, pin_number): | |
pin = Pin(pin_number, Pin.OUT) | |
self.motor = PWM(pin) | |
self.motor.freq(1000) | |
self.motor.duty(1) | |
def set_value(self, value=1): | |
self.motor.duty(value) | |
def forward(self): | |
self.set_value(1020) | |
def backward(self): | |
self.set_value(100) | |
def stop(self): | |
self.set_value(1) | |
motor1 = Motor(13) | |
motor2 = Motor(15) | |
m1f = motor1.forward | |
m1b = motor1.backward | |
m1s = motor1.stop | |
m2f = motor2.forward | |
m2b = motor2.backward | |
m2s = motor2.stop |
<!-- minified with on https://kangax.github.io/html-minifier/ --> | |
<html> | |
<head> | |
<meta charset='utf-8'> | |
<title>Remote Control</title> | |
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' /> | |
<style> | |
.pad { | |
width:50%; | |
height:50%; | |
position:absolute | |
} | |
</style> | |
</head> | |
<body> | |
<div style='width:100vw;height100vh;'> | |
<div id='m1f' class='pad' style='top:0;left:0;background:#6686b7'></div> | |
<div id='m1b' class='pad' style='top:50%;left:0;background:#54c1de'></div> | |
<div id='m2f' class='pad' style='top:0;right:0;background:#ff5e63'></div> | |
<div id='m2b' class='pad' style='top:50%;right:0;background:#fcba55'></div> | |
</div> | |
<script type="text/javascript" src="webrepl.js"></script> | |
<script type='text/javascript'> | |
// Please: All the credit to the FABULOUS work of https://github.com/micropython/webrepl | |
class WebREPL { | |
constructor(opts) { | |
opts = opts || {} | |
this.binaryState = 0 | |
this.ip = opts.ip || '192.168.1.4' | |
this.password = opts.password || 'micropythoN' | |
this.sendFileName = '' | |
this.sendFileData = new ArrayBuffer() | |
this.getFileName = '' | |
this.getFileData = new ArrayBuffer() | |
this.STOP = '\r\x03' // CTRL-C 2x | |
this.RESET = '\r\x04' // CTRL-D | |
this.ENTER_RAW_REPL = '\r\x01' // CTRL-A | |
this.EXIT_RAW_REPL = '\r\x04\r\x02' // CTRL-D + CTRL-B | |
if (opts.autoconnect) { | |
this.connect() | |
} | |
} | |
_decodeResp(data) { | |
if (data[0] == 'W'.charCodeAt(0) && data[1] == 'B'.charCodeAt(0)) { | |
var code = data[2] | (data[3] << 8) | |
return code; | |
} else { | |
return -1; | |
} | |
} | |
_handleMessage(event) { | |
if (event.data instanceof ArrayBuffer) { | |
let data = new Uint8Array(event.data) | |
switch (this.binaryState) { | |
case 11: | |
// first response for put | |
if (this._decodeResp(data) == 0) { | |
// send file data in chunks | |
for (let offset = 0; offset < this.sendFileData.length; offset += 1024) { | |
this.ws.send(this.sendFileData.slice(offset, offset + 1024)) | |
} | |
this.binaryState = 12 | |
} | |
break | |
case 12: | |
// final response for put | |
if (this._decodeResp(data) == 0) { | |
console.log(`Sent ${this.sendFileName}, ${this.sendFileData.length} bytes`) | |
} else { | |
console.log(`Failed sending ${this.sendFileName}`) | |
} | |
this.binaryState = 0 | |
break; | |
case 21: | |
// first response for get | |
if (this._decodeResp(data) == 0) { | |
this.binaryState = 22 | |
var rec = new Uint8Array(1) | |
rec[0] = 0 | |
this.ws.send(rec) | |
} | |
break; | |
case 22: { | |
// file data | |
var sz = data[0] | (data[1] << 8) | |
if (data.length == 2 + sz) { | |
// we assume that the data comes in single chunks | |
if (sz == 0) { | |
// end of file | |
this.binaryState = 23 | |
} else { | |
// accumulate incoming data to this.getFileData | |
var new_buf = new Uint8Array(this.getFileData.length + sz) | |
new_buf.set(this.getFileData) | |
new_buf.set(data.slice(2), this.getFileData.length) | |
this.getFileData = new_buf | |
console.log('Getting ' + this.getFileName + ', ' + this.getFileData.length + ' bytes') | |
var rec = new Uint8Array(1) | |
rec[0] = 0 | |
this.ws.send(rec) | |
} | |
} else { | |
this.binaryState = 0 | |
} | |
break; | |
} | |
case 23: | |
// final response | |
if (this._decodeResp(data) == 0) { | |
console.log(`Got ${this.getFileName}, ${this.getFileData.length} bytes`) | |
this.saveAs(new Blob([this.getFileData], {type: "application/octet-stream"}), this.getFileName) | |
} else { | |
console.log(`Failed getting ${this.getFileName}`) | |
} | |
this.binaryState = 0 | |
break | |
case 31: | |
// first (and last) response for GET_VER | |
console.log('GET_VER', data) | |
this.binaryState = 0 | |
break | |
} | |
} | |
// If is asking for password, send password | |
if( event.data == 'Password: ' ) { | |
this.ws.send(`${this.password}\r`) | |
} | |
this.onMessage(event.data) | |
} | |
connect() { | |
this.ws = new WebSocket(`ws://${this.ip}:8266`) | |
this.ws.binaryType = 'arraybuffer' | |
this.ws.onopen = () => { | |
this.onConnected() | |
this.ws.onmessage = this._handleMessage.bind(this) | |
} | |
} | |
disconnect() { | |
this.ws.close() | |
} | |
onConnected() { | |
console.log('onConnected') | |
} | |
onMessage(msg) { | |
console.log('onMessage', msg) | |
} | |
saveAs(blob) { | |
console.log(`saving as: ${blob}`) | |
} | |
sendStop() { | |
this.eval(this.STOP) | |
} | |
softReset() { | |
this.sendStop() | |
this.eval(this.RESET) | |
} | |
enterRawRepl() { | |
this.eval(this.ENTER_RAW_REPL) | |
} | |
exitRawRepl() { | |
this.eval(this.EXIT_RAW_REPL) | |
} | |
execRaw(raw) { | |
this.eval(raw) | |
if (raw.indexOf('\n') == -1) { | |
this.eval('\r') | |
} | |
} | |
exec(command) { | |
this.eval(command) | |
} | |
execFromString(code) { | |
this.sendStop() | |
this.enterRawRepl() | |
this.execRaw(code) | |
this.exitRawRepl() | |
} | |
eval(command) { | |
this.ws.send(`${command}`) | |
} | |
_sendFile() { | |
let dest_fname = this.sendFileName | |
let dest_fsize = this.sendFileData.length | |
// WEBREPL_FILE = "<2sBBQLH64s" | |
let rec = new Uint8Array(2 + 1 + 1 + 8 + 4 + 2 + 64) | |
rec[0] = 'W'.charCodeAt(0) | |
rec[1] = 'A'.charCodeAt(0) | |
rec[2] = 1 // put | |
rec[3] = 0 | |
rec[4] = 0; rec[5] = 0; rec[6] = 0; rec[7] = 0; rec[8] = 0; rec[9] = 0; rec[10] = 0; rec[11] = 0; | |
rec[12] = dest_fsize & 0xff; rec[13] = (dest_fsize >> 8) & 0xff; rec[14] = (dest_fsize >> 16) & 0xff; rec[15] = (dest_fsize >> 24) & 0xff; | |
rec[16] = dest_fname.length & 0xff; rec[17] = (dest_fname.length >> 8) & 0xff; | |
for (let i = 0; i < 64; ++i) { | |
if (i < dest_fname.length) { | |
rec[18 + i] = dest_fname.charCodeAt(i) | |
} else { | |
rec[18 + i] = 0 | |
} | |
} | |
// initiate put | |
this.binaryState = 11 | |
console.log('Sending ' + this.sendFileName + '...') | |
this.ws.send(rec) | |
} | |
sendFile(file) { | |
this.sendFileName = file.name | |
let reader = new FileReader() | |
reader.onload = (e) => { | |
this.sendFileData = new Uint8Array(e.target.result) | |
this._sendFile() | |
}; | |
reader.readAsArrayBuffer(file) | |
} | |
loadFile(path) { | |
// WEBREPL_FILE = "<2sBBQLH64s" | |
let rec = new Uint8Array(2 + 1 + 1 + 8 + 4 + 2 + 64); | |
rec[0] = 'W'.charCodeAt(0); | |
rec[1] = 'A'.charCodeAt(0); | |
rec[2] = 2; // get | |
rec[3] = 0; | |
rec[4] = 0; rec[5] = 0; rec[6] = 0; rec[7] = 0; rec[8] = 0; rec[9] = 0; rec[10] = 0; rec[11] = 0; | |
rec[12] = 0; rec[13] = 0; rec[14] = 0; rec[15] = 0; | |
rec[16] = path.length & 0xff; rec[17] = (path.length >> 8) & 0xff; | |
for (let i = 0; i < 64; ++i) { | |
if (i < path.length) { | |
rec[18 + i] = path.charCodeAt(i); | |
} else { | |
rec[18 + i] = 0; | |
} | |
} | |
// initiate get | |
this.binaryState = 21; | |
this.getFileName = path; | |
this.getFileData = new Uint8Array(0); | |
console.log('Getting ' + this.getFileName + '...'); | |
this.ws.send(rec); | |
} | |
removeFile(filename) { | |
const pCode = `from os import remove | |
remove('${filename}')` | |
this.execFromString(pCode) | |
} | |
} | |
window.onload = function () { | |
boardPath = location.hash ? location.hash.substring(1) : location.hostname; | |
window.repl = new WebREPL({ | |
ip: boardPath || '192.168.0.17', | |
password: '123456', | |
autoconnect: true | |
}) | |
repl.onMessage = (msg) => { | |
if (typeof msg === 'string') { | |
console.log(msg) | |
// consoleOut.innerText = (consoleOut.innerText + msg).slice(-100) | |
} | |
} | |
createEvent = function (n) { | |
return function (e) { | |
// console.log(`${n}()\r\n`); | |
e.preventDefault(); | |
repl.eval(`${n}()\r\n`) | |
}; | |
}; | |
registerEvents = function (n) { | |
forwardButton = document.getElementById('m'+n+'f'); | |
backwardButton = document.getElementById('m'+n+'b'); | |
forwardButton.addEventListener('touchstart', createEvent('m'+n+'f')); | |
forwardButton.addEventListener('mousedown', createEvent('m'+n+'f')); | |
forwardButton.addEventListener('touchend', createEvent('m'+n+'s')); | |
forwardButton.addEventListener('mouseup', createEvent('m'+n+'s')); | |
backwardButton.addEventListener('touchstart', createEvent('m'+n+'b')); | |
backwardButton.addEventListener('mousedown', createEvent('m'+n+'b')); | |
backwardButton.addEventListener('touchend', createEvent('m'+n+'s')); | |
backwardButton.addEventListener('mouseup', createEvent('m'+n+'s')); | |
} | |
registerEvents(1); | |
registerEvents(2); | |
}; | |
</script> | |
</body> | |
</html> |
<!-- minified with on https://kangax.github.io/html-minifier/ --> | |
<html> | |
<head> | |
<meta charset='utf-8'> | |
<title>Remote Control</title> | |
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' /> | |
<style> | |
.pad { | |
width:50%; | |
height:50%; | |
position:absolute | |
} | |
</style> | |
</head> | |
<body> | |
<div style='width:100vw;height100vh;'> | |
<div id='m1f' class='pad' style='top:0;left:0;background:#6686b7'></div> | |
<div id='m1b' class='pad' style='top:50%;left:0;background:#54c1de'></div> | |
<div id='m2f' class='pad' style='top:0;right:0;background:#ff5e63'></div> | |
<div id='m2b' class='pad' style='top:50%;right:0;background:#fcba55'></div> | |
</div> | |
<script type='text/javascript'> | |
window.onload = function () { | |
boardPath = location.hash ? location.hash.substring(1) : location.hostname; | |
connection = new WebSocket('ws://'+boardPath+':81/', ['arduino']); | |
connection.onopen = function () { | |
connection.send('Connect ' + new Date()); | |
}; | |
connection.onerror = function (error) { | |
console.log('WebSocket Error ', error); | |
}; | |
connection.onmessage = function (e) { | |
console.log('Server: ', e.data); | |
}; | |
createEvent = function (n) { | |
return function (e) { | |
console.log(n); | |
e.preventDefault(); | |
connection.send(n); | |
}; | |
}; | |
registerEvents = function (n) { | |
forwardButton = document.getElementById('m'+n+'f'); | |
backwardButton = document.getElementById('m'+n+'b'); | |
forwardButton.addEventListener('touchstart', createEvent('m'+n+'f')); | |
forwardButton.addEventListener('mousedown', createEvent('m'+n+'f')); | |
forwardButton.addEventListener('touchend', createEvent('m'+n+'s')); | |
forwardButton.addEventListener('mouseup', createEvent('m'+n+'s')); | |
backwardButton.addEventListener('touchstart', createEvent('m'+n+'b')); | |
backwardButton.addEventListener('mousedown', createEvent('m'+n+'b')); | |
backwardButton.addEventListener('touchend', createEvent('m'+n+'s')); | |
backwardButton.addEventListener('mouseup', createEvent('m'+n+'s')); | |
} | |
registerEvents(1); | |
registerEvents(2); | |
}; | |
</script> | |
</body> | |
</html> |