Web client Умного Дома на Arduino

kiberfaust
Offline
Зарегистрирован: 13.02.2018

Добрый день.

Решил поставить ардуино и сделать дом чуть умнее, но возникли некоторые проблемы.

Скетч:

#include <Ethernet.h>
byte mac[] = { 0x78, 0xAC, 0xC0, 0xDA, 0xEC, 0xEC };
EthernetClient client;
char server[] = "it-levashi2.myjino.ru";

void setup(){
pinMode(3, OUTPUT);
Ethernet.begin(mac);
}

void loop(){
  Serial.begin(9600);
  String currentLine = "";
  String inChar = "";
  client.connect(server, 80);
  client.print( "GET /svet1.txt");
  client.println(" HTTP/1.1");
  client.print("Host: it-levashi2.myjino.ru");
  client.println();
  client.println();
  delay(100);
  while (client.available()){
    char inChar = client.read();
    currentLine += inChar;
    if (currentLine == "1"){digitalWrite(3, HIGH);}
    if (currentLine == "0"){digitalWrite(3, LOW);}
  }
  client.stop();
  Serial.print(currentLine);
  delay(10000);
}

На сервере в файле svet1.txt есть только одна цифра 1, она меняется на 0 из браузера с соответствуюшей кнопки.

Проблема в том что 3й пин не работает изза получаемых данных с сервера, вот такие данные приходят на ком порт:

HTTP/1.1 200 OK
Date: Wed, 14 Feb 2018 14:13:06 GMT
Content-Type: text/plain
Content-Length: 1
Connection: keep-alive
Server: Jino.ru/mod_pizza
Last-Modified: Wed, 14 Feb 2018 14:12:29 GMT
ETag: "ae06ba-1-5652cb393bc54"
Accept-Ranges: bytes
Vary: Accept-Encoding
 

1

HTTP/1.1 200 OK
Date: Wed, 14 Feb 2018 14:13:06 GMT
Content-Type: text/plain
Content-Length: 1
Connection: keep-alive
Server: Jino.ru/mod_pizza
Last-Modified: Wed, 14 Feb 2018 14:12:29 GMT
ETag: "ae06ba-1-5652cb393bc54"
Accept-Ranges: bytes
Vary: Accept-Encoding
 

0

Использую ардуино уно и w5100. Система должна работать из интернет с любой точки мира.

Как отфильтровать полученное чтоб осталась последняя строка где есть 1 или 0 ? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Всё у Вас отлично - это нормальные служебные записи.

kiberfaust пишет:

Как отфильтровать полученное чтоб осталась последняя строка где есть 1 или 0 ? 

Ну, это-то я Вам скажу - служебная информация заканчивается двумя подряд переводами строки, а после них идут данные (Ваши 0 и 1). Вот и ищите два перевода строки, а после них читайте данные.

Только это Вам не поможет. Чтобы  "сделать свой дом умнее", начните с себя и просто не поленитесь почитать описание HTTP-протокола, раз уж Вы взялись с ним работать. Иначе, через день, будет новая тема. подобная этой.

kiberfaust
Offline
Зарегистрирован: 13.02.2018

А как искать эти два перевода и после них читать данные?

Не факт что надо почитать описание HTTP-протокола, в дальнейшем займусь этим. Но на сей раз подскажите пожалуйста что и как добавить в код.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Раз используете String то смотрите его методы. lastIndexOf потом substring

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kiberfaust пишет:

Не факт что надо почитать описание HTTP-протокола

Понятно. Совет остаётся в силе: хотите сделать свой дом умнее, начните с себя. Пока Вы выглядите Митрофанушкой, которому ни хрена знать не надо - ямщик довезёт. Удачи!

MaksVV
Offline
Зарегистрирован: 06.08.2015
     if (currentLine.endsWith("1")) digitalWrite(3, HIGH);
else if (currentLine.endsWith("0")) digitalWrite(3, LOW);
b707
Offline
Зарегистрирован: 26.05.2017

MaksVV пишет:

     if (currentLine.endsWith("1")) digitalWrite(3, HIGH);
else if (currentLine.endsWith("0")) digitalWrite(3, LOW);

Ох, Макс... Ваши условия срабаотает на первой же строке заголовка - там есть и "1" и "0"

b707
Offline
Зарегистрирован: 26.05.2017

