我正在研究一个小型的Arduino项目,当一个新的追随者获得时,它会使LED灯闪烁。很显然,我受到了Twitter方面的一些规则(来自服务器的请求数量等)的限制,但我找到了一种方法可以让它发挥作用。
我有一个PHP脚本,可以检查我拥有的关注者数量。第一次运行脚本时,如果不存在文件,则会创建一个文本文件,其中包含关注者数量作为文件的唯一内容。如果我有42个粉丝,那么该文件将包含42
,而不包含任何其他内容。在后续运行中,脚本会检查文件的内容是否与新的跟随者计数相匹配。如果是,则对文件不执行任何操作并输出n
。如果数字不匹配(意味着我获得了新的关注者),那么我更新文本文件并输出y
。
在Arduino方面,我只是检查脚本页面的输出是否包含y
或n
,意图是前者导致我的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");
}
答案 0 :(得分:0)
对于问题的第一部分,使用额外的1和0,看起来它可能是HTTP分块编码,其中服务器以块为前缀的响应发送响应。如果是这种情况,则响应中将出现类似Transfer-Encoding: chunked
的标头,这表示客户端必须解码分块编码以获取原始有效负载。您可以通过在PHP脚本中显式设置Content-Length标头来阻止服务器使用分块编码:
header('Content-Length: 1');
根据所提供的信息,您不能100%清楚为什么您会间歇性地看到HTTP标头显示为有效负载,但通常HTTP有一堆可能在这里发挥作用的繁琐功能。由于您控制此服务器并且它与您的Arduino项目紧密耦合,因此快速而肮脏的解决方案是将您的信令字节更改为您知道在HTTP标头中永远不会出现的值,例如某些大于127的字节值。可以在Arduino端完全处理分块编码和其他HTTP功能,但是对于这个应用程序来说可能是不值得的,因为你已经将服务器定制为Arduino草图了。