diff --git a/WebSocketClient.cpp b/WebSocketClient.cpp index 335329b..bd4f1f7 100644 --- a/WebSocketClient.cpp +++ b/WebSocketClient.cpp @@ -2,17 +2,17 @@ WebsocketClient, a websocket client for Arduino Copyright 2011 Kevin Rohling http://kevinrohling.com - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -26,6 +26,7 @@ #include #include #include +#include "WiFlyClient.h" prog_char stringVar[] PROGMEM = "{0}"; prog_char clientHandshakeLine1[] PROGMEM = "GET {0} HTTP/1.1"; @@ -36,7 +37,7 @@ prog_char clientHandshakeLine5[] PROGMEM = "Origin: ArduinoWebSocketClient"; prog_char serverHandshake[] PROGMEM = "HTTP/1.1 101"; PROGMEM const char *WebSocketClientStringTable[] = -{ +{ stringVar, clientHandshakeLine1, clientHandshakeLine2, @@ -46,20 +47,33 @@ PROGMEM const char *WebSocketClientStringTable[] = serverHandshake }; +#ifdef WIFLY +WebSocketClient::WebSocketClient(WiFlySerial &WiFly) : _client(WiFly) { +} + +WebSocketClient::WebSocketClient(const char *ssid, const char *password) : _client(ssid, password) { +} + +WebSocketClient::WebSocketClient(int rxPin, int txPin, const char *ssid, const char *password) : _client(rxPin, txPin, ssid, password) { +} +#endif + + String WebSocketClient::getStringTableItem(int index) { char buffer[35]; strcpy_P(buffer, (char*)pgm_read_word(&(WebSocketClientStringTable[index]))); return String(buffer); } -bool WebSocketClient::connect(char hostname[], char path[], int port) { + +bool WebSocketClient::connect(const char *hostname, const char *path, int port) { bool result = false; if (_client.connect(hostname, port)) { sendHandshake(hostname, path); result = readHandshake(); } - + return result; } @@ -74,7 +88,7 @@ void WebSocketClient::disconnect() { void WebSocketClient::monitor () { char character; - + if (_client.available() > 0 && (character = _client.read()) == 0) { String data = ""; bool endReached = false; @@ -86,7 +100,7 @@ void WebSocketClient::monitor () { data += character; } } - + if (_dataArrivedDelegate != NULL) { _dataArrivedDelegate(*this, data); } @@ -94,21 +108,21 @@ void WebSocketClient::monitor () { } void WebSocketClient::setDataArrivedDelegate(DataArrivedDelegate dataArrivedDelegate) { - _dataArrivedDelegate = dataArrivedDelegate; + _dataArrivedDelegate = dataArrivedDelegate; } -void WebSocketClient::sendHandshake(char hostname[], char path[]) { +void WebSocketClient::sendHandshake(const char *hostname, const char *path) { String stringVar = getStringTableItem(0); String line1 = getStringTableItem(1); String line2 = getStringTableItem(2); String line3 = getStringTableItem(3); String line4 = getStringTableItem(4); String line5 = getStringTableItem(5); - + line1.replace(stringVar, path); line4.replace(stringVar, hostname); - + _client.println(line1); _client.println(line2); _client.println(line3); @@ -122,37 +136,37 @@ bool WebSocketClient::readHandshake() { char character; String handshake = "", line; int maxAttempts = 300, attempts = 0; - - while(_client.available() == 0 && attempts < maxAttempts) - { - delay(100); + + while(_client.available() == 0 && attempts < maxAttempts) + { + delay(100); attempts++; } - + while((line = readLine()) != "") { handshake += line + '\n'; } - + String response = getStringTableItem(6); result = handshake.indexOf(response) != -1; - + if(!result) { _client.stop(); } - + return result; } String WebSocketClient::readLine() { String line = ""; char character; - + while(_client.available() > 0 && (character = _client.read()) != '\n') { if (character != '\r' && character != -1) { line += character; } } - + return line; } @@ -162,3 +176,36 @@ void WebSocketClient::send (String data) { _client.print((char)255); } +// implementation thanks to Tom Waldock and his +// his WiFlySerial project. + +// setDebugChannel +// Conduit for debug output +// must not be a NewSoftSerial instance as incoming interrupts conflicts with outgoing data. +void WebSocketClient::setDebugChannel(Print* pChannel) { + pDebugChannel = pChannel; +#ifdef WIFLY + _client.setDebugChannel(pChannel); +#endif +} +void WebSocketClient::clearDebugChannel() { + pDebugChannel = NULL; +#ifdef WIFLY + _client.clearDebugChannel(); +#endif +} + +void WebSocketClient::DebugPrint(const char* pMessage) { + if ( pDebugChannel ) + pDebugChannel->println(pMessage); +} +void WebSocketClient::DebugPrint(const int iNumber) { + if ( pDebugChannel ) + pDebugChannel->println(iNumber); +} +void WebSocketClient::DebugPrint(const char ch) { + if ( pDebugChannel ) + pDebugChannel->print(ch); +} + + diff --git a/WebSocketClient.h b/WebSocketClient.h index ab4ff77..73bda26 100644 --- a/WebSocketClient.h +++ b/WebSocketClient.h @@ -2,17 +2,17 @@ WebsocketClient, a websocket client for Arduino Copyright 2011 Kevin Rohling http://kevinrohling.com - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -25,28 +25,66 @@ #ifndef WEBSOCKETCLIENT_H #define WEBSOCKETCLIENT_H_ +//Uncomment this to use WIFLY Client +#define WIFLY true + #include #include #include + + +#ifdef WIFLY +#include "WiFlyClient.h" +#include +#else #include -#include "Arduino.h" +#endif -//Uncomment this to use WIFLY Client -#define WIFLY true +#include "Arduino.h" class WebSocketClient { - public: - typedef void (*DataArrivedDelegate)(WebSocketClient client, String data); - bool connect(char hostname[], char path[] = "/", int port = 80); + + public: + +#ifdef WIFLY + WebSocketClient(WiFlySerial &WiFly); + WebSocketClient(const char *ssid, const char *password); + WebSocketClient(int rxPin, int txPin, const char *ssid, const char *password); +#else + WebSocketClient(); +#endif + + typedef void (*DataArrivedDelegate)(WebSocketClient client, String data); + bool connect(const char *hostname, const char *path = "/", int port = 80); bool connected(); void disconnect(); - void monitor(); - void setDataArrivedDelegate(DataArrivedDelegate dataArrivedDelegate); - void send(String data); - private: + void monitor(); + void setDataArrivedDelegate(DataArrivedDelegate dataArrivedDelegate); + void send(String data); + + // debug utilities - use Serial : not NewSoftSerial as it will affect incoming stream. + // should change these to use stream << + void setDebugChannel( Print* pDebug); + Print* getDebugChannel() { return pDebugChannel; }; + void clearDebugChannel(); + void DebugPrint( const char* pMessage); + void DebugPrint( const int iNumber); + void DebugPrint( const char ch); + + + private: + String getStringTableItem(int index); - void sendHandshake(char hostname[], char path[]); + void sendHandshake(const char *hostname, const char *path); + Print* pDebugChannel; + + +#ifndef WIFLY EthernetClient _client; +#else + WiFlyClient _client; +#endif + DataArrivedDelegate _dataArrivedDelegate; bool readHandshake(); String readLine(); diff --git a/WiFlyClient.cpp b/WiFlyClient.cpp new file mode 100644 index 0000000..3485e12 --- /dev/null +++ b/WiFlyClient.cpp @@ -0,0 +1,93 @@ +#include "WiFlyClient.h" +#include + +#define ARD_DEFAULT_RX_PIN 2 +#define ARD_DEFAULT_TX_PIN 3 + +WiFlyClient::WiFlyClient(int rxPin, int txPin, const char *ssid, const char *password) : _WiFly(rxPin, txPin) { + initializeWiFly(ssid, password); +} + +WiFlyClient::WiFlyClient(const char *ssid, const char *password) : _WiFly(ARD_DEFAULT_RX_PIN, ARD_DEFAULT_TX_PIN) { + initializeWiFly(ssid, password); +} + +WiFlyClient::WiFlyClient(WiFlySerial &WiFly) : _WiFly(WiFly) { + +} + + +void WiFlyClient::initializeWiFly(const char *ssid, const char *password) { + _WiFly.begin(); + if (!_WiFly.isConnected()) { + _WiFly.leave(); // restart my link + _WiFly.SendCommand("set com remote 0", "AOK"); + _WiFly.SendCommand("set opt jointmr 5000", "AOK"); + _WiFly.setSSID(ssid); + _WiFly.setPassphrase(password); + _WiFly.join(); + } +} + +bool WiFlyClient::connect(const char *hostname, int port) { + return _WiFly.openConnection(hostname, port); +} + +void WiFlyClient::print(const char &s) { + _WiFly.uart.print(s); +} + +void WiFlyClient::print(const String &s) { + _WiFly.uart.print(s); +} + +void WiFlyClient::println(const String &s) { + _WiFly.uart.println(s); +} + +void WiFlyClient::println() { + _WiFly.uart.println("\n"); +} + +int WiFlyClient::read() { + return _WiFly.uart.read(); +} + +int WiFlyClient::available() { + return _WiFly.uart.available(); +} + +bool WiFlyClient::connected() { + return _WiFly.isConnected(); +} + +void WiFlyClient::stop() { + _WiFly.closeConnection(); +} + +// implementation thanks to Tom Waldock and his +// his WiFlySerial project. + +// setDebugChannel +// Conduit for debug output +// must not be a NewSoftSerial instance as incoming interrupts conflicts with outgoing data. +void WiFlyClient::setDebugChannel(Print* pChannel) { + pDebugChannel = pChannel; +} +void WiFlyClient::clearDebugChannel() { + pDebugChannel = NULL; +} + +void WiFlyClient::DebugPrint(const char* pMessage) { + if ( pDebugChannel ) + pDebugChannel->println(pMessage); +} +void WiFlyClient::DebugPrint(const int iNumber) { + if ( pDebugChannel ) + pDebugChannel->println(iNumber); +} +void WiFlyClient::DebugPrint(const char ch) { + if ( pDebugChannel ) + pDebugChannel->print(ch); +} + diff --git a/WiFlyClient.h b/WiFlyClient.h new file mode 100644 index 0000000..9b260f9 --- /dev/null +++ b/WiFlyClient.h @@ -0,0 +1,54 @@ +#ifndef WIFLYCLIENT_H +#define WIFLYCLIENT_H + +#include "Arduino.h" + +#include +#include +#include + +class WiFlyClient { + + public: + + // constructor expects an initialized, and fully + // connected instance of the WiFly driver. + // Let the user worry about authentication and pin mapping. + WiFlyClient(WiFlySerial &WiFly); + + WiFlyClient(const char *ssid, const char *password); + + WiFlyClient(int rxPin, int txPin, const char *ssid, const char *password); + + bool connect(const char *hostname, int port = 80); + + void print(const char &s); + void print(const String &s); + + void println(const String &s); + void println(); + + int read(); + int available(); + + bool connected(); + void stop(); + + // debug utilities - use Serial : not NewSoftSerial as it will affect incoming stream. + // should change these to use stream << + void setDebugChannel( Print* pDebug); + Print* getDebugChannel() { return pDebugChannel; }; + void clearDebugChannel(); + void DebugPrint( const char* pMessage); + void DebugPrint( const int iNumber); + void DebugPrint( const char ch); + + private: + + WiFlySerial _WiFly; + Print* pDebugChannel; + void initializeWiFly(const char *ssid, const char *password); + +}; + +#endif \ No newline at end of file diff --git a/examples/EchoExample/WiFly_EchoExample/WiFly_EchoExample.ino b/examples/EchoExample/WiFly_EchoExample/WiFly_EchoExample.ino new file mode 100644 index 0000000..5768026 --- /dev/null +++ b/examples/EchoExample/WiFly_EchoExample/WiFly_EchoExample.ino @@ -0,0 +1,26 @@ +#include "Arduino.h" +#include +#include +#include +#include + +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +char server[] = "echo.websocket.org"; +WebSocketClient client(2, 3, "2WIRE598", "8888986907"); + +void setup() { + Serial.begin(9600); + client.setDebugChannel( (Print*) &Serial); + client.connect(server); + client.setDataArrivedDelegate(dataArrived); + client.send("Hello World!"); + Serial.println("here"); +} + +void loop() { + client.monitor(); +} + +void dataArrived(WebSocketClient client, String data) { + Serial.println("Data Arrived: " + data); +}