Я только начал с веб-программирования & Arduino. Я пытаюсь узнать, как Arduino взаимодействует с веб-сервером.
У меня есть Arduino UNO, который общается с моим Веб сервер через SimComm SIM808 GSM-GPRS модуль. У меня есть файл с именем retrieve.php на моем веб-сервере, который в основном выбирает данные из базы данных & доставляет их тому, кто делает запрос.
Моя программа Arduino читает файл, но читает больше, чем должна.
retrieve.php эхо двух значений 1 & 1. Вы можете взглянуть на это Вот
Проблема в том, что когда я заставляю свой Arduino вызывать этот файл, он все читает & это то, что я получаю
GSM Shield testing.
status=READY
status=ATTACHED
100.107.219.185
H
Number of data received:
1
Data received:
H
TTP/1.1 200 OK
Date: Sat, 04 Jun 2016 13:07:05 GMT
Server: Apache
X-Powered-By: PHP/5.5.35
Content-Length: 2
Connection: close
Content-Type: text/html
11
CLOSED
мой Arduino код указан ниже:
#include "SIM900.h"#include <SoftwareSerial.h>
#include "inetGSM.h"//#include "sms.h"//#include "call.h"
//To change pins for Software Serial, use the two lines in GSM.cpp.
//GSM Shield for Arduino
//www.open-electronics.org
//this code is based on the example of Arduino Labs.
//Simple sketch to start a connection as client.
InetGSM inet;
//CallGSM call;
//SMSGSM sms;
char msg[50];
int numdata;
char inSerial[50];
int i=0;
boolean started=false;
void setup()
{
//Serial connection.
Serial.begin(9600);
Serial.println("GSM Shield testing.");
//Start configuration of shield with baudrate.
//For http uses is raccomanded to use 4800 or slower.
if (gsm.begin(2400)) {
Serial.println("\nstatus=READY");
started=true;
} else Serial.println("\nstatus=IDLE");
if(started) {
//GPRS attach, put in order APN, username and password.
//If no needed auth let them blank.
if (inet.attachGPRS("TATA.DOCOMO.INTERNET", "", ""))
Serial.println("status=ATTACHED");
else Serial.println("status=ERROR");
delay(1000);
//Read IP address.
gsm.SimpleWriteln("AT+CIFSR");
delay(5000);
//Read until serial buffer is empty.
gsm.WhileSimpleRead();
//TCP Client GET, send a GET request to the server and
//save the reply.
numdata=inet.httpGET("www.boat.esy.es", 80, "/retrieve.php", msg, 1);
//Print the results.
Serial.println("\nNumber of data received:");
Serial.println(numdata);
Serial.println("\nData received:");
//Serial.println(msg);
char* content = strstr(msg,"\r\n\r\n");
content = content+4;
Serial.println(content);
}
};
void loop()
{
//Read for new byte on serial hardware,
//and write them on NewSoftSerial.
serialhwread();
//Read for new byte on NewSoftSerial.
serialswread();
};
void serialhwread()
{
i=0;
if (Serial.available() > 0) {
while (Serial.available() > 0) {
inSerial[i]=(Serial.read());
delay(10);
i++;
}
inSerial[i]='\0';
if(!strcmp(inSerial,"/END")) {
Serial.println("_");
inSerial[0]=0x1a;
inSerial[1]='\0';
gsm.SimpleWriteln(inSerial);
}
//Send a saved AT command using serial port.
if(!strcmp(inSerial,"TEST")) {
Serial.println("SIGNAL QUALITY");
gsm.SimpleWriteln("AT+CSQ");
}
//Read last message saved.
if(!strcmp(inSerial,"MSG")) {
Serial.println(msg);
} else {
Serial.println(inSerial);
gsm.SimpleWriteln(inSerial);
}
inSerial[0]='\0';
}
}
void serialswread()
{
gsm.SimpleRead();
}
А это мой PHP код
<?php
$server = "mysql.hostinger.in";
$user = "xxxxxxxxxx";
$password = "xxxxxx";
$db = "xxxxxxx";
$lck;
$ign;
$conn = mysqli_connect($server,$user,$password,$db);
if($conn->connect_error)
{
die("Connection Failed:" . $conn->connect_error);
}
$query = "SELECT unlck_lck, ignition FROM BOATOP";
$res = $conn->query($query);
if($res->num_rows>0)
{
$row = $res->fetch_assoc();
$lck = $row["unlck_lck"];
$ign = $row["ignition"];
echo $lck;
echo $ign;
}
mysqli_close($conn);?>
Я хочу, чтобы мой Arduino читал только вывод, отраженный моим PHP-файлом. Но в настоящее время он читает все.
И я также должен упомянуть здесь одну вещь. Для моего Arduino GSM Shield я не использовал примеры или библиотеки, поставляемые с установочным пакетом Arduino, поскольку библиотеки не были совместимы с моим GSM Shield. Вместо этого я использовал некоторые библиотеки, которые я нашел в Интернете. Я не размещал эти файлы здесь, потому что они сделали бы мой пост очень длинным. Пожалуйста, дайте мне знать, если вам нужно взглянуть на них.
ОБНОВЛЕНИЕ 1
Содержание, показывающее ноль
Модификация Arduino
content = strstr(msg,"\r\n\r\n");
if(content == NULL) {
Serial.println("ERROR IN CONTENT READING");
} else {
content = content + 4;
Serial.println("The Content Is:");
Serial.println(content);
}
Результат:
GSM Shield testing.
status=READY
status=ATTACHED
100.110.244.218
Number of data received:
50
Data received:
ERROR IN CONTENT READING
HTTP/1.1 200 OK
Date: Sat, 04 Jun 2016 17:17:12 GMT
Server: Apache
X-Powered-By: PHP/5.5.35
Content-Length: 2
Connection: close
Content-Type: text/html
11
CLOSED
Ваша проблема на самом деле не одна. Вы должны прочитать больше о спецификации протокола HTTP, чтобы полностью понять, в чем ваша проблема.
Когда ваш PHP-скрипт возвращает какой-то вывод, он обслуживается HTTP-сервером. Ваш клиент взаимодействует с сервером по хорошо документированному протоколу, такому как:
Пожалуйста, дайте мне страницу по этому адресу!
GET www.boat.esy.es/retrieve.php HTTP/1.1
Эй, вот несколько деталей о вашем запросе, а затем ваш контент
HTTP/1.1 200 OK
Date: Sat, 04 Jun 2016 13:07:05 GMT
Server: Apache
X-Powered-By: PHP/5.5.35
Content-Length: 2
Connection: close
Content-Type: text/html
11
данный контекст обычно помогает вашему веб-браузеру лучше обрабатывать ваши данные. Но во встроенной среде это тоже может вам помочь. Например, если Content-Length
слишком велика для вашей переменной, вы можете обнаружить это и показать ошибку, что вы не можете хранить столько данных в памяти!
Таким образом, как простое решение в вашем коде Arduino, вам нужно прочитать выходные данные веб-сервера, отбрасывая каждую строку, которую он выводит, пока не достигнет \r\n\r\n
который в протоколе HTTP является разделителем между заголовками и контентом. Тогда все следующие данные будут вашим контентом, поскольку они были выведены вашим PHP-кодом.
Способ сделать это будет сделать:
numdata=inet.httpGET("www.boat.esy.es", 80, "/retrieve.php", msg, 1);
// look up substring '\r\n\r\n' within msg, and allocate content with it
char * content = strstr(msg, "\r\n\r\n");
if (content == NULL) {
Serial.println("Couldn't find the contents within the message!");
} else {
// then we skip the '\r\n\r\n' substring to only keep the contents
content = content+4; // we skip 4 characters
Serial.print("The content is: ");
Serial.println(content);
}
Если бы вы попытались извлечь заголовок content-length, вы могли бы сделать то же самое:
// lookup the content-length header
char* content = strstr(msg, "Content-Length: ");
// skip the size of the looked up string
content = content+strlen("Content-Length: ");
// store the size of the contents in number of characters
int nb_chars = atoi(content);
// lookup the content
content = strstr(msg, "\r\n\r\n");
// check that the substring has been found
if (content == NULL) {
Serial.println("Couldn't find the contents within the message!");
} else {
// skip the header-content delimiter
content = content+4;
// and do useful things with the extracted data
if (nb_chars == 2) {
Serial.print("The content is:");
Serial.println(content);
} else {
Serial.println("There's been an error processing the request.");
}
}
Вы найдете работающую версию кода там:
В качестве теста вы можете распечатать коды ASCII каждого символа строки, чтобы проверить его, вместо оригинала Serial.println(msg)
пытаться:
for (int c=0; c<strlen(msg); ++c) {
Serial.print((int)msg[c], HEX);
Serial.print(" ");
}
Serial.println("");
который должен произвести следующий вывод:
0048 0054 0054 0050 002F 0031 002E 0031 0020 0032 0030 0030 0020 004F 004B 000D 000A 0044 0061 0074 0065 003A 0020 0053 0061 0074 002C 0020 0030 0034 0020 004A 0075 006E 0020 0032 0030 0031 0036 0020 0031 0033 003A 0030 0037 003A 0030 0035 0020 0047 004D 0054 000D 000A 0053 0065 0072 0076 0065 0072 003A 0020 0041 0070 0061 0063 0068 0065 000D 000A 0058 002D 0050 006F 0077 0065 0072 0065 0064 002D 0042 0079 003A 0020 0050 0048 0050 002F 0035 002E 0035 002E 0033 0035 000D 000A 0043 006F 006E 0074 0065 006E 0074 002D 004C 0065 006E 0067 0074 0068 003A 0020 0032 000D 000A 0043 006F 006E 006E 0065 0063 0074 0069 006F 006E 003A 0020 0063 006C 006F 0073 0065 000D 000A 0043 006F 006E 0074 0065 006E 0074 002D 0054 0079 0070 0065 003A 0020 0074 0065 0078 0074 002F 0068 0074 006D 006C 000D 000A 000D 000A 0031 0031 000D 000A
^^^^ ^^^^ ^^^^ ^^^^
Здесь 000D 000A
соответственно \r\n
, Так что вы должны найти 000D 000A 000D 000A
последовательность в той же позиции, как выделено с ^^^^ ^^^^ ^^^^ ^^^^
,
Это должно помочь вам дважды проверить, что строка, генерируемая сервером, является той, которую мы ожидаем при разборе с strstr()
,
НТН
Других решений пока нет …