├── .codespellrc ├── .github ├── dependabot.yml └── workflows │ ├── check-arduino.yml │ ├── compile-examples.yml │ ├── report-size-deltas.yml │ └── spell-check.yml ├── README.adoc ├── examples ├── Bridge │ └── Bridge.ino ├── ConsoleAsciiTable │ └── ConsoleAsciiTable.ino ├── ConsolePixel │ └── ConsolePixel.ino ├── ConsoleRead │ └── ConsoleRead.ino ├── Datalogger │ └── Datalogger.ino ├── FileWriteScript │ └── FileWriteScript.ino ├── HttpClient │ └── HttpClient.ino ├── HttpClientConsole │ └── HttpClientConsole.ino ├── MailboxReadMessage │ └── MailboxReadMessage.ino ├── Process │ └── Process.ino ├── RemoteDueBlink │ └── RemoteDueBlink.ino ├── ShellCommands │ └── ShellCommands.ino ├── TemperatureWebPanel │ ├── TemperatureWebPanel.ino │ └── www │ │ ├── index.html │ │ └── zepto.min.js ├── TimeCheck │ └── TimeCheck.ino ├── WiFiStatus │ └── WiFiStatus.ino ├── YunFirstConfig │ └── YunFirstConfig.ino └── YunSerialTerminal │ └── YunSerialTerminal.ino ├── keywords.txt ├── library.properties └── src ├── Bridge.cpp ├── Bridge.h ├── BridgeClient.cpp ├── BridgeClient.h ├── BridgeSSLClient.cpp ├── BridgeSSLClient.h ├── BridgeServer.cpp ├── BridgeServer.h ├── BridgeUdp.cpp ├── BridgeUdp.h ├── Console.cpp ├── Console.h ├── FileIO.cpp ├── FileIO.h ├── HttpClient.cpp ├── HttpClient.h ├── Mailbox.cpp ├── Mailbox.h ├── Process.cpp ├── Process.h ├── YunClient.h └── YunServer.h /.codespellrc: -------------------------------------------------------------------------------- 1 | # See: https://github.com/codespell-project/codespell#using-a-config-file 2 | [codespell] 3 | # In the event of a false positive, add the problematic word, in all lowercase, to a comma-separated list here: 4 | ignore-words-list = readed,tre 5 | check-filenames = 6 | check-hidden = 7 | skip = ./.git 8 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # See: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#about-the-dependabotyml-file 2 | version: 2 3 | 4 | updates: 5 | # Configure check for outdated GitHub Actions actions in workflows. 6 | # See: https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot 7 | - package-ecosystem: github-actions 8 | directory: / # Check the repository's workflows under /.github/workflows/ 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/workflows/check-arduino.yml: -------------------------------------------------------------------------------- 1 | name: Check Arduino 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | pull_request: 7 | schedule: 8 | # Run every Tuesday at 8 AM UTC to catch breakage caused by new rules added to Arduino Lint. 9 | - cron: "0 8 * * TUE" 10 | workflow_dispatch: 11 | repository_dispatch: 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v2 20 | 21 | - name: Arduino Lint 22 | uses: arduino/arduino-lint-action@v1 23 | with: 24 | compliance: specification 25 | library-manager: update 26 | # Always use this setting for official repositories. Remove for 3rd party projects. 27 | official: true 28 | project-type: library 29 | -------------------------------------------------------------------------------- /.github/workflows/compile-examples.yml: -------------------------------------------------------------------------------- 1 | name: Compile Examples 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | paths: 7 | - ".github/workflows/compile-examples.yml" 8 | - "library.properties" 9 | - "examples/**" 10 | - "src/**" 11 | pull_request: 12 | paths: 13 | - ".github/workflows/compile-examples.yml" 14 | - "library.properties" 15 | - "examples/**" 16 | - "src/**" 17 | schedule: 18 | # Run every Tuesday at 8 AM UTC to catch breakage caused by changes to external resources (libraries, platforms). 19 | - cron: "0 8 * * TUE" 20 | workflow_dispatch: 21 | repository_dispatch: 22 | 23 | jobs: 24 | build: 25 | name: ${{ matrix.board.fqbn }} 26 | runs-on: ubuntu-latest 27 | 28 | env: 29 | SKETCHES_REPORTS_PATH: sketches-reports 30 | 31 | strategy: 32 | fail-fast: false 33 | 34 | matrix: 35 | board: 36 | - fqbn: arduino:avr:yun 37 | platforms: | 38 | - name: arduino:avr 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | - name: Compile examples 45 | uses: arduino/compile-sketches@v1 46 | with: 47 | github-token: ${{ secrets.GITHUB_TOKEN }} 48 | fqbn: ${{ matrix.board.fqbn }} 49 | platforms: ${{ matrix.board.platforms }} 50 | libraries: | 51 | # Install the library from the local path. 52 | - source-path: ./ 53 | # Additional library dependencies can be listed here. 54 | # See: https://github.com/arduino/compile-sketches#libraries 55 | sketch-paths: | 56 | - examples 57 | enable-deltas-report: true 58 | sketches-report-path: ${{ env.SKETCHES_REPORTS_PATH }} 59 | 60 | - name: Save sketches report as workflow artifact 61 | uses: actions/upload-artifact@v2 62 | with: 63 | if-no-files-found: error 64 | path: ${{ env.SKETCHES_REPORTS_PATH }} 65 | name: ${{ env.SKETCHES_REPORTS_PATH }} 66 | -------------------------------------------------------------------------------- /.github/workflows/report-size-deltas.yml: -------------------------------------------------------------------------------- 1 | name: Report Size Deltas 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | paths: 7 | - ".github/workflows/report-size-deltas.yml" 8 | schedule: 9 | # Run at the minimum interval allowed by GitHub Actions. 10 | # Note: GitHub Actions periodically has outages which result in workflow failures. 11 | # In this event, the workflows will start passing again once the service recovers. 12 | - cron: "*/5 * * * *" 13 | workflow_dispatch: 14 | repository_dispatch: 15 | 16 | jobs: 17 | report: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Comment size deltas reports to PRs 21 | uses: arduino/report-size-deltas@v1 22 | with: 23 | # The name of the workflow artifact created by the sketch compilation workflow 24 | sketches-reports-source: sketches-reports 25 | -------------------------------------------------------------------------------- /.github/workflows/spell-check.yml: -------------------------------------------------------------------------------- 1 | name: Spell Check 2 | 3 | # See: https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows 4 | on: 5 | push: 6 | pull_request: 7 | schedule: 8 | # Run every Tuesday at 8 AM UTC to catch new misspelling detections resulting from dictionary updates. 9 | - cron: "0 8 * * TUE" 10 | workflow_dispatch: 11 | repository_dispatch: 12 | 13 | jobs: 14 | spellcheck: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v2 20 | 21 | - name: Spell check 22 | uses: codespell-project/actions-codespell@master 23 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | :repository-owner: arduino-libraries 2 | :repository-name: Bridge 3 | 4 | = {repository-name} Library for Arduino = 5 | 6 | image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml/badge.svg["Check Arduino status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/check-arduino.yml"] 7 | image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml/badge.svg["Compile Examples status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/compile-examples.yml"] 8 | image:https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml/badge.svg["Spell Check status", link="https://github.com/{repository-owner}/{repository-name}/actions/workflows/spell-check.yml"] 9 | 10 | The Bridge library simplifies communication between the ATmega32U4 and the AR9331. 11 | 12 | For more information about this library please visit us at 13 | http://www.arduino.cc/en/Reference/YunBridgeLibrary 14 | 15 | == License == 16 | 17 | Copyright (c) 2014 Arduino LLC. All right reserved. 18 | 19 | This library is free software; you can redistribute it and/or 20 | modify it under the terms of the GNU Lesser General Public 21 | License as published by the Free Software Foundation; either 22 | version 2.1 of the License, or (at your option) any later version. 23 | 24 | This library is distributed in the hope that it will be useful, 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 | Lesser General Public License for more details. 28 | 29 | You should have received a copy of the GNU Lesser General Public 30 | License along with this library; if not, write to the Free Software 31 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 32 | -------------------------------------------------------------------------------- /examples/Bridge/Bridge.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino Yún Bridge example 3 | 4 | This example for the Yun Shield/Yún shows how 5 | to use the Bridge library to access the digital and 6 | analog pins on the board through REST calls. 7 | It demonstrates how you can create your own API when 8 | using REST style calls through the browser. 9 | 10 | Possible commands created in this sketch: 11 | 12 | "/arduino/digital/13" -> digitalRead(13) 13 | "/arduino/digital/13/1" -> digitalWrite(13, HIGH) 14 | "/arduino/analog/2/123" -> analogWrite(2, 123) 15 | "/arduino/analog/2" -> analogRead(2) 16 | "/arduino/mode/13/input" -> pinMode(13, INPUT) 17 | "/arduino/mode/13/output" -> pinMode(13, OUTPUT) 18 | 19 | This example code is part of the public domain 20 | 21 | https://www.arduino.cc/en/Tutorial/LibraryExamples/Bridge 22 | 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | // Listen to the default port 5555, the Yún webserver 30 | // will forward there all the HTTP requests you send 31 | BridgeServer server; 32 | 33 | void setup() { 34 | // Bridge startup 35 | pinMode(13, OUTPUT); 36 | digitalWrite(13, LOW); 37 | Bridge.begin(); 38 | digitalWrite(13, HIGH); 39 | 40 | // Listen for incoming connection only from localhost 41 | // (no one from the external network could connect) 42 | server.listenOnLocalhost(); 43 | server.begin(); 44 | } 45 | 46 | void loop() { 47 | // Get clients coming from server 48 | BridgeClient client = server.accept(); 49 | 50 | // There is a new client? 51 | if (client) { 52 | // Process request 53 | process(client); 54 | 55 | // Close connection and free resources. 56 | client.stop(); 57 | } 58 | 59 | delay(50); // Poll every 50 ms 60 | } 61 | 62 | void process(BridgeClient client) { 63 | // read the command 64 | String command = client.readStringUntil('/'); 65 | 66 | // is "digital" command? 67 | if (command == "digital") { 68 | digitalCommand(client); 69 | } 70 | 71 | // is "analog" command? 72 | if (command == "analog") { 73 | analogCommand(client); 74 | } 75 | 76 | // is "mode" command? 77 | if (command == "mode") { 78 | modeCommand(client); 79 | } 80 | } 81 | 82 | void digitalCommand(BridgeClient client) { 83 | int pin, value; 84 | 85 | // Read pin number 86 | pin = client.parseInt(); 87 | 88 | // If the next character is a '/' it means we have an URL 89 | // with a value like: "/digital/13/1" 90 | if (client.read() == '/') { 91 | value = client.parseInt(); 92 | digitalWrite(pin, value); 93 | } else { 94 | value = digitalRead(pin); 95 | } 96 | 97 | // Send feedback to client 98 | client.print(F("Pin D")); 99 | client.print(pin); 100 | client.print(F(" set to ")); 101 | client.println(value); 102 | 103 | // Update datastore key with the current pin value 104 | String key = "D"; 105 | key += pin; 106 | Bridge.put(key, String(value)); 107 | } 108 | 109 | void analogCommand(BridgeClient client) { 110 | int pin, value; 111 | 112 | // Read pin number 113 | pin = client.parseInt(); 114 | 115 | // If the next character is a '/' it means we have an URL 116 | // with a value like: "/analog/5/120" 117 | if (client.read() == '/') { 118 | // Read value and execute command 119 | value = client.parseInt(); 120 | analogWrite(pin, value); 121 | 122 | // Send feedback to client 123 | client.print(F("Pin D")); 124 | client.print(pin); 125 | client.print(F(" set to analog ")); 126 | client.println(value); 127 | 128 | // Update datastore key with the current pin value 129 | String key = "D"; 130 | key += pin; 131 | Bridge.put(key, String(value)); 132 | } else { 133 | // Read analog pin 134 | value = analogRead(pin); 135 | 136 | // Send feedback to client 137 | client.print(F("Pin A")); 138 | client.print(pin); 139 | client.print(F(" reads analog ")); 140 | client.println(value); 141 | 142 | // Update datastore key with the current pin value 143 | String key = "A"; 144 | key += pin; 145 | Bridge.put(key, String(value)); 146 | } 147 | } 148 | 149 | void modeCommand(BridgeClient client) { 150 | int pin; 151 | 152 | // Read pin number 153 | pin = client.parseInt(); 154 | 155 | // If the next character is not a '/' we have a malformed URL 156 | if (client.read() != '/') { 157 | client.println(F("error")); 158 | return; 159 | } 160 | 161 | String mode = client.readStringUntil('\r'); 162 | 163 | if (mode == "input") { 164 | pinMode(pin, INPUT); 165 | // Send feedback to client 166 | client.print(F("Pin D")); 167 | client.print(pin); 168 | client.print(F(" configured as INPUT!")); 169 | return; 170 | } 171 | 172 | if (mode == "output") { 173 | pinMode(pin, OUTPUT); 174 | // Send feedback to client 175 | client.print(F("Pin D")); 176 | client.print(pin); 177 | client.print(F(" configured as OUTPUT!")); 178 | return; 179 | } 180 | 181 | client.print(F("error: invalid mode ")); 182 | client.print(mode); 183 | } 184 | -------------------------------------------------------------------------------- /examples/ConsoleAsciiTable/ConsoleAsciiTable.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Console ASCII table for Yun Shield/Yún 3 | Prints out byte values in all possible formats: 4 | * as raw binary values 5 | * as ASCII-encoded decimal, hex, octal, and binary values 6 | 7 | For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII 8 | 9 | The circuit: 10 | - Yun Shield/Yún 11 | 12 | created 2006 13 | by Nicholas Zambetti 14 | http://www.zambetti.com 15 | modified 9 Apr 2012 16 | by Tom Igoe 17 | modified 22 May 2013 18 | by Cristian Maglie 19 | 20 | This example code is in the public domain. 21 | 22 | https://www.arduino.cc/en/Tutorial/LibraryExamples/ConsoleAsciiTable 23 | 24 | */ 25 | 26 | #include 27 | 28 | void setup() { 29 | //Initialize Console and wait for port to open: 30 | Bridge.begin(); 31 | Console.begin(); 32 | 33 | // Uncomment the following line to enable buffering: 34 | // - better transmission speed and efficiency 35 | // - needs to call Console.flush() to ensure that all 36 | // transmitted data is sent 37 | 38 | //Console.buffer(64); 39 | 40 | while (!Console) { 41 | ; // wait for Console port to connect. 42 | } 43 | 44 | // prints title with ending line break 45 | Console.println("ASCII Table ~ Character Map"); 46 | } 47 | 48 | // first visible ASCIIcharacter '!' is number 33: 49 | int thisByte = 33; 50 | // you can also write ASCII characters in single quotes. 51 | // for example. '!' is the same as 33, so you could also use this: 52 | //int thisByte = '!'; 53 | 54 | void loop() { 55 | // prints value unaltered, i.e. the raw binary version of the 56 | // byte. The Console monitor interprets all bytes as 57 | // ASCII, so 33, the first number, will show up as '!' 58 | Console.write(thisByte); 59 | 60 | Console.print(", dec: "); 61 | // prints value as string as an ASCII-encoded decimal (base 10). 62 | // Decimal is the default format for Console.print() and Console.println(), 63 | // so no modifier is needed: 64 | Console.print(thisByte); 65 | // But you can declare the modifier for decimal if you want to. 66 | //this also works if you uncomment it: 67 | 68 | // Console.print(thisByte, DEC); 69 | 70 | Console.print(", hex: "); 71 | // prints value as string in hexadecimal (base 16): 72 | Console.print(thisByte, HEX); 73 | 74 | Console.print(", oct: "); 75 | // prints value as string in octal (base 8); 76 | Console.print(thisByte, OCT); 77 | 78 | Console.print(", bin: "); 79 | // prints value as string in binary (base 2) 80 | // also prints ending line break: 81 | Console.println(thisByte, BIN); 82 | 83 | // if printed last visible character '~' or 126, stop: 84 | if (thisByte == 126) { // you could also use if (thisByte == '~') { 85 | // ensure the latest bit of data is sent 86 | Console.flush(); 87 | 88 | // This loop loops forever and does nothing 89 | while (true) { 90 | continue; 91 | } 92 | } 93 | // go on to the next character 94 | thisByte++; 95 | } 96 | -------------------------------------------------------------------------------- /examples/ConsolePixel/ConsolePixel.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Console Pixel 3 | 4 | An example of using Yun Shield/Yún board to receive data from the 5 | Console on the Yún. In this case, the board turns on an LED when 6 | it receives the character 'H', and turns off the LED when it 7 | receives the character 'L'. 8 | 9 | To see the Console, pick your Yún's name and IP address in the Port menu 10 | then open the Port Monitor. You can also see it by opening a terminal window 11 | and typing 12 | ssh root@ yourYunsName.local 'telnet localhost 6571' 13 | then pressing enter. When prompted for the password, enter it. 14 | 15 | 16 | The circuit: 17 | * LED connected from digital pin 13 to ground 18 | 19 | created 2006 20 | by David A. Mellis 21 | modified 25 Jun 2013 22 | by Tom Igoe 23 | 24 | This example code is in the public domain. 25 | 26 | https://www.arduino.cc/en/Tutorial/LibraryExamples/ConsolePixel 27 | 28 | */ 29 | 30 | #include 31 | 32 | const int ledPin = 13; // the pin that the LED is attached to 33 | char incomingByte; // a variable to read incoming Console data into 34 | 35 | void setup() { 36 | Bridge.begin(); // Initialize Bridge 37 | Console.begin(); // Initialize Console 38 | 39 | // Wait for the Console port to connect 40 | while (!Console); 41 | 42 | Console.println("type H or L to turn pin 13 on or off"); 43 | 44 | // initialize the LED pin as an output: 45 | pinMode(ledPin, OUTPUT); 46 | } 47 | 48 | void loop() { 49 | // see if there's incoming Console data: 50 | if (Console.available() > 0) { 51 | // read the oldest byte in the Console buffer: 52 | incomingByte = Console.read(); 53 | Console.println(incomingByte); 54 | // if it's a capital H (ASCII 72), turn on the LED: 55 | if (incomingByte == 'H') { 56 | digitalWrite(ledPin, HIGH); 57 | } 58 | // if it's an L (ASCII 76) turn off the LED: 59 | if (incomingByte == 'L') { 60 | digitalWrite(ledPin, LOW); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /examples/ConsoleRead/ConsoleRead.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Console Read example for Yun Shield/Yún 3 | 4 | Read data coming from bridge using the Console.read() function 5 | and store it in a string. 6 | 7 | To see the Console, pick your Yún's name and IP address in the Port menu 8 | then open the Port Monitor. You can also see it by opening a terminal window 9 | and typing: 10 | ssh root@ yourYunsName.local 'telnet localhost 6571' 11 | then pressing enter. When prompted for the password, enter it. 12 | 13 | created 13 Jun 2013 14 | by Angelo Scialabba 15 | modified 16 June 2013 16 | by Tom Igoe 17 | 18 | This example code is in the public domain. 19 | 20 | https://www.arduino.cc/en/Tutorial/LibraryExamples/ConsoleRead 21 | 22 | */ 23 | 24 | #include 25 | 26 | String name; 27 | 28 | void setup() { 29 | // Initialize Console and wait for port to open: 30 | Bridge.begin(); 31 | Console.begin(); 32 | 33 | // Wait for Console port to connect 34 | while (!Console); 35 | 36 | Console.println("Hi, what's your name?"); 37 | } 38 | 39 | void loop() { 40 | if (Console.available() > 0) { 41 | char c = Console.read(); // read the next char received 42 | // look for the newline character, this is the last character in the string 43 | if (c == '\n') { 44 | //print text with the name received 45 | Console.print("Hi "); 46 | Console.print(name); 47 | Console.println("! Nice to meet you!"); 48 | Console.println(); 49 | // Ask again for name and clear the old name 50 | Console.println("Hi, what's your name?"); 51 | name = ""; // clear the name string 52 | } else { // if the buffer is empty Console.read() returns -1 53 | name += c; // append the read char from Console to the name string 54 | } 55 | } else { 56 | delay(100); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/Datalogger/Datalogger.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SD card datalogger 3 | 4 | This example shows how to log data from three analog sensors 5 | to an SD card mounted on the Yun Shield/Yún using the Bridge library. 6 | 7 | The circuit: 8 | * analog sensors on analog pins 0, 1 and 2 9 | * SD card attached to SD card slot of the Yun Shield/Yún 10 | 11 | Prepare your SD card by creating an empty folder in the SD root 12 | named "arduino". This will ensure that the Yún will create a link 13 | to the SD to the "/mnt/sd" path. 14 | 15 | You can remove the SD card while Linux and the 16 | sketch are running but be careful not to remove it while 17 | the system is writing to it. 18 | 19 | created 24 Nov 2010 20 | modified 9 Apr 2012 21 | by Tom Igoe 22 | adapted to the Yún Bridge library 20 Jun 2013 23 | by Federico Vanzati 24 | modified 21 Jun 2013 25 | by Tom Igoe 26 | 27 | This example code is in the public domain. 28 | 29 | https://www.arduino.cc/en/Tutorial/LibraryExamples/YunDatalogger 30 | 31 | */ 32 | 33 | #include 34 | 35 | void setup() { 36 | // Initialize the Bridge and the Serial 37 | Bridge.begin(); 38 | Serial.begin(9600); 39 | FileSystem.begin(); 40 | 41 | while (!SerialUSB); // wait for Serial port to connect. 42 | SerialUSB.println("Filesystem datalogger\n"); 43 | } 44 | 45 | 46 | void loop() { 47 | // make a string that start with a timestamp for assembling the data to log: 48 | String dataString; 49 | dataString += getTimeStamp(); 50 | dataString += " = "; 51 | 52 | // read three sensors and append to the string: 53 | for (int analogPin = 0; analogPin < 3; analogPin++) { 54 | int sensor = analogRead(analogPin); 55 | dataString += String(sensor); 56 | if (analogPin < 2) { 57 | dataString += ","; // separate the values with a comma 58 | } 59 | } 60 | 61 | // open the file. note that only one file can be open at a time, 62 | // so you have to close this one before opening another. 63 | // The FileSystem card is mounted at the following "/mnt/FileSystema1" 64 | File dataFile = FileSystem.open("/mnt/sd/datalog.txt", FILE_APPEND); 65 | 66 | // if the file is available, write to it: 67 | if (dataFile) { 68 | dataFile.println(dataString); 69 | dataFile.close(); 70 | // print to the serial port too: 71 | SerialUSB.println(dataString); 72 | } 73 | // if the file isn't open, pop up an error: 74 | else { 75 | SerialUSB.println("error opening datalog.txt"); 76 | } 77 | 78 | delay(15000); 79 | 80 | } 81 | 82 | // This function returns a string with the timestamp 83 | String getTimeStamp() { 84 | String result; 85 | Process time; 86 | // date is a command line utility to get the date and the time 87 | // in different formats depending on the additional parameter 88 | time.begin("date"); 89 | time.addParameter("+%D-%T"); // parameters: D for the complete date mm/dd/yy 90 | // T for the time hh:mm:ss 91 | time.run(); // run the command 92 | 93 | // read the output of the command 94 | while (time.available() > 0) { 95 | char c = time.read(); 96 | if (c != '\n') { 97 | result += c; 98 | } 99 | } 100 | 101 | return result; 102 | } 103 | -------------------------------------------------------------------------------- /examples/FileWriteScript/FileWriteScript.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Write to file using FileIO classes. 3 | 4 | This sketch demonstrate how to write file into the Yun Shield/Yún filesystem. 5 | A shell script file is created in /tmp, and it is executed afterwards. 6 | 7 | created 7 June 2010 8 | by Cristian Maglie 9 | 10 | This example code is in the public domain. 11 | 12 | https://www.arduino.cc/en/Tutorial/LibraryExamples/FileWriteScript 13 | 14 | */ 15 | 16 | #include 17 | 18 | void setup() { 19 | // Setup Bridge (needed every time we communicate with the Arduino Yún) 20 | Bridge.begin(); 21 | // Initialize the Serial 22 | SerialUSB.begin(9600); 23 | 24 | while (!SerialUSB); // wait for Serial port to connect. 25 | SerialUSB.println("File Write Script example\n\n"); 26 | 27 | // Setup File IO 28 | FileSystem.begin(); 29 | 30 | // Upload script used to gain network statistics 31 | uploadScript(); 32 | } 33 | 34 | void loop() { 35 | // Run stats script every 5 secs. 36 | runScript(); 37 | delay(5000); 38 | } 39 | 40 | // this function creates a file into the Linux processor that contains a shell script 41 | // to check the network traffic of the WiFi interface 42 | void uploadScript() { 43 | // Write our shell script in /tmp 44 | // Using /tmp stores the script in RAM this way we can preserve 45 | // the limited amount of FLASH erase/write cycles 46 | File script = FileSystem.open("/tmp/wlan-stats.sh", FILE_WRITE); 47 | // Shell script header 48 | script.print("#!/bin/sh\n"); 49 | // shell commands: 50 | // ifconfig: is a command line utility for controlling the network interfaces. 51 | // wlan0 is the interface we want to query 52 | // grep: search inside the output of the ifconfig command the "RX bytes" keyword 53 | // and extract the line that contains it 54 | script.print("ifconfig wlan0 | grep 'RX bytes'\n"); 55 | script.close(); // close the file 56 | 57 | // Make the script executable 58 | Process chmod; 59 | chmod.begin("chmod"); // chmod: change mode 60 | chmod.addParameter("+x"); // x stays for executable 61 | chmod.addParameter("/tmp/wlan-stats.sh"); // path to the file to make it executable 62 | chmod.run(); 63 | } 64 | 65 | 66 | // this function runs the script and reads the output data 67 | void runScript() { 68 | // Run the script and show results on the Serial 69 | Process myscript; 70 | myscript.begin("/tmp/wlan-stats.sh"); 71 | myscript.run(); 72 | 73 | String output = ""; 74 | 75 | // read the output of the script 76 | while (myscript.available()) { 77 | output += (char)myscript.read(); 78 | } 79 | // remove the blank spaces at the beginning and the end of the string 80 | output.trim(); 81 | SerialUSB.println(output); 82 | SerialUSB.flush(); 83 | } 84 | -------------------------------------------------------------------------------- /examples/HttpClient/HttpClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Yún HTTP Client 3 | 4 | This example for the Yun Shield/Yún shows how create a basic 5 | HTTP client that connects to the internet and downloads 6 | content. In this case, you'll connect to the Arduino 7 | website and download a version of the logo as ASCII text. 8 | 9 | created by Tom igoe 10 | May 2013 11 | 12 | This example code is in the public domain. 13 | 14 | https://www.arduino.cc/en/Tutorial/LibraryExamples/HttpClient 15 | 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | void setup() { 22 | // Bridge takes about two seconds to start up 23 | // it can be helpful to use the on-board LED 24 | // as an indicator for when it has initialized 25 | pinMode(13, OUTPUT); 26 | digitalWrite(13, LOW); 27 | Bridge.begin(); 28 | digitalWrite(13, HIGH); 29 | 30 | SerialUSB.begin(9600); 31 | 32 | while (!SerialUSB); // wait for a serial connection 33 | } 34 | 35 | void loop() { 36 | // Initialize the client library 37 | HttpClient client; 38 | 39 | // Make a HTTP request: 40 | client.get("http://www.arduino.cc/asciilogo.txt"); 41 | 42 | // if there are incoming bytes available 43 | // from the server, read them and print them: 44 | while (client.available()) { 45 | char c = client.read(); 46 | SerialUSB.print(c); 47 | } 48 | SerialUSB.flush(); 49 | 50 | delay(5000); 51 | } 52 | -------------------------------------------------------------------------------- /examples/HttpClientConsole/HttpClientConsole.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Yún HTTP Client Console version for Arduino Uno and Mega using Yún Shield 3 | 4 | This example for the Yun Shield/Yún shows how create a basic 5 | HTTP client that connects to the internet and downloads 6 | content. In this case, you'll connect to the Arduino 7 | website and download a version of the logo as ASCII text. 8 | 9 | created by Tom igoe 10 | May 2013 11 | modified by Marco Brianza to use Console 12 | 13 | This example code is in the public domain. 14 | 15 | https://www.arduino.cc/en/Tutorial/LibraryExamples/HttpClient 16 | 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | void setup() { 24 | // Bridge takes about two seconds to start up 25 | // it can be helpful to use the on-board LED 26 | // as an indicator for when it has initialized 27 | pinMode(13, OUTPUT); 28 | digitalWrite(13, LOW); 29 | Bridge.begin(); 30 | digitalWrite(13, HIGH); 31 | 32 | Console.begin(); 33 | 34 | while (!Console); // wait for a serial connection 35 | } 36 | 37 | void loop() { 38 | // Initialize the client library 39 | HttpClient client; 40 | 41 | // Make a HTTP request: 42 | client.get("http://www.arduino.cc/asciilogo.txt"); 43 | 44 | // if there are incoming bytes available 45 | // from the server, read them and print them: 46 | while (client.available()) { 47 | char c = client.read(); 48 | Console.print(c); 49 | } 50 | Console.flush(); 51 | 52 | delay(5000); 53 | } 54 | -------------------------------------------------------------------------------- /examples/MailboxReadMessage/MailboxReadMessage.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Read Messages from the Mailbox 3 | 4 | This example for the Yun Shield/Yún shows how to 5 | read the messages queue, called Mailbox, using the 6 | Bridge library. 7 | The messages can be sent to the queue through REST calls. 8 | Append the message in the URL after the keyword "/mailbox". 9 | Example 10 | 11 | "/mailbox/hello" 12 | 13 | created 3 Feb 2014 14 | by Federico Vanzati & Federico Fissore 15 | 16 | This example code is in the public domain. 17 | 18 | https://www.arduino.cc/en/Tutorial/LibraryExamples/MailboxReadMessage 19 | 20 | */ 21 | 22 | #include 23 | 24 | void setup() { 25 | pinMode(13, OUTPUT); 26 | digitalWrite(13, LOW); 27 | // Initialize Bridge and Mailbox 28 | Bridge.begin(); 29 | Mailbox.begin(); 30 | digitalWrite(13, HIGH); 31 | 32 | // Initialize Serial 33 | SerialUSB.begin(9600); 34 | 35 | // Wait until a Serial Monitor is connected. 36 | while (!SerialUSB); 37 | 38 | SerialUSB.println("Mailbox Read Message\n"); 39 | SerialUSB.println("The Mailbox is checked every 10 seconds. The incoming messages will be shown below.\n"); 40 | } 41 | 42 | void loop() { 43 | String message; 44 | 45 | // if there is a message in the Mailbox 46 | if (Mailbox.messageAvailable()) { 47 | // read all the messages present in the queue 48 | while (Mailbox.messageAvailable()) { 49 | Mailbox.readMessage(message); 50 | SerialUSB.println(message); 51 | } 52 | 53 | SerialUSB.println("Waiting 10 seconds before checking the Mailbox again"); 54 | } 55 | 56 | // wait 10 seconds 57 | delay(10000); 58 | } 59 | -------------------------------------------------------------------------------- /examples/Process/Process.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Running process using Process class. 3 | 4 | This sketch demonstrates how to run Linux processes 5 | using a Yun Shield/Yún 6 | 7 | created 5 Jun 2013 8 | by Cristian Maglie 9 | 10 | This example code is in the public domain. 11 | 12 | https://www.arduino.cc/en/Tutorial/LibraryExamples/Process 13 | 14 | */ 15 | 16 | #include 17 | 18 | void setup() { 19 | // Initialize Bridge 20 | Bridge.begin(); 21 | 22 | // Initialize Serial 23 | SerialUSB.begin(9600); 24 | 25 | // Wait until a Serial Monitor is connected. 26 | while (!SerialUSB); 27 | 28 | // run various example processes 29 | runCurl(); 30 | runCpuInfo(); 31 | } 32 | 33 | void loop() { 34 | // Do nothing here. 35 | } 36 | 37 | void runCurl() { 38 | // Launch "curl" command and get Arduino ASCII art logo from the network 39 | // curl is command line program for transferring data using different internet protocols 40 | Process p; // Create a process and call it "p" 41 | p.begin("curl"); // Process that launch the "curl" command 42 | p.addParameter("http://www.arduino.cc/asciilogo.txt"); // Add the URL parameter to "curl" 43 | p.run(); // Run the process and wait for its termination 44 | 45 | // Print Arduino logo over the Serial 46 | // A process output can be read with the stream methods 47 | while (p.available() > 0) { 48 | char c = p.read(); 49 | SerialUSB.print(c); 50 | } 51 | // Ensure the last bit of data is sent. 52 | SerialUSB.flush(); 53 | } 54 | 55 | void runCpuInfo() { 56 | // Launch "cat /proc/cpuinfo" command (shows info on Atheros CPU) 57 | // cat is a command line utility that shows the content of a file 58 | Process p; // Create a process and call it "p" 59 | p.begin("cat"); // Process that launch the "cat" command 60 | p.addParameter("/proc/cpuinfo"); // Add the cpuifo file path as parameter to cut 61 | p.run(); // Run the process and wait for its termination 62 | 63 | // Print command output on the SerialUSB. 64 | // A process output can be read with the stream methods 65 | while (p.available() > 0) { 66 | char c = p.read(); 67 | SerialUSB.print(c); 68 | } 69 | // Ensure the last bit of data is sent. 70 | SerialUSB.flush(); 71 | } 72 | -------------------------------------------------------------------------------- /examples/RemoteDueBlink/RemoteDueBlink.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Blink 3 | Turns on an LED on for one second, then off for one second, repeatedly. 4 | 5 | Most Arduinos have an on-board LED you can control. On the Uno and 6 | Leonardo, it is attached to digital pin 13. If you're unsure what 7 | pin the on-board LED is connected to on your Arduino model, check 8 | the documentation at http://www.arduino.cc 9 | 10 | This example code is in the public domain. 11 | 12 | modified 8 May 2014 13 | by Scott Fitzgerald 14 | 15 | modified by Marco Brianza to show the remote sketch update feature on Arduino Due using Yún Shield 16 | */ 17 | 18 | #include 19 | 20 | // the setup function runs once when you press reset or power the board 21 | void setup() { 22 | checkForRemoteSketchUpdate(); 23 | // initialize digital pin 13 as an output. 24 | pinMode(13, OUTPUT); 25 | } 26 | 27 | // the loop function runs over and over again forever 28 | void loop() { 29 | digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) 30 | delay(100); // wait for a second 31 | digitalWrite(13, LOW); // turn the LED off by making the voltage LOW 32 | delay(100); // wait for a second 33 | } 34 | -------------------------------------------------------------------------------- /examples/ShellCommands/ShellCommands.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Running shell commands using Process class. 3 | 4 | This sketch demonstrate how to run Linux shell commands 5 | using a Yun Shield/Yún. It runs the wifiCheck script on the Linux side 6 | of the Yún, then uses grep to get just the signal strength line. 7 | Then it uses parseInt() to read the WiFi signal strength as an integer, 8 | and finally uses that number to fade an LED using analogWrite(). 9 | 10 | The circuit: 11 | * Yun Shield/Yún with LED connected to pin 9 12 | 13 | created 12 Jun 2013 14 | by Cristian Maglie 15 | modified 25 June 2013 16 | by Tom Igoe 17 | 18 | This example code is in the public domain. 19 | 20 | http://www.arduino.cc/en/Tutorial/ShellCommands 21 | 22 | */ 23 | 24 | #include 25 | 26 | void setup() { 27 | Bridge.begin(); // Initialize the Bridge 28 | SerialUSB.begin(9600); // Initialize the Serial 29 | 30 | // Wait until a Serial Monitor is connected. 31 | while (!SerialUSB); 32 | } 33 | 34 | void loop() { 35 | Process p; 36 | // This command line runs the WifiStatus script, (/usr/bin/pretty-wifi-info.lua), then 37 | // sends the result to the grep command to look for a line containing the word 38 | // "Signal:" the result is passed to this sketch: 39 | p.runShellCommand("/usr/bin/pretty-wifi-info.lua | grep Signal"); 40 | 41 | // do nothing until the process finishes, so you get the whole output: 42 | while (p.running()); 43 | 44 | // Read command output. runShellCommand() should have passed "Signal: xx&": 45 | while (p.available()) { 46 | int result = p.parseInt(); // look for an integer 47 | int signal = map(result, 0, 100, 0, 255); // map result from 0-100 range to 0-255 48 | analogWrite(9, signal); // set the brightness of LED on pin 9 49 | SerialUSB.println(result); // print the number as well 50 | } 51 | delay(5000); // wait 5 seconds before you do it again 52 | } 53 | -------------------------------------------------------------------------------- /examples/TemperatureWebPanel/TemperatureWebPanel.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Temperature web interface 3 | 4 | This example shows how to serve data from an analog input 5 | via the Yun Shield/Yún built-in webserver using the Bridge library. 6 | 7 | The circuit: 8 | * TMP36 temperature sensor on analog pin A1 9 | * SD card attached to SD card slot of the Yun Shield/Yún 10 | 11 | This sketch must be uploaded via WiFi. REST API must be set to "open". 12 | 13 | Prepare your SD card with an empty folder in the SD root 14 | named "arduino" and a subfolder of that named "www". 15 | This will ensure that the Yún will create a link 16 | to the SD to the "/mnt/sd" path. 17 | 18 | In this sketch folder is a basic webpage and a copy of zepto.js, a 19 | minimized version of jQuery. When you upload your sketch, these files 20 | will be placed in the /arduino/www/TemperatureWebPanel folder on your SD card. 21 | 22 | You can then go to http://arduino.local/sd/TemperatureWebPanel 23 | to see the output of this sketch. 24 | 25 | You can remove the SD card while the Linux and the 26 | sketch are running but be careful not to remove it while 27 | the system is writing to it. 28 | 29 | created 6 July 2013 30 | by Tom Igoe 31 | 32 | This example code is in the public domain. 33 | 34 | https://www.arduino.cc/en/Tutorial/LibraryExamples/TemperatureWebPanel 35 | 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | // Listen on default port 5555, the webserver on the Yún 43 | // will forward there all the HTTP requests for us. 44 | BridgeServer server; 45 | String startString; 46 | long hits = 0; 47 | 48 | void setup() { 49 | SerialUSB.begin(9600); 50 | 51 | // Bridge startup 52 | pinMode(13, OUTPUT); 53 | digitalWrite(13, LOW); 54 | Bridge.begin(); 55 | digitalWrite(13, HIGH); 56 | 57 | // using A0 and A2 as Vcc and gnd for the TMP36 sensor: 58 | pinMode(A0, OUTPUT); 59 | pinMode(A2, OUTPUT); 60 | digitalWrite(A0, HIGH); 61 | digitalWrite(A2, LOW); 62 | 63 | // Listen for incoming connection only from localhost 64 | // (no one from the external network could connect) 65 | server.listenOnLocalhost(); 66 | server.begin(); 67 | 68 | // get the time that this sketch started: 69 | Process startTime; 70 | startTime.runShellCommand("date"); 71 | while (startTime.available()) { 72 | char c = startTime.read(); 73 | startString += c; 74 | } 75 | } 76 | 77 | void loop() { 78 | // Get clients coming from server 79 | BridgeClient client = server.accept(); 80 | 81 | // There is a new client? 82 | if (client) { 83 | // read the command 84 | String command = client.readString(); 85 | command.trim(); //kill whitespace 86 | SerialUSB.println(command); 87 | // is "temperature" command? 88 | if (command == "temperature") { 89 | 90 | // get the time from the server: 91 | Process time; 92 | time.runShellCommand("date"); 93 | String timeString = ""; 94 | while (time.available()) { 95 | char c = time.read(); 96 | timeString += c; 97 | } 98 | SerialUSB.println(timeString); 99 | int sensorValue = analogRead(A1); 100 | // convert the reading to millivolts: 101 | float voltage = sensorValue * (5000.0f / 1024.0f); 102 | // convert the millivolts to temperature celsius: 103 | float temperature = (voltage - 500.0f) / 10.0f; 104 | // print the temperature: 105 | client.print("Current time on the Yún: "); 106 | client.println(timeString); 107 | client.print("
Current temperature: "); 108 | client.print(temperature); 109 | client.print(" °C"); 110 | client.print("
This sketch has been running since "); 111 | client.print(startString); 112 | client.print("
Hits so far: "); 113 | client.print(hits); 114 | } 115 | 116 | // Close connection and free resources. 117 | client.stop(); 118 | hits++; 119 | } 120 | 121 | delay(50); // Poll every 50ms 122 | } 123 | -------------------------------------------------------------------------------- /examples/TemperatureWebPanel/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 0 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/TemperatureWebPanel/www/zepto.min.js: -------------------------------------------------------------------------------- 1 | /* Zepto v1.0-1-ga3cab6c - polyfill zepto detect event ajax form fx - zeptojs.com/license */ 2 | (function(a){String.prototype.trim===a&&(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),Array.prototype.reduce===a&&(Array.prototype.reduce=function(b){if(this===void 0||this===null)throw new TypeError;var c=Object(this),d=c.length>>>0,e=0,f;if(typeof b!="function")throw new TypeError;if(d==0&&arguments.length==1)throw new TypeError;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);while(e0?c.fn.concat.apply([],a):a}function O(a){return a.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function P(a){return a in j?j[a]:j[a]=new RegExp("(^|\\s)"+a+"(\\s|$)")}function Q(a,b){return typeof b=="number"&&!l[O(a)]?b+"px":b}function R(a){var b,c;return i[a]||(b=h.createElement(a),h.body.appendChild(b),c=k(b,"").getPropertyValue("display"),b.parentNode.removeChild(b),c=="none"&&(c="block"),i[a]=c),i[a]}function S(a){return"children"in a?f.call(a.children):c.map(a.childNodes,function(a){if(a.nodeType==1)return a})}function T(c,d,e){for(b in d)e&&(J(d[b])||K(d[b]))?(J(d[b])&&!J(c[b])&&(c[b]={}),K(d[b])&&!K(c[b])&&(c[b]=[]),T(c[b],d[b],e)):d[b]!==a&&(c[b]=d[b])}function U(b,d){return d===a?c(b):c(b).filter(d)}function V(a,b,c,d){return F(b)?b.call(a,c,d):b}function W(a,b,c){c==null?a.removeAttribute(b):a.setAttribute(b,c)}function X(b,c){var d=b.className,e=d&&d.baseVal!==a;if(c===a)return e?d.baseVal:d;e?d.baseVal=c:b.className=c}function Y(a){var b;try{return a?a=="true"||(a=="false"?!1:a=="null"?null:isNaN(b=Number(a))?/^[\[\{]/.test(a)?c.parseJSON(a):a:b):a}catch(d){return a}}function Z(a,b){b(a);for(var c in a.childNodes)Z(a.childNodes[c],b)}var a,b,c,d,e=[],f=e.slice,g=e.filter,h=window.document,i={},j={},k=h.defaultView.getComputedStyle,l={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},m=/^\s*<(\w+|!)[^>]*>/,n=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,o=/^(?:body|html)$/i,p=["val","css","html","text","data","width","height","offset"],q=["after","prepend","before","append"],r=h.createElement("table"),s=h.createElement("tr"),t={tr:h.createElement("tbody"),tbody:r,thead:r,tfoot:r,td:s,th:s,"*":h.createElement("div")},u=/complete|loaded|interactive/,v=/^\.([\w-]+)$/,w=/^#([\w-]*)$/,x=/^[\w-]+$/,y={},z=y.toString,A={},B,C,D=h.createElement("div");return A.matches=function(a,b){if(!a||a.nodeType!==1)return!1;var c=a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.matchesSelector;if(c)return c.call(a,b);var d,e=a.parentNode,f=!e;return f&&(e=D).appendChild(a),d=~A.qsa(e,b).indexOf(a),f&&D.removeChild(a),d},B=function(a){return a.replace(/-+(.)?/g,function(a,b){return b?b.toUpperCase():""})},C=function(a){return g.call(a,function(b,c){return a.indexOf(b)==c})},A.fragment=function(b,d,e){b.replace&&(b=b.replace(n,"<$1>")),d===a&&(d=m.test(b)&&RegExp.$1),d in t||(d="*");var g,h,i=t[d];return i.innerHTML=""+b,h=c.each(f.call(i.childNodes),function(){i.removeChild(this)}),J(e)&&(g=c(h),c.each(e,function(a,b){p.indexOf(a)>-1?g[a](b):g.attr(a,b)})),h},A.Z=function(a,b){return a=a||[],a.__proto__=c.fn,a.selector=b||"",a},A.isZ=function(a){return a instanceof A.Z},A.init=function(b,d){if(!b)return A.Z();if(F(b))return c(h).ready(b);if(A.isZ(b))return b;var e;if(K(b))e=M(b);else if(I(b))e=[J(b)?c.extend({},b):b],b=null;else if(m.test(b))e=A.fragment(b.trim(),RegExp.$1,d),b=null;else{if(d!==a)return c(d).find(b);e=A.qsa(h,b)}return A.Z(e,b)},c=function(a,b){return A.init(a,b)},c.extend=function(a){var b,c=f.call(arguments,1);return typeof a=="boolean"&&(b=a,a=c.shift()),c.forEach(function(c){T(a,c,b)}),a},A.qsa=function(a,b){var c;return H(a)&&w.test(b)?(c=a.getElementById(RegExp.$1))?[c]:[]:a.nodeType!==1&&a.nodeType!==9?[]:f.call(v.test(b)?a.getElementsByClassName(RegExp.$1):x.test(b)?a.getElementsByTagName(b):a.querySelectorAll(b))},c.contains=function(a,b){return a!==b&&a.contains(b)},c.type=E,c.isFunction=F,c.isWindow=G,c.isArray=K,c.isPlainObject=J,c.isEmptyObject=function(a){var b;for(b in a)return!1;return!0},c.inArray=function(a,b,c){return e.indexOf.call(b,a,c)},c.camelCase=B,c.trim=function(a){return a.trim()},c.uuid=0,c.support={},c.expr={},c.map=function(a,b){var c,d=[],e,f;if(L(a))for(e=0;e=0?b:b+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){this.parentNode!=null&&this.parentNode.removeChild(this)})},each:function(a){return e.every.call(this,function(b,c){return a.call(b,c,b)!==!1}),this},filter:function(a){return F(a)?this.not(this.not(a)):c(g.call(this,function(b){return A.matches(b,a)}))},add:function(a,b){return c(C(this.concat(c(a,b))))},is:function(a){return this.length>0&&A.matches(this[0],a)},not:function(b){var d=[];if(F(b)&&b.call!==a)this.each(function(a){b.call(this,a)||d.push(this)});else{var e=typeof b=="string"?this.filter(b):L(b)&&F(b.item)?f.call(b):c(b);this.forEach(function(a){e.indexOf(a)<0&&d.push(a)})}return c(d)},has:function(a){return this.filter(function(){return I(a)?c.contains(this,a):c(this).find(a).size()})},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){var a=this[0];return a&&!I(a)?a:c(a)},last:function(){var a=this[this.length-1];return a&&!I(a)?a:c(a)},find:function(a){var b,d=this;return typeof a=="object"?b=c(a).filter(function(){var a=this;return e.some.call(d,function(b){return c.contains(b,a)})}):this.length==1?b=c(A.qsa(this[0],a)):b=this.map(function(){return A.qsa(this,a)}),b},closest:function(a,b){var d=this[0],e=!1;typeof a=="object"&&(e=c(a));while(d&&!(e?e.indexOf(d)>=0:A.matches(d,a)))d=d!==b&&!H(d)&&d.parentNode;return c(d)},parents:function(a){var b=[],d=this;while(d.length>0)d=c.map(d,function(a){if((a=a.parentNode)&&!H(a)&&b.indexOf(a)<0)return b.push(a),a});return U(b,a)},parent:function(a){return U(C(this.pluck("parentNode")),a)},children:function(a){return U(this.map(function(){return S(this)}),a)},contents:function(){return this.map(function(){return f.call(this.childNodes)})},siblings:function(a){return U(this.map(function(a,b){return g.call(S(b.parentNode),function(a){return a!==b})}),a)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(a){return c.map(this,function(b){return b[a]})},show:function(){return this.each(function(){this.style.display=="none"&&(this.style.display=null),k(this,"").getPropertyValue("display")=="none"&&(this.style.display=R(this.nodeName))})},replaceWith:function(a){return this.before(a).remove()},wrap:function(a){var b=F(a);if(this[0]&&!b)var d=c(a).get(0),e=d.parentNode||this.length>1;return this.each(function(f){c(this).wrapAll(b?a.call(this,f):e?d.cloneNode(!0):d)})},wrapAll:function(a){if(this[0]){c(this[0]).before(a=c(a));var b;while((b=a.children()).length)a=b.first();c(a).append(this)}return this},wrapInner:function(a){var b=F(a);return this.each(function(d){var e=c(this),f=e.contents(),g=b?a.call(this,d):a;f.length?f.wrapAll(g):e.append(g)})},unwrap:function(){return this.parent().each(function(){c(this).replaceWith(c(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(b){return this.each(function(){var d=c(this);(b===a?d.css("display")=="none":b)?d.show():d.hide()})},prev:function(a){return c(this.pluck("previousElementSibling")).filter(a||"*")},next:function(a){return c(this.pluck("nextElementSibling")).filter(a||"*")},html:function(b){return b===a?this.length>0?this[0].innerHTML:null:this.each(function(a){var d=this.innerHTML;c(this).empty().append(V(this,b,a,d))})},text:function(b){return b===a?this.length>0?this[0].textContent:null:this.each(function(){this.textContent=b})},attr:function(c,d){var e;return typeof c=="string"&&d===a?this.length==0||this[0].nodeType!==1?a:c=="value"&&this[0].nodeName=="INPUT"?this.val():!(e=this[0].getAttribute(c))&&c in this[0]?this[0][c]:e:this.each(function(a){if(this.nodeType!==1)return;if(I(c))for(b in c)W(this,b,c[b]);else W(this,c,V(this,d,a,this.getAttribute(c)))})},removeAttr:function(a){return this.each(function(){this.nodeType===1&&W(this,a)})},prop:function(b,c){return c===a?this[0]&&this[0][b]:this.each(function(a){this[b]=V(this,c,a,this[b])})},data:function(b,c){var d=this.attr("data-"+O(b),c);return d!==null?Y(d):a},val:function(b){return b===a?this[0]&&(this[0].multiple?c(this[0]).find("option").filter(function(a){return this.selected}).pluck("value"):this[0].value):this.each(function(a){this.value=V(this,b,a,this.value)})},offset:function(a){if(a)return this.each(function(b){var d=c(this),e=V(this,a,b,d.offset()),f=d.offsetParent().offset(),g={top:e.top-f.top,left:e.left-f.left};d.css("position")=="static"&&(g.position="relative"),d.css(g)});if(this.length==0)return null;var b=this[0].getBoundingClientRect();return{left:b.left+window.pageXOffset,top:b.top+window.pageYOffset,width:Math.round(b.width),height:Math.round(b.height)}},css:function(a,c){if(arguments.length<2&&typeof a=="string")return this[0]&&(this[0].style[B(a)]||k(this[0],"").getPropertyValue(a));var d="";if(E(a)=="string")!c&&c!==0?this.each(function(){this.style.removeProperty(O(a))}):d=O(a)+":"+Q(a,c);else for(b in a)!a[b]&&a[b]!==0?this.each(function(){this.style.removeProperty(O(b))}):d+=O(b)+":"+Q(b,a[b])+";";return this.each(function(){this.style.cssText+=";"+d})},index:function(a){return a?this.indexOf(c(a)[0]):this.parent().children().indexOf(this[0])},hasClass:function(a){return e.some.call(this,function(a){return this.test(X(a))},P(a))},addClass:function(a){return this.each(function(b){d=[];var e=X(this),f=V(this,a,b,e);f.split(/\s+/g).forEach(function(a){c(this).hasClass(a)||d.push(a)},this),d.length&&X(this,e+(e?" ":"")+d.join(" "))})},removeClass:function(b){return this.each(function(c){if(b===a)return X(this,"");d=X(this),V(this,b,c,d).split(/\s+/g).forEach(function(a){d=d.replace(P(a)," ")}),X(this,d.trim())})},toggleClass:function(b,d){return this.each(function(e){var f=c(this),g=V(this,b,e,X(this));g.split(/\s+/g).forEach(function(b){(d===a?!f.hasClass(b):d)?f.addClass(b):f.removeClass(b)})})},scrollTop:function(){if(!this.length)return;return"scrollTop"in this[0]?this[0].scrollTop:this[0].scrollY},position:function(){if(!this.length)return;var a=this[0],b=this.offsetParent(),d=this.offset(),e=o.test(b[0].nodeName)?{top:0,left:0}:b.offset();return d.top-=parseFloat(c(a).css("margin-top"))||0,d.left-=parseFloat(c(a).css("margin-left"))||0,e.top+=parseFloat(c(b[0]).css("border-top-width"))||0,e.left+=parseFloat(c(b[0]).css("border-left-width"))||0,{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||h.body;while(a&&!o.test(a.nodeName)&&c(a).css("position")=="static")a=a.offsetParent;return a})}},c.fn.detach=c.fn.remove,["width","height"].forEach(function(b){c.fn[b]=function(d){var e,f=this[0],g=b.replace(/./,function(a){return a[0].toUpperCase()});return d===a?G(f)?f["inner"+g]:H(f)?f.documentElement["offset"+g]:(e=this.offset())&&e[b]:this.each(function(a){f=c(this),f.css(b,V(this,d,a,f[b]()))})}}),q.forEach(function(a,b){var d=b%2;c.fn[a]=function(){var a,e=c.map(arguments,function(b){return a=E(b),a=="object"||a=="array"||b==null?b:A.fragment(b)}),f,g=this.length>1;return e.length<1?this:this.each(function(a,h){f=d?h:h.parentNode,h=b==0?h.nextSibling:b==1?h.firstChild:b==2?h:null,e.forEach(function(a){if(g)a=a.cloneNode(!0);else if(!f)return c(a).remove();Z(f.insertBefore(a,h),function(a){a.nodeName!=null&&a.nodeName.toUpperCase()==="SCRIPT"&&(!a.type||a.type==="text/javascript")&&!a.src&&window.eval.call(window,a.innerHTML)})})})},c.fn[d?a+"To":"insert"+(b?"Before":"After")]=function(b){return c(b)[a](this),this}}),A.Z.prototype=c.fn,A.uniq=C,A.deserializeValue=Y,c.zepto=A,c}();window.Zepto=Zepto,"$"in window||(window.$=Zepto),function(a){function b(a){var b=this.os={},c=this.browser={},d=a.match(/WebKit\/([\d.]+)/),e=a.match(/(Android)\s+([\d.]+)/),f=a.match(/(iPad).*OS\s([\d_]+)/),g=!f&&a.match(/(iPhone\sOS)\s([\d_]+)/),h=a.match(/(webOS|hpwOS)[\s\/]([\d.]+)/),i=h&&a.match(/TouchPad/),j=a.match(/Kindle\/([\d.]+)/),k=a.match(/Silk\/([\d._]+)/),l=a.match(/(BlackBerry).*Version\/([\d.]+)/),m=a.match(/(BB10).*Version\/([\d.]+)/),n=a.match(/(RIM\sTablet\sOS)\s([\d.]+)/),o=a.match(/PlayBook/),p=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),q=a.match(/Firefox\/([\d.]+)/);if(c.webkit=!!d)c.version=d[1];e&&(b.android=!0,b.version=e[2]),g&&(b.ios=b.iphone=!0,b.version=g[2].replace(/_/g,".")),f&&(b.ios=b.ipad=!0,b.version=f[2].replace(/_/g,".")),h&&(b.webos=!0,b.version=h[2]),i&&(b.touchpad=!0),l&&(b.blackberry=!0,b.version=l[2]),m&&(b.bb10=!0,b.version=m[2]),n&&(b.rimtabletos=!0,b.version=n[2]),o&&(c.playbook=!0),j&&(b.kindle=!0,b.version=j[1]),k&&(c.silk=!0,c.version=k[1]),!k&&b.android&&a.match(/Kindle Fire/)&&(c.silk=!0),p&&(c.chrome=!0,c.version=p[1]),q&&(c.firefox=!0,c.version=q[1]),b.tablet=!!(f||o||e&&!a.match(/Mobile/)||q&&a.match(/Tablet/)),b.phone=!b.tablet&&!!(e||g||h||l||m||p&&a.match(/Android/)||p&&a.match(/CriOS\/([\d.]+)/)||q&&a.match(/Mobile/))}b.call(a,navigator.userAgent),a.__detect=b}(Zepto),function(a){function g(a){return a._zid||(a._zid=d++)}function h(a,b,d,e){b=i(b);if(b.ns)var f=j(b.ns);return(c[g(a)]||[]).filter(function(a){return a&&(!b.e||a.e==b.e)&&(!b.ns||f.test(a.ns))&&(!d||g(a.fn)===g(d))&&(!e||a.sel==e)})}function i(a){var b=(""+a).split(".");return{e:b[0],ns:b.slice(1).sort().join(" ")}}function j(a){return new RegExp("(?:^| )"+a.replace(" "," .* ?")+"(?: |$)")}function k(b,c,d){a.type(b)!="string"?a.each(b,d):b.split(/\s/).forEach(function(a){d(a,c)})}function l(a,b){return a.del&&(a.e=="focus"||a.e=="blur")||!!b}function m(a){return f[a]||a}function n(b,d,e,h,j,n){var o=g(b),p=c[o]||(c[o]=[]);k(d,e,function(c,d){var e=i(c);e.fn=d,e.sel=h,e.e in f&&(d=function(b){var c=b.relatedTarget;if(!c||c!==this&&!a.contains(this,c))return e.fn.apply(this,arguments)}),e.del=j&&j(d,c);var g=e.del||d;e.proxy=function(a){var c=g.apply(b,[a].concat(a.data));return c===!1&&(a.preventDefault(),a.stopPropagation()),c},e.i=p.length,p.push(e),b.addEventListener(m(e.e),e.proxy,l(e,n))})}function o(a,b,d,e,f){var i=g(a);k(b||"",d,function(b,d){h(a,b,d,e).forEach(function(b){delete c[i][b.i],a.removeEventListener(m(b.e),b.proxy,l(b,f))})})}function t(b){var c,d={originalEvent:b};for(c in b)!r.test(c)&&b[c]!==undefined&&(d[c]=b[c]);return a.each(s,function(a,c){d[a]=function(){return this[c]=p,b[a].apply(b,arguments)},d[c]=q}),d}function u(a){if(!("defaultPrevented"in a)){a.defaultPrevented=!1;var b=a.preventDefault;a.preventDefault=function(){this.defaultPrevented=!0,b.call(this)}}}var b=a.zepto.qsa,c={},d=1,e={},f={mouseenter:"mouseover",mouseleave:"mouseout"};e.click=e.mousedown=e.mouseup=e.mousemove="MouseEvents",a.event={add:n,remove:o},a.proxy=function(b,c){if(a.isFunction(b)){var d=function(){return b.apply(c,arguments)};return d._zid=g(b),d}if(typeof c=="string")return a.proxy(b[c],b);throw new TypeError("expected function")},a.fn.bind=function(a,b){return this.each(function(){n(this,a,b)})},a.fn.unbind=function(a,b){return this.each(function(){o(this,a,b)})},a.fn.one=function(a,b){return this.each(function(c,d){n(this,a,b,null,function(a,b){return function(){var c=a.apply(d,arguments);return o(d,b,a),c}})})};var p=function(){return!0},q=function(){return!1},r=/^([A-Z]|layer[XY]$)/,s={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};a.fn.delegate=function(b,c,d){return this.each(function(e,f){n(f,c,d,b,function(c){return function(d){var e,g=a(d.target).closest(b,f).get(0);if(g)return e=a.extend(t(d),{currentTarget:g,liveFired:f}),c.apply(g,[e].concat([].slice.call(arguments,1)))}})})},a.fn.undelegate=function(a,b,c){return this.each(function(){o(this,b,c,a)})},a.fn.live=function(b,c){return a(document.body).delegate(this.selector,b,c),this},a.fn.die=function(b,c){return a(document.body).undelegate(this.selector,b,c),this},a.fn.on=function(b,c,d){return!c||a.isFunction(c)?this.bind(b,c||d):this.delegate(c,b,d)},a.fn.off=function(b,c,d){return!c||a.isFunction(c)?this.unbind(b,c||d):this.undelegate(c,b,d)},a.fn.trigger=function(b,c){if(typeof b=="string"||a.isPlainObject(b))b=a.Event(b);return u(b),b.data=c,this.each(function(){"dispatchEvent"in this&&this.dispatchEvent(b)})},a.fn.triggerHandler=function(b,c){var d,e;return this.each(function(f,g){d=t(typeof b=="string"?a.Event(b):b),d.data=c,d.target=g,a.each(h(g,b.type||b),function(a,b){e=b.proxy(d);if(d.isImmediatePropagationStopped())return!1})}),e},"focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)}}),["focus","blur"].forEach(function(b){a.fn[b]=function(a){return a?this.bind(b,a):this.each(function(){try{this[b]()}catch(a){}}),this}}),a.Event=function(a,b){typeof a!="string"&&(b=a,a=b.type);var c=document.createEvent(e[a]||"Events"),d=!0;if(b)for(var f in b)f=="bubbles"?d=!!b[f]:c[f]=b[f];return c.initEvent(a,d,!0,null,null,null,null,null,null,null,null,null,null,null,null),c.isDefaultPrevented=function(){return this.defaultPrevented},c}}(Zepto),function($){function triggerAndReturn(a,b,c){var d=$.Event(b);return $(a).trigger(d,c),!d.defaultPrevented}function triggerGlobal(a,b,c,d){if(a.global)return triggerAndReturn(b||document,c,d)}function ajaxStart(a){a.global&&$.active++===0&&triggerGlobal(a,null,"ajaxStart")}function ajaxStop(a){a.global&&!--$.active&&triggerGlobal(a,null,"ajaxStop")}function ajaxBeforeSend(a,b){var c=b.context;if(b.beforeSend.call(c,a,b)===!1||triggerGlobal(b,c,"ajaxBeforeSend",[a,b])===!1)return!1;triggerGlobal(b,c,"ajaxSend",[a,b])}function ajaxSuccess(a,b,c){var d=c.context,e="success";c.success.call(d,a,e,b),triggerGlobal(c,d,"ajaxSuccess",[b,c,a]),ajaxComplete(e,b,c)}function ajaxError(a,b,c,d){var e=d.context;d.error.call(e,c,b,a),triggerGlobal(d,e,"ajaxError",[c,d,a]),ajaxComplete(b,c,d)}function ajaxComplete(a,b,c){var d=c.context;c.complete.call(d,b,a),triggerGlobal(c,d,"ajaxComplete",[b,c]),ajaxStop(c)}function empty(){}function mimeToDataType(a){return a&&(a=a.split(";",2)[0]),a&&(a==htmlType?"html":a==jsonType?"json":scriptTypeRE.test(a)?"script":xmlTypeRE.test(a)&&"xml")||"text"}function appendQuery(a,b){return(a+"&"+b).replace(/[&?]{1,2}/,"?")}function serializeData(a){a.processData&&a.data&&$.type(a.data)!="string"&&(a.data=$.param(a.data,a.traditional)),a.data&&(!a.type||a.type.toUpperCase()=="GET")&&(a.url=appendQuery(a.url,a.data))}function parseArguments(a,b,c,d){var e=!$.isFunction(b);return{url:a,data:e?b:undefined,success:e?$.isFunction(c)?c:undefined:b,dataType:e?d||c:c}}function serialize(a,b,c,d){var e,f=$.isArray(b);$.each(b,function(b,g){e=$.type(g),d&&(b=c?d:d+"["+(f?"":b)+"]"),!d&&f?a.add(g.name,g.value):e=="array"||!c&&e=="object"?serialize(a,g,c,b):a.add(b,g)})}var jsonpID=0,document=window.document,key,name,rscript=/)<[^<]*)*<\/script>/gi,scriptTypeRE=/^(?:text|application)\/javascript/i,xmlTypeRE=/^(?:text|application)\/xml/i,jsonType="application/json",htmlType="text/html",blankRE=/^\s*$/;$.active=0,$.ajaxJSONP=function(a){if("type"in a){var b="jsonp"+ ++jsonpID,c=document.createElement("script"),d=function(){clearTimeout(g),$(c).remove(),delete window[b]},e=function(c){d();if(!c||c=="timeout")window[b]=empty;ajaxError(null,c||"abort",f,a)},f={abort:e},g;return ajaxBeforeSend(f,a)===!1?(e("abort"),!1):(window[b]=function(b){d(),ajaxSuccess(b,f,a)},c.onerror=function(){e("error")},c.src=a.url.replace(/=\?/,"="+b),$("head").append(c),a.timeout>0&&(g=setTimeout(function(){e("timeout")},a.timeout)),f)}return $.ajax(a)},$.ajaxSettings={type:"GET",beforeSend:empty,success:empty,error:empty,complete:empty,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript",json:jsonType,xml:"application/xml, text/xml",html:htmlType,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},$.ajax=function(options){var settings=$.extend({},options||{});for(key in $.ajaxSettings)settings[key]===undefined&&(settings[key]=$.ajaxSettings[key]);ajaxStart(settings),settings.crossDomain||(settings.crossDomain=/^([\w-]+:)?\/\/([^\/]+)/.test(settings.url)&&RegExp.$2!=window.location.host),settings.url||(settings.url=window.location.toString()),serializeData(settings),settings.cache===!1&&(settings.url=appendQuery(settings.url,"_="+Date.now()));var dataType=settings.dataType,hasPlaceholder=/=\?/.test(settings.url);if(dataType=="jsonp"||hasPlaceholder)return hasPlaceholder||(settings.url=appendQuery(settings.url,"callback=?")),$.ajaxJSONP(settings);var mime=settings.accepts[dataType],baseHeaders={},protocol=/^([\w-]+:)\/\//.test(settings.url)?RegExp.$1:window.location.protocol,xhr=settings.xhr(),abortTimeout;settings.crossDomain||(baseHeaders["X-Requested-With"]="XMLHttpRequest"),mime&&(baseHeaders.Accept=mime,mime.indexOf(",")>-1&&(mime=mime.split(",",2)[0]),xhr.overrideMimeType&&xhr.overrideMimeType(mime));if(settings.contentType||settings.contentType!==!1&&settings.data&&settings.type.toUpperCase()!="GET")baseHeaders["Content-Type"]=settings.contentType||"application/x-www-form-urlencoded";settings.headers=$.extend(baseHeaders,settings.headers||{}),xhr.onreadystatechange=function(){if(xhr.readyState==4){xhr.onreadystatechange=empty,clearTimeout(abortTimeout);var result,error=!1;if(xhr.status>=200&&xhr.status<300||xhr.status==304||xhr.status==0&&protocol=="file:"){dataType=dataType||mimeToDataType(xhr.getResponseHeader("content-type")),result=xhr.responseText;try{dataType=="script"?(1,eval)(result):dataType=="xml"?result=xhr.responseXML:dataType=="json"&&(result=blankRE.test(result)?null:$.parseJSON(result))}catch(e){error=e}error?ajaxError(error,"parsererror",xhr,settings):ajaxSuccess(result,xhr,settings)}else ajaxError(null,xhr.status?"error":"abort",xhr,settings)}};var async="async"in settings?settings.async:!0;xhr.open(settings.type,settings.url,async);for(name in settings.headers)xhr.setRequestHeader(name,settings.headers[name]);return ajaxBeforeSend(xhr,settings)===!1?(xhr.abort(),!1):(settings.timeout>0&&(abortTimeout=setTimeout(function(){xhr.onreadystatechange=empty,xhr.abort(),ajaxError(null,"timeout",xhr,settings)},settings.timeout)),xhr.send(settings.data?settings.data:null),xhr)},$.get=function(a,b,c,d){return $.ajax(parseArguments.apply(null,arguments))},$.post=function(a,b,c,d){var e=parseArguments.apply(null,arguments);return e.type="POST",$.ajax(e)},$.getJSON=function(a,b,c){var d=parseArguments.apply(null,arguments);return d.dataType="json",$.ajax(d)},$.fn.load=function(a,b,c){if(!this.length)return this;var d=this,e=a.split(/\s/),f,g=parseArguments(a,b,c),h=g.success;return e.length>1&&(g.url=e[0],f=e[1]),g.success=function(a){d.html(f?$("
").html(a.replace(rscript,"")).find(f):a),h&&h.apply(d,arguments)},$.ajax(g),this};var escape=encodeURIComponent;$.param=function(a,b){var c=[];return c.add=function(a,b){this.push(escape(a)+"="+escape(b))},serialize(c,a,b),c.join("&").replace(/%20/g,"+")}}(Zepto),function(a){a.fn.serializeArray=function(){var b=[],c;return a(Array.prototype.slice.call(this.get(0).elements)).each(function(){c=a(this);var d=c.attr("type");this.nodeName.toLowerCase()!="fieldset"&&!this.disabled&&d!="submit"&&d!="reset"&&d!="button"&&(d!="radio"&&d!="checkbox"||this.checked)&&b.push({name:c.attr("name"),value:c.val()})}),b},a.fn.serialize=function(){var a=[];return this.serializeArray().forEach(function(b){a.push(encodeURIComponent(b.name)+"="+encodeURIComponent(b.value))}),a.join("&")},a.fn.submit=function(b){if(b)this.bind("submit",b);else if(this.length){var c=a.Event("submit");this.eq(0).trigger(c),c.defaultPrevented||this.get(0).submit()}return this}}(Zepto),function(a,b){function s(a){return t(a.replace(/([a-z])([A-Z])/,"$1-$2"))}function t(a){return a.toLowerCase()}function u(a){return d?d+a:t(a)}var c="",d,e,f,g={Webkit:"webkit",Moz:"",O:"o",ms:"MS"},h=window.document,i=h.createElement("div"),j=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i,k,l,m,n,o,p,q,r={};a.each(g,function(a,e){if(i.style[a+"TransitionProperty"]!==b)return c="-"+t(a)+"-",d=e,!1}),k=c+"transform",r[l=c+"transition-property"]=r[m=c+"transition-duration"]=r[n=c+"transition-timing-function"]=r[o=c+"animation-name"]=r[p=c+"animation-duration"]=r[q=c+"animation-timing-function"]="",a.fx={off:d===b&&i.style.transitionProperty===b,speeds:{_default:400,fast:200,slow:600},cssPrefix:c,transitionEnd:u("TransitionEnd"),animationEnd:u("AnimationEnd")},a.fn.animate=function(b,c,d,e){return a.isPlainObject(c)&&(d=c.easing,e=c.complete,c=c.duration),c&&(c=(typeof c=="number"?c:a.fx.speeds[c]||a.fx.speeds._default)/1e3),this.anim(b,c,d,e)},a.fn.anim=function(c,d,e,f){var g,h={},i,t="",u=this,v,w=a.fx.transitionEnd;d===b&&(d=.4),a.fx.off&&(d=0);if(typeof c=="string")h[o]=c,h[p]=d+"s",h[q]=e||"linear",w=a.fx.animationEnd;else{i=[];for(g in c)j.test(g)?t+=g+"("+c[g]+") ":(h[g]=c[g],i.push(s(g)));t&&(h[k]=t,i.push(k)),d>0&&typeof c=="object"&&(h[l]=i.join(", "),h[m]=d+"s",h[n]=e||"linear")}return v=function(b){if(typeof b!="undefined"){if(b.target!==b.currentTarget)return;a(b.target).unbind(w,v)}a(this).css(r),f&&f.call(this)},d>0&&this.bind(w,v),this.size()&&this.get(0).clientLeft,this.css(h),d<=0&&setTimeout(function(){u.each(function(){v.call(this)})},0),this},i=null}(Zepto) 3 | -------------------------------------------------------------------------------- /examples/TimeCheck/TimeCheck.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Time Check 3 | 4 | Gets the time from Linux via Bridge then parses out hours, 5 | minutes and seconds using a Yun Shield/Yún. 6 | 7 | created 27 May 2013 8 | modified 21 June 2013 9 | By Tom Igoe 10 | 11 | This example code is in the public domain. 12 | 13 | https://www.arduino.cc/en/Tutorial/LibraryExamples/TimeCheck 14 | 15 | */ 16 | 17 | 18 | #include 19 | 20 | Process date; // process used to get the date 21 | int hours, minutes, seconds; // for the results 22 | int lastSecond = -1; // need an impossible value for comparison 23 | 24 | void setup() { 25 | Bridge.begin(); // initialize Bridge 26 | SerialUSB.begin(9600); // initialize serial 27 | 28 | while (!Serial); // wait for Serial Monitor to open 29 | SerialUSB.println("Time Check"); // Title of sketch 30 | 31 | // run an initial date process. Should return: 32 | // hh:mm:ss : 33 | if (!date.running()) { 34 | date.begin("date"); 35 | date.addParameter("+%T"); 36 | date.run(); 37 | } 38 | } 39 | 40 | void loop() { 41 | 42 | if (lastSecond != seconds) { // if a second has passed 43 | // print the time: 44 | if (hours <= 9) { 45 | SerialUSB.print("0"); // adjust for 0-9 46 | } 47 | SerialUSB.print(hours); 48 | SerialUSB.print(":"); 49 | if (minutes <= 9) { 50 | SerialUSB.print("0"); // adjust for 0-9 51 | } 52 | SerialUSB.print(minutes); 53 | SerialUSB.print(":"); 54 | if (seconds <= 9) { 55 | SerialUSB.print("0"); // adjust for 0-9 56 | } 57 | SerialUSB.println(seconds); 58 | 59 | // restart the date process: 60 | if (!date.running()) { 61 | date.begin("date"); 62 | date.addParameter("+%T"); 63 | date.run(); 64 | } 65 | } 66 | 67 | //if there's a result from the date process, parse it: 68 | while (date.available() > 0) { 69 | // get the result of the date process (should be hh:mm:ss): 70 | String timeString = date.readString(); 71 | 72 | // find the colons: 73 | int firstColon = timeString.indexOf(":"); 74 | int secondColon = timeString.lastIndexOf(":"); 75 | 76 | // get the substrings for hour, minute second: 77 | String hourString = timeString.substring(0, firstColon); 78 | String minString = timeString.substring(firstColon + 1, secondColon); 79 | String secString = timeString.substring(secondColon + 1); 80 | 81 | // convert to ints,saving the previous second: 82 | hours = hourString.toInt(); 83 | minutes = minString.toInt(); 84 | lastSecond = seconds; // save to do a time comparison 85 | seconds = secString.toInt(); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /examples/WiFiStatus/WiFiStatus.ino: -------------------------------------------------------------------------------- 1 | /* 2 | WiFi Status 3 | 4 | This sketch runs a script called "pretty-wifi-info.lua" 5 | installed on your Yún in folder /usr/bin. 6 | It prints information about the status of your WiFi connection. 7 | 8 | It uses Serial to print, so you need to connect your Yun Shield/Yún to your 9 | computer using a USB cable and select the appropriate port from 10 | the Port menu 11 | 12 | created 18 June 2013 13 | By Federico Fissore 14 | 15 | This example code is in the public domain. 16 | 17 | https://www.arduino.cc/en/Tutorial/LibraryExamples/WiFiStatus 18 | 19 | */ 20 | 21 | #include 22 | 23 | void setup() { 24 | SerialUSB.begin(9600); // initialize serial communication 25 | while (!SerialUSB); // do nothing until the Serial Monitor is opened 26 | 27 | SerialUSB.println("Starting bridge...\n"); 28 | pinMode(13, OUTPUT); 29 | digitalWrite(13, LOW); 30 | Bridge.begin(); // make contact with the Linux processor 31 | digitalWrite(13, HIGH); // Led on pin 13 turns on when the bridge is ready 32 | 33 | delay(2000); // wait 2 seconds 34 | } 35 | 36 | void loop() { 37 | Process wifiCheck; // initialize a new process 38 | 39 | wifiCheck.runShellCommand("/usr/bin/pretty-wifi-info.lua"); // command you want to run 40 | 41 | // while there's any characters coming back from the 42 | // process, print them to the Serial Monitor: 43 | while (wifiCheck.available() > 0) { 44 | char c = wifiCheck.read(); 45 | SerialUSB.print(c); 46 | } 47 | 48 | SerialUSB.println(); 49 | 50 | delay(5000); 51 | } 52 | -------------------------------------------------------------------------------- /examples/YunFirstConfig/YunFirstConfig.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino Yún First configuration sketch 3 | 4 | Configures the Yun Shield/Yún WiFi and infos via the Bridge 5 | Works correctly if Line Ending is set as "NewLine" 6 | If your board has two USB ports, use the Native one 7 | 8 | The circuit: 9 | Arduino Yun Shield 10 | (or any Yun model with firmware > 1.6.1) 11 | 12 | created March 2016 13 | by Arduino LLC 14 | 15 | This example code is in the public domain. 16 | 17 | https://www.arduino.cc/en/Tutorial/LibraryExamples/YunFirstConfig 18 | */ 19 | 20 | #include 21 | 22 | #define MAX_WIFI_LIST 10 23 | 24 | String networks[MAX_WIFI_LIST]; 25 | String yunName; 26 | String yunPassword; 27 | 28 | void setup() { 29 | SERIAL_PORT_USBVIRTUAL.begin(9600); // initialize serial communication 30 | while (!SERIAL_PORT_USBVIRTUAL); // do nothing until the Serial Monitor is opened 31 | 32 | SERIAL_PORT_USBVIRTUAL.println(F("Hi! Nice to see you!")); 33 | SERIAL_PORT_USBVIRTUAL.println(F("I'm your Yun assistant sketch")); 34 | SERIAL_PORT_USBVIRTUAL.println(F("I'll help you configuring your Yun in a matter of minutes")); 35 | 36 | SERIAL_PORT_USBVIRTUAL.println(F("Let's start by communicating with the Linux processor")); 37 | SERIAL_PORT_USBVIRTUAL.println(F("When LED (L13) will light up we'll be ready to go!")); 38 | SERIAL_PORT_USBVIRTUAL.println(F("Waiting...")); 39 | SERIAL_PORT_USBVIRTUAL.println(F("(in the meanwhile, if you are using the IDE's Serial Monitor, make sure that it's configured to send a \"Newline\")\n")); 40 | pinMode(13, OUTPUT); 41 | digitalWrite(13, LOW); 42 | Bridge.begin(); // make contact with the Linux processor 43 | digitalWrite(13, HIGH); // Led on pin 13 turns on when the bridge is ready 44 | 45 | // Recover if the board is in AP mode - unused 46 | Process wifiList; 47 | bool master = false; 48 | wifiList.runShellCommand(F("iwinfo | grep \"Mode: Master\"")); 49 | while (wifiList.available() > 0) { 50 | wifiList.read(); 51 | master = true; 52 | } 53 | 54 | // Get the list of reachable networks 55 | wifiList.runShellCommand(F("iwinfo wlan0 scan | grep ESSID | cut -d\"\\\"\" -f2")); 56 | 57 | uint8_t num_networks = 0; 58 | uint8_t i = 0; 59 | char c; 60 | bool dropNet = false; 61 | 62 | networks[0].reserve(32); 63 | 64 | while (wifiList.available() > 0 && i < MAX_WIFI_LIST) { 65 | c = wifiList.read(); 66 | if (c != '\n') { 67 | networks[i] += c; 68 | } else { 69 | // check if we already found networks[i] and eventually drop it 70 | for (uint8_t s = 0; s < i; s++) { 71 | if (networks[i].equals(networks[s])) { 72 | dropNet = true; 73 | } 74 | } 75 | if (networks[i].c_str()[0] == ' ') { 76 | dropNet = true; 77 | } 78 | if (i < MAX_WIFI_LIST && dropNet == false) { 79 | networks[i++].reserve(32); 80 | } else { 81 | dropNet = false; 82 | networks[i] = ""; 83 | } 84 | } 85 | } 86 | 87 | num_networks = i; 88 | 89 | String encryption; 90 | String password; 91 | int chose = 0; 92 | 93 | // If networks number is 0, start manual configuration 94 | if (num_networks == 0) { 95 | SERIAL_PORT_USBVIRTUAL.println(F("Oops, it seems that you have no WiFi network available")); 96 | SERIAL_PORT_USBVIRTUAL.println(F("Let's configure it manually")); 97 | SERIAL_PORT_USBVIRTUAL.println(F("SSID of the network you want to connect to: ")); 98 | networks[0] = getUserInput(networks[0], false); 99 | SERIAL_PORT_USBVIRTUAL.println(F("Password for the network you want to connect to: ")); 100 | password = getUserInput(password, true); 101 | SERIAL_PORT_USBVIRTUAL.print(F("Encryption (eg WPA, WPA2, WEP): ")); 102 | encryption = getUserInput(encryption, false); 103 | } else { 104 | // else print them prepending a number 105 | SERIAL_PORT_USBVIRTUAL.print(F("It looks like you have ")); 106 | SERIAL_PORT_USBVIRTUAL.print(num_networks); 107 | SERIAL_PORT_USBVIRTUAL.println(F(" networks around you ")); 108 | SERIAL_PORT_USBVIRTUAL.println(F("Which one do you want to connect to?\n")); 109 | for (i = 0; i < num_networks && i < MAX_WIFI_LIST; i++) { 110 | SERIAL_PORT_USBVIRTUAL.print(i); 111 | SERIAL_PORT_USBVIRTUAL.println(") " + networks[i]); 112 | } 113 | String selection; 114 | selection = getUserInput(selection, false); 115 | chose = atoi(selection.c_str()); 116 | } 117 | 118 | // Extract the selected network security 119 | bool openNet = false; 120 | wifiList.runShellCommand("iwinfo wlan0 scan | grep \"" + networks[chose] + "\" -A5 | grep Encryption | cut -f2 -d\":\""); 121 | while (wifiList.available() > 0) { 122 | c = wifiList.read(); 123 | encryption += c; 124 | } 125 | 126 | if (encryption.indexOf("none") >= 0) { 127 | openNet = true; 128 | encryption = "none"; 129 | } 130 | if (encryption.indexOf("WPA2") >= 0) { 131 | encryption = "psk2"; 132 | } 133 | if (encryption.indexOf("WPA") >= 0) { 134 | encryption = "psk"; 135 | } 136 | if (encryption.indexOf("WEP") >= 0) { 137 | encryption = "wep"; 138 | } 139 | 140 | if (openNet == false && password.length() == 0) { 141 | SERIAL_PORT_USBVIRTUAL.print(F("It looks like you need a password to connect to ")); 142 | SERIAL_PORT_USBVIRTUAL.println(networks[chose]); 143 | SERIAL_PORT_USBVIRTUAL.print(F("Write it here: ")); 144 | password = getUserInput(password, true); 145 | } 146 | 147 | // Change hostname/root password 148 | SERIAL_PORT_USBVIRTUAL.println(F("We are almost done! Give a name and a password to your Yun")); 149 | SERIAL_PORT_USBVIRTUAL.print(F("Name: ")); 150 | yunName = getUserInput(yunName, false); 151 | SERIAL_PORT_USBVIRTUAL.print(F("Password: ")); 152 | yunPassword = getUserInput(yunPassword, true); 153 | 154 | // Select a country code 155 | String countryCode; 156 | SERIAL_PORT_USBVIRTUAL.println(F("One last question: where do you live?")); 157 | SERIAL_PORT_USBVIRTUAL.print(F("Insert a two letters county code (eg IT, US, DE): ")); 158 | countryCode = getUserInput(countryCode, false); 159 | 160 | yunName.trim(); 161 | yunPassword.trim(); 162 | networks[chose].trim(); 163 | password.trim(); 164 | countryCode.trim(); 165 | 166 | // Configure the Yun with user provided strings 167 | wifiConfig(yunName, yunPassword, networks[chose], password, "YUN" + yunName + "AP", countryCode, encryption); 168 | 169 | SERIAL_PORT_USBVIRTUAL.print(F("Waiting for the Yun to connect to the network")); 170 | } 171 | 172 | bool Connected = false; 173 | bool serialTerminalMode = false; 174 | int runs = 0; 175 | 176 | void loop() { 177 | if (!serialTerminalMode) { 178 | String resultStr = ""; 179 | 180 | if (!Connected) { 181 | SERIAL_PORT_USBVIRTUAL.print("."); 182 | runs++; 183 | } 184 | 185 | // If it takes more than 20 seconds to connect, stop trying 186 | if (runs > 20) { 187 | SERIAL_PORT_USBVIRTUAL.println(""); 188 | SERIAL_PORT_USBVIRTUAL.println(F("We couldn't connect to the network.")); 189 | SERIAL_PORT_USBVIRTUAL.println(F("Restart the board if you want to execute the wizard again")); 190 | resultStr = getUserInput(resultStr, false); 191 | } 192 | 193 | // Check if we have an IP address 194 | Process wifiCheck; 195 | wifiCheck.runShellCommand(F("/usr/bin/pretty-wifi-info.lua | grep \"IP address\" | cut -f2 -d\":\" | cut -f1 -d\"/\"" )); // command you want to run 196 | while (wifiCheck.available() > 0) { 197 | char c = wifiCheck.read(); 198 | resultStr += c; 199 | } 200 | 201 | delay(1000); 202 | 203 | if (resultStr != "") { 204 | // We got an IP, freeze the loop, display the value and "spawn" a serial terminal 205 | Connected = true; 206 | resultStr.trim(); 207 | SERIAL_PORT_USBVIRTUAL.println(""); 208 | SERIAL_PORT_USBVIRTUAL.print(F("\nGreat! You can now reach your Yun from a browser typing http://")); 209 | SERIAL_PORT_USBVIRTUAL.println(resultStr); 210 | SERIAL_PORT_USBVIRTUAL.print(F("Press 'Enter' key twice to start a serial terminal")); 211 | resultStr = getUserInput(resultStr, false); 212 | serialTerminalMode = true; 213 | //startSerialTerminal(); 214 | SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command 215 | delay(100); 216 | SERIAL_PORT_HARDWARE.println("\nreset\n\n"); 217 | SERIAL_PORT_HARDWARE.flush(); 218 | SERIAL_PORT_HARDWARE.println("\nreset\n\n"); 219 | SERIAL_PORT_HARDWARE.write((uint8_t *)"\n", 1); 220 | // discard all stuff for 2 seconds 221 | long start = millis(); 222 | while (millis() - start < 2000) { 223 | if (SERIAL_PORT_HARDWARE.available()) { 224 | SERIAL_PORT_HARDWARE.read(); 225 | } 226 | } 227 | } 228 | 229 | } else { 230 | loopSerialTerminal(); 231 | } 232 | } 233 | 234 | String getUserInput(String out, bool obfuscated) { 235 | /* 236 | while (SerialUSB.available() <= 0) {} 237 | while (SerialUSB.available() > 0) { 238 | char c = SerialUSB.read(); 239 | out += c; 240 | } 241 | return out; 242 | */ 243 | while (SERIAL_PORT_USBVIRTUAL.available() <= 0) {} 244 | while (1) { 245 | char c = SERIAL_PORT_USBVIRTUAL.read(); 246 | char next = SERIAL_PORT_USBVIRTUAL.peek(); 247 | if (c == '\n' || c == '\r') { 248 | if (next == '\n') { 249 | // discard it 250 | SERIAL_PORT_USBVIRTUAL.read(); 251 | } 252 | break; 253 | } 254 | else { 255 | if (c != -1) { 256 | out += c; 257 | if (obfuscated) 258 | SERIAL_PORT_USBVIRTUAL.print("*"); 259 | else 260 | SERIAL_PORT_USBVIRTUAL.print(c); 261 | } 262 | } 263 | } 264 | SERIAL_PORT_USBVIRTUAL.println(""); 265 | return out; 266 | } 267 | 268 | void wifiConfig(String yunName, String yunPsw, String wifissid, String wifipsw, String wifiAPname, String countryCode, String encryption) { 269 | Process p; 270 | 271 | p.runShellCommand("blink-start 100"); //start the blue blink 272 | 273 | p.runShellCommand("hostname " + yunName); //change the current hostname 274 | p.runShellCommand("uci set system.@system[0].hostname='" + yunName + "'"); //change the hostname in uci 275 | 276 | p.runShellCommand("uci set arduino.@arduino[0].access_point_wifi_name='" + wifiAPname + "'"); 277 | 278 | //this block resets the WiFi psw 279 | p.runShellCommand("uci set wireless.@wifi-iface[0].encryption='" + encryption + "'"); 280 | p.runShellCommand("uci set wireless.@wifi-iface[0].mode='sta'\n"); 281 | p.runShellCommand("uci set wireless.@wifi-iface[0].ssid='" + wifissid + "'"); 282 | p.runShellCommand("uci set wireless.@wifi-iface[0].key='" + wifipsw + "'"); 283 | p.runShellCommand("uci set wireless.radio0.channel='auto'"); 284 | p.runShellCommand("uci set wireless.radio0.country='" + countryCode + "'"); 285 | p.runShellCommand("uci delete network.lan.ipaddr"); 286 | p.runShellCommand("uci delete network.lan.netmask"); 287 | p.runShellCommand("uci set network.lan.proto='dhcp'"); 288 | 289 | p.runShellCommand("echo -e \"" + yunPsw + "\n" + yunPsw + "\" | passwd root"); //change the password 290 | p.runShellCommand("uci commit"); //save the mods done via UCI 291 | p.runShellCommand("blink-stop"); //start the blue blink 292 | 293 | p.runShellCommand("wifi "); 294 | } 295 | 296 | long linuxBaud = 250000; 297 | 298 | void startSerialTerminal() { 299 | SERIAL_PORT_USBVIRTUAL.begin(115200); // open serial connection via USB-Serial 300 | SERIAL_PORT_HARDWARE.begin(linuxBaud); // open serial connection to Linux 301 | } 302 | 303 | bool commandMode = false; 304 | void loopSerialTerminal() { 305 | // copy from USB-CDC to UART 306 | int c = SERIAL_PORT_USBVIRTUAL.read(); // read from USB-CDC 307 | if (c != -1) { // got anything? 308 | if (commandMode == false) { // if we aren't in command mode... 309 | if (c == '~') { // Tilde '~' key pressed? 310 | commandMode = true; // enter in command mode 311 | } else { 312 | SERIAL_PORT_HARDWARE.write(c); // otherwise write char to UART 313 | } 314 | } else { // if we are in command mode... 315 | if (c == '0') { // '0' key pressed? 316 | SERIAL_PORT_HARDWARE.begin(57600); // set speed to 57600 317 | SERIAL_PORT_USBVIRTUAL.println("Speed set to 57600"); 318 | } else if (c == '1') { // '1' key pressed? 319 | SERIAL_PORT_HARDWARE.begin(115200); // set speed to 115200 320 | SERIAL_PORT_USBVIRTUAL.println("Speed set to 115200"); 321 | } else if (c == '2') { // '2' key pressed? 322 | SERIAL_PORT_HARDWARE.begin(250000); // set speed to 250000 323 | SERIAL_PORT_USBVIRTUAL.println("Speed set to 250000"); 324 | } else if (c == '3') { // '3' key pressed? 325 | SERIAL_PORT_HARDWARE.begin(500000); // set speed to 500000 326 | SERIAL_PORT_USBVIRTUAL.println("Speed set to 500000"); 327 | } else if (c == '~') { // '~` key pressed? 328 | SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command 329 | SERIAL_PORT_USBVIRTUAL.println("Sending bridge's shutdown command"); 330 | } else { // any other key pressed? 331 | SERIAL_PORT_HARDWARE.write('~'); // write '~' to UART 332 | SERIAL_PORT_HARDWARE.write(c); // write char to UART 333 | } 334 | commandMode = false; // in all cases exit from command mode 335 | } 336 | } 337 | 338 | // copy from UART to USB-CDC 339 | c = SERIAL_PORT_HARDWARE.read(); // read from UART 340 | if (c != -1) { // got anything? 341 | SERIAL_PORT_USBVIRTUAL.write(c); // write to USB-CDC 342 | } 343 | } 344 | -------------------------------------------------------------------------------- /examples/YunSerialTerminal/YunSerialTerminal.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Arduino Yún USB-to-Serial 3 | 4 | Allows you to use the Yun Shield/Yún processor as a 5 | serial terminal for the Linux side on the Yún. 6 | 7 | Upload this to a Yun Shield/Yún via serial (not WiFi) then open 8 | the Serial Monitor at 115200 to see the boot process of Linux. 9 | You can also use the Serial Monitor as a basic command line 10 | interface for Linux using this sketch. 11 | 12 | From the Serial Monitor the following commands can be issued: 13 | 14 | '~' followed by '0' -> Set the UART speed to 57600 baud 15 | '~' followed by '1' -> Set the UART speed to 115200 baud 16 | '~' followed by '2' -> Set the UART speed to 250000 baud 17 | '~' followed by '3' -> Set the UART speed to 500000 baud 18 | '~' followed by '~' -> Sends the bridge's shutdown command to 19 | obtain the console. 20 | 21 | The circuit: 22 | Yun Shield/Yún 23 | 24 | created March 2013 25 | by Massimo Banzi 26 | modified by Cristian Maglie 27 | 28 | This example code is in the public domain. 29 | 30 | https://www.arduino.cc/en/Tutorial/LibraryExamples/YunSerialTerminal 31 | 32 | */ 33 | 34 | long linuxBaud = 250000; 35 | 36 | void setup() { 37 | SERIAL_PORT_USBVIRTUAL.begin(115200); // open serial connection via USB-Serial 38 | SERIAL_PORT_HARDWARE.begin(linuxBaud); // open serial connection to Linux 39 | } 40 | 41 | bool commandMode = false; 42 | 43 | void loop() { 44 | // copy from USB-CDC to UART 45 | int c = SERIAL_PORT_USBVIRTUAL.read(); // read from USB-CDC 46 | if (c != -1) { // got anything? 47 | if (commandMode == false) { // if we aren't in command mode... 48 | if (c == '~') { // Tilde '~' key pressed? 49 | commandMode = true; // enter in command mode 50 | } else { 51 | SERIAL_PORT_HARDWARE.write(c); // otherwise write char to UART 52 | } 53 | } else { // if we are in command mode... 54 | if (c == '0') { // '0' key pressed? 55 | SERIAL_PORT_HARDWARE.begin(57600); // set speed to 57600 56 | SERIAL_PORT_USBVIRTUAL.println("Speed set to 57600"); 57 | } else if (c == '1') { // '1' key pressed? 58 | SERIAL_PORT_HARDWARE.begin(115200); // set speed to 115200 59 | SERIAL_PORT_USBVIRTUAL.println("Speed set to 115200"); 60 | } else if (c == '2') { // '2' key pressed? 61 | SERIAL_PORT_HARDWARE.begin(250000); // set speed to 250000 62 | SERIAL_PORT_USBVIRTUAL.println("Speed set to 250000"); 63 | } else if (c == '3') { // '3' key pressed? 64 | SERIAL_PORT_HARDWARE.begin(500000); // set speed to 500000 65 | SERIAL_PORT_USBVIRTUAL.println("Speed set to 500000"); 66 | } else if (c == '~') { // '~` key pressed? 67 | SERIAL_PORT_HARDWARE.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11); // send "bridge shutdown" command 68 | SERIAL_PORT_USBVIRTUAL.println("Sending bridge's shutdown command"); 69 | } else { // any other key pressed? 70 | SERIAL_PORT_HARDWARE.write('~'); // write '~' to UART 71 | SERIAL_PORT_HARDWARE.write(c); // write char to UART 72 | } 73 | commandMode = false; // in all cases exit from command mode 74 | } 75 | } 76 | 77 | // copy from UART to USB-CDC 78 | c = SERIAL_PORT_HARDWARE.read(); // read from UART 79 | if (c != -1) { // got anything? 80 | SERIAL_PORT_USBVIRTUAL.write(c); // write to USB-CDC 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Bridge 3 | ####################################### 4 | 5 | ####################################### 6 | # Class (KEYWORD1) 7 | ####################################### 8 | 9 | Bridge KEYWORD1 YunBridgeLibrary 10 | FileIO KEYWORD1 YunFileIOConstructor 11 | FileSystem KEYWORD1 YunFileIOConstructor 12 | Console KEYWORD1 YunConsoleConstructor 13 | Process KEYWORD1 YunProcessConstructor 14 | Mailbox KEYWORD1 YunMailboxConstructor 15 | HttpClient KEYWORD1 YunHttpClientConstructor 16 | YunServer KEYWORD1 YunServerConstructor 17 | YunClient KEYWORD1 YunClientConstructor 18 | BridgeServer KEYWORD1 YunServerConstructor 19 | BridgeClient KEYWORD1 YunClientConstructor 20 | BridgeSSLClient KEYWORD1 YunClientConstructor 21 | 22 | ####################################### 23 | # Methods and Functions (KEYWORD2) 24 | ####################################### 25 | 26 | # method names in common 27 | begin KEYWORD2 28 | end KEYWORD2 29 | available KEYWORD2 30 | read KEYWORD2 31 | peek KEYWORD2 32 | write KEYWORD2 33 | flush KEYWORD2 34 | bool KEYWORD2 35 | 36 | # Bridge Class 37 | transfer KEYWORD2 38 | put KEYWORD2 39 | get KEYWORD2 40 | 41 | # Console Class 42 | buffer KEYWORD2 43 | noBuffer KEYWORD2 44 | connected KEYWORD2 45 | 46 | # FileIO Class 47 | File KEYWORD2 48 | BridgeFile KEYWORD2 49 | seek KEYWORD2 50 | position KEYWORD2 51 | size KEYWORD2 52 | close KEYWORD2 53 | name KEYWORD2 54 | isDirectory KEYWORD2 55 | openNextFile KEYWORD2 56 | rewindDirectory KEYWORD2 57 | 58 | # Process Class 59 | addParameter KEYWORD2 60 | runAsynchronously KEYWORD2 61 | run KEYWORD2 62 | running KEYWORD2 63 | exitValue KEYWORD2 64 | runShellCommand KEYWORD2 65 | runShellCommandAsynchronously KEYWORD2 66 | 67 | # Mailbox Class 68 | readMessage KEYWORD2 69 | writeMessage KEYWORD2 70 | writeJSON KEYWORD2 71 | messageAvailable KEYWORD2 72 | 73 | # HttpClient Class 74 | getAsynchronously KEYWORD2 75 | ready KEYWORD2 76 | getResult KEYWORD2 77 | 78 | # BridgeServer Class 79 | accept KEYWORD2 80 | stop KEYWORD2 81 | connect KEYWORD2 82 | connectSSL KEYWORD2 83 | connected KEYWORD2 84 | 85 | 86 | ####################################### 87 | # Constants (LITERAL1) 88 | ####################################### 89 | 90 | FILE_READ LITERAL1 91 | FILE_WRITE LITERAL1 92 | FILE_APPEND LITERAL1 93 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Bridge 2 | version=1.7.0 3 | author=Arduino 4 | maintainer=Arduino 5 | sentence=Enables communication between the Linux processor and the microcontroller. For Arduino Yún, Yún Shield and TRE only. 6 | paragraph=The Bridge library features: access to the shared storage, run and manage Linux processes, open a remote console, access to the Linux file system, including the SD card, establish HTTP clients or servers. 7 | category=Communication 8 | url=http://www.arduino.cc/en/Reference/YunBridgeLibrary 9 | architectures=* 10 | dot_a_linkage=true 11 | -------------------------------------------------------------------------------- /src/Bridge.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include "Bridge.h" 20 | 21 | BridgeClass::BridgeClass(Stream &_stream) : 22 | index(0), stream(_stream), started(false), max_retries(0) { 23 | // Empty 24 | } 25 | 26 | void BridgeClass::begin() { 27 | if (started) 28 | return; 29 | started = true; 30 | 31 | // Wait for U-boot to finish startup 32 | do { 33 | dropAll(); 34 | delay(1000); 35 | } while (stream.available() > 0); 36 | 37 | while (true) { 38 | // Bridge interrupt: 39 | // - Ask the bridge to close itself 40 | uint8_t quit_cmd[] = {'X', 'X', 'X', 'X', 'X'}; 41 | max_retries = 1; 42 | transfer(quit_cmd, 5); 43 | 44 | // Bridge startup: 45 | // - If the bridge is not running starts it safely 46 | stream.print(CTRL_C); 47 | delay(250); 48 | stream.print(F("\n")); 49 | delay(250); 50 | stream.print(F("\n")); 51 | delay(500); 52 | // Wait for OpenWRT message 53 | // "Press enter to activate console" 54 | stream.print(F("run-bridge\n")); 55 | delay(500); 56 | dropAll(); 57 | 58 | // Reset the bridge to check if it is running 59 | uint8_t cmd[] = {'X', 'X', '1', '0', '0'}; 60 | uint8_t res[4]; 61 | max_retries = 50; 62 | uint16_t l = transfer(cmd, 5, res, 4); 63 | if (l == TRANSFER_TIMEOUT) { 64 | // Bridge didn't start... 65 | // Maybe the board is starting-up? 66 | 67 | // Wait and retry 68 | delay(1000); 69 | continue; 70 | } 71 | if (res[0] != 0) 72 | while (true); 73 | 74 | // Detect bridge version 75 | if (l == 4) { 76 | bridgeVersion = (res[1]-'0')*100 + (res[2]-'0')*10 + (res[3]-'0'); 77 | } else { 78 | // Bridge v1.0.0 didn't send any version info 79 | bridgeVersion = 100; 80 | } 81 | 82 | max_retries = 50; 83 | return; 84 | } 85 | } 86 | 87 | void BridgeClass::end() { 88 | 89 | while (true) { 90 | // Bridge interrupt: 91 | // - Ask the bridge to close itself 92 | uint8_t quit_cmd[] = {'X', 'X', 'X', 'X', 'X'}; 93 | max_retries = 1; 94 | transfer(quit_cmd, 5); 95 | delay(100); 96 | stream.print(CTRL_C); 97 | delay(250); 98 | stream.print(F("cd \n")); 99 | //expect a shell 100 | bool done = false; 101 | delay(100); 102 | while (stream.available()) { 103 | char c = stream.read(); 104 | if (c == '#') { 105 | done = true; 106 | break; 107 | } 108 | } 109 | if (done) { 110 | stream.print(F("reset\n")); 111 | break; 112 | } 113 | } 114 | delay(100); 115 | dropAll(); 116 | } 117 | 118 | void BridgeClass::put(const char *key, const char *value) { 119 | // TODO: do it in a more efficient way 120 | String cmd = "D"; 121 | uint8_t res[1]; 122 | cmd += key; 123 | cmd += "\xFE"; 124 | cmd += value; 125 | transfer((uint8_t*)cmd.c_str(), cmd.length(), res, 1); 126 | } 127 | 128 | unsigned int BridgeClass::get(const char *key, uint8_t *value, unsigned int maxlen) { 129 | uint8_t cmd[] = {'d'}; 130 | unsigned int l = transfer(cmd, 1, (uint8_t *)key, strlen(key), value, maxlen); 131 | if (l < maxlen) 132 | value[l] = 0; // Zero-terminate string 133 | return l; 134 | } 135 | 136 | #if defined(ARDUINO_ARCH_AVR) 137 | // AVR use an optimized implementation of CRC 138 | #include 139 | #else 140 | // Generic implementation for non-AVR architectures 141 | uint16_t _crc_ccitt_update(uint16_t crc, uint8_t data) 142 | { 143 | data ^= crc & 0xff; 144 | data ^= data << 4; 145 | return ((((uint16_t)data << 8) | ((crc >> 8) & 0xff)) ^ 146 | (uint8_t)(data >> 4) ^ 147 | ((uint16_t)data << 3)); 148 | } 149 | #endif 150 | 151 | void BridgeClass::crcUpdate(uint8_t c) { 152 | CRC = _crc_ccitt_update(CRC, c); 153 | } 154 | 155 | void BridgeClass::crcReset() { 156 | CRC = 0xFFFF; 157 | } 158 | 159 | void BridgeClass::crcWrite() { 160 | stream.write((char)(CRC >> 8)); 161 | stream.write((char)(CRC & 0xFF)); 162 | } 163 | 164 | bool BridgeClass::crcCheck(uint16_t _CRC) { 165 | return CRC == _CRC; 166 | } 167 | 168 | uint16_t BridgeClass::transfer(const uint8_t *buff1, uint16_t len1, 169 | const uint8_t *buff2, uint16_t len2, 170 | const uint8_t *buff3, uint16_t len3, 171 | uint8_t *rxbuff, uint16_t rxlen) 172 | { 173 | uint16_t len = len1 + len2 + len3; 174 | uint8_t retries = 0; 175 | for ( ; retries < max_retries; retries++, delay(100), dropAll() /* Delay for retransmission */) { 176 | // Send packet 177 | crcReset(); 178 | stream.write((char)0xFF); // Start of packet (0xFF) 179 | crcUpdate(0xFF); 180 | stream.write((char)index); // Message index 181 | crcUpdate(index); 182 | stream.write((char)((len >> 8) & 0xFF)); // Message length (hi) 183 | crcUpdate((len >> 8) & 0xFF); 184 | stream.write((char)(len & 0xFF)); // Message length (lo) 185 | crcUpdate(len & 0xFF); 186 | for (uint16_t i = 0; i < len1; i++) { // Payload 187 | stream.write((char)buff1[i]); 188 | crcUpdate(buff1[i]); 189 | } 190 | for (uint16_t i = 0; i < len2; i++) { // Payload 191 | stream.write((char)buff2[i]); 192 | crcUpdate(buff2[i]); 193 | } 194 | for (uint16_t i = 0; i < len3; i++) { // Payload 195 | stream.write((char)buff3[i]); 196 | crcUpdate(buff3[i]); 197 | } 198 | crcWrite(); // CRC 199 | 200 | // Wait for ACK in 200ms 201 | if (timedRead(200) != 0xFF) 202 | continue; 203 | crcReset(); 204 | crcUpdate(0xFF); 205 | 206 | // Check packet index 207 | if (timedRead(5) != index) 208 | continue; 209 | crcUpdate(index); 210 | 211 | // Recv len 212 | int lh = timedRead(10); 213 | if (lh < 0) 214 | continue; 215 | crcUpdate(lh); 216 | int ll = timedRead(10); 217 | if (ll < 0) 218 | continue; 219 | crcUpdate(ll); 220 | uint16_t l = lh; 221 | l <<= 8; 222 | l += ll; 223 | 224 | // Recv data 225 | for (uint16_t i = 0; i < l; i++) { 226 | // Cut received data if rxbuffer is too small 227 | if (i >= rxlen) 228 | break; 229 | int c = timedRead(5); 230 | if (c < 0) 231 | continue; 232 | rxbuff[i] = c; 233 | crcUpdate(c); 234 | } 235 | 236 | // Check CRC 237 | int crc_hi = timedRead(5); 238 | if (crc_hi < 0) 239 | continue; 240 | int crc_lo = timedRead(5); 241 | if (crc_lo < 0) 242 | continue; 243 | if (!crcCheck((crc_hi << 8) + crc_lo)) 244 | continue; 245 | 246 | // Increase index 247 | index++; 248 | 249 | // Return bytes received 250 | if (l > rxlen) 251 | return rxlen; 252 | return l; 253 | } 254 | 255 | // Max retries exceeded 256 | return TRANSFER_TIMEOUT; 257 | } 258 | 259 | int BridgeClass::timedRead(unsigned int timeout) { 260 | int c; 261 | unsigned long _startMillis = millis(); 262 | do { 263 | c = stream.read(); 264 | if (c >= 0) return c; 265 | } while (millis() - _startMillis < timeout); 266 | return -1; // -1 indicates timeout 267 | } 268 | 269 | void BridgeClass::dropAll() { 270 | while (stream.available() > 0) { 271 | stream.read(); 272 | } 273 | } 274 | 275 | #if defined(ARDUINO_ARCH_SAM) 276 | #include 277 | #endif 278 | 279 | #if defined(ARDUINO_ARCH_SAM) 280 | void checkForRemoteSketchUpdate(uint8_t pin) { 281 | // The host force pin LOW to signal that a new sketch is coming 282 | pinMode(pin, INPUT_PULLUP); 283 | delay(50); 284 | if (digitalRead(pin) == LOW) { 285 | initiateReset(1); 286 | while (true) 287 | ; // Wait for reset to SAM-BA 288 | } 289 | 290 | // Restore in standard state 291 | pinMode(pin, INPUT); 292 | } 293 | #else 294 | void checkForRemoteSketchUpdate(uint8_t /* pin */) { 295 | // Empty, bootloader is enough. 296 | } 297 | #endif 298 | 299 | // Bridge instance 300 | #if defined(SERIAL_PORT_LINUXBRIDGE) 301 | SerialBridgeClass Bridge(SERIAL_PORT_LINUXBRIDGE); 302 | #elif defined(SERIAL_PORT_HARDWARE) 303 | SerialBridgeClass Bridge(SERIAL_PORT_HARDWARE); 304 | #elif defined(SERIAL_PORT_HARDWARE_OPEN) 305 | SerialBridgeClass Bridge(SERIAL_PORT_HARDWARE_OPEN); 306 | #elif defined(__AVR_ATmega32U4__) // Legacy fallback 307 | // Leonardo variants (where HardwareSerial is Serial1) 308 | SerialBridgeClass Bridge(Serial1); 309 | #else 310 | SerialBridgeClass Bridge(Serial); 311 | #endif 312 | -------------------------------------------------------------------------------- /src/Bridge.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef BRIDGE_H_ 20 | #define BRIDGE_H_ 21 | 22 | #ifndef BRIDGE_BAUDRATE 23 | #define BRIDGE_BAUDRATE 250000 24 | #endif 25 | 26 | #include 27 | #include 28 | 29 | class BridgeClass { 30 | public: 31 | BridgeClass(Stream &_stream); 32 | void begin(); 33 | void end(); 34 | 35 | // Methods to handle key/value datastore 36 | void put(const char *key, const char *value); 37 | void put(const String &key, const String &value) 38 | { 39 | put(key.c_str(), value.c_str()); 40 | } 41 | unsigned int get(const char *key, uint8_t *buff, unsigned int size); 42 | unsigned int get(const char *key, char *value, unsigned int maxlen) 43 | { 44 | return get(key, reinterpret_cast(value), maxlen); 45 | } 46 | 47 | // Transfer a frame (with error correction and response) 48 | uint16_t transfer(const uint8_t *buff1, uint16_t len1, 49 | const uint8_t *buff2, uint16_t len2, 50 | const uint8_t *buff3, uint16_t len3, 51 | uint8_t *rxbuff, uint16_t rxlen); 52 | // multiple inline versions of the same function to allow efficient frame concatenation 53 | uint16_t transfer(const uint8_t *buff1, uint16_t len1) 54 | { 55 | return transfer(buff1, len1, NULL, 0); 56 | } 57 | uint16_t transfer(const uint8_t *buff1, uint16_t len1, 58 | uint8_t *rxbuff, uint16_t rxlen) 59 | { 60 | return transfer(buff1, len1, NULL, 0, rxbuff, rxlen); 61 | } 62 | uint16_t transfer(const uint8_t *buff1, uint16_t len1, 63 | const uint8_t *buff2, uint16_t len2, 64 | uint8_t *rxbuff, uint16_t rxlen) 65 | { 66 | return transfer(buff1, len1, buff2, len2, NULL, 0, rxbuff, rxlen); 67 | } 68 | 69 | uint16_t getBridgeVersion() 70 | { 71 | return bridgeVersion; 72 | } 73 | 74 | static const uint16_t TRANSFER_TIMEOUT = 0xFFFF; 75 | 76 | private: 77 | uint8_t index; 78 | int timedRead(unsigned int timeout); 79 | void dropAll(); 80 | uint16_t bridgeVersion; 81 | 82 | private: 83 | void crcUpdate(uint8_t c); 84 | void crcReset(); 85 | void crcWrite(); 86 | bool crcCheck(uint16_t _CRC); 87 | uint16_t CRC; 88 | 89 | private: 90 | static const char CTRL_C = 3; 91 | Stream &stream; 92 | bool started; 93 | uint8_t max_retries; 94 | }; 95 | 96 | // This subclass uses a serial port Stream 97 | class SerialBridgeClass : public BridgeClass { 98 | public: 99 | SerialBridgeClass(HardwareSerial &_serial) 100 | : BridgeClass(_serial), serial(_serial) { 101 | // Empty 102 | } 103 | 104 | void begin(unsigned long baudrate = BRIDGE_BAUDRATE) { 105 | serial.begin(baudrate); 106 | BridgeClass::begin(); 107 | } 108 | 109 | void end(unsigned long baudrate = BRIDGE_BAUDRATE) { 110 | serial.begin(baudrate); 111 | BridgeClass::end(); 112 | } 113 | 114 | private: 115 | HardwareSerial &serial; 116 | }; 117 | 118 | extern SerialBridgeClass Bridge; 119 | 120 | // Some microcrontrollers don't start the bootloader after a reset. 121 | // This function is intended to let the microcontroller erase its 122 | // flash after checking a specific signal coming from the external 123 | // device without the need to press the erase button on the board. 124 | // The purpose is to enable a software update that does not require 125 | // a manual interaction with the board. 126 | extern void checkForRemoteSketchUpdate(uint8_t pin = 7); 127 | 128 | #endif /* BRIDGE_H_ */ 129 | 130 | #include 131 | #include 132 | -------------------------------------------------------------------------------- /src/BridgeClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include 20 | 21 | BridgeClient::BridgeClient(uint8_t _h, BridgeClass &_b) : 22 | bridge(_b), handle(_h), opened(true), buffered(0) { 23 | } 24 | 25 | BridgeClient::BridgeClient(BridgeClass &_b) : 26 | bridge(_b), handle(0), opened(false), buffered(0) { 27 | } 28 | 29 | BridgeClient::~BridgeClient() { 30 | } 31 | 32 | BridgeClient& BridgeClient::operator=(const BridgeClient &_x) { 33 | opened = _x.opened; 34 | handle = _x.handle; 35 | return *this; 36 | } 37 | 38 | void BridgeClient::stop() { 39 | if (opened) { 40 | uint8_t cmd[] = {'j', handle}; 41 | bridge.transfer(cmd, 2); 42 | } 43 | opened = false; 44 | buffered = 0; 45 | readPos = 0; 46 | } 47 | 48 | void BridgeClient::doBuffer() { 49 | // If there are already char in buffer exit 50 | if (buffered > 0) 51 | return; 52 | 53 | // Try to buffer up to 32 characters 54 | readPos = 0; 55 | uint8_t cmd[] = {'K', handle, sizeof(buffer)}; 56 | buffered = bridge.transfer(cmd, 3, buffer, sizeof(buffer)); 57 | } 58 | 59 | int BridgeClient::available() { 60 | // Look if there is new data available 61 | doBuffer(); 62 | return buffered; 63 | } 64 | 65 | int BridgeClient::read() { 66 | doBuffer(); 67 | if (buffered == 0) 68 | return -1; // no chars available 69 | else { 70 | buffered--; 71 | return buffer[readPos++]; 72 | } 73 | } 74 | 75 | int BridgeClient::read(uint8_t *buff, size_t size) { 76 | size_t readed = 0; 77 | do { 78 | if (buffered == 0) { 79 | doBuffer(); 80 | if (buffered == 0) 81 | return readed; 82 | } 83 | buff[readed++] = buffer[readPos++]; 84 | buffered--; 85 | } while (readed < size); 86 | return readed; 87 | } 88 | 89 | int BridgeClient::peek() { 90 | doBuffer(); 91 | if (buffered == 0) 92 | return -1; // no chars available 93 | else 94 | return buffer[readPos]; 95 | } 96 | 97 | size_t BridgeClient::write(uint8_t c) { 98 | if (!opened) 99 | return 0; 100 | uint8_t cmd[] = {'l', handle, c}; 101 | bridge.transfer(cmd, 3); 102 | return 1; 103 | } 104 | 105 | size_t BridgeClient::write(const uint8_t *buf, size_t size) { 106 | if (!opened) 107 | return 0; 108 | uint8_t cmd[] = {'l', handle}; 109 | bridge.transfer(cmd, 2, buf, size, NULL, 0); 110 | return size; 111 | } 112 | 113 | void BridgeClient::flush() { 114 | } 115 | 116 | uint8_t BridgeClient::connected() { 117 | if (!opened) 118 | return false; 119 | // Client is "connected" if it has unread bytes 120 | if (available()) 121 | return true; 122 | 123 | uint8_t cmd[] = {'L', handle}; 124 | uint8_t res[1]; 125 | bridge.transfer(cmd, 2, res, 1); 126 | return (res[0] == 1); 127 | } 128 | 129 | int BridgeClient::connect(IPAddress ip, uint16_t port) { 130 | String address; 131 | address.reserve(18); 132 | address += ip[0]; 133 | address += '.'; 134 | address += ip[1]; 135 | address += '.'; 136 | address += ip[2]; 137 | address += '.'; 138 | address += ip[3]; 139 | return connect(address.c_str(), port); 140 | } 141 | 142 | int BridgeClient::connect(const char *host, uint16_t port) { 143 | uint8_t tmp[] = { 144 | 'C', 145 | static_cast(port >> 8), 146 | static_cast(port) 147 | }; 148 | uint8_t res[1]; 149 | int l = bridge.transfer(tmp, 3, (const uint8_t *)host, strlen(host), res, 1); 150 | if (l == 0) 151 | return 0; 152 | handle = res[0]; 153 | 154 | // wait for connection 155 | uint8_t tmp2[] = { 'c', handle }; 156 | uint8_t res2[1]; 157 | while (true) { 158 | bridge.transfer(tmp2, 2, res2, 1); 159 | if (res2[0] == 0) 160 | break; 161 | delay(1); 162 | } 163 | opened = true; 164 | 165 | // check for successful connection 166 | if (connected()) 167 | return 1; 168 | 169 | stop(); 170 | handle = 0; 171 | return 0; 172 | } 173 | 174 | int BridgeClient::connectSSL(const char *host, uint16_t port) { 175 | if (bridge.getBridgeVersion() < 161) 176 | return -1; 177 | 178 | uint8_t tmp[] = { 179 | 'Z', 180 | static_cast(port >> 8), 181 | static_cast(port) 182 | }; 183 | uint8_t res[1]; 184 | int l = bridge.transfer(tmp, 3, (const uint8_t *)host, strlen(host), res, 1); 185 | if (l == 0) 186 | return 0; 187 | handle = res[0]; 188 | 189 | // wait for connection 190 | uint8_t tmp2[] = { 'c', handle }; 191 | uint8_t res2[1]; 192 | while (true) { 193 | bridge.transfer(tmp2, 2, res2, 1); 194 | if (res2[0] == 0) 195 | break; 196 | delay(1); 197 | } 198 | opened = true; 199 | 200 | // check for successful connection 201 | if (connected()) 202 | return 1; 203 | 204 | stop(); 205 | handle = 0; 206 | return 0; 207 | } 208 | -------------------------------------------------------------------------------- /src/BridgeClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef _BRIDGE_CLIENT_H_ 20 | #define _BRIDGE_CLIENT_H_ 21 | 22 | #include 23 | #include 24 | 25 | class BridgeClient : public Client { 26 | public: 27 | // Constructor with a user provided BridgeClass instance 28 | BridgeClient(uint8_t _h, BridgeClass &_b = Bridge); 29 | BridgeClient(BridgeClass &_b = Bridge); 30 | ~BridgeClient(); 31 | 32 | // Stream methods 33 | // (read message) 34 | virtual int available(); 35 | virtual int read(); 36 | virtual int read(uint8_t *buf, size_t size); 37 | virtual int peek(); 38 | // (write response) 39 | virtual size_t write(uint8_t); 40 | virtual size_t write(const uint8_t *buf, size_t size); 41 | virtual void flush(); 42 | // TODO: add optimized function for block write 43 | 44 | virtual operator bool () { 45 | return opened; 46 | } 47 | 48 | virtual BridgeClient& operator=(const BridgeClient &_x); 49 | 50 | virtual void stop(); 51 | virtual uint8_t connected(); 52 | 53 | virtual int connect(IPAddress ip, uint16_t port); 54 | virtual int connect(const char *host, uint16_t port); 55 | int connectSSL(const char* host, uint16_t port); 56 | 57 | private: 58 | BridgeClass &bridge; 59 | uint8_t handle; 60 | boolean opened; 61 | 62 | private: 63 | void doBuffer(); 64 | uint8_t buffered; 65 | uint8_t readPos; 66 | static const int BUFFER_SIZE = 64; 67 | uint8_t buffer[BUFFER_SIZE]; 68 | 69 | }; 70 | 71 | #endif // _BRIDGE_CLIENT_H_ 72 | -------------------------------------------------------------------------------- /src/BridgeSSLClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include 20 | 21 | BridgeSSLClient::BridgeSSLClient(uint8_t _h, BridgeClass &_b) : 22 | BridgeClient(_h, _b) 23 | { 24 | } 25 | 26 | BridgeSSLClient::BridgeSSLClient(BridgeClass &_b): 27 | BridgeClient(_b) 28 | { 29 | } 30 | 31 | BridgeSSLClient::~BridgeSSLClient() { 32 | } 33 | 34 | int BridgeSSLClient::connect(const char *host, uint16_t port) { 35 | return BridgeClient::connectSSL(host, port); 36 | } 37 | -------------------------------------------------------------------------------- /src/BridgeSSLClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef _BRIDGE_SSL_CLIENT_H_ 20 | #define _BRIDGE_SSL_CLIENT_H_ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | class BridgeSSLClient : public BridgeClient { 27 | public: 28 | // Constructor with a user provided BridgeClass instance 29 | BridgeSSLClient(uint8_t _h, BridgeClass &_b = Bridge); 30 | BridgeSSLClient(BridgeClass &_b = Bridge); 31 | ~BridgeSSLClient(); 32 | 33 | virtual int connect(const char* host, uint16_t port); 34 | }; 35 | 36 | #endif // _BRIDGE_SSL_CLIENT_H_ 37 | -------------------------------------------------------------------------------- /src/BridgeServer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | BridgeServer::BridgeServer(uint16_t _p, BridgeClass &_b) : 23 | bridge(_b), port(_p), listening(false), useLocalhost(false) { 24 | } 25 | 26 | void BridgeServer::begin() { 27 | uint8_t tmp[] = { 28 | 'N', 29 | static_cast(port >> 8), 30 | static_cast(port) 31 | }; 32 | uint8_t res[1]; 33 | String address = F("127.0.0.1"); 34 | if (!useLocalhost) 35 | address = F("0.0.0.0"); 36 | bridge.transfer(tmp, 3, (const uint8_t *)address.c_str(), address.length(), res, 1); 37 | listening = (res[0] == 1); 38 | } 39 | 40 | BridgeClient BridgeServer::accept() { 41 | uint8_t cmd[] = {'k'}; 42 | uint8_t res[1]; 43 | unsigned int l = bridge.transfer(cmd, 1, res, 1); 44 | if (l == 0) 45 | return BridgeClient(); 46 | return BridgeClient(res[0]); 47 | } 48 | 49 | size_t BridgeServer::write(uint8_t c) { 50 | uint8_t cmd[] = { 'b', c }; 51 | bridge.transfer(cmd, 2); 52 | return 1; 53 | } 54 | -------------------------------------------------------------------------------- /src/BridgeServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef _BRIDGE_SERVER_H_ 20 | #define _BRIDGE_SERVER_H_ 21 | 22 | #include 23 | #include 24 | 25 | class BridgeClient; 26 | 27 | class BridgeServer : public Server { 28 | public: 29 | // Constructor with a user provided BridgeClass instance 30 | BridgeServer(uint16_t port = 5555, BridgeClass &_b = Bridge); 31 | 32 | void begin(); 33 | BridgeClient accept(); 34 | 35 | virtual size_t write(uint8_t c); 36 | 37 | void listenOnLocalhost() { 38 | useLocalhost = true; 39 | } 40 | void noListenOnLocalhost() { 41 | useLocalhost = false; 42 | } 43 | 44 | private: 45 | BridgeClass &bridge; 46 | uint16_t port; 47 | bool listening; 48 | bool useLocalhost; 49 | }; 50 | 51 | #endif // _BRIDGE_SERVER_H_ 52 | -------------------------------------------------------------------------------- /src/BridgeUdp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include "BridgeUdp.h" 20 | 21 | BridgeUDP::BridgeUDP(BridgeClass &_b) : 22 | bridge(_b), opened(false), avail(0), buffered(0), readPos(0) { 23 | } 24 | 25 | /* Start BridgeUDP socket, listening at local port PORT */ 26 | uint8_t BridgeUDP::begin(uint16_t port) { 27 | if (opened) 28 | return 0; 29 | uint8_t cmd[] = {'e', (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)}; 30 | uint8_t res[2]; 31 | bridge.transfer(cmd, 3, res, 2); 32 | if (res[1] == 1) // Error... 33 | return 0; 34 | handle = res[0]; 35 | opened = true; 36 | return 1; 37 | } 38 | 39 | /* Release any resources being used by this BridgeUDP instance */ 40 | void BridgeUDP::stop() 41 | { 42 | if (!opened) 43 | return; 44 | uint8_t cmd[] = {'q', handle}; 45 | bridge.transfer(cmd, 2); 46 | opened = false; 47 | } 48 | 49 | int BridgeUDP::beginPacket(const char *host, uint16_t port) 50 | { 51 | if (!opened) 52 | return 0; 53 | uint8_t cmd[] = {'E', handle, (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)}; 54 | uint8_t res[1]; 55 | bridge.transfer(cmd, 4, (const uint8_t *)host, strlen(host), res, 1); 56 | return res[0]; // 1=Success, 0=Error 57 | } 58 | 59 | int BridgeUDP::beginBroadcastPacket(uint16_t port) 60 | { 61 | if (!opened) 62 | return 0; 63 | uint8_t cmd[] = {'v', handle, (uint8_t)((port >> 8) & 0xFF), (uint8_t)(port & 0xFF)}; 64 | uint8_t res[1]; 65 | bridge.transfer(cmd, 4, res, 1); 66 | return res[0]; // 1=Success, 0=Error 67 | } 68 | 69 | int BridgeUDP::beginPacket(IPAddress ip, uint16_t port) 70 | { 71 | if (!opened) 72 | return 0; 73 | String address; 74 | address.reserve(18); 75 | address += ip[0]; 76 | address += '.'; 77 | address += ip[1]; 78 | address += '.'; 79 | address += ip[2]; 80 | address += '.'; 81 | address += ip[3]; 82 | return beginPacket(address.c_str(), port); 83 | } 84 | 85 | int BridgeUDP::endPacket() 86 | { 87 | if (!opened) 88 | return 0; 89 | uint8_t cmd[] = {'H', handle}; 90 | uint8_t res[1]; 91 | bridge.transfer(cmd, 2, res, 1); 92 | return res[0]; // 1=Success, 0=Error 93 | } 94 | 95 | size_t BridgeUDP::write(const uint8_t *buffer, size_t size) 96 | { 97 | if (!opened) 98 | return 0; 99 | uint8_t cmd[] = {'h', handle}; 100 | uint8_t res[1]; 101 | bridge.transfer(cmd, 2, buffer, size, res, 1); 102 | return res[0]; // 1=Success, 0=Error 103 | } 104 | 105 | int BridgeUDP::parsePacket() 106 | { 107 | if (!opened) 108 | return 0; 109 | buffered = 0; 110 | readPos = 0; 111 | uint8_t cmd[] = {'Q', handle}; 112 | uint8_t res[3]; 113 | bridge.transfer(cmd, 2, res, 3); 114 | if (res[0] == 0) { 115 | // There aren't any packets available 116 | return 0; 117 | } 118 | avail = (res[1] << 8) + res[2]; 119 | return 1; 120 | } 121 | 122 | void BridgeUDP::doBuffer() { 123 | // If there are already char in buffer exit 124 | if (buffered > 0) 125 | return; 126 | if (avail == 0) 127 | return; 128 | 129 | // Try to buffer up to 32 characters 130 | readPos = 0; 131 | uint8_t cmd[] = {'u', handle, sizeof(buffer)}; 132 | buffered = bridge.transfer(cmd, 3, buffer, sizeof(buffer)); 133 | } 134 | 135 | int BridgeUDP::read() 136 | { 137 | if (!opened) 138 | return -1; 139 | doBuffer(); 140 | if (buffered == 0) { 141 | return -1; // no chars available 142 | } 143 | buffered--; 144 | avail--; 145 | return buffer[readPos++]; 146 | } 147 | 148 | int BridgeUDP::read(unsigned char* buff, size_t size) 149 | { 150 | if (!opened) 151 | return -1; 152 | size_t readed = 0; 153 | do { 154 | if (buffered == 0) { 155 | doBuffer(); 156 | if (buffered == 0) 157 | return readed; 158 | } 159 | buff[readed++] = buffer[readPos++]; 160 | buffered--; 161 | avail--; 162 | } while (readed < size); 163 | return readed; 164 | } 165 | 166 | int BridgeUDP::peek() 167 | { 168 | if (!opened) 169 | return -1; 170 | doBuffer(); 171 | if (buffered == 0) 172 | return -1; // no chars available 173 | return buffer[readPos]; 174 | } 175 | 176 | IPAddress BridgeUDP::remoteIP() 177 | { 178 | if (!opened) 179 | return -1; 180 | uint8_t cmd[] = {'T', handle}; 181 | uint8_t res[7]; 182 | bridge.transfer(cmd, 2, res, 7); 183 | if (res[0] == 0) 184 | return IPAddress(0,0,0,0); 185 | return IPAddress(res[1], res[2], res[3], res[4]); 186 | } 187 | 188 | uint16_t BridgeUDP::remotePort() 189 | { 190 | if (!opened) 191 | return -1; 192 | uint8_t cmd[] = {'T', handle}; 193 | uint8_t res[7]; 194 | bridge.transfer(cmd, 2, res, 7); 195 | if (res[0] == 0) 196 | return 0; 197 | return (res[5] << 8) + res[6]; 198 | } 199 | -------------------------------------------------------------------------------- /src/BridgeUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #pragma once 20 | 21 | #include 22 | #include "Bridge.h" 23 | 24 | class BridgeUDP : public UDP { 25 | 26 | public: 27 | BridgeUDP(BridgeClass &_b = Bridge); 28 | virtual uint8_t begin(uint16_t); 29 | virtual void stop(); 30 | 31 | virtual int beginPacket(IPAddress ip, uint16_t port); 32 | virtual int beginPacket(const char *host, uint16_t port); 33 | virtual int beginBroadcastPacket(uint16_t port); 34 | virtual int endPacket(); 35 | virtual size_t write(uint8_t d) { return write(&d, 1); } 36 | virtual size_t write(const uint8_t *buffer, size_t size); 37 | 38 | using Print::write; 39 | 40 | virtual int parsePacket(); 41 | /* return number of bytes available in the current packet, 42 | will return zero if parsePacket hasn't been called yet */ 43 | virtual int available() { return avail; } 44 | virtual int read(); 45 | virtual int read(unsigned char* buffer, size_t len); 46 | virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; 47 | virtual int peek(); 48 | virtual void flush() { avail = 0; } 49 | 50 | virtual IPAddress remoteIP(); 51 | virtual uint16_t remotePort(); 52 | 53 | private: 54 | BridgeClass &bridge; 55 | uint8_t handle; 56 | boolean opened; 57 | 58 | private: 59 | void doBuffer(); 60 | uint16_t avail; 61 | uint8_t buffered; 62 | uint8_t readPos; 63 | static const int BUFFER_SIZE = 64; 64 | uint8_t buffer[BUFFER_SIZE]; 65 | }; 66 | -------------------------------------------------------------------------------- /src/Console.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include 20 | 21 | // Default constructor uses global Bridge instance 22 | ConsoleClass::ConsoleClass() : 23 | bridge(Bridge), inBuffered(0), inReadPos(0), inBuffer(NULL), 24 | autoFlush(true) 25 | { 26 | // Empty 27 | } 28 | 29 | // Constructor with a user provided BridgeClass instance 30 | ConsoleClass::ConsoleClass(BridgeClass &_b) : 31 | bridge(_b), inBuffered(0), inReadPos(0), inBuffer(NULL), 32 | autoFlush(true) 33 | { 34 | // Empty 35 | } 36 | 37 | ConsoleClass::~ConsoleClass() { 38 | end(); 39 | } 40 | 41 | size_t ConsoleClass::write(uint8_t c) { 42 | if (autoFlush) { 43 | uint8_t tmp[] = { 'P', c }; 44 | bridge.transfer(tmp, 2); 45 | } else { 46 | outBuffer[outBuffered++] = c; 47 | if (outBuffered == outBufferSize) 48 | flush(); 49 | } 50 | return 1; 51 | } 52 | 53 | size_t ConsoleClass::write(const uint8_t *buff, size_t size) { 54 | if (autoFlush) { 55 | uint8_t tmp[] = { 'P' }; 56 | bridge.transfer(tmp, 1, buff, size, NULL, 0); 57 | } else { 58 | size_t sent = size; 59 | while (sent > 0) { 60 | outBuffer[outBuffered++] = *buff++; 61 | sent--; 62 | if (outBuffered == outBufferSize) 63 | flush(); 64 | } 65 | } 66 | return size; 67 | } 68 | 69 | void ConsoleClass::flush() { 70 | if (autoFlush) 71 | return; 72 | 73 | bridge.transfer(outBuffer, outBuffered); 74 | outBuffered = 1; 75 | } 76 | 77 | void ConsoleClass::noBuffer() { 78 | if (autoFlush) 79 | return; 80 | delete[] outBuffer; 81 | autoFlush = true; 82 | } 83 | 84 | void ConsoleClass::buffer(uint8_t size) { 85 | noBuffer(); 86 | if (size == 0) 87 | return; 88 | outBuffer = new uint8_t[size + 1]; 89 | outBuffer[0] = 'P'; // WRITE tag 90 | outBufferSize = size + 1; 91 | outBuffered = 1; 92 | autoFlush = false; 93 | } 94 | 95 | bool ConsoleClass::connected() { 96 | uint8_t tmp = 'a'; 97 | bridge.transfer(&tmp, 1, &tmp, 1); 98 | return tmp == 1; 99 | } 100 | 101 | int ConsoleClass::available() { 102 | // Look if there is new data available 103 | doBuffer(); 104 | return inBuffered; 105 | } 106 | 107 | int ConsoleClass::read() { 108 | doBuffer(); 109 | if (inBuffered == 0) 110 | return -1; // no chars available 111 | else { 112 | inBuffered--; 113 | return inBuffer[inReadPos++]; 114 | } 115 | } 116 | 117 | int ConsoleClass::peek() { 118 | doBuffer(); 119 | if (inBuffered == 0) 120 | return -1; // no chars available 121 | else 122 | return inBuffer[inReadPos]; 123 | } 124 | 125 | void ConsoleClass::doBuffer() { 126 | // If there are already char in buffer exit 127 | if (inBuffered > 0) 128 | return; 129 | 130 | // Try to buffer up to 32 characters 131 | inReadPos = 0; 132 | uint8_t tmp[] = { 'p', BUFFER_SIZE }; 133 | inBuffered = bridge.transfer(tmp, 2, inBuffer, BUFFER_SIZE); 134 | } 135 | 136 | void ConsoleClass::begin() { 137 | bridge.begin(); 138 | end(); 139 | inBuffer = new uint8_t[BUFFER_SIZE]; 140 | } 141 | 142 | void ConsoleClass::end() { 143 | noBuffer(); 144 | if (inBuffer) { 145 | delete[] inBuffer; 146 | inBuffer = NULL; 147 | } 148 | } 149 | 150 | ConsoleClass Console; 151 | -------------------------------------------------------------------------------- /src/Console.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef CONSOLE_H_ 20 | #define CONSOLE_H_ 21 | 22 | #include 23 | 24 | class ConsoleClass : public Stream { 25 | public: 26 | // Default constructor uses global Bridge instance 27 | ConsoleClass(); 28 | // Constructor with a user provided BridgeClass instance 29 | ConsoleClass(BridgeClass &_b); 30 | ~ConsoleClass(); 31 | 32 | void begin(); 33 | void end(); 34 | 35 | void buffer(uint8_t size); 36 | void noBuffer(); 37 | 38 | bool connected(); 39 | 40 | // Stream methods 41 | // (read from console socket) 42 | int available(); 43 | int read(); 44 | int peek(); 45 | // (write to console socket) 46 | size_t write(uint8_t); 47 | size_t write(const uint8_t *buffer, size_t size); 48 | void flush(); 49 | 50 | operator bool () { 51 | return connected(); 52 | } 53 | 54 | private: 55 | BridgeClass &bridge; 56 | 57 | void doBuffer(); 58 | uint8_t inBuffered; 59 | uint8_t inReadPos; 60 | static const int BUFFER_SIZE = 32; 61 | uint8_t *inBuffer; 62 | 63 | bool autoFlush; 64 | uint8_t outBuffered; 65 | uint8_t outBufferSize; 66 | uint8_t *outBuffer; 67 | }; 68 | 69 | extern ConsoleClass Console; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/FileIO.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include 20 | 21 | namespace BridgeLib { 22 | 23 | File::File(BridgeClass &b) : bridge(b), mode(255) { 24 | // Empty 25 | } 26 | 27 | File::File(const char *_filename, uint8_t _mode, BridgeClass &b) : bridge(b), mode(_mode) { 28 | filename = _filename; 29 | uint8_t modes[] = {'r', 'w', 'a'}; 30 | uint8_t cmd[] = {'F', modes[mode]}; 31 | uint8_t res[2]; 32 | dirPosition = 1; 33 | bridge.transfer(cmd, 2, (uint8_t*)filename.c_str(), filename.length(), res, 2); 34 | if (res[0] != 0) { // res[0] contains error code 35 | mode = 255; // In case of error keep the file closed 36 | return; 37 | } 38 | handle = res[1]; 39 | buffered = 0; 40 | } 41 | 42 | File::operator bool() { 43 | return (mode != 255); 44 | } 45 | 46 | File::~File() { 47 | close(); 48 | } 49 | 50 | size_t File::write(uint8_t c) { 51 | return write(&c, 1); 52 | } 53 | 54 | size_t File::write(const uint8_t *buf, size_t size) { 55 | if (mode == 255) 56 | return -1; 57 | uint8_t cmd[] = {'g', handle}; 58 | uint8_t res[1]; 59 | bridge.transfer(cmd, 2, buf, size, res, 1); 60 | if (res[0] != 0) // res[0] contains error code 61 | return -res[0]; 62 | return size; 63 | } 64 | 65 | int File::read() { 66 | doBuffer(); 67 | if (buffered == 0) 68 | return -1; // no chars available 69 | else { 70 | buffered--; 71 | return buffer[readPos++]; 72 | } 73 | } 74 | 75 | int File::peek() { 76 | doBuffer(); 77 | if (buffered == 0) 78 | return -1; // no chars available 79 | else 80 | return buffer[readPos]; 81 | } 82 | 83 | boolean File::seek(uint32_t position) { 84 | uint8_t cmd[] = { 85 | 's', 86 | handle, 87 | static_cast(position >> 24), 88 | static_cast(position >> 16), 89 | static_cast(position >> 8), 90 | static_cast(position) 91 | }; 92 | uint8_t res[1]; 93 | bridge.transfer(cmd, 6, res, 1); 94 | if (res[0] == 0) { 95 | // If seek succeeds then flush buffers 96 | buffered = 0; 97 | return true; 98 | } 99 | return false; 100 | } 101 | 102 | uint32_t File::position() { 103 | uint8_t cmd[] = {'S', handle}; 104 | uint8_t res[5]; 105 | bridge.transfer(cmd, 2, res, 5); 106 | //err = res[0]; // res[0] contains error code 107 | uint32_t pos; 108 | pos = static_cast(res[1]) << 24; 109 | pos += static_cast(res[2]) << 16; 110 | pos += static_cast(res[3]) << 8; 111 | pos += static_cast(res[4]); 112 | return pos - buffered; 113 | } 114 | 115 | void File::doBuffer() { 116 | // If there are already char in buffer exit 117 | if (buffered > 0) 118 | return; 119 | 120 | // Try to buffer up to BUFFER_SIZE characters 121 | readPos = 0; 122 | uint8_t cmd[] = {'G', handle, BUFFER_SIZE - 1}; 123 | uint16_t readed = bridge.transfer(cmd, 3, buffer, BUFFER_SIZE); 124 | //err = buff[0]; // First byte is error code 125 | if (readed == BridgeClass::TRANSFER_TIMEOUT || readed == 0) { 126 | // transfer failed to retrieve any data 127 | buffered = 0; 128 | } else { 129 | // transfer retrieved at least one byte of data so skip the error code character 130 | readPos++; 131 | buffered = readed - 1; 132 | } 133 | } 134 | 135 | int File::available() { 136 | // Look if there is new data available 137 | doBuffer(); 138 | return buffered; 139 | } 140 | 141 | void File::flush() { 142 | } 143 | 144 | int File::read(void *buff, uint16_t nbyte) { 145 | uint16_t n = 0; 146 | uint8_t *p = reinterpret_cast(buff); 147 | while (n < nbyte) { 148 | if (buffered == 0) { 149 | doBuffer(); 150 | if (buffered == 0) 151 | break; 152 | } 153 | *p++ = buffer[readPos++]; 154 | buffered--; 155 | n++; 156 | } 157 | return n; 158 | } 159 | 160 | uint32_t File::size() { 161 | if (bridge.getBridgeVersion() < 101) 162 | return 0; 163 | uint8_t cmd[] = {'t', handle}; 164 | uint8_t buff[5]; 165 | bridge.transfer(cmd, 2, buff, 5); 166 | //err = res[0]; // First byte is error code 167 | uint32_t res; 168 | res = ((uint32_t)buff[1]) << 24; 169 | res |= ((uint32_t)buff[2]) << 16; 170 | res |= ((uint32_t)buff[3]) << 8; 171 | res |= ((uint32_t)buff[4]); 172 | return res; 173 | } 174 | 175 | void File::close() { 176 | if (mode == 255) 177 | return; 178 | uint8_t cmd[] = {'f', handle}; 179 | uint8_t ret[1]; 180 | bridge.transfer(cmd, 2, ret, 1); 181 | mode = 255; 182 | } 183 | 184 | const char *File::name() { 185 | return filename.c_str(); 186 | } 187 | 188 | 189 | boolean File::isDirectory() { 190 | uint8_t res[1]; 191 | uint8_t cmd[] = {'i'}; 192 | if (mode != 255) 193 | return 0; 194 | 195 | bridge.transfer(cmd, 1, (uint8_t *)filename.c_str(), filename.length(), res, 1); 196 | return res[0]; 197 | } 198 | 199 | 200 | File File::openNextFile(uint8_t mode) { 201 | Process awk; 202 | char tmp; 203 | String command; 204 | String filepath; 205 | if (dirPosition == 0xFFFF) return File(); 206 | 207 | command = "ls "; 208 | command += filename; 209 | command += " | awk 'NR=="; 210 | command += dirPosition; 211 | command += "'"; 212 | 213 | awk.runShellCommand(command); 214 | 215 | while (awk.running()); 216 | 217 | command = ""; 218 | 219 | while (awk.available()) { 220 | tmp = awk.read(); 221 | if (tmp != '\n') command += tmp; 222 | } 223 | if (command.length() == 0) 224 | return File(); 225 | dirPosition++; 226 | filepath = filename + "/" + command; 227 | return File(filepath.c_str(), mode); 228 | 229 | } 230 | 231 | void File::rewindDirectory(void) { 232 | dirPosition = 1; 233 | } 234 | 235 | 236 | 237 | 238 | 239 | 240 | boolean FileSystemClass::begin() { 241 | return true; 242 | } 243 | 244 | File FileSystemClass::open(const char *filename, uint8_t mode) { 245 | return File(filename, mode); 246 | } 247 | 248 | boolean FileSystemClass::exists(const char *filepath) { 249 | Process ls; 250 | ls.begin("ls"); 251 | ls.addParameter(filepath); 252 | int res = ls.run(); 253 | return (res == 0); 254 | } 255 | 256 | boolean FileSystemClass::mkdir(const char *filepath) { 257 | Process mk; 258 | mk.begin("mkdir"); 259 | mk.addParameter("-p"); 260 | mk.addParameter(filepath); 261 | int res = mk.run(); 262 | return (res == 0); 263 | } 264 | 265 | boolean FileSystemClass::remove(const char *filepath) { 266 | Process rm; 267 | rm.begin("rm"); 268 | rm.addParameter(filepath); 269 | int res = rm.run(); 270 | return (res == 0); 271 | } 272 | 273 | boolean FileSystemClass::rmdir(const char *filepath) { 274 | Process rm; 275 | rm.begin("rmdir"); 276 | rm.addParameter(filepath); 277 | int res = rm.run(); 278 | return (res == 0); 279 | } 280 | 281 | FileSystemClass FileSystem; 282 | 283 | } 284 | -------------------------------------------------------------------------------- /src/FileIO.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef __FILEIO_H__ 20 | #define __FILEIO_H__ 21 | 22 | #include 23 | 24 | #define FILE_READ 0 25 | #define FILE_WRITE 1 26 | #define FILE_APPEND 2 27 | 28 | namespace BridgeLib { 29 | 30 | class File : public Stream { 31 | 32 | public: 33 | File(BridgeClass &b = Bridge); 34 | File(const char *_filename, uint8_t _mode, BridgeClass &b = Bridge); 35 | ~File(); 36 | 37 | virtual size_t write(uint8_t); 38 | virtual size_t write(const uint8_t *buf, size_t size); 39 | virtual int read(); 40 | virtual int peek(); 41 | virtual int available(); 42 | virtual void flush(); 43 | int read(void *buf, uint16_t nbyte); 44 | boolean seek(uint32_t pos); 45 | uint32_t position(); 46 | uint32_t size(); 47 | void close(); 48 | operator bool(); 49 | const char * name(); 50 | boolean isDirectory(); 51 | File openNextFile(uint8_t mode = FILE_READ); 52 | void rewindDirectory(void); 53 | 54 | //using Print::write; 55 | 56 | private: 57 | void doBuffer(); 58 | uint8_t buffered; 59 | uint8_t readPos; 60 | uint16_t dirPosition; 61 | static const int BUFFER_SIZE = 64; 62 | uint8_t buffer[BUFFER_SIZE]; 63 | 64 | 65 | private: 66 | BridgeClass &bridge; 67 | String filename; 68 | uint8_t mode; 69 | uint8_t handle; 70 | 71 | }; 72 | 73 | class FileSystemClass { 74 | public: 75 | FileSystemClass() : bridge(Bridge) { } 76 | FileSystemClass(BridgeClass &_b) : bridge(_b) { } 77 | 78 | boolean begin(); 79 | 80 | // Open the specified file/directory with the supplied mode (e.g. read or 81 | // write, etc). Returns a File object for interacting with the file. 82 | // Note that currently only one file can be open at a time. 83 | File open(const char *filename, uint8_t mode = FILE_READ); 84 | 85 | // Methods to determine if the requested file path exists. 86 | boolean exists(const char *filepath); 87 | 88 | // Create the requested directory hierarchy--if intermediate directories 89 | // do not exist they will be created. 90 | boolean mkdir(const char *filepath); 91 | 92 | // Delete the file. 93 | boolean remove(const char *filepath); 94 | 95 | boolean rmdir(const char *filepath); 96 | 97 | private: 98 | friend class File; 99 | 100 | BridgeClass &bridge; 101 | }; 102 | 103 | extern FileSystemClass FileSystem; 104 | 105 | }; 106 | 107 | // We enclose File and FileSystem classes in namespace BridgeLib to avoid 108 | // conflicts with legacy SD library. 109 | 110 | // This ensure compatibility with older sketches that uses only Bridge lib 111 | // (the user can still use File instead of BridgeFile) 112 | using namespace BridgeLib; 113 | 114 | // This allows sketches to use BridgeLib::File together with SD library 115 | // (you must use BridgeFile instead of File when needed to disambiguate) 116 | typedef BridgeLib::File BridgeFile; 117 | typedef BridgeLib::FileSystemClass BridgeFileSystemClass; 118 | #define BridgeFileSystem BridgeLib::FileSystem 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /src/HttpClient.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013-2014 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include "HttpClient.h" 20 | 21 | HttpClient::HttpClient() : 22 | insecure(false) { 23 | // Empty 24 | } 25 | 26 | unsigned int HttpClient::get(String &url) { 27 | begin("curl"); 28 | if (insecure) { 29 | addParameter("-k"); 30 | } 31 | addHeader(); 32 | addParameter(url); 33 | return run(); 34 | } 35 | 36 | unsigned int HttpClient::get(const char *url) { 37 | begin("curl"); 38 | if (insecure) { 39 | addParameter("-k"); 40 | } 41 | addHeader(); 42 | addParameter(url); 43 | return run(); 44 | } 45 | 46 | void HttpClient::getAsynchronously(String &url) { 47 | begin("curl"); 48 | if (insecure) { 49 | addParameter("-k"); 50 | } 51 | addHeader(); 52 | addParameter(url); 53 | runAsynchronously(); 54 | } 55 | 56 | void HttpClient::getAsynchronously(const char *url) { 57 | begin("curl"); 58 | if (insecure) { 59 | addParameter("-k"); 60 | } 61 | addHeader(); 62 | addParameter(url); 63 | runAsynchronously(); 64 | } 65 | 66 | unsigned int HttpClient::post(String &url, String &data) { 67 | return post(url.c_str(), data.c_str()); 68 | } 69 | 70 | unsigned int HttpClient::post(const char *url, const char *data) { 71 | begin("curl"); 72 | if (insecure) { 73 | addParameter("-k"); 74 | } 75 | addParameter("--request"); 76 | addParameter("POST"); 77 | addParameter("--data"); 78 | addParameter(data); 79 | addHeader(); 80 | addParameter(url); 81 | return run(); 82 | } 83 | 84 | void HttpClient::postAsynchronously(String &url, String &data) { 85 | postAsynchronously(url.c_str(), data.c_str()); 86 | } 87 | 88 | void HttpClient::postAsynchronously(const char *url, const char *data) { 89 | begin("curl"); 90 | if (insecure) { 91 | addParameter("-k"); 92 | } 93 | addParameter("--request"); 94 | addParameter("POST"); 95 | addParameter("--data"); 96 | addParameter(data); 97 | addHeader(); 98 | addParameter(url); 99 | runAsynchronously(); 100 | } 101 | 102 | unsigned int HttpClient::patch(String &url, String &data) { 103 | return patch(url.c_str(), data.c_str()); 104 | } 105 | 106 | unsigned int HttpClient::patch(const char *url, const char *data) { 107 | begin("curl"); 108 | if (insecure) { 109 | addParameter("-k"); 110 | } 111 | addParameter("--request"); 112 | addParameter("PATCH"); 113 | addParameter("--data"); 114 | addParameter(data); 115 | addHeader(); 116 | addParameter(url); 117 | return run(); 118 | } 119 | 120 | void HttpClient::patchAsynchronously(String &url, String &data) { 121 | patchAsynchronously(url.c_str(), data.c_str()); 122 | } 123 | 124 | void HttpClient::patchAsynchronously(const char *url, const char *data) { 125 | begin("curl"); 126 | if (insecure) { 127 | addParameter("-k"); 128 | } 129 | addParameter("--request"); 130 | addParameter("PATCH"); 131 | addParameter("--data"); 132 | addParameter(data); 133 | addHeader(); 134 | addParameter(url); 135 | runAsynchronously(); 136 | } 137 | 138 | unsigned int HttpClient::put(String &url, String &data) { 139 | return put(url.c_str(), data.c_str()); 140 | } 141 | 142 | unsigned int HttpClient::put(const char *url, const char *data) { 143 | begin("curl"); 144 | if (insecure) { 145 | addParameter("-k"); 146 | } 147 | addParameter("--request"); 148 | addParameter("PUT"); 149 | addParameter("--data"); 150 | addParameter(data); 151 | addHeader(); 152 | addParameter(url); 153 | return run(); 154 | } 155 | 156 | void HttpClient::putAsynchronously(String &url, String &data) { 157 | putAsynchronously(url.c_str(), data.c_str()); 158 | } 159 | 160 | void HttpClient::putAsynchronously(const char *url, const char *data) { 161 | begin("curl"); 162 | if (insecure) { 163 | addParameter("-k"); 164 | } 165 | addParameter("--request"); 166 | addParameter("PUT"); 167 | addParameter("--data"); 168 | addParameter(data); 169 | addHeader(); 170 | addParameter(url); 171 | runAsynchronously(); 172 | } 173 | 174 | boolean HttpClient::ready() { 175 | return !running(); 176 | } 177 | 178 | unsigned int HttpClient::getResult() { 179 | return exitValue(); 180 | } 181 | 182 | void HttpClient::noCheckSSL() { 183 | insecure = true; 184 | } 185 | 186 | void HttpClient::checkSSL() { 187 | insecure = false; 188 | } 189 | 190 | void HttpClient::setHeader(String &header) { 191 | this->header = header; 192 | } 193 | 194 | void HttpClient::setHeader(const char * header) { 195 | this->header = String(header); 196 | } 197 | 198 | void HttpClient::addHeader() { 199 | if (header.length() > 0) { 200 | addParameter("--header"); 201 | addParameter(header); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/HttpClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013-2014 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef HTTPCLIENT_H_ 20 | #define HTTPCLIENT_H_ 21 | 22 | #include 23 | 24 | class HttpClient : public Process { 25 | public: 26 | HttpClient(); 27 | 28 | unsigned int get(String &url); 29 | unsigned int get(const char * url); 30 | void getAsynchronously(String &url); 31 | void getAsynchronously(const char * url); 32 | unsigned int post(String &url, String &data); 33 | unsigned int post(const char * url, const char * data); 34 | void postAsynchronously(String &url, String &data); 35 | void postAsynchronously(const char * url, const char * data); 36 | unsigned int patch(String &url, String &data); 37 | unsigned int patch(const char * url, const char * data); 38 | void patchAsynchronously(String &url, String &data); 39 | void patchAsynchronously(const char * url, const char * data); 40 | unsigned int put(String &url, String &data); 41 | unsigned int put(const char * url, const char * data); 42 | void putAsynchronously(String &url, String &data); 43 | void putAsynchronously(const char * url, const char * data); 44 | void setHeader(String &header); 45 | void setHeader(const char * header); 46 | boolean ready(); 47 | unsigned int getResult(); 48 | void noCheckSSL(); 49 | void checkSSL(); 50 | 51 | private: 52 | boolean insecure; 53 | 54 | private: 55 | void addHeader(); 56 | String header; 57 | }; 58 | 59 | #endif /* HTTPCLIENT_H_ */ 60 | -------------------------------------------------------------------------------- /src/Mailbox.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include 20 | 21 | unsigned int MailboxClass::readMessage(uint8_t *buff, unsigned int size) { 22 | uint8_t tmp[] = { 'm' }; 23 | return bridge.transfer(tmp, 1, buff, size); 24 | } 25 | 26 | void MailboxClass::readMessage(String &str, unsigned int maxLength) { 27 | uint8_t tmp[] = { 'm' }; 28 | // XXX: Is there a better way to create the string? 29 | uint8_t buff[maxLength + 1]; 30 | int l = bridge.transfer(tmp, 1, buff, maxLength); 31 | buff[l] = 0; 32 | str = (const char *)buff; 33 | } 34 | 35 | void MailboxClass::writeMessage(const uint8_t *buff, unsigned int size) { 36 | uint8_t cmd[] = {'M'}; 37 | bridge.transfer(cmd, 1, buff, size, NULL, 0); 38 | } 39 | 40 | void MailboxClass::writeMessage(const String& str) { 41 | writeMessage((uint8_t*) str.c_str(), str.length()); 42 | } 43 | 44 | void MailboxClass::writeJSON(const String& str) { 45 | uint8_t cmd[] = {'J'}; 46 | bridge.transfer(cmd, 1, (uint8_t*) str.c_str(), str.length(), NULL, 0); 47 | } 48 | 49 | unsigned int MailboxClass::messageAvailable() { 50 | uint8_t tmp[] = {'n'}; 51 | uint8_t res[2]; 52 | bridge.transfer(tmp, 1, res, 2); 53 | return (res[0] << 8) + res[1]; 54 | } 55 | 56 | MailboxClass Mailbox(Bridge); 57 | -------------------------------------------------------------------------------- /src/Mailbox.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef _MAILBOX_CLASS_H_INCLUDED_ 20 | #define _MAILBOX_CLASS_H_INCLUDED_ 21 | 22 | #include 23 | 24 | class MailboxClass { 25 | public: 26 | MailboxClass(BridgeClass &b = Bridge) : bridge(b) { } 27 | 28 | void begin() { } 29 | void end() { } 30 | 31 | // Receive a message and store it inside a buffer 32 | unsigned int readMessage(uint8_t *buffer, unsigned int size); 33 | // Receive a message and store it inside a String 34 | void readMessage(String &str, unsigned int maxLength = 128); 35 | 36 | // Send a message 37 | void writeMessage(const uint8_t *buffer, unsigned int size); 38 | // Send a message 39 | void writeMessage(const String& str); 40 | // Send a JSON message 41 | void writeJSON(const String& str); 42 | 43 | // Return the size of the next available message, 0 if there are 44 | // no messages in queue. 45 | unsigned int messageAvailable(); 46 | 47 | private: 48 | BridgeClass &bridge; 49 | }; 50 | 51 | extern MailboxClass Mailbox; 52 | 53 | #endif // _MAILBOX_CLASS_H_INCLUDED_ 54 | -------------------------------------------------------------------------------- /src/Process.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include 20 | 21 | Process::~Process() { 22 | close(); 23 | } 24 | 25 | size_t Process::write(uint8_t c) { 26 | uint8_t cmd[] = {'I', handle, c}; 27 | bridge.transfer(cmd, 3); 28 | return 1; 29 | } 30 | 31 | void Process::flush() { 32 | } 33 | 34 | int Process::available() { 35 | // Look if there is new data available 36 | doBuffer(); 37 | return buffered; 38 | } 39 | 40 | int Process::read() { 41 | doBuffer(); 42 | if (buffered == 0) 43 | return -1; // no chars available 44 | else { 45 | buffered--; 46 | return buffer[readPos++]; 47 | } 48 | } 49 | 50 | int Process::peek() { 51 | doBuffer(); 52 | if (buffered == 0) 53 | return -1; // no chars available 54 | else 55 | return buffer[readPos]; 56 | } 57 | 58 | void Process::doBuffer() { 59 | // If there are already char in buffer exit 60 | if (buffered > 0) 61 | return; 62 | 63 | // Try to buffer up to 32 characters 64 | readPos = 0; 65 | uint8_t cmd[] = {'O', handle, sizeof(buffer)}; 66 | buffered = bridge.transfer(cmd, 3, buffer, sizeof(buffer)); 67 | } 68 | 69 | void Process::begin(const String &command) { 70 | close(); 71 | cmdline = new String(command); 72 | } 73 | 74 | void Process::addParameter(const String ¶m) { 75 | *cmdline += "\xFE"; 76 | *cmdline += param; 77 | } 78 | 79 | void Process::runAsynchronously() { 80 | uint8_t cmd[] = {'R'}; 81 | uint8_t res[2]; 82 | bridge.transfer(cmd, 1, (uint8_t*)cmdline->c_str(), cmdline->length(), res, 2); 83 | handle = res[1]; 84 | 85 | delete cmdline; 86 | cmdline = NULL; 87 | 88 | if (res[0] == 0) // res[0] contains error code 89 | started = true; 90 | } 91 | 92 | boolean Process::running() { 93 | uint8_t cmd[] = {'r', handle}; 94 | uint8_t res[1]; 95 | bridge.transfer(cmd, 2, res, 1); 96 | return (res[0] == 1); 97 | } 98 | 99 | unsigned int Process::exitValue() { 100 | uint8_t cmd[] = {'W', handle}; 101 | uint8_t res[2]; 102 | bridge.transfer(cmd, 2, res, 2); 103 | return (res[0] << 8) + res[1]; 104 | } 105 | 106 | unsigned int Process::run() { 107 | runAsynchronously(); 108 | while (running()) 109 | delay(100); 110 | return exitValue(); 111 | } 112 | 113 | void Process::close() { 114 | if (started) { 115 | uint8_t cmd[] = {'w', handle}; 116 | bridge.transfer(cmd, 2); 117 | } 118 | started = false; 119 | } 120 | 121 | unsigned int Process::runShellCommand(const String &command) { 122 | runShellCommandAsynchronously(command); 123 | while (running()) 124 | delay(100); 125 | return exitValue(); 126 | } 127 | 128 | void Process::runShellCommandAsynchronously(const String &command) { 129 | begin("/bin/ash"); 130 | addParameter("-c"); 131 | addParameter(command); 132 | runAsynchronously(); 133 | } 134 | 135 | // This method is currently unused 136 | //static unsigned int __commandOutputAvailable(uint8_t handle) { 137 | // uint8_t cmd[] = {'o', handle}; 138 | // uint8_t res[1]; 139 | // Bridge.transfer(cmd, 2, res, 1); 140 | // return res[0]; 141 | //} 142 | -------------------------------------------------------------------------------- /src/Process.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef PROCESS_H_ 20 | #define PROCESS_H_ 21 | 22 | #include 23 | 24 | class Process : public Stream { 25 | public: 26 | // Constructor with a user provided BridgeClass instance 27 | Process(BridgeClass &_b = Bridge) : 28 | bridge(_b), started(false), buffered(0), readPos(0) { } 29 | ~Process(); 30 | 31 | void begin(const String &command); 32 | void addParameter(const String ¶m); 33 | unsigned int run(); 34 | void runAsynchronously(); 35 | boolean running(); 36 | unsigned int exitValue(); 37 | void close(); 38 | 39 | unsigned int runShellCommand(const String &command); 40 | void runShellCommandAsynchronously(const String &command); 41 | 42 | operator bool () { 43 | return started; 44 | } 45 | 46 | // Stream methods 47 | // (read from process stdout) 48 | int available(); 49 | int read(); 50 | int peek(); 51 | // (write to process stdin) 52 | size_t write(uint8_t); 53 | void flush(); 54 | // TODO: add optimized function for block write 55 | 56 | private: 57 | BridgeClass &bridge; 58 | uint8_t handle; 59 | String *cmdline; 60 | boolean started; 61 | 62 | private: 63 | void doBuffer(); 64 | uint8_t buffered; 65 | uint8_t readPos; 66 | static const int BUFFER_SIZE = 64; 67 | uint8_t buffer[BUFFER_SIZE]; 68 | 69 | }; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/YunClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef _YUN_CLIENT_H_ 20 | #define _YUN_CLIENT_H_ 21 | 22 | #include 23 | 24 | #warning "The use of YunClient is deprecated. Use BridgeClient instead!" 25 | typedef BridgeClient YunClient; 26 | 27 | #endif // _YUN_CLIENT_H_ 28 | -------------------------------------------------------------------------------- /src/YunServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014 Arduino LLC. All right reserved. 3 | 4 | This library is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public 6 | License as published by the Free Software Foundation; either 7 | version 2.1 of the License, or (at your option) any later version. 8 | 9 | This library is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #ifndef _YUN_SERVER_H_ 20 | #define _YUN_SERVER_H_ 21 | 22 | #include 23 | 24 | #warning "The use of YunServer is deprecated. Use BridgeServer instead!" 25 | typedef BridgeServer YunServer; 26 | 27 | #endif // _YUN_SERVER_H_ 28 | --------------------------------------------------------------------------------