/*
    Web Scraper using Lantronix
    Microcontroller is connected to a Lantronix Xport
    serial-to-ethernet device. This program connects
    to a HTTP server through the Xport, makes a HTTP GET
    request for a PHP script, and parses the returned string.

    Xport communicates at 9600-8-n-1 non-inverted (true) serial.

    By Tom Igoe, 13 April 2006
*/



// Defines for the Xport's status (used for staus variable):
#define disconnected 0
#define connected 1
#define connecting 2
#define requesting 3
#define reading 4

/*
  Note: Status LEDs correspond to status states, as follows:
 disconnected LED:  Arduino digital I/O 6
 connected LED:  Arduino digital I/O 7
 connecting LED:  Arduino digital I/O 8
 requesting LED:  Arduino digital I/O 9
 */


// Defines for I/O pins:
#define xportResetPin 10
#define meterPin 11        // I/O pin that the VU meter is on

// defines for voltmeter:
#define meterMax 165       // max value on the meter
#define meterScale 150      // my meter reads 0 - 150

// Define for clock tick interval, in ms:
#define interval 20

// variables:
int inByte= -1;          // incoming byte from serial RX
char inString[32];       // string for incoming serial data
int stringPos = 0;       // string index counter
int kilobytes = 0;       // number of kilobytes of mail

int status = 0;          // Xport's connection status
int secs = 0;            // second counter (used to sleep between checks)

void setup() {
  int i = 0;               // generic loop counter
  // set all status LED pins and Xport reset pin:
  for (i = 6; i < 11; i++) {
    pinMode(i, OUTPUT);
  }

  // set up reset LED pin as output:
  pinMode(13, OUTPUT);

  // start serial port, 9600 8-N-1:
  Serial.begin(9600);

  // blink reset LED and reset Xport:
  blink(3);
  resetXport();
}

void loop() {
  int i = 0;               // generic loop counter

  // set the status lights:
  for (i = 6; i < 10; i++) {
    if (status == i - 6) {
      digitalWrite(i, HIGH);
    } 
    else {
      digitalWrite(i, LOW);
    }
  }

  // if you're connected to the server,  make a HTTP call.  
  // If not, connect to the server:

  if(status == disconnected) {
    // attempt to connect to the server:
    xportConnect();
  } 

  if (status == connecting) {
    // read the serial port:
    if (Serial.available()) {
      inByte = Serial.read();
      // Serial.print(inByte, DEC);
      if (inByte == 67) {  // 'C' in ascii
        status = connected;    
      }
    }

  }
  if (status == connected) {
    // send HTTP GET request for CGI script:
    httpRequest();
  }  

  if (status == requesting) {
    // wait for bytes from server:
    // read the serial port:
    if (Serial.available()) {
      inByte = Serial.read();
      // If you get a "<", what follows is the air quality index:
      if (inByte == 60) {
        stringPos = 0;
        status = reading;
      }
    }
  }

  if (status == reading) {
    if (Serial.available()) {
      inByte = Serial.read();
      // Keep reading until you get a ">":
      if (inByte != 62) {
        // save only ASCII numeric characters:
        if ((inByte >= 48) && (inByte <= 57)){
          inString[stringPos] = inByte;
          stringPos++;
        }
      } 
      else {
        // convert the string to a numeric value:
        int airQuality = stringToNumber(inString, stringPos);
        // set the meter appropriately:
        setMeter(airQuality);
        status = disconnected;

        // wait 60 seconds before trying again:
        for (secs = 0; secs < 60; secs++) {
          delay(1000);
        }

        // reset Xport before next request:
        resetXport();
      }
    }
  }
}

void xportConnect() {
  //   send out the server address and 
  //   wait for a "C" byte to come back.
  //   fill in your server's numerical address below:
  Serial.print("C192.168.1.23/80\n");
  status = connecting;
}

void httpRequest() {
  int i = 0;               // generic loop counter
  inByte = -1;  
  stringPos = 0;
  //  Make HTTP GET request. Fill in the path to your version
  //  of the CGI script:
  Serial.print("GET /~username/scraper.php HTTP/1.1\n");
  delay(250);
  //  Fill in your server's name:
  Serial.print("HOST: www.myserver.com\n\n");
  status = requesting;
}

void setMeter(int desiredValue) {
  int airQualityValue = 0;
  // if the value won't peg the meter, convert it
  // to the meter scale and send it out:
  if (desiredValue <= meterScale) {
    airQualityValue = desiredValue * meterMax /meterScale;
    analogWrite(meterPin, airQualityValue); 
  } 
}

void printResults() {
  // this routine used in debugging only, to print out the results:
  Serial.print(" I got ");
  Serial.print(stringPos, DEC);
  if (stringPos > 0) {
    Serial.print(" bytes, total:  ");
    Serial.print(kilobytes, DEC); 
    Serial.print(" string: " );
    for (int i = 0; i=0; thisChar--) {
    char thisByte = thisString[thisChar] - 48;
    value = value + powerOfTen(thisByte, (length-1)-thisChar);
  } 
  return value;
}

/*
  This method takes a number between 0 and 9, 
 and multiplies it by ten raised to a second number.
 */

long powerOfTen(char digit, int power) {
  long val = 1;
  if (power == 0) {
    return digit;
  } 
  else {
    for (int i = power; i >=1 ; i--) {
      val = 10 * val;
    }
    return digit * val;
  }
}