kiberfaust пишет:

 Но на сей раз подскажите пожалуйста что и как добавить в код.

нет, так не пойдет. Если мы вам подскажем - зачем вам тогда нужно будет читать про протокол?

Правильнее будет вам прочитать и самому написать нужные строки.

MaksVV
Offline
Зарегистрирован: 06.08.2015

b707 пишет:

MaksVV пишет:

     if (currentLine.endsWith("1")) digitalWrite(3, HIGH);
else if (currentLine.endsWith("0")) digitalWrite(3, LOW);

Ох, Макс... Ваши условия срабаотает на первой же строке заголовка - там есть и "1" и "0"

вот скетч, работает.  если эти 0 или 1 убрать в конце, условия не выполняются , т.е. не видит нули и едице ранее в заголовке и т.д. Он же с конца ищет. 

String currentLine = "HTTP/1.1 200 OKDate: Wed, 14 Feb 2018 14:13:06 GMTContent-Length: 1ncoding\n\r\n\r 0";
void setup() {
Serial.begin (9600);
Serial.println(currentLine);
     if (currentLine.endsWith("1")) Serial.print ("DA DA odin)))");
else if (currentLine.endsWith("0")) Serial.print ("DA DA nol)))");
}

void loop() {


}


 

b707
Offline
Зарегистрирован: 26.05.2017

MaksVV пишет:

Он же с конца ищет. 

Ок, пусть с конца - но вот на строке

Content-Length: 1

разве не сработает?

ИМХО - не надежно это, искать одиночный символ.

MaksVV
Offline
Зарегистрирован: 06.08.2015

неа, не сработает. Специально проверил. надёжно так будет работать. Функция не ищет одиночный символ, она проверяет  заканчивается ли искомая строка нашей строкой (ну или символом в данном случае). Всё норм

b707
Offline
Зарегистрирован: 26.05.2017

MaksVV пишет:

 Функция не ищет одиночный символ, она проверяет  заканчивается ли искомая строка нашей строкой (ну или символом в данном случае). Всё норм

А что, разве строка

Content-Length: 1

не заканчивается на "1" ?

Что-то вы не так тестируете - должно срабатывать.

kiberfaust
Offline
Зарегистрирован: 13.02.2018

Пытался по словам Penni сделать:

#include <Ethernet.h>
byte mac[] = { 0x78, 0xAC, 0xC0, 0xDA, 0xEC, 0xEC };
EthernetClient client;
char server[] = "it-levashi2.myjino.ru";

void setup(){
pinMode(3, OUTPUT);
Ethernet.begin(mac);
}

void loop(){
  Serial.begin(9600);
  String currentLine = "";
  String inChar = "";
  String stringOne = "";
  client.connect(server, 80);
  client.print( "GET /svet1.txt");
  client.println(" HTTP/1.1");
  client.print("Host: it-levashi2.myjino.ru");
  client.println();
  client.println();
  delay(100);
  while (client.available()){
    char inChar = client.read();
    currentLine += inChar;
    stringOne = currentLine;  
    int lastOpeningBracket = stringOne.lastIndexOf('1');
    Serial.println(lastOpeningBracket);
    if (lastOpeningBracket == "1"){digitalWrite(3, HIGH);}
    if (lastOpeningBracket == "0"){digitalWrite(3, LOW);}
  }
  client.stop();
  delay(10000);
}

не получилось.

Сделал по словам MaksVV все получилось:

#include <Ethernet.h>
byte mac[] = { 0x78, 0xAC, 0xC0, 0xDA, 0xEC, 0xEC };
EthernetClient client;
char server[] = "it-levashi2.myjino.ru";

void setup(){
pinMode(3, OUTPUT);
Ethernet.begin(mac);
}

void loop(){
  Serial.begin(9600);
  String currentLine = "";
  String inChar = "";
  client.connect(server, 80);
  client.print( "GET /svet1.txt");
  client.println(" HTTP/1.1");
  client.print("Host: it-levashi2.myjino.ru");
  client.println();
  client.println();
  delay(100);
  while (client.available()){
    char inChar = client.read();
    currentLine += inChar;
  }
  if (currentLine.endsWith("1")) digitalWrite(3, 1);
  else if (currentLine.endsWith("0")) digitalWrite(3, 0);
  client.stop();
  delay(2000);
}


