diff options
Diffstat (limited to 'libraries/Bridge')
-rw-r--r-- | libraries/Bridge/Bridge.cpp | 261 | ||||
-rw-r--r-- | libraries/Bridge/Bridge.h | 107 | ||||
-rw-r--r-- | libraries/Bridge/Console.cpp | 152 | ||||
-rw-r--r-- | libraries/Bridge/Console.h | 68 | ||||
-rw-r--r-- | libraries/Bridge/FileIO.cpp.disabled | 162 | ||||
-rw-r--r-- | libraries/Bridge/FileIO.h | 96 | ||||
-rw-r--r-- | libraries/Bridge/HttpClient.cpp | 53 | ||||
-rw-r--r-- | libraries/Bridge/HttpClient.h | 36 | ||||
-rw-r--r-- | libraries/Bridge/Process.cpp | 115 | ||||
-rw-r--r-- | libraries/Bridge/Process.h | 66 | ||||
-rw-r--r-- | libraries/Bridge/examples/Bridge/Bridge.ino | 104 | ||||
-rw-r--r-- | libraries/Bridge/examples/FileTest/FileTest.ino | 50 | ||||
-rw-r--r-- | libraries/Bridge/examples/HttpClient/HttpClient.ino | 23 | ||||
-rw-r--r-- | libraries/Bridge/examples/Process/Process.ino | 25 |
14 files changed, 1318 insertions, 0 deletions
diff --git a/libraries/Bridge/Bridge.cpp b/libraries/Bridge/Bridge.cpp new file mode 100644 index 0000000..440cde0 --- /dev/null +++ b/libraries/Bridge/Bridge.cpp @@ -0,0 +1,261 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Bridge.h" + +BridgeClass::BridgeClass(Stream &_stream) : index(0), stream(_stream), started(false) { + // Empty +} + +void BridgeClass::begin() { + if (started) + return; + started = true; + + // TODO: A more robust restart + + // Wait for Atheros bootloader to finish startup + do { + dropAll(); + delay(1100); + } while (available()>0); + + // Bridge startup: + // - If the bridge is not running starts it safely + print(CTRL_C); + print(F("\n")); + delay(500); + // Wait for OpenWRT message + // "Press enter to activate console" + print(F("\ncd /usr/lib/python2.7/bridge\n")); + delay(100); + print(F("python -B bridge.py\n")); + delay(1000); + dropAll(); + + // - If the bridge was already running previous commands + // are ignored as "invalid packets". + + // Reset the brigde + uint8_t cmd[] = {'X','X'}; + transfer(cmd, 2); +} + +uint8_t BridgeClass::runCommand(String &command) { + // TODO: do it in a more efficient way + String cmd = "R" + command; + uint8_t res[1]; + transfer((uint8_t*)cmd.c_str(), cmd.length(), res, 1); + return res[0]; +} + +bool BridgeClass::commandIsRunning(uint8_t handle) { + uint8_t cmd[] = {'r', handle}; + uint8_t res[1]; + transfer(cmd, 2, res, 1); + return (res[0] == 1); +} + +unsigned int BridgeClass::commandExitValue(uint8_t handle) { + uint8_t cmd[] = {'W', handle}; + uint8_t res[2]; + transfer(cmd, 2, res, 2); + return (res[0] << 8) + res[1]; +} + +void BridgeClass::cleanCommand(uint8_t handle) { + uint8_t cmd[] = {'w', handle}; + transfer(cmd, 2); +} + +unsigned int BridgeClass::commandOutputAvailable(uint8_t handle) { + uint8_t cmd[] = {'o', handle}; + uint8_t res[1]; + transfer(cmd, 2, res, 1); + return res[0]; +} + +unsigned int BridgeClass::readCommandOutput(uint8_t handle, + uint8_t *buffer, unsigned int size) { + if (size > 255) + size = 255; + uint8_t cmd[] = {'O', handle, size}; + return transfer(cmd, 3, buffer, size); +} + +void BridgeClass::writeCommandInput(uint8_t handle, + const uint8_t *buff, unsigned int size) { + // TODO: do it in a more efficient way + uint8_t *tmp = new uint8_t[size+2]; + tmp[0] = 'I'; + tmp[1] = handle; + memcpy(tmp+2, buff, size); + transfer(tmp, size+2); + delete[] tmp; +} + +unsigned int BridgeClass::readMessage(uint8_t *buff, unsigned int size) { + uint8_t tmp[] = { 'm' }; + return transfer(tmp, 1, buff, size); +} + +void BridgeClass::writeMessage(const uint8_t *buff, unsigned int size) { + // TODO: do it in a more efficient way + uint8_t *tmp = new uint8_t[size+1]; + tmp[0] = 'M'; + memcpy(tmp+1, buff, size); + transfer(tmp, size+1); + delete[] tmp; +} + +unsigned int BridgeClass::messageAvailable() { + uint8_t tmp[] = { 'n' }; + uint8_t res[2]; + transfer(tmp, 1, res, 2); + return (res[0] << 8) + res[1]; +} + +void BridgeClass::put(const char *key, const char *value) { + // TODO: do it in a more efficient way + String cmd = "D"; + cmd += key; + cmd += "\xFE"; + cmd += value; + transfer((uint8_t*)cmd.c_str(), cmd.length()); +} + +unsigned int BridgeClass::get(const char *key, uint8_t *value, unsigned int maxlen) { + // TODO: do it in a more efficient way + unsigned int l = strlen(key); + uint8_t *tmp = new uint8_t[l+1]; + tmp[0] = 'd'; + memcpy(tmp+1, key, strlen(key)); + l = transfer(tmp, l+1, value, maxlen); + if (l<maxlen) + value[l] = 0; // Zero-terminate string + delete[] tmp; + return l; +} + +void BridgeClass::crcUpdate(uint8_t c) { + CRC = CRC ^ c; + CRC = (CRC >> 8) + (CRC << 8); +} + +void BridgeClass::crcReset() { + CRC = 0xAAAA; +} + +void BridgeClass::crcWrite() { + write((char)(CRC >> 8)); + write((char)(CRC & 0xFF)); +} + +bool BridgeClass::crcCheck(uint16_t _CRC) { + return CRC == _CRC; +} + +uint8_t BridgeClass::transfer(const uint8_t *buff, uint8_t len, + uint8_t *rxbuff, uint8_t rxlen) +{ + for ( ; ; delay(100), dropAll() /* Delay for retransmission */) { + // Send packet + crcReset(); + write((char)0xFF); // Start of packet (0xFF) + crcUpdate(0xFF); + write((char)index); // Message index + crcUpdate(index); + write((char)len); // Message length + crcUpdate(len); + for (uint8_t i=0; i<len; i++) { // Payload + write((char)buff[i]); + crcUpdate(buff[i]); + } + crcWrite(); // CRC + + // Wait for ACK in 100ms + if (timedRead(100) != 0xFF) + continue; + crcReset(); + crcUpdate(0xFF); + + // Check packet index + if (timedRead(5) != index) + continue; + crcUpdate(index); + + // Recv len + uint8_t l = timedRead(5); + if (l < 0) + continue; + crcUpdate(l); + + // Recv data + for (uint8_t i=0; i<l; i++) { + int c = timedRead(5); + if (c < 0) + continue; + // Cut received data if rxbuffer is too small + if (i < rxlen) + rxbuff[i] = c; + crcUpdate(c); + } + + // Check CRC + int crc_hi = timedRead(5); + if (crc_hi < 0) + continue; + int crc_lo = timedRead(5); + if (crc_lo < 0) + continue; + if (!crcCheck((crc_hi<<8)+crc_lo)) + continue; + + // Increase index + index++; + + // Return bytes received + if (l > rxlen) + return rxlen; + return l; + } +} + +int BridgeClass::timedRead(unsigned int timeout) { + int c; + unsigned long _startMillis = millis(); + do { + c = read(); + if (c >= 0) return c; + } while(millis() - _startMillis < timeout); + return -1; // -1 indicates timeout +} + +void BridgeClass::dropAll() { + while (available() > 0) { + read(); + } +} + +// Bridge instance +#ifdef __AVR_ATmega32U4__ + // Leonardo variants (where HardwareSerial is Serial1) + SerialBridgeClass Bridge(Serial1); +#else + SerialBridgeClass Bridge(Serial); +#endif diff --git a/libraries/Bridge/Bridge.h b/libraries/Bridge/Bridge.h new file mode 100644 index 0000000..f85fa07 --- /dev/null +++ b/libraries/Bridge/Bridge.h @@ -0,0 +1,107 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef BRIDGE_H_ +#define BRIDGE_H_ + +#include <Arduino.h> +#include <Stream.h> + +class BridgeClass: public Stream { +public: + BridgeClass(Stream &_stream); + void begin(); + + // Methods to handle processes on the linux side + uint8_t runCommand(String &command); + bool commandIsRunning(uint8_t handle); + unsigned int commandExitValue(uint8_t handle); + void cleanCommand(uint8_t handle); + + unsigned int commandOutputAvailable(uint8_t handle); + unsigned int readCommandOutput(uint8_t handle, uint8_t *buff, unsigned int size); + unsigned int readCommandOutput(uint8_t handle, char *buff, unsigned int size) + { return readCommandOutput(handle, reinterpret_cast<uint8_t *>(buff), size); } + + void writeCommandInput(uint8_t handle, const uint8_t *buff, unsigned int size); + void writeCommandInput(uint8_t handle, const char *buff, unsigned int size) + { writeCommandInput(handle, reinterpret_cast<const uint8_t *>(buff), size); } + + // Methods to handle mailbox messages + unsigned int readMessage(uint8_t *buffer, unsigned int size); + void writeMessage(const uint8_t *buffer, unsigned int size); + unsigned int messageAvailable(); + + // Methods to handle key/value datastore + void put(const char *key, const char *value); + unsigned int get(const char *key, uint8_t *buff, unsigned int size); + unsigned int get(const char *key, char *value, unsigned int maxlen) + { get(key, reinterpret_cast<uint8_t *>(value), maxlen); } + + // Print methods (proxy to "stream" object) [CM: are these really needed?] + size_t write(uint8_t c) { return stream.write(c); } + size_t write(const uint8_t *buffer, size_t size) + { return stream.write(buffer, size); } + + // Stream methods (proxy to "stream" object) [CM: are these really needed?] + int available() { return stream.available(); } + int read() { return stream.read(); } + int peek() { return stream.peek(); } + void flush() { stream.flush(); } + + // Trasnfer a frame (with error correction and response) + uint8_t transfer(const uint8_t *buff, uint8_t len, + uint8_t *rxbuff=NULL, uint8_t rxlen=0); +private: + uint8_t index; + int timedRead(unsigned int timeout); + void dropAll(); + +private: + void crcUpdate(uint8_t c); + void crcReset(); + void crcWrite(); + bool crcCheck(uint16_t _CRC); + uint16_t CRC; + +private: + static const char CTRL_C = 3; + Stream &stream; + bool started; +}; + +// This subclass uses a serial port Stream +class SerialBridgeClass : public BridgeClass { +public: + SerialBridgeClass(HardwareSerial &_serial) + : BridgeClass(_serial), serial(_serial) { + // Empty + } + + void begin() { + serial.begin(115200); + BridgeClass::begin(); + } + +private: + HardwareSerial &serial; +}; + +extern SerialBridgeClass Bridge; + +#endif /* BRIDGE_H_ */ diff --git a/libraries/Bridge/Console.cpp b/libraries/Bridge/Console.cpp new file mode 100644 index 0000000..76c6481 --- /dev/null +++ b/libraries/Bridge/Console.cpp @@ -0,0 +1,152 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <Console.h> + +// Default constructor uses global Bridge instance +ConsoleClass::ConsoleClass() : + bridge(Bridge), buffered(0), readPos(0), buffer(NULL) +{ + // Empty +} + +// Constructor with a user provided BridgeClass instance +ConsoleClass::ConsoleClass(BridgeClass &_b) : + bridge(_b), buffered(0), readPos(0), buffer(NULL), + autoFlush(true) +{ + // Empty +} + +ConsoleClass::~ConsoleClass() { + end(); +} + +size_t ConsoleClass::write(uint8_t c) { + if (autoFlush) { + uint8_t tmp[] = { 'P', c }; + bridge.transfer(tmp, 2); + return 1; + } else { + outBuffer[outBuffered++] = c; + if (outBuffered == outBufferSize) + flush(); + } +} + +size_t ConsoleClass::write(const uint8_t *buffer, size_t size) { + if (autoFlush) { + // TODO: do it in a more efficient way + uint8_t *tmp = new uint8_t[size+1]; + tmp[0] = 'P'; + memcpy(tmp+1, buffer, size); + bridge.transfer(tmp, size+1); + delete[] tmp; + return size; + } else { + while (size > 0) { + outBuffer[outBuffered++] = *buffer++; + size--; + if (outBuffered == outBufferSize) + flush(); + } + } +} + +void ConsoleClass::flush() { + if (autoFlush) + return; + + bridge.transfer(outBuffer, outBuffered); + outBuffered = 1; +} + +void ConsoleClass::setBuffer(uint8_t size) { + if (size==0) { + if (!autoFlush) { + delete[] outBuffer; + autoFlush = true; + } + } else { + if (autoFlush) + setBuffer(0); + outBuffer = new uint8_t[size+1]; + outBuffer[0] = 'P'; // WRITE tag + outBufferSize = size+1; + outBuffered = 1; + } +} + +bool ConsoleClass::connected() { + uint8_t tmp = 'a'; + bridge.transfer(&tmp, 1, &tmp, 1); + return tmp==1; +} + +int ConsoleClass::available() { + // Look if there is new data available + doBuffer(); + return buffered; +} + +int ConsoleClass::read() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else { + buffered--; + return buffer[readPos++]; + } +} + +int ConsoleClass::peek() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else + return buffer[readPos]; +} + +void ConsoleClass::doBuffer() { + // If there are already char in buffer exit + if (buffered > 0) + return; + + // Try to buffer up to 32 characters + readPos = 0; + uint8_t tmp[] = { 'p', BUFFER_SIZE }; + buffered = bridge.transfer(tmp, 2, buffer, BUFFER_SIZE); +} + +void ConsoleClass::begin() { + bridge.begin(); + end(); + buffer = new uint8_t[BUFFER_SIZE]; +} + +void ConsoleClass::end() { + if (autoFlush) { + setBuffer(0); + } + if (buffer) { + delete[] buffer; + buffer = NULL; + } +} + +ConsoleClass Console; diff --git a/libraries/Bridge/Console.h b/libraries/Bridge/Console.h new file mode 100644 index 0000000..72a3967 --- /dev/null +++ b/libraries/Bridge/Console.h @@ -0,0 +1,68 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef CONSOLE_H_ +#define CONSOLE_H_ + +#include <Bridge.h> + +class ConsoleClass : public Stream { +public: + // Default constructor uses global Bridge instance + ConsoleClass(); + // Constructor with a user provided BridgeClass instance + ConsoleClass(BridgeClass &_b); + ~ConsoleClass(); + + void begin(); + void end(); + + void setBuffer(uint8_t size); + + bool connected(); + + // Stream methods + // (read from console socket) + int available(); + int read(); + int peek(); + // (write to console socket) + size_t write(uint8_t); + size_t write(const uint8_t *buffer, size_t size); + void flush(); + + operator bool () { return connected(); } + +private: + BridgeClass &bridge; + + void doBuffer(); + uint8_t buffered; + uint8_t readPos; + static const int BUFFER_SIZE = 32; + uint8_t *buffer; + + bool autoFlush; + uint8_t outBuffered; + uint8_t outBufferSize; + uint8_t *outBuffer; +}; + +extern ConsoleClass Console; + +#endif diff --git a/libraries/Bridge/FileIO.cpp.disabled b/libraries/Bridge/FileIO.cpp.disabled new file mode 100644 index 0000000..fc6d3df --- /dev/null +++ b/libraries/Bridge/FileIO.cpp.disabled @@ -0,0 +1,162 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <FileIO.h> + +File::File() : mode(255), filename(NULL) { + // Empty +} + +File::File(const char *_filename, uint8_t _mode) : mode(_mode) { + filename = new char[strlen(_filename)+1]; + strcpy(filename, _filename); +} + +File::operator bool() { + return (mode != 255); +} + +File::~File() { + if (filename) + delete[] filename; +} + +char toHex(uint8_t c) { + if (c<10) + return '0' + c; + else + return 'A' + c - 10; +} + +size_t File::write(uint8_t c) { + Process echo; + echo.begin("arduino-append"); + echo.addParameter(filename); + char chars[] = { '\\', 'x', toHex(c >> 4), toHex(c & 0x0F), '\0' }; + echo.addParameter(chars); + echo.run(); + return 1; +} + +size_t File::write(const uint8_t *buf, size_t size) { + Process echo; + echo.begin("arduino-append"); + echo.addParameter(filename); + echo.addParameter(" \"", true); + for (unsigned int i=0; i<size; i++) { + // slow but requires less memory + char c = buf[i]; + char chars[] = { '\\', 'x', toHex(c >> 4), toHex(c & 0x0F), '\0' }; + echo.addParameter(chars, true); + } + echo.addParameter("\"", true); + echo.run(); + return size; +} + +int File::read() { + return 1; +} + +int File::peek() { + return 1; +} + +int File::available() { + return 1; +} + +void File::flush() { +} + +//int read(void *buf, uint16_t nbyte) +//boolean seek(uint32_t pos) +//uint32_t position() +//uint32_t size() + +void File::close() { + mode = 255; +} + +char *File::name() { + return filename; +} + +//boolean isDirectory(void) +//File openNextFile(uint8_t mode = O_RDONLY); +//void rewindDirectory(void) + + + + + + +boolean SDClass::begin() { + return true; +} + +File SDClass::open(const char *filename, uint8_t mode) { + if (mode == FILE_READ) { + if (exists(filename)) + return File(filename, mode); + } + if (mode == FILE_WRITE) { + Process touch; + touch.begin(">"); + touch.addParameter(filename); + int res = touch.run(); + if (res == 0) + return File(filename, mode); + } + return File(); +} + +boolean SDClass::exists(const char *filepath) { + Process ls; + ls.begin("ls"); + ls.addParameter(filepath); + int res = ls.run(); + return (res == 0); +} + +boolean SDClass::mkdir(const char *filepath) { + Process mk; + mk.begin("mkdir"); + mk.addParameter("-p"); + mk.addParameter(filepath); + int res = mk.run(); + return (res == 0); +} + +boolean SDClass::remove(const char *filepath) { + Process rm; + rm.begin("rm"); + rm.addParameter(filepath); + int res = rm.run(); + return (res == 0); +} + +boolean SDClass::rmdir(const char *filepath) { + Process rm; + rm.begin("rmdir"); + rm.addParameter(filepath); + int res = rm.run(); + return (res == 0); +} + +SDClass SD; diff --git a/libraries/Bridge/FileIO.h b/libraries/Bridge/FileIO.h new file mode 100644 index 0000000..a90ff46 --- /dev/null +++ b/libraries/Bridge/FileIO.h @@ -0,0 +1,96 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __SD_H__ +#define __SD_H__ + +#include <Process.h> + +//#define FILE_READ O_READ +//#define FILE_WRITE (O_READ | O_WRITE | O_CREAT) + +#define FILE_READ 0 +#define FILE_WRITE 1 + +class File : public Process { + +public: + File(); + File(const char *_filename, uint8_t _mode); + ~File(); + + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int read(); + virtual int peek(); + virtual int available(); + virtual void flush(); + int read(void *buf, uint16_t nbyte); + boolean seek(uint32_t pos); + uint32_t position(); + uint32_t size(); + void close(); + operator bool(); + char * name(); + + boolean isDirectory(void); + //File openNextFile(uint8_t mode = O_RDONLY); + void rewindDirectory(void); + + using Print::write; + +private: + char *filename; + uint8_t mode; +}; + +class SDClass { +public: + SDClass() : bridge(Bridge) { } + SDClass(BridgeClass &_b) : bridge(_b) { } + + // This needs to be called to set up the connection to the SD card + // before other methods are used. + boolean begin(); + + // Open the specified file/directory with the supplied mode (e.g. read or + // write, etc). Returns a File object for interacting with the file. + // Note that currently only one file can be open at a time. + File open(const char *filename, uint8_t mode = FILE_READ); + + // Methods to determine if the requested file path exists. + boolean exists(const char *filepath); + + // Create the requested directory heirarchy--if intermediate directories + // do not exist they will be created. + boolean mkdir(const char *filepath); + + // Delete the file. + boolean remove(const char *filepath); + + boolean rmdir(const char *filepath); + +private: + friend class File; + + BridgeClass &bridge; +}; + +extern SDClass SD; + +#endif diff --git a/libraries/Bridge/HttpClient.cpp b/libraries/Bridge/HttpClient.cpp new file mode 100644 index 0000000..510af38 --- /dev/null +++ b/libraries/Bridge/HttpClient.cpp @@ -0,0 +1,53 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "HttpClient.h" + +unsigned int HttpClient::get(String &url) { + begin("curl"); + addParameter(url); + return run(); +} + +unsigned int HttpClient::get(const char *url) { + begin("curl"); + addParameter(url); + return run(); +} + +void HttpClient::getAsynchronously(String &url) { + begin("curl"); + addParameter(url); + runAsynchronously(); +} + +void HttpClient::getAsynchronously(const char *url) { + begin("curl"); + addParameter(url); + runAsynchronously(); +} + +boolean HttpClient::ready() { + return running(); +} + +unsigned int HttpClient::getResult() { + return exitValue(); +} + + diff --git a/libraries/Bridge/HttpClient.h b/libraries/Bridge/HttpClient.h new file mode 100644 index 0000000..940a66d --- /dev/null +++ b/libraries/Bridge/HttpClient.h @@ -0,0 +1,36 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef HTTPCLIENT_H_ +#define HTTPCLIENT_H_ + +#include <Process.h> + +class HttpClient : public Process { +public: + + unsigned int get(String &url); + unsigned int get(const char * url); + void getAsynchronously(String &url); + void getAsynchronously(const char * url); + boolean ready(); + unsigned int getResult(); + +}; + +#endif /* HTTPCLIENT_H_ */ diff --git a/libraries/Bridge/Process.cpp b/libraries/Bridge/Process.cpp new file mode 100644 index 0000000..7265119 --- /dev/null +++ b/libraries/Bridge/Process.cpp @@ -0,0 +1,115 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <Process.h> + +Process::~Process() { + close(); +} + +size_t Process::write(uint8_t c) { + bridge.writeCommandInput(handle, &c, 1); + return 1; +} + +void Process::flush() { +} + +int Process::available() { + // Look if there is new data available + doBuffer(); + return buffered; +} + +int Process::read() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else { + buffered--; + return buffer[readPos++]; + } +} + +int Process::peek() { + doBuffer(); + if (buffered == 0) + return -1; // no chars available + else + return buffer[readPos]; +} + +void Process::doBuffer() { + // If there are already char in buffer exit + if (buffered > 0) + return; + + // Try to buffer up to 32 characters + readPos = 0; + buffered = bridge.readCommandOutput(handle, buffer, sizeof(buffer)); +} + +void Process::begin(String &command) { + close(); + cmdline = new String(command); +} + +void Process::begin(const char *command) { + close(); + cmdline = new String(command); +} + +void Process::addParameter(const char *param) { + *cmdline += "\xFE"; + *cmdline += param; +} + +void Process::addParameter(String ¶m) { + *cmdline += "\xFE"; + *cmdline += param; +} + +void Process::runAsynchronously() { + handle = bridge.runCommand(*cmdline); + delete cmdline; + cmdline = NULL; + + started = true; +} + +boolean Process::running() { + return bridge.commandIsRunning(handle); +} + +unsigned int Process::exitValue() { + return bridge.commandExitValue(handle); +} + +unsigned int Process::run() { + runAsynchronously(); + while (running()) + delay(100); + return exitValue(); +} + +void Process::close() { + if (started) + bridge.cleanCommand(handle); + started = false; +} + diff --git a/libraries/Bridge/Process.h b/libraries/Bridge/Process.h new file mode 100644 index 0000000..b48e046 --- /dev/null +++ b/libraries/Bridge/Process.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2013 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef PROCESS_H_ +#define PROCESS_H_ + +#include <Bridge.h> + +class Process : public Stream { +public: + // Default constructor uses global Bridge instance + Process() : bridge(Bridge), started(false), buffered(0), readPos(0) { } + // Constructor with a user provided BridgeClass instance + Process(BridgeClass &_b) : bridge(_b), started(false), buffered(0), readPos(0) { } + ~Process(); + + void begin(String &command); + void begin(const char *command); + void addParameter(String ¶m); + void addParameter(const char *param); + unsigned int run(); + void runAsynchronously(); + boolean running(); + unsigned int exitValue(); + void close(); + + // Stream methods + // (read from process stdout) + int available(); + int read(); + int peek(); + // (write to process stdin) + size_t write(uint8_t); + void flush(); + +private: + BridgeClass &bridge; + unsigned int handle; + String *cmdline; + boolean started; + +private: + void doBuffer(); + uint8_t buffered; + uint8_t readPos; + static const int BUFFER_SIZE = 64; + uint8_t buffer[BUFFER_SIZE]; + +}; + +#endif diff --git a/libraries/Bridge/examples/Bridge/Bridge.ino b/libraries/Bridge/examples/Bridge/Bridge.ino new file mode 100644 index 0000000..dc453c4 --- /dev/null +++ b/libraries/Bridge/examples/Bridge/Bridge.ino @@ -0,0 +1,104 @@ + +#include <Bridge.h> + +void setup() { + pinMode(13,OUTPUT); + digitalWrite(13, LOW); + Bridge.begin(); + digitalWrite(13, HIGH); +} + +void loop() { + while (Bridge.messageAvailable()) { + uint8_t buff[64]; + int l = Bridge.readMessage(buff, 64); + process(buff, l); + } + delay(100); // Poll every 0.100s +} + +void process(uint8_t buff[], int l) { + // "DWppv" -> digitalWrite(pp, v) + // "DRpp" -> digitalRead(pp) -> "Dpp0" / "Dpp1" + // "AWppvvv" -> analogWrite(pp, vvv) + // "ARpp" -> analogRead(pp) -> "App0000" - "App1023" + // "PIpp" -> pinMode(pp, INPUT) + // "POpp" -> pinMode(pp, OUTPUT) + + // Sanity check + if (l<4 || l>7) + return; + if (buff[2]<'0' || buff[2]>'9') + return; + if (buff[3]<'0' || buff[3]>'9') + return; + char cmd0 = buff[0]; + char cmd1 = buff[1]; + int pin = (buff[2]-'0')*10 + (buff[3]-'0'); + if (pin<0 || pin>13) + return; + + // Command selection + if (l==5 && cmd0=='D' && cmd1=='W') { + char c = buff[4]; + if (c=='0' || c=='1') { + digitalWrite(pin, c-'0'); + reportDigitalRead(pin, true, true); + } + } else if (l==4 && cmd0=='D' && cmd1=='R') { + reportDigitalRead(pin, true, true); + } else if (l==7 && cmd0=='A' && cmd1=='W') { + analogWrite(pin, buff[4]); + reportAnalogRead(pin); + } else if (l==4 && cmd0=='A' && cmd1=='R') { + reportAnalogRead(pin); + } else if (l==4 && cmd0=='P' && cmd1=='I') { + pinMode(pin, INPUT); + reportPinMode(pin, INPUT); + } else if (l==4 && cmd0=='P' && cmd1=='O') { + pinMode(pin, OUTPUT); + reportPinMode(pin, OUTPUT); + } +} + +void reportPinMode(int pin, uint8_t dir) { + uint8_t buff[] = { 'P', 'I', '0', '0' }; + buff[1] = dir == INPUT ? 'I' : 'O'; + buff[2] += pin/10; + buff[3] += pin%10; + Bridge.writeMessage(buff, 4); +} + +void reportDigitalRead(int pin, boolean raw, boolean dataset) { + // "Dpp0" - "Dpp1" + // 0 1 2 3 + uint8_t buff[] = { 'D', '0', '0', '0' }; + buff[1] += pin/10; + buff[2] += pin%10; + if (digitalRead(pin) == HIGH) + buff[3] = '1'; + if (raw) + Bridge.writeMessage(buff, 4); + if (dataset) { + char *val = "0"; + val[0] = buff[3]; + buff[3] = 0; + Bridge.put((const char *)buff, val); + } +} + +void reportAnalogRead(int pin) { + // "App0000" - "App1023" + // 0 1 2 3 4 5 6 + uint8_t buff[] = { 'A', '0', '0', '0', '0', '0', '0' }; + buff[1] += pin/10; + buff[2] += pin%10; + + int v = analogRead(pin); + buff[6] += v%10; v /= 10; + buff[5] += v%10; v /= 10; + buff[4] += v%10; v /= 10; + buff[3] += v; + Bridge.writeMessage(buff, 7); +} + diff --git a/libraries/Bridge/examples/FileTest/FileTest.ino b/libraries/Bridge/examples/FileTest/FileTest.ino new file mode 100644 index 0000000..3fd7ce9 --- /dev/null +++ b/libraries/Bridge/examples/FileTest/FileTest.ino @@ -0,0 +1,50 @@ + +#include <FileIO.h> + +void setup() { + Bridge.begin(); + SD.begin(); + + boolean r; + r=SD.exists("/arduino/test"); + if (r) error("1"); + r=SD.exists("/arduino"); + if (!r) error("2"); + + r=SD.mkdir("/arduino/test"); + if (!r) error("3"); + r=SD.exists("/arduino/test"); + if (!r) error("4"); + + File f = SD.open("/arduino/test/bla", FILE_WRITE); + if (!f) error("5"); + f.println("CIAO!"); + f.close(); + + delay(10000); + + r=SD.rmdir("/arduino/test"); + if (r) error("6"); + r=SD.remove("/arduino/test"); + if (r) error("7"); + + r=SD.remove("/arduino/test/bla"); + if (!r) error("8"); + r=SD.rmdir("/arduino/test"); + if (!r) error("9"); + r=SD.exists("/arduino/test"); + if (r) error("10"); +} + + +void error(const char *s) { + Bridge.print("# ERROR "); + Bridge.println(s); + while (true); +} + +void loop() { +} + + + diff --git a/libraries/Bridge/examples/HttpClient/HttpClient.ino b/libraries/Bridge/examples/HttpClient/HttpClient.ino new file mode 100644 index 0000000..bf5e8ff --- /dev/null +++ b/libraries/Bridge/examples/HttpClient/HttpClient.ino @@ -0,0 +1,23 @@ + +#include <HttpClient.h> + +void setup() { + pinMode(13, OUTPUT); + digitalWrite(13, LOW); + Bridge.begin(); +} + +void loop() { + HttpClient client; + client.get("http://my.server.address/file.php"); + + char c = client.read(); + if (c=='1') + digitalWrite(13, HIGH); + if (c=='0') + digitalWrite(13, LOW); + + delay(5000); +} + + diff --git a/libraries/Bridge/examples/Process/Process.ino b/libraries/Bridge/examples/Process/Process.ino new file mode 100644 index 0000000..248db39 --- /dev/null +++ b/libraries/Bridge/examples/Process/Process.ino @@ -0,0 +1,25 @@ +#include <Process.h> + +void setup() { + pinMode(13,OUTPUT); + digitalWrite(13,LOW); + + Serial.begin(9600); + Bridge.begin(); + + digitalWrite(13,HIGH); + delay(2000); + + Process p; + p.begin("curl"); + p.addParameter("http://arduino.cc/asciilogo.txt"); + p.run(); + + while (p.available()>0) { + char c = p.read(); + Serial.print(c); + } +} + +void loop() { +} |