Simple WebSocket server to control a tank.

Dependencies:   SNICInterface_mod WebSocketServer mbed-rtos mbed PowerControl C12832

au Firefox OS WoTハッカソン on ホワイトデーで使用した、タンクを動かすプログラムです。 ゲームパッドでタンクを操縦します。

ゲームパッドは PC に接続し、ブラウザ上の Web アプリから Gamepad API で入力を取得します。 取得した入力データは WebSocket で mbed 上の WebSocket サーバに送信します。

WebSocket サーバのコードはライブラリ化したので、他のプログラムでもインポートして使えます。

使用した機材

  • LPC1768
  • Murata TypeYD
  • LPC1768 用アプリケーションボード
  • TAMIYA トラック&ホイールセット
  • TAMIYA ダブルキヤボックス(左右独立4速タイプ)
  • TAMIYA ユニバーサルプレート
  • TOSHIBA TA7291P x 2
  • その他、モバイルバッテリー、電池ボックス等

左右のモータードライバにそれぞれ LPC1768 の p12, p13 と p14, p15 のピンを割り当てていますが、必要に応じてコードを変更してください。

コントローラー側(Webアプリ)

https://github.com/chikoski/wotxwot-control

Firefox ブラウザで動作確認しています(他のブラウザでは動かないかも)。 ゲームパッドの左右のスティックの前後の操作が左右それぞれのモータの前転・後転に対応しています。

動いているところの動画

https://www.facebook.com/video.php?v=456620974491805

ハッカソンでは ARM 賞をいただきました!

(参考) au Firefox OS WoTハッカソン on ホワイトデー

http://au-fx.kddi.com/event/20150314/wot_hackathon0314.html

Files at this revision

API Documentation at this revision

Comitter:
flatbird
Date:
Sat Mar 14 00:14:40 2015 +0900
Parent:
6:79ecd4e53456
Child:
8:6635ca3b5a5c
Commit message:
add websocket data frame handling.

Changed in this revision