MaksVV респект и уважуха.

Парни спасибо всем.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

:) Там из моего совета одна функция и та неправильно применена. А сравнивать int и "1"...

MaksVV
Offline
Зарегистрирован: 06.08.2015

b707 пишет:
А что, разве строка

Content-Length: 1

не заканчивается на "1" ?

Что-то вы не так тестируете - должно срабатывать.

насколько я знаю, концом строки String не является перевод строки и каретки, поэтому  Content-Length: 1 это не конечная часть строки, соответсвтенно и данная 1 тоже не конец строки. Возьмите да сами проверьте.

 

 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Мужики, знаете чего я не пойму? У меня к вам два вопроса:

1.
Вот Вы там ищете единицу или 0. А если завтра среди параметров 2-ойка появится, чего делать-то? Неужели, искать два перевода строки, а потом парсить то, что после них, камасутра не позволяет? Или Клапауций запретил?

2.
нахрена Вы помогаете ленивой заднице, которая прямо сказала, что читать описание протока ему не нужно - сами объясняйте? неужели приятно ощущать, что тебя использует лодырь, не желающий палец об палец ударить?

MaksVV
Offline
Зарегистрирован: 06.08.2015

ЕвгенийП пишет:

Вот Вы там ищете единицу или 0. А если завтра среди параметров 2-ойка появится, чего делать-то?

else if (currentLine.endsWith("2")) Serial.print ("DA DA dwa)))");

не пойму проблемы, так ведь проще

ЕвгенийП пишет:
нахрена Вы помогаете ленивой заднице, которая прямо сказала, что читать описание протока ему не нужно - сами объясняйте? неужели приятно ощущать, что тебя используют?

а я себе помогаю, учусь программировать, стараюсь, когда есть время, разные задачки на форуме решать

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

MaksVV пишет:

else if (currentLine.endsWith("2")) Serial.print ("DA DA dwa)))");

Да, нет, ну, что Вы, ну это же параметры. Там может быть всё что угодно. Найдите Вы два перевода строки, а после них парсите - это универсальный подход. Иначе Вам придётся под каждый параметр переделывать. А не дай бог там поле формы? Тогда параметр вообще выглядит как name=то_что_юзер_ввёл. И чего тогда искать будете? Юзер то может что угодно ввести. Раз уж учитесь, привыкайте делать правильно.

MaksVV
Offline
Зарегистрирован: 06.08.2015

хорошо, я вас понял. Я вообще не разбираюсь в HTML, но всё таки покажите на строке ТС как это 

ЕвгенийП пишет:
ну это же параметры. Там может быть всё что угодно.... А не дай бог там поле формы? Тогда параметр вообще выглядит как name=то_что_юзер_ввёл.

будет выглядеть 

HTTP/1.1 200 OK
Date: Wed, 14 Feb 2018 14:13:06 GMT
Content-Type: text/plain
Content-Length: 1
Connection: keep-alive
Server: Jino.ru/mod_pizza
Last-Modified: Wed, 14 Feb 2018 14:12:29 GMT
ETag: "ae06ba-1-5652cb393bc54"
Accept-Ranges: bytes
Vary: Accept-Encoding
 
0

 

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015
String http_answer = "тут ответ полученный";
int rnrn_pos = http_answer.lastIndexOf("\r\n\r\n");
String http_answer_body = http_answer.substring(rnrn_pos+4);
// в http_answer_body будет тело ответа без заголовка,
// а дальше с ним можно делать что угодно.
Serial.println(http_answer_body);
// или если точно уверен что всегда цифра или целое число то
Serial.println(http_answer_body.toInt());

 

kiberfaust
Offline
Зарегистрирован: 13.02.2018

ЕвгенийП пишет:

нахрена Вы помогаете ленивой заднице, которая прямо сказала, что читать описание протока ему не нужно - сами объясняйте? неужели приятно ощущать, что тебя использует лодырь, не желающий палец об палец ударить?

Не оскорбляй. Форумы на то и придуманы чтобы обсуждать, помогать и обучаться. Не желающий палец об палец ударить прикупил бы готовое и установщик поставил бы его ему.

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

Вот Вы там ищете единицу или 0. А если завтра среди параметров 2-ойка появится, чего делать-то?

нахрена Вы помогаете ленивой заднице

