新推特粉丝上的LED闪烁

时间:2013-12-24 05:05:28

标签: c arduino httprequest

我正在研究一个小型的Arduino项目,当一个新的追随者获得时,它会使LED灯闪烁。很显然,我受到了Twitter方面的一些规则(来自服务器的请求数量等)的限制,但我找到了一种方法可以让它发挥作用。

我有一个PHP脚本,可以检查我拥有的关注者数量。第一次运行脚本时,如果不存在文件,则会创建一个文本文件,其中包含关注者数量作为文件的唯一内容。如果我有42个粉丝,那么该文件将包含42,而不包含任何其他内容。在后续运行中,脚本会检查文件的内容是否与新的跟随者计数相匹配。如果是,则对文件不执行任何操作并输出n。如果数字不匹配(意味着我获得了新的关注者),那么我更新文本文件并输出y

在Arduino方面,我只是检查脚本页面的输出是否包含yn,意图是前者导致我的LED闪烁。

我遇到的两个问题:

通常,当我从脚本文件本身读取时,如果响应为n,我的输出结果如下:

1
n
0

这很奇怪,1和0来自哪里?它们在页面输出本身中不可见。我已经将编码类型设置为plain/text了。当我从常规文本文件中读取时,我只获取文件的内容(在这种情况下,它将是n)。

我面临的另一个问题是,有时候,我获得了整个HTTP响应,而不是获得上述输出。那就是:

HTTP/1.1 200 OK
Date: Tue, 24 Dec 2013 04:03:32 GMT
Server: Apache
X-Powered-By

请注意,它在我的输出中停止,因为我有y的代码检查。这显然是有缺陷的,但我希望能在我解决第一个问题后立即对其进行扩展。话虽这么说,为什么它有时会给我这样的整个HTTP响应?

所以问题是:我的代码是否有问题造成这种情况?如果是这样,我如何修改它以更好地读取我喜欢的HTTP响应?

如果没有代码,这将是一个无用的问题,所以在这里(当然没有互联网登录信息......我也在这里链接了它 - CODE):

#include <SPI.h>
#include <WiFi.h>
#include <Twitter.h>

int led = 13;

char ssid[] = ""; //  your network SSID (name) 
char pass[] = "";    // your network password (use for WPA, or use as key for WEP)

int keyIndex = 0;            // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS; // status of the wifi connection

// initialize the library instance:
WiFiClient client;

const unsigned long requestInterval = 30*1000;    // delay between requests; 30 seconds

// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(199,59,149,200);    // numeric IP for api.twitter.com
char server[] = "raw-d.com";     // name address for twitter API

boolean requested;                     // whether you've made a request since connecting
unsigned long lastAttemptTime = 0;     // last time you connected to the server, in milliseconds

String currentLine = "";               // string to hold the text from server
String tweet = "";                     // string to hold the tweet
boolean readingTweet = false;          // if you're currently reading the tweet

String lastCount = ""; //last number counted

int numberOfBytes=0;

char* textFound;


void setup()
{
  // reserve space for the strings:
  currentLine.reserve(256);
  tweet.reserve(150);
  //Initialize serial and wait for port to open:
  Serial.begin(9600); 
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present"); 
    // don't continue:
    while(true);
  } 

  // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) { 
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:    
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  } 
  // you're connected now, so print out the status: (or not)
  //printWifiStatus();
//  connectToServer();
}

void loop()
{
  //connectToServer();
  //delay(10000);
  if (client.connected())
  {
    Serial.println("Connected. Checking for availabiilty of client...");
    if (client.available())
    {
      Serial.println("Client is available! Trying to read from client...");
      // read incoming bytes:

      if(client.find("\r\n\r\n"))
      {
      char inChar;

      while(inChar=client.read())
      {
        if(inChar==-1) break;
        currentLine+=inChar; //read in all characters of count
        Serial.print("\n\nCurrent follower count: " + currentLine + "\n\n");
        if(inChar=='y' || inChar == 'n') break;
      }
      if(inChar=='y')
      {
        //lastCount=currentLine;
        Serial.println("BLINKING LED");
        blink(); //blink LED
      }
      else
      {
        Serial.println("NOT BLINKING.");
      }
      currentLine=""; //clear
      delay(5000); //delay 5 seconds (don't kill server)
     }
     else
     {
       Serial.println("newlines not found - error with request");
     }
    }  
  }
  else if (millis() - lastAttemptTime > requestInterval)
  {
    // if you're not connected, and two minutes have passed since
    // your last connection, then attempt to connect again:
    connectToServer();
  }
}

void blink()
{
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(3000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  //delay(1000);               // wait for a second
}

void connectToServer()
{
  // attempt to connect, and wait a millisecond:
  Serial.println("connecting to server...");
  if (client.connect(server, 80))
  {
    Serial.println("making HTTP request...");
    // make HTTP GET request to twitter:
    client.println("GET /private/followers.php HTTP/1.1");
    client.println("Host:raw-d.com");
    client.println("Connection:close");
    client.println();


  }
  else
  {
    Serial.println("Failure to connect.");
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
}

void runPhpScript()
{
  // attempt to connect, and wait a millisecond:
  Serial.println("connecting to server...");
  if (client.connect(server, 80))
  {
    Serial.println("making HTTP request...");
    client.println("GET /private/followers.php HTTP/1.1");
    client.println("Host:raw-d.com");
    client.println("Connection:close");
    client.println();
  }
  else
  {
    Serial.println("Failure to run script.");
  }
  // note the time of this connect attempt:
  lastAttemptTime = millis();
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

1 个答案:

答案 0 :(得分:0)

对于问题的第一部分,使用额外的1和0,看起来它可能是HTTP分块编码,其中服务器以块为前缀的响应发送响应。如果是这种情况,则响应中将出现类似Transfer-Encoding: chunked的标头,这表示客户端必须解码分块编码以获取原始有效负载。您可以通过在PHP脚本中显式设置Content-Length标头来阻止服务器使用分块编码:

header('Content-Length: 1');

根据所提供的信息,您不能100%清楚为什么您会间歇性地看到HTTP标头显示为有效负载,但通常HTTP有一堆可能在这里发挥作用的繁琐功能。由于您控制此服务器并且它与您的Arduino项目紧密耦合,因此快速而肮脏的解决方案是将您的信令字节更改为您知道在HTTP标头中永远不会出现的值,例如某些大于127的字节值。可以在Arduino端完全处理分块编码和其他HTTP功能,但是对于这个应用程序来说可能是不值得的,因为你已经将服务器定制为Arduino草图了。