Чтение HTTP страницы ethernet shield enc28j60
- Войдите на сайт для отправки комментариев
Ср, 26/09/2018 - 07:00
Здравствуйте!
Задача: считать страницу с сайта-сервера.
Работает связка Аруино мега+ethernet shield enc28j60. По ссылки арудинка проходит-всё ОК. А вот как считать страницу ни как не пойму. Есть какая нибудь спец функция для этого?
#include <EtherCard.h>
// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
byte Ethernet::buffer[700];
static uint32_t timer;
const char website[] PROGMEM = "www.myserver.com";
// called when the client request is complete
static void my_callback (byte status, word off, word len) {
Serial.println(">>>");
Ethernet::buffer[off+300] = 0;
Serial.print((const char*) Ethernet::buffer + off);
Serial.println("...");
}
void setup () {
Serial.begin(57600);
Serial.println(F("\n[webClient]"));
// Change 'SS' to your Slave Select pin, if you arn't using the default pin
if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)
Serial.println(F("Failed to access Ethernet controller"));
if (!ether.dhcpSetup())
Serial.println(F("DHCP failed"));
ether.printIp("IP: ", ether.myip);
ether.printIp("GW: ", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);
#if 1
// use DNS to resolve the website's IP address
if (!ether.dnsLookup(website))
Serial.println("DNS failed");
#elif 2
// if website is a string containing an IP address instead of a domain name,
// then use it directly. Note: the string can not be in PROGMEM.
char websiteIP[] = "192.168.1.1";
ether.parseIp(ether.hisip, websiteIP);
#else
// or provide a numeric IP address instead of a string
byte hisip[] = { 192,168,1,1 };
ether.copyIp(ether.hisip, hisip);
#endif
ether.printIp("SRV: ", ether.hisip);
}
void loop () {
ether.packetLoop(ether.packetReceive());
if (millis() > timer) {
timer = millis() + 5000;
Serial.println();
Serial.print("<<< REQ ");
ether.browseUrl(PSTR("/foo/"), "bar", website, my_callback);
}
}
А памяти на страницу точно хватить?
Там страница 20 символов
Перейдите на UIPEthernet и возьмите за основу пример WebClient от стандартного Ethernet.h
IPAddress ip(192, 168, 0, 177); // Initialize the Ethernet client library // with the IP address and port of the server // that you want to connect to (port 80 is default for HTTP): EthernetClient client; void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // try to congifure using IP address instead of DHCP: Ethernet.begin(mac, ip); } // give the Ethernet shield a second to initialize: delay(1000); Serial.println("connecting..."); // if you get a connection, report back via serial: if (client.connect(server, 80)) { Serial.println("connected"); // Make a HTTP request: client.println("GET /get.php?login=Loke"); client.println("Host: www.tabloseller.ru"); client.println("Connection: close"); client.println(); } else { // if you didn't get a connection to the server: Serial.println("connection failed"); } } void loop() { // if there are incoming bytes available // from the server, read them and print them: if (client.available()) { char c = client.read(); Serial.print(c); } // if the server's disconnected, stop the client: if (!client.connected()) { Serial.println(); Serial.println("disconnecting."); client.stop(); // do nothing forevermore: while (true); } }ОТВЕТ
Ну, а какой-нибудь там yandex.ru читает?
Спасибо все заработало! Была проблема в ссылке!
Вопрос другого плана:
Как считать именно запись-можно ли выкинуть шапку?
Что значит "выкинуть"?
Если она Вам не нужна, просто не нужно ее сохранять.
Как ее не сохранять?
Как ее не сохранять?
например, встроить в начало своих данных уникальный маркер:
RK9uba: 1000|100|1111|1111
и пропускать все строчки ответа, не начинающиеся с "RK9uba:"
Как ее не сохранять?
использовать циклический буфер.
читать литературу по словам - "алгоритм поиска по тексту / поиск ключевых слов".
например:
byte findCmdFromBuf(char* textCmd) { if (cmd_buf[pos_cmd] > 0) { byte idxBuf; if (pos_cmd == 0) idxBuf = max_size_cmd - 1; else idxBuf = pos_cmd - 1; byte lenResp = strlen(textCmd); byte idxResp = lenResp - 1; byte cntResp = 0; for (byte i = 0; i < max_size_cmd; ++i) { if (cmd_buf[idxBuf] == 0) break; if (cmd_buf[idxBuf] == textCmd[idxResp]) { --idxResp; if ((++cntResp) == lenResp) return 1; } else { cntResp = 0; idxResp = lenResp - 1; } if ((--idxBuf) == 0) idxBuf = max_size_cmd - 1; } } else if (pos_cmd > 0) { if (strPos(cmd_buf, textCmd) >= 0) { return 1; } } return 0; } char* LastPos(char *str1, char *str2) { // find substring in string int L1 = strlen(str1); int L2 = strlen(str2); for (int i = L1 - L2; i >= 0; i--) { int j = 0; for (; j < L2; j++) if ((str1[i + j] != str2[j])) break; if (j == L2) return str1 + i; } return 0; } int strPos(char *str11, char *str22) { // find position in string(1) substring(2) char*p = LastPos(str11, str22); int n = p - str11; return n; }// from the server, read them and print them: if (client.available()) { c = client.read(); if(c=='$') { w=1; } if(w==1) { Serial.print(c); } }Вставил спецсимвол в свою строку $ и по нему делаю распознование. Всем спасибо!
Лучше \n\n ловить. В куках может $ прилететь за нефиг делать.
// from the server, read them and print them: if (client.available()) { c = client.read(); if(c=='$') { w=1; } if(w==1) { Serial.print(c); } }Вставил спецсимвол в свою строку $ и по нему делаю распознование. Всем спасибо!
Явный претендент на звание самого кривого костыля года. Про CRLF два раза в конце хедера не слышал?
Явный претендент на звание самого кривого костыля года. Про CRLF два раза в конце хедера не слышал?
не соглашусь. "CRLF два раза в конце хедера" -это отлично, пока на странице только нужные данные. Но согласитесь, что так бывает крайне редко, а на коммерческих серверах - так вообще никогда.
А если все равно искать на странице нужное - то уникальный маркер в начале строки - это решение.
Хотя согласен, что символ '$' - плохой выбор.
Разницу между хедером и страницей b707 ниосилил. Жаль. Ну и ладно ;)
Разницу между хедером и страницей b707 ниосилил. Жаль. Ну и ладно ;)
из чего вы сделали такой вывод?
Наоборот, мне со своей стороны кажется. что это Logic недопонял тот текст, на который пытался отвечать :)
Товарищи, еще же не пятница...
Разницу между хедером и страницей b707 ниосилил. Жаль. Ну и ладно ;)
ну-ка ну-ка расскажите , очень любопытно что такое хедер и страница? :)
а то мне вот сервер строчку выдает "INFO INSERT!" - не пойму где что находиться :(
Товарищи, еще же не пятница...
Садман, не переживай, я понимаю, с кем спорю и далеко не пойду :)
а то мне вот сервер строчку выдает "INFO INSERT!" - не пойму где что находиться :(
скорее всего вы смотрите ответ программой, которая скрывает от вас "ненужные детали". Дума, что полный ответ что-то типа этого:
Я смотрю ответ командой httpread на модеме sim800, а отсылаю на php сервере командой echo без всяких заголовков и прочего.
ЗЫ. Допускаю что я чего то не понимаю и или чего-то не знаю.
краткий поиск по гуглю выдал ответ - команда HTTPREAD выдает только тело (httpbody) HTML странички, скрывая от вас хидер - как я и предполагал. Хотя тоже не исключаю, что в своем кратком поиске что-то недосмотрел.
это внутренняя команда модемов SIMxxx
echo() в php пишет в body. В хидер информация засовывается через функцию header().
да, был не прав, просто не вижу заголовок.
Так чё, уже разобрались пока я отобедал? На всяк случай - согласно стандарту протокола HTTP ответ состоит из хедера (набора строк вида имя параметра:значение), названого ТС "шапка" и тела - "страницы" в местной терминологии, хотя вобщето там могут быть очень разнообразные данные. Строки хедера завершаются CRLF. Хедер завершается пустой строкой, следовательно имеем два подряд CRLF. Это и отделяет хедер от данных. Этим и пользоватся. Остальное - х-ня от безмозглых. Хотябы потому, что прилететь от сервера может и Content-Type: отличный от text/html; и в нем уже будут и "$" и "RK9uba:", что вызовет ошибку. И в составе хедера значения параметров могут совпасть. А вот уже в данных можна уже делать как душе угодно, но помнить про Content-Type. Конкретно ТС очевидно для его бинарных данных как бы логично использовать application/octet-stream.
Просто игнорить хедер - нехороше, надо бы хотяб удостоверится в том что ОК, что длина данных не ноль, что тип ожидаемый.
Просто игнорить хедер - нехороше, надо бы хотяб удостоверится в том что ОК, что длина данных не ноль, что тип ожидаемый.
с этим не спорю
а с чем спорите?
а с чем спорите?
с безаппеляционным "только CRLF и ничего более, остальное от безмозглых". Но я даже не спорю... просто не согласен, затевать флейм неохота :)
;)
Вся возня с хедером на самом деле очень не сложна, чтото типа
if (Serial.available()) { c = Serial.read(); if(c==0x0d) fl|=1; else if(c!=0x0a) fl=0; else { if(fl==1) { fl<=1; buf[p]=0; //пришло CRLF разбор строки в буфере p=0; } else if(fl==3) { //пришло два CRLF, весь хедер пришел дальше тело принимаем } } if(p<sizeof(buf)) { buf[p]=c; p++; } }Драл из старого проекта, там по сириалу бегало, вроде работало.
Вся возня с хедером на самом деле очень не сложна, чтото типа
да это все понятно.
Но вспомните статью, что мы недавно обсуждали в теме "Субботнее". "Пустая" страница фейсбука весит толи 1.5, толи 15 мегабайт. И чтобы найти на такой "пустой" странице свои 10 байт данных - мало отбросить хидер, хорошо бы иметь уникальную строчку, по которой мы сможем найти данные в этой куче Г, которым является современный HTML