Ответ сразу на 2 вопроса :) - я вылез именно потому. что Макс, кмк. обрабатывает строку неверно. А насчет "игнорить лентяев и халявщиков" - поддерживаю.

Макс - главная ваша ошибка. что признак "единица в конце строки" - очень расплывчатый. Начать с того. что ответ на запрос довольно большой и за один раз в строку может и не влезть. И тогда ваша конструкция "конец строки" будет указаывать на случайное место в тексте, а не на то, что надо.

b707
Offline
Зарегистрирован: 26.05.2017

kiberfaust пишет:

Не оскорбляй. Форумы на то и придуманы чтобы обсуждать, помогать и обучаться.

Ну это наше дело, кому помогать и кого обучать. Ты показал себя тупым халявщиком и вряд ли  стоит с тобой общаться и тебя обучать.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Penni пишет:

String http_answer = "тут ответ полученный";
int rnrn_pos = http_answer.lastIndexOf("\r\n\r\n");
String http_answer_body = http_answer.substring(rnrn_pos+4);
// в http_answer_body будет тело ответа без заголовка,
// а дальше с ним можно делать что угодно.
Serial.println(http_answer_body);
// или если точно уверен что всегда цифра или целое число то
Serial.println(http_answer_body.toInt());

 

Плохой пример, негодный. Объяснить почему? Представь, что тебе упадёт килобайт ответа в теле, после двух переводов строки. Ок, пока оперативки хватает. И тут ты, ВНЕЗАПНО, выкусываешь этот ответ в отдельную область памяти, при этом он остаётся лежать ещё и в http_answer, т.е. ты ещё килобайтик откусываешь от оперативы.

Как итог  - что? Правильно: если у нас два килобайта оперативы - прощай, дунька, виси на суку, покачиваясь по ветру.

Так с памятью обходиться - грешно. Есть же c_str(), необязательно реаллокатить память, чтобы работать с телом ответа ;)

kiberfaust
Offline
Зарегистрирован: 13.02.2018

b707 пишет:

Ну это наше дело, кому помогать и кого обучать. Ты показал себя тупым халявщиком и вряд ли  стоит с тобой общаться и тебя обучать.

 

Меня обучать ненадо сам обучусь. Я просил помоши(не обучения). На свете есть люди которые реально помогают и не посылают обучаться или хают сразу. Если не хотите помогать, незнаете как помочь или нехотите общаться можноже промолчать.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kiberfaust пишет:
можноже промолчать.
Можно. А можно и сказать чего-нибудь. Или Вы намерены поучить нас как нам общаться на форуме, на котором мы живём больше лет, чем Вы дней?

MaksVV
Offline
Зарегистрирован: 06.08.2015

b707 пишет:
Макс - главная ваша ошибка. что признак "единица в конце строки" - очень расплывчатый. Начать с того. что ответ на запрос довольно большой и за один раз в строку может и не влезть. И тогда ваша конструкция "конец строки" будет указаывать на случайное место в тексте, а не на то, что надо.

с этим соглансен. так и надо было сразу говорить - если строка раздробиться. А то мне показалось вы меня пытались убедить, что в той единой притяной строке endsWith не сработает как надо. 

Я вообщето не пытался предложить ТС идеальное решение. Само применение String уже шляпа, тем более, что в  него вся длинная строка пишется.  Я подкинул простое решение ТС, которое он сможет применить в этой конкретной маленькой задаче. А то тут про высказывания Гауса говорили. Как бы из пушки по воробьям не получилось

MaksVV
Offline
Зарегистрирован: 06.08.2015

можно, например, ждать перевода строки и только потом String заполнять. Тогда килобайт параметров ни как не скажется? или там тоже переводы строки бывают?

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Можно делать read и если встретили \n делать peek и если там \r то это двойной перевод строки после этого начать читать тело ответа в стринг.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

kiberfaust пишет:

Не факт что надо почитать описание HTTP-протокола, в дальнейшем займусь этим. Но на сей раз подскажите пожалуйста что и как добавить в код.

Не факт, что мне нужно что-то тебе объяснять, в дальнейшем займусь этим. Но на сей раз пойди пожалуйста нах.

Совсем уже халявщики охренели. Раньше хоть врали, что всё читают и весь интернет перекопали, а теперь уже откровенно на голову садятся.