WebSocketServer.cpp Show annotated file Show diff for this revision Revisions of this file
WebSocketServer.h Show annotated file Show diff for this revision Revisions of this file
--- a/WebSocketServer.cpp	Fri Mar 13 11:55:55 2015 +0000
+++ b/WebSocketServer.cpp	Sat Mar 14 00:14:40 2015 +0900
@@ -25,20 +25,20 @@
 }
 
 void WebSocketServer::run() {
-	TCPSocketConnection connection;
+	// TCPSocketConnection connection;
 	char buf[1024];
 
 	while (true) {
 		bool isWebSocket = false;
-		int ret = mTCPSocketServer.accept(connection);
+		int ret = mTCPSocketServer.accept(mConnection);
 		if (ret != 0) {
 			continue;
 		}
 		printf("New connection\r\n");
-		connection.set_blocking(true);
+		mConnection.set_blocking(true);
 
-		while (connection.is_connected()) {
-			ret = connection.receive(buf, sizeof(buf) - 1);
+		while (mConnection.is_connected()) {
+			ret = mConnection.receive(buf, sizeof(buf) - 1);
 			if (ret == 0) {
 //				printf("No data to receive\r\n");
 				continue;
@@ -48,7 +48,7 @@
 				break;
 			}
 			if (!isWebSocket) {
-				if (this->handleHTTP(buf, ret, connection)) {
+				if (this->handleHTTP(buf, ret)) {
 					isWebSocket = true;
 				} else {
 					printf("ERROR: Non websocket\r\n");
@@ -61,11 +61,12 @@
 			}
 		}
 		printf("closed\r\n");
-		connection.close();
+		mConnection.close();
 	}
 }
 
 bool WebSocketServer::setHandler(const char* path, WebSocketHandler* handler) {
+	mHandler = handler; // support only one handler now
 	return true;
 }
 
@@ -73,7 +74,7 @@
 #define SEC_WEBSOCKET_KEY	"Sec-WebSocket-Key:"
 #define MAGIC_NUMBER		"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
 
-bool WebSocketServer::handleHTTP(char* buf, int size, TCPSocketConnection& connection) {
+bool WebSocketServer::handleHTTP(char* buf, int size) {
 	char* line = &buf[0];
 	char key[128];
 	bool isUpgradeWebSocket = false;
@@ -109,16 +110,70 @@
 	}
 
 	if (isUpgradeWebSocket && isSecWebSocketKeyFound) {
-		this->sendUpgradeResponse(key, connection);
+		this->sendUpgradeResponse(key);
 		return true;
 	}
 
 	return false;
 }
 
+#define OP_CONT		0x0
+#define OP_TEXT		0x1
+#define OP_BINARY	0x2
+#define OP_CLOSE	0x8
+#define OP_PING		0x9
+#define OP_PONG		0xA
+
 bool WebSocketServer::handleWebSocket(char* buf, int size) {
-	buf[size] = '\0';
-	printf("%s\r\n", buf);
+	uint8_t* ptr = (uint8_t*)buf;
+
+	bool fin = (*ptr & 0x80) == 0x80;
+	uint8_t opcode = *ptr & 0xF;
+
+	printf("opcode=%d\r\n", opcode);
+	if (opcode == OP_PING) {
+		*ptr = ((*ptr & 0xF0) | OP_PONG);
+		mConnection.send_all(buf, size);
+		return true;
+	}
+	if (opcode == OP_CLOSE) {
+		return false;
+	}
+	ptr++;
+
+	mPrevFin = fin;
+	if (!fin || !mPrevFin) {
+		printf("WARN: Data consists of multiple frame not supported\r\n");
+		return true; // not an error, just discard it
+	}
+
+	bool mask = (*ptr & 0x80) == 1;
+	uint8_t len = *ptr & 0x7F;
+	ptr++;
+
+	if (len > 125) {
+		printf("WARN: Extended payload lenght not supported\r\n");
+		return true; // not an error, just discard it
+	}
+
+	char* data;
+	if (mask) {
+		char* maskingKey = (char*)ptr;
+		data = (char*)(ptr + 4);
+		for (int i = 0; i < len; i++) {
+        	data[i] = data[i] ^ maskingKey[(i % 4)];
+        }
+	} else {
+		data = (char*)ptr;
+	}
+	if (mHandler) {
+		if (opcode == OP_TEXT) {
+			data[len] = '\0';
+			mHandler->onMessage(data);
+		} else if (opcode == OP_BINARY) {
+			mHandler->onMessage(data, len);
+		}
+	}
 	return true;
 }
 
@@ -169,7 +224,7 @@
     return encoded_data;
 }
 
-bool WebSocketServer::sendUpgradeResponse(char* key, TCPSocketConnection& connection) {
+bool WebSocketServer::sendUpgradeResponse(char* key) {
 	char buf[128];
 
 	if (strlen(key) + sizeof(MAGIC_NUMBER) > sizeof(buf)) {
@@ -191,7 +246,7 @@
     strcpy(ptr, encoded);
     strcpy(ptr+strlen(encoded), "\r\n\r\n");
 
-    int ret = connection.send_all(resp, strlen(resp));
+    int ret = mConnection.send_all(resp, strlen(resp));
     if (ret < 0) {
     	printf("ERROR: Failed to send response\r\n");
     	return false;
--- a/WebSocketServer.h	Fri Mar 13 11:55:55 2015 +0000
+++ b/WebSocketServer.h	Sat Mar 14 00:14:40 2015 +0900
@@ -8,7 +8,8 @@
 public:
     virtual void onOpen() = 0;
     virtual void onClose() = 0;
-    virtual void onMessage() = 0;
+    virtual void onMessage(char* text) = 0;
+    virtual void onMessage(char* data, size_t size) = 0;
     virtual void onError() = 0;
 };
 
@@ -23,11 +24,14 @@
     bool setHandler(const char* path, WebSocketHandler* handler);
 
 private:
-    bool handleHTTP(char* buf, int size, TCPSocketConnection& connection);
+    bool handleHTTP(char* buf, int size);
     bool handleWebSocket(char* buf, int size);
-    bool sendUpgradeResponse(char* key, TCPSocketConnection& connection);
+    bool sendUpgradeResponse(char* key);
 
     TCPSocketServer mTCPSocketServer;
+    TCPSocketConnection mConnection;
+    WebSocketHandler* mHandler; // support only one handler now
+    bool mPrevFin;
 };
 
 #endif
\ No newline at end of file