microAJAX для Ардуино

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

К написанию этого этюда меня подвиг очередной пост-вопрос о том, как организовать показ в браузере изменяющихся данных на странице, которая генерируется из Arduino.

Этот вопрос на форуме всплывает регулярно. Обычно, человеку нужно показать одно, два, ну пусть десяток значений, но он хочет, чтобы значения менялись сами, без перезагрузки страницы. В большинстве тем человеку немедленно советуют использовать ajax, что совершенно правильно – эта библиотека как раз для таких дел и предназначена. Беда лишь в том, что если нужно показать пару чисел типа температуру на кухне и влажность в ванной, то ajax – это такая пушка для этого воробья … К тому же эта пушка ещё и весит за 70 килобайт и ни в какую ардуину не полезет. В итоге, ради пары чисел на экране, человеку советуют ещё и прикрутить  к ардуине SD карту. Оно стоит того? Я Вас умоляю!

Давайте разберёмся как это можно сделать по простому, без SD, без 70КБ – просто в несколько строк. Кстати, техника, которую мы будем использовать, используется и в ajax – ничего нового мы не изобретаем. Просто вместо пушки применим для воробья пневматическое ружьё – это более адекватно.

Немного теории. Как это всё работает

Допустим у Вас на сервере (например, на localhost)  есть некий файл, a.htm. Тогда, загрузка этого файла в браузер будет выглядеть так: http://localhost/a.htm. Когда браузер загрузил файл (и показал его) больше на экране ничего не меняется. Всё статично.

Однако, в Вашем файле a.htm может присутствовать т.н. «активный сценарий» (скрипт) – это программа обычно (но не обязательно) на языке JavaScript, которую Браузер может исполнять.

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

Т.е., здесь Вы должны чётко понимать: сервер должен уметь обрабатывать два вида запросов. Запрос на файл a.htm Вы посылаете руками, когда набираете его адрес в браузере. Этот запрос выполняется один раз. А запрос на данные выполняет скрипт, размещённый  в файле a.htm. В ответ сервер возвращает нужные данные, скрипт размещает данные в документ и снова исполняет тот же запрос к серверу. Снова получает данные, размещает их в документе и так до бесконечности.

Скрипт microAJAX

Я написал для Вас компактный, но достаточно универсальный скрипт, который как раз этим и занимается – запрашивает с сервера данные и вставляет их в документ с нужной Вам периодичностью. Скрипт никак не привязан к конкретным данным и конкретной странице и может без изменений использоваться для показа самых разных данных.

К сожалению, в жертву компактности принесена обработка ошибок, что затрудняет отладку, но в конце этого материала я приведу «отладочную версию» скрипта – чуть менее компактную, но снабжённую механизмом контроля ошибок и выдачи сообщений.

Скрипт собственно вот он:

<script language="JavaScript">
	var o=new XMLHttpRequest();
	function dR() {
		o.open("GET","data.txt?r="+Math.random(),1);
		o.onload=function(){
			var a=this.responseText.replace(/\s*[\r\n=]+\s*/g, "=").replace(/^\s+/,"").replace(/\s+$/,"").match( /([^=]+)/g);
			for (var i=0, len=a.length; i< len; i+=2) try { document.getElementById(a[i]).innerText=a[i+1]; } catch(e) {};
			setTimeout("dR()", 10);
		}
		o.send();
	}
</script>

Для  того  чтобы вставить его в Вашу Web-страницу необходимо сделать две вещи:

1. вставить приведённые 12 строк внутрь тэга HEAD (т.е. между <HEAD> и </HEAD>);
2. В тэг BODY вставить обработчик события onload=”dR”. Тэг может выглядеть, например, так:

<body onload="dR()">

В строке 8 имеется константа 10 – это задержка в миллисекундах между вставкой полученных с сервера данных в документ и выполнением нового запроса к серверу. Можете поставить число побольше, чтобы не гонять дурной траффик. Чем меньше это число, тем быстрее будут меняться данные на странице при изменении данных на сервере. И наоборот, чем задержка больше, тем реже будут обновляться данные. Если, например, вместо 10 поставить 1000, данные будут обновляться только раз в секунду.

В строке 8 имеется константа 10 – это задержка в миллисекундах между вставкой полученных с сервера данных в документ и выполнением нового запроса к серверу. Можете поставить число побольше, чтобы не гонять дурной траффик. Чем меньше это число, тем быстрее будут меняться данные на странице при изменении данных на сервере. И наоборот, чем задержка больше, тем реже будут обновляться данные. Если, например, вместо 10 поставить 1000, данные будут обновляться только раз в секунду.

Ну, работает это всё достаточно просто.

  1. cразу же по загрузке страницы, вызывается функция dR() (для этого мы писали обработчик события в тэге BODY);
  2. функция dR в строке 4 формирует запрос к серверу на файл data.txt. параметр запроса (случайное число) сам по себе не нужен, но служит для того, чтобы браузер реально запросил data.txt у сервера, а не выдал нам старую, кешированную версию.
  3. в строка 5-9 браузеру говорится, что когда данные с сервера будут получены, следует вызвать для их обработки безымянную функцию (строки 6-8), мы к ней ещё вернёмся.
  4. наконец, в строке 10 сформированный запрос отправляется на сервер.

Как только данные с сервера получены, вызывается безымянная функция, заданная в строка 6-8. Она делает следующее

  1. разбирает полученные данные (строка 6). Это делается с помощью регулярных выражений. Объяснение их работы несколько выходит за рамки этой статьи. Просто скажу, что если данные сформированы правильно (см. формат данных ниже), то в результате получается массив а, который в чётных элементах содержит названия данных, а в нечётных – значения;
  2. строка 7. Раскладывает значения по элементам HTML документа, ID которых совпадают с названиями данных;
  3. строка 8. Указывает браузеры на необходимость вызвать функцию dR ещё раз через 10 миллисекунд (можете поменять 10 на что-либо другое).

Формат данных в файле data.txt

Данные в файле data.txt записываются построчно в формате:

<имя> = <значение>

при этом в начале, в конце, а также слева и справа от знака = допускается любое (включая и нулевое) количество пробелов и/или знаков табуляции. Если же пробелы встречаются внутри имени или данных, они остаются на месте и попадают в документ. Имя должно записываться по правилам записи ID в HTML (латинские буквы, цифры, пробелы допускаются)

Например, вполне правильный файл:

temperature kitchen = 25
temperature kidsroom = 27
temperature bathroom = 30

Связывание данных с элементами документа

Для того, чтобы скрипт знал куда вставить данные, в HTML документе должны быть элементы (SPAN, DIV, TD и т.п.) с ID точно (регистр букв, пробелы - точно!) совпадающими с именами данных.

Например, для файла данных, приведённого в предыдущем разделе, HTM файл может выглядеть так:

<html>
   <head>
      <title>Cool dynamic page!!!</title>
      <script language="JavaScript">
      var o=new XMLHttpRequest();
      function dR() {
         o.open("GET","data.txt?r="+Math.random(),1);
         o.onload=function(){
            var a=this.responseText.replace(/\s*[\r\n=]+\s*/g, "=").replace(/^\s+/,"").replace(/\s+$/,"").match( /([^=]+)/g);
            for (var i=0, len=a.length; i< len; i+=2) try { document.getElementById(a[i]).innerText=a[i+1]; } catch(e) {};
            setTimeout("dR()", 10);
         }
         o.send();
      }
      </script>
   </head>
   <body onload="dR()">
      <h1>Temperatures:</h1>
      <p>
         Kitchen: <span id="temperature kitchen"></span>.
      </p>
      <p>
         Kidsroom: <span id="temperature kidsroom"></span>.
      </p>
      <p>
         Bathroom: <span id="temperature bathroom"></span>.
      </p>
   </body>
</html>

Как видите, ID элементов в строках 20б 23 и 26 точно совпадают с именами данных из приведённого в предыдущем разделе файла data.txt. И наш скрипт вставит значение 25 в элемент в строке 20, 27 – в элемент в строке 23 и 30 – в элемент в строке 26.

Работающий пример

Для того чтобы убедиться, что всё это работает, возьмите файл данных из пред-предыдущего размера и поместите его на сервер с именем data.txt. Также возьмите HTML файл из предыдущего раздела и поместите его рядышком (в одной директории с файлом данных) под именем test.htm.

Откройте браузер и загрузите http://localhost/test.htm (если у Вас не localhost – укажите правильный сервер).

Когда файл загрузится, данные должны отобразиться! Это должно выглядеть примерно так:

Temperatures:

Kitchen: 25.

Kidsroom: 27.

Bathroom: 30.

Теперь, откройте в текстовом редакторе файл data.txt и поменяйте какое-нибудь значение (только имена не обижайте!). Сохраните файл и как только Вы это сделаете, значение тут же поменяется и в браузере!

Если у Вас всё получилось так, как я описал, значит у Вас всё отлично работает, можете себя поздравить.

Попробуйте со своими файлами. Ещё раз – Вы можете сделать любой HTML файл и показывать в нём любые (и любое количество) изменяемых значений. Всё, что Вам нужно соблюсти:

1. вставить скрипт внутрь тэга HEAD (т.е. между <HEAD> и </HEAD>);
2. В тэг BODY вставить обработчик события onload=”dR”.
3. Подготовить файл с данными в котором имена данных точно совпадают с ID элементов html-файла

И всё у Вас получится. Попробуйте, пощупайте, освойтесь.

Как всё это использовать в Ардуино

Этот раздел предполагает, что Вы уже умеете принять на ардуино запрос к серверу и ответить на него (например, чтобы в браузере появилось слово «Hello!»). Если Вы этого не умеете, то смотрите примеры к используемой Вами библиотеке Internet модуля. Там есть простейшие серверы.

Для того, чтобы сделать Web-страницу с использованием microAJAX я Вам советую, сначала сделать её (страницу) и необходимый файл данных на сервере (как мы делали в предыдущем примере). Отладить её в браузере и только тогда, когда она Вас полностью устраивает, переходить к Ардуино.

Скетч для сервера Ардуино должен работать так:

1.
Если к нему пришёл запрос на файл «как он там у Вас называется.htm» - необходимо вертуть Ваш html файл как строку ничего в нём не меняя. 

2.
Если к серверу пришёл запрос на файл data.txt, надо вернуть Ваш файл данных, только вместо константных значений скетч должен подставить реальные (измеренные или рассчитанные) значения. При это Context-type следует указать text/plain.

Вот собственно и всё. Если Вы это сделаете, то у Вас получится самообновляемая из Ардуино странница. 

Сложного ничего нет. Если Вы умеете выдать хоть что-нибудь (как я писал в начале этого раздела), то Вы сумеете выдать то, что нужно. Успехов!

К огромному сожалению у меня сейчас нет под рукой никакого интернетного модуля и я не могу дать Вам пример готового скетча (не выкладывать же непроверенный код!) Большая просьба к тем, у кого есть интернетный модуль и кто будет пробовать мой скрипт с ним: пожалуйста, как отладитесь, выложите здесь скетч – это многим поможет. Мог бы, я бы сам сделал.


Приложение: Обещанная отладочная версия

Ошибки в моём microAJAX не обрабатываются. Ну, ошибка - ошибке рознь, например потерю связи с сервером мы обрабатывать не будем - она и так очевидна.

Но есть одна ошибка, которая может попортить кровь разработчику - это неправильное написание имени. Когда в данных имя есть, а в html элемента с таким ID нет. Эту ошибку мы обработаем.

Приведённый ниже скрипт такой же, как и microAJAX, но с двумя отличиями: 

1) он не обновляет дааных. Вернее, обновляет их один раз при загрузке страницы
2) он протоколирует всю работу посредством сообщений браузера.

Вот текст отладочного скрипта:

<script language="JavaScript">
var o=new XMLHttpRequest();
function dR() {
   o.open("GET","data.txt?r="+Math.random(),1);
   o.onload=function(){
      alert("RECEIVED:\n" + this.responseText);
      var a=this.responseText.replace(/\s*[\r\n=]+\s*/g, "=").replace(/^\s+/,"").replace(/\s+$/,"").match( /([^=]+)/g);
      for (var i=0, len=a.length; i< len; i+=2) {
         try { 
            document.getElementById(a[i]).innerText=a[i+1]; 
         } catch(e) {
            alert("ERROR: ID '" + a[i] + "' not found in the document");
         }
      }
   }
   o.send();
}
</script>

при загрузке данных он покажет сообщение со словом "RECEIVED" и после него будет идти файл данных КАК СКРИПТ ЕГО ПОЛУЧИЛ! Вы сможете визуально проконтролировать всё ли нормально передаётся и, если что, поправить свой скетч.

В случае, если в данных обнаружится имя не имеющее соответствующего ID в html файле, будет выдано сообщение с этим именем и Вы легко сможете поправить ошибку.

OlegM
Offline
Зарегистрирован: 14.06.2016

ajax это хорошо ), но меня интересует вот что, я с ардуино посылаю ГЕТ запрос на сервер, ну там тип температуру, а сервер выдает в ответ инфо, тип имя=значение, вот тип так, нашел на странице о есп,я похожее делать буду:

+IPD,201:HTTP/1.1 200 OK
Date: Tue, 07 Jun 2016 19:53:34 GMT
Server: Apache/2.2.25 (Win32) PHP/5.4.30
X-Powered-By: PHP/5.4.30
Content-Length: 13
Connection: close
Content-Type: text/html

tmp=hj&hmd=20CLOSED

Посоветуйте как принимать данные от сервера, что-бы управлять ардуино? Я думаю делать свой парсер, есть что-то в ардуино или все таки делать свой велосипед, мне можно как то полученные данные от сервера передавать в ардуино и в ардуино ими пользоватся тип как имя_переменной=значение ?

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

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

Парсить на ардуино ... я бы парсил вручную. Где-то была библиотека регулярных выражений, но тоже ведь пушка по воробью. Проще распарсить руками, тем более формат-то тривиальный.

OlegM
Offline
Зарегистрирован: 14.06.2016

думаю без регулярок обойтись, у меня уно, он и так слабенький.

ну а после этого я возьмусь за АЯКС, так как буду выводить инфо на страницу, ну распарсить это еще ладно, а как мне сделать так -> имя=значение, в массив загнать ? в ардуино вроде нельзя такой массив создавать "ассоциативный" arr['name'] = value; ?

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

OlegM пишет:

думаю без регулярок обойтись, у меня уно, он и так слабенький.

Вот и я ж про то же.

OlegM пишет:

 а как мне сделать так -> имя=значение, в массив загнать ? в ардуино вроде нельзя такой массив создавать "ассоциативный" arr['name'] = value; ?

Ну, стопиццот способов есть. Сделайте структуру с двумя полями: имя и значение, или два массива - в одном миена, а в другом значения. А, кстати, можно и в лоб - сделать класс с хитро определённой операцией взятия индекса, тогда вообще всё красиво будет.

 

 

OlegM
Offline
Зарегистрирован: 14.06.2016

я думал двумерный массив сделать тип так, char arr[3][10]; ,  в первом - это номер переменной, а во вотром значение, тип так "0""value",  но вот насчет struct - это вариант. ) 

 

хотя )) это можно и без структуры делать, просто записывать значения в переменные тип так char* tmp = arr[0]  и т.д.

Logik
Offline
Зарегистрирован: 05.08.2014

Вобще  подход хороший. 

Имена переменным ниразу не надо. Именами будут ID жестко прописанніе в ардуине, в форме намболее простой и удобной для ардуин. А в скриптах к ним приспособится не сложно.

Я давно о таком подходе думал, и останавливает только вот что. Внешний облик страницы, тексты и сам скрипт у нас лежит  в a.htm. А сам a.htm в ардуино, где нет места. Любая правка a.htm это перезаливка ардуины. Плохо.

В идеале в ардуино надо держать только некую ссылку на глубины инета, где выложен a.htm. А броузер пойдет по этой ссылке, загрузит и выполнив скрипт из a.htm поймет что за data.txt  надо пойти по указаному адресу, вероятно статическому IP используя собственно предложенный механизм.

А возможно и ссылку в ардуино на a.htm не обязательно, просто разнести a.htm где-то на серваке, чтоб и этим ардуину не беспокоить, а за data.txt уже на ардуину.

 

OlegM
Offline
Зарегистрирован: 14.06.2016

я так и делаю, ардуино посылает гет или пост запрос на сторонний сервер, настройки и всякие параметры  для обработки ардуино  сервер отсылает, вот и все, а всю красоту АЯКСом выводим, застопорился только как ответ принимать, но походу ВЕЛОСИПЕДОМ ))

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Всех приветствую.

Евгений. Благодарю, всё грамотно, ясно и доходчиво. Статья хорошая.

#include <EtherCard.h>
 
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,1,100 };
 
const char website[] PROGMEM = "192.168.1.100";
byte Ethernet::buffer[500];
 
BufferFiller bfill;
 
void setup () {
 ether.begin(sizeof Ethernet::buffer, mymac, 10);
 ether.staticSetup(myip);
 Serial.begin(9600);}
 
void loop () {
 word pos = ether.packetLoop(ether.packetReceive());
 if (pos){
// получаем заголовки
 char *data = (char *) Ethernet::buffer + pos;
// проверяем на наличие в заголовках нужных нам строк
 if (strstr(data, "index.htm")){
Serial.println(data);
bfill = ether.tcpOffset();
 bfill.emit_p(PSTR(
 "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/html\r\n"
 "\r\n"
"<html>"
"<head>"
"<title>Cool dynamic page</title>"
"<script src=\"http://test1.ru/skript.js\"></script>"
"</head>"
"<body onload=\"dR()\">"
"<h1>Temperatures:</h1>"
"<p>Komnata 1:<span id=\"komnata1\"></span></p>"
"<p>Komnata 2:<span id=\"komnata2\"></span></p>"
"<p>Komnata 3:<span id=\"komnata3\"></span></p>"
"</body>"
"</html>"

 ));
}
if (strstr(data, "data.txt")){
Serial.println(data);
bfill = ether.tcpOffset();
 bfill.emit_p(PSTR(
 "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/plain\r\n"
 "\r\n"
"komnata1 = 10\r\n"
"komnata2 = 20\r\n"
"komnata3 = 30\r\n"
 ));
}

 
 ether.httpServerReply(bfill.position());
 }
}

Значит захожу по адресу http://192.168.1.100/index.htm, получаю:

Temperatures:
 
Komnata 1:
 
Komnata 2:
 
Komnata 3:
 

Знчит захожу по адресу http://192.168.1.100/data.txt, получаю:

  komnata1 = 10
  komnata2 = 20
  komnata3 = 30 
"<script src=\"http://test1.ru/skript.js\"></script>"

Здесь вышеизложенный скрипт, т.к. ардуинка ругаеться на строчку

var a=this.responseText.replace(/\s*[\r\n=]+\s*/g, "=").replace(/^\s+/,"").replace(/\s+$/,"").match( /([^=]+)/g);

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

32 строка, это сайт изменил

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

Logic, ну, конечно, так лучше, кто бы спорил. Я просто думаю, что сервера на радуино делают тогда, когда нет возможности держать хозяйство на внешнем сервере. А если возможность есть есть, так понятно, что лучше там.

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

Sergeyevd пишет:

32 строка, это сайт изменил

В 32 строке Вы не все кавычки предварили \. Посмотрите внимательно.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Заработало )))

Вместо

if (strstr(data, "index.htm")){

if (strstr(data, "data.txt")){

сделал 

if (strstr(data, "GET /index.htm")){

if (strstr(data, "GET /data.txt")){

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Попробую разобраться со своим скриптом графического термометра

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

Ну, заработало и слава Богу. Только, думается вы что-то ещё сделали. Экспериментируйте дальше. Привыкните и поймёте, что там нет ничего сложного.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014


#include <EtherCard.h>
int randNumber;

static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,1,100 };
 
const char website[] PROGMEM = "192.168.1.100";
byte Ethernet::buffer[900];
 
BufferFiller bfill;
 
void setup () {
 ether.begin(sizeof Ethernet::buffer, mymac, 10);
 ether.staticSetup(myip);
 Serial.begin(9600);}
 
void loop () {
word pos = ether.packetLoop(ether.packetReceive());
if (pos){
// получаем заголовки
 char *data = (char *) Ethernet::buffer + pos;
// проверяем на наличие в заголовках нужных нам строк
 if (strstr(data, "GET /index.htm")){
Serial.println(data);
bfill = ether.tcpOffset();
 bfill.emit_p(PSTR(
 "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/html\r\n"
 "\r\n"
"<html>"
"<head>"
"<title>Cool dynamic page</title>"
"<script>var CANV_GAUGE_FONTS_PATH = \"/fonts\"</script>"//Шрифт графического термометра
"<script src=\"/gauge.min.js\"></script>"//Скрипт графического термометра
"</head>"
"<body onload=\"dR()\">"
"<canvas id=\"gauge\"></canvas>"
"<div id=\"console\"></div>"
"<script src=\"/skript.js\"></script>"//Параметры графического термометра и скрипт получения температуры
"Komnata 1:<span id=\"komnata1\"></span><br>"
"Komnata 2:<span id=\"komnata2\"></span><br>"
"Komnata 3:<span id=\"komnata3\"></span><br>"
"<script type=\"text/javascript\">" 
"gauge.setValue(<span id=\"komnata1\"></span>);"
"</script>"
"</body>"
"</html>"
 ));
}
if (strstr(data, "GET /data.txt")){
randNumber = analogRead(1);
bfill = ether.tcpOffset();
 bfill.emit_p(PSTR(
 "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/plain\r\n"
 "\r\n"
"komnata1 = $D\r\n"
"komnata2 = $D\r\n"
"komnata3 = $D\r\n"
 ),randNumber,randNumber,randNumber);
}

 ether.httpServerReply(bfill.position());
 }
}

В коде адрес до скрипта не указал полностью, редактор на сайте ругается и кракозябы выдаёт.

Возникла пара вопросов:

byte Ethernet::buffer[900];

Это я указал вручную, а как узнать сколько нужно? Или так оставить, прибавляя по необходимости?

44 строка 

"gauge.setValue(<span id=\"komnata1\"></span>);"

не работает

gauge.setValue(значение);

toc
Offline
Зарегистрирован: 09.02.2013

Logik пишет:
... разнести a.htm где-то на серваке, чтоб и этим ардуину не беспокоить, а за data.txt уже на ардуину.

По-моему, все браузеры будут активно препятствовать работе такого сценария. Ради безопасности запрещают странице полученной с сайта 1 общаться с сайтом 2.

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

toc пишет:
По-моему, все браузеры будут активно препятствовать работе такого сценария. Ради безопасности запрещают странице полученной с сайта 1 общаться с сайтом 2.

Будут, но в разумных пределах это обходится.

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

Sergeyevd пишет:

"gauge.setValue(<span id=\"komnata1\"></span>);"

не работает

gauge.setValue(значение);

Сергей, вот честное слово, я не знаю что такое gauge. Вы чем-то пользуетесь, но я не знаю чем.

alexvs
Offline
Зарегистрирован: 22.07.2014

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

Sergeyevd пишет:

"gauge.setValue(<span id=\"komnata1\"></span>);"

не работает

gauge.setValue(значение);

Сергей, вот честное слово, я не знаю что такое gauge. Вы чем-то пользуетесь, но я не знаю чем.

Сдается мне что это аналоговый показометр, напрмер как здесь http://startingelectronics.org/projects/arduino-projects/web-server-two-temperature-gauges/

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Сдается мне что это аналоговый показометр, напрмер как здесь

Да, именно

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
<html style="width:100%;height:100%">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Gauge Test</title>
	<script>var CANV_GAUGE_FONTS_PATH = '../fonts'</script>
	<script src="../gauge.min.js"></script>
	<style>body{padding:0;margin:0;background:#222}</style>
</head>
<body style="width:100%;height:100%">
	<canvas id="gauge"></canvas>
	<div id="console"></div>
<script>
	var gauge = new Gauge({
		renderTo    : 'gauge',
		width       : 200,
		height      : 200,
		glow        : true,
		units       : 'Km/h',
		title       : false,
		minValue    : 0,
		maxValue    : 1200,
		majorTicks  : ['100','200','300','400','500','600','700','800','900','1000','1100','1200'],
		minorTicks  : 2,
		strokeTicks : false,
		highlights  : [
			{ from : 0,   to : 100, color : 'rgba(0,   255, 0, .15)' },
			{ from : 100, to : 200, color : 'rgba(255, 255, 0, .15)' },
			{ from : 200, to : 300, color : 'rgba(255, 30,  0, .25)' },
			{ from : 300, to : 400, color : 'rgba(255, 0,  225, .25)' },
			{ from : 400, to : 500, color : 'rgba(0, 0,  255, .25)' },
			{ from : 500, to : 600, color : 'rgba(0, 0,  255, .25)' },
			{ from : 600, to : 700, color : 'rgba(0, 0,  255, .25)' },
			{ from : 700, to : 800, color : 'rgba(0, 0,  255, .25)' },
			{ from : 800, to : 900, color : 'rgba(0, 0,  255, .25)' },
			{ from : 900, to : 1000, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1000, to : 1100, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1100, to : 1200, color : 'rgba(0, 0,  255, .25)' },
		],
		colors      : {
			plate      : '#222',
			majorTicks : '#f5f5f5',
			minorTicks : '#ddd',
			title      : '#fff',
			units      : '#ccc',
			numbers    : '#eee',
			needle     : { start : 'rgba(240, 128, 128, 1)', end : 'rgba(255, 160, 122, .9)' }
		}
	});

	gauge.onready = function() {
		setInterval( function() {
			gauge.setValue( Math.random() * 220);
		}, 1000);
	};

	gauge.draw();

window.onresize= function() {
	gauge.updateConfig({
		width  : document.body.offsetWidth,
		height : document.body.offsetHeight
	});
};
</script>

</html>

 

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
#include <EtherCard.h>
#include <SD.h>
File myFile;

static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,1,100 };
const char website[] PROGMEM = "192.168.1.100";

byte Ethernet::buffer[100];
 BufferFiller bfill;
 
void setup () {

  Serial.begin(9600);
 
  Serial.print("Initializing SD card...");
pinMode(4, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");


 ether.begin(sizeof Ethernet::buffer, mymac, 10);
 ether.staticSetup(myip);

 }
void loop () {
    
word pos = ether.packetLoop(ether.packetReceive());
if (pos){
// получаем заголовки
 char *data = (char *) Ethernet::buffer + pos;
// проверяем на наличие в заголовках нужных нам строк
 if (strstr(data, "GET /index.htm")){

// открываем файл только для чтения
  myFile = SD.open("index.htm");
  if (myFile) {
    Serial.println("index.htm:");
    // читаем файл посимвольно до конца:
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // закрываем файл:
    myFile.close();
  } else {
    // если файл не открылся, сообщает об ошибке:
    Serial.println("error opening test.txt");
  }

bfill = ether.tcpOffset();
 bfill.emit_p(PSTR(
  "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/html\r\n"
 "Connnection: close"
 "\r\n"
));
}

if (strstr(data, "GET /data.txt")){
bfill = ether.tcpOffset();
 bfill.emit_p(PSTR(
 "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/plain\r\n"
 "\r\n"
"komnata1 = $D\r\n"
"komnata2 = $D\r\n"
"komnata3 = $D\r\n"
 ),analogRead(0),analogRead(1),analogRead(2));
}


 ether.httpServerReply(bfill.position());
 }
}

При запросе 192.168.1.100/index.htm в порт начинает посимвольно выводиться текст из index.htm очень медленноооо

А как мне этот файл поставить в ответ 192.168.1.100/index.htm

 

bfill = ether.tcpOffset();
 bfill.emit_p(PSTR(
  "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/html\r\n"
 "Connnection: close"
 "\r\n"
));
Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Или по другому, чтоб понять

Если <span id=\"komnata1\"></span> = 100

то

Как организовать это условие?

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

Никак. Если Вы делаете с моим скриптом, то в html файле у Вас должно быть

<span id=\"komnata1\"></span>

и всё!

А в файле данных должно быть

komnata1 = 100

Тогда всё само подставится. Скрипт загрузит данные, вытащит эту 100 и вставит её в нужный span.

А если при очередном обращении к серверу за данными тот вернёт

komnata1 = 101

то это снова подставится и, таким образом, само поменяется в браузере.

 

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Это я понимаю.

"gauge.setValue(<span id=\"komnata1\"></span>);"

не воспнинимает значение komnata1

"gauge.setValue(130);"

 

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

"Комната 1:<span id=\"komnata1\"></span>градусов<br>"

"Комната 2:<span id=\"komnata2\"></span>градусов<br>"
"Комната 3:<span id=\"komnata3\"></span>градусов<br>"
"<script type=\"text/javascript\">" 
"gauge.setValue(<span id=\"komnata1\"></span>);"
"</script>"
 
Так работают только первые три строчки.
 
Комната 1:500градусов
Комната 2:440градусов
Комната 3:472градусов
 
"Комната 1:<span id=\"komnata1\"></span>градусов<br>"
"Комната 2:<span id=\"komnata2\"></span>градусов<br>"
"Комната 3:<span id=\"komnata3\"></span>градусов<br>"
//"<script type=\"text/javascript\">" 
"gauge.setValue(<span id=\"komnata1\"></span>);"
//"</script>"

Закомментировал скрипт

Комната 1:507градусов
Комната 2:434градусов
Комната 3:463градусов
gauge.setValue();
 
//"Комната 1:<span id=\"komnata1\"></span>градусов<br>"
"Комната 2:<span id=\"komnata2\"></span>градусов<br>"
"Комната 3:<span id=\"komnata3\"></span>градусов<br>"
//"<script type=\"text/javascript\">" 
"gauge.setValue(<span id=\"komnata1\"></span>);"
//"</script>"

Закомментировал первую строку и скрипт (нельзя использовать два раза одно и тоже <span id=\"komnata1\"></span>)

Комната 2:433градусов
Комната 3:461градусов
gauge.setValue(507);
 
Теперь значение меняется, но внутри скрипта нет.
Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Gauge Test</title>
	<script>var CANV_GAUGE_FONTS_PATH = '../fonts'</script>
	<script src="../gauge.min.js"></script>
	
</head>
<body onload="dR()">
	<canvas id="gauge"></canvas>
	<canvas id="termo"></canvas>
	<canvas id="zal"></canvas>
	<div id="console"></div>
	
<script>
	var gauge = new Gauge({
		renderTo    : 'gauge',
		width       : 200,
		height      : 200,
		glow        : true,
		units       : '111',
		title       : false,
		minValue    : 0,
		maxValue    : 1200,
		majorTicks  : ['0','100','200','300','400','500','600','700','800','900','1000','1100','1200'],
		minorTicks  : 2,
		strokeTicks : false,
		highlights  : [
			{ from : 0,   to : 100, color : 'rgba(0,   255, 0, .15)' },
			{ from : 100, to : 200, color : 'rgba(255, 255, 0, .15)' },
			{ from : 200, to : 300, color : 'rgba(255, 30,  0, .25)' },
			{ from : 300, to : 400, color : 'rgba(255, 0,  225, .25)' },
			{ from : 400, to : 500, color : 'rgba(0, 0,  255, .25)' },
			{ from : 500, to : 600, color : 'rgba(0, 0,  255, .25)' },
			{ from : 600, to : 700, color : 'rgba(0, 0,  255, .25)' },
			{ from : 700, to : 800, color : 'rgba(0, 0,  255, .25)' },
			{ from : 800, to : 900, color : 'rgba(0, 0,  255, .25)' },
			{ from : 900, to : 1000, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1000, to : 1100, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1100, to : 1200, color : 'rgba(0, 0,  255, .25)' },
		],
		colors      : {
			plate      : '#222',
			majorTicks : '#f5f5f5',
			minorTicks : '#ddd',
			title      : '#fff',
			units      : '#ccc',
			numbers    : '#eee',
			needle     : { start : 'rgba(240, 128, 128, 1)', end : 'rgba(255, 160, 122, .9)' }
		}
	});

	

	gauge.draw();

window.onresize= function() {
	gauge.updateConfig({
		width  : document.body.offsetWidth,
		height : document.body.offsetHeight
	});
};



	var termo = new Gauge({
		renderTo    : 'termo',
		width       : 200,
		height      : 200,
		glow        : true,
		units       : 'Km/h',
		title       : false,
		minValue    : 0,
		maxValue    : 1200,
		majorTicks  : ['0','100','200','300','400','500','600','700','800','900','1000','1100','1200'],
		minorTicks  : 2,
		strokeTicks : false,
		highlights  : [
			{ from : 0,   to : 100, color : 'rgba(0,   255, 0, .15)' },
			{ from : 100, to : 200, color : 'rgba(255, 255, 0, .15)' },
			{ from : 200, to : 300, color : 'rgba(255, 30,  0, .25)' },
			{ from : 300, to : 400, color : 'rgba(255, 0,  225, .25)' },
			{ from : 400, to : 500, color : 'rgba(0, 0,  255, .25)' },
			{ from : 500, to : 600, color : 'rgba(0, 0,  255, .25)' },
			{ from : 600, to : 700, color : 'rgba(0, 0,  255, .25)' },
			{ from : 700, to : 800, color : 'rgba(0, 0,  255, .25)' },
			{ from : 800, to : 900, color : 'rgba(0, 0,  255, .25)' },
			{ from : 900, to : 1000, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1000, to : 1100, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1100, to : 1200, color : 'rgba(0, 0,  255, .25)' },
		],
		colors      : {
			plate      : '#222',
			majorTicks : '#f5f5f5',
			minorTicks : '#ddd',
			title      : '#fff',
			units      : '#ccc',
			numbers    : '#eee',
			needle     : { start : 'rgba(240, 128, 128, 1)', end : 'rgba(255, 160, 122, .9)' }
		}
	});



	termo.draw();

window.onresize= function() {
gauge.updateConfig({
		width  : document.body.offsetWidth,
		height : document.body.offsetHeight
	});
};

	var zal = new Gauge({
		renderTo    : 'zal',
		width       : 200,
		height      : 200,
		glow        : true,
		units       : 'Km/h',
		title       : false,
		minValue    : 0,
		maxValue    : 1200,
		majorTicks  : ['0','100','200','300','400','500','600','700','800','900','1000','1100','1200'],
		minorTicks  : 2,
		strokeTicks : false,
		highlights  : [
			{ from : 0,   to : 100, color : 'rgba(0,   255, 0, .15)' },
			{ from : 100, to : 200, color : 'rgba(255, 255, 0, .15)' },
			{ from : 200, to : 300, color : 'rgba(255, 30,  0, .25)' },
			{ from : 300, to : 400, color : 'rgba(255, 0,  225, .25)' },
			{ from : 400, to : 500, color : 'rgba(0, 0,  255, .25)' },
			{ from : 500, to : 600, color : 'rgba(0, 0,  255, .25)' },
			{ from : 600, to : 700, color : 'rgba(0, 0,  255, .25)' },
			{ from : 700, to : 800, color : 'rgba(0, 0,  255, .25)' },
			{ from : 800, to : 900, color : 'rgba(0, 0,  255, .25)' },
			{ from : 900, to : 1000, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1000, to : 1100, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1100, to : 1200, color : 'rgba(0, 0,  255, .25)' },
		],
		colors      : {
			plate      : '#222',
			majorTicks : '#f5f5f5',
			minorTicks : '#ddd',
			title      : '#fff',
			units      : '#ccc',
			numbers    : '#eee',
			needle     : { start : 'rgba(240, 128, 128, 1)', end : 'rgba(255, 160, 122, .9)' }
		}
	});



	zal.draw();

window.onresize= function() {
gauge.updateConfig({
		width  : document.body.offsetWidth,
		height : document.body.offsetHeight
	});
};


	var o=new XMLHttpRequest();
function dR() {
  o.open("GET", "data.txt?r=" + Math.random(), 1);
  o.onload = function() {
    var a = this.responseText;
    a = a.replace(/\s*[\r\n=]+\s*/g, "=");
    a = a.replace(/^\s+/, "");
    a = a.replace(/\s+$/, "");
    a = a.match( /([^=]+)/g);
    
    for (var i = 0, len = a.length; i < len; i += 2) {
      try {
        document.getElementById(a[i]).innerText = a[i + 1];
        
     
          gauge.setValue(a[1]);
          termo.setValue(a[3]);
		  zal.setValue(a[5]);
       
      } catch(e) {};
    }
    
    setTimeout("dR()", 1000);
  }
  
  o.send();
}
</script>
<p><b>Температура в комнате =  <span id="komnata"></span> &#176;C</b></p> 
<p><b>Температура на кухне =  <span id="kux"></span> &#176;C</b></p> 
<p><b>Температура в зале =  <span id="zal"></span> &#176;C</b></p> 
</body>
</html>

 

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Работает. Но решил попробовать сделать три термометра.

1-2-3 термометр работает

p><b>Температура в зале =  <span id="zal"></span> &#176;C</b></p>

не отображает температуру в зале

 

 

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

Sergeyevd пишет:

Это я понимаю.

"gauge.setValue(<span id=\"komnata1\"></span>);"

не воспнинимает значение komnata1

Стоп.

gauge исполняется на клиентской стороне.

Ну, тогда так и пишите

gauge.setValue(document.komnata1.innerText);

По идее, должно сработать. Если нет, попробуйте

gauge.setValue(document.komnata1.innerText);

gauge.setValue(parseInt(document.getElementById("komnata1").innerText));

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Gauge Test</title>
	<script>var CANV_GAUGE_FONTS_PATH = '../fonts'</script>
	<script src="../gauge.min.js"></script>
	
</head>
<body onload="dR()">
	<canvas id="gauge"></canvas>
	<div id="console"></div>
	<script>
	var gauge = new Gauge({
		renderTo    : 'gauge',
		width       : 200,
		height      : 200,
		glow        : true,
		units       : '111',
		title       : false,
		minValue    : 0,
		maxValue    : 1200,
		majorTicks  : ['0','100','200','300','400','500','600','700','800','900','1000','1100','1200'],
		minorTicks  : 2,
		strokeTicks : false,
		highlights  : [
			{ from : 0,   to : 100, color : 'rgba(0,   255, 0, .15)' },
			{ from : 100, to : 200, color : 'rgba(255, 255, 0, .15)' },
			{ from : 200, to : 300, color : 'rgba(255, 30,  0, .25)' },
			{ from : 300, to : 400, color : 'rgba(255, 0,  225, .25)' },
			{ from : 400, to : 500, color : 'rgba(0, 0,  255, .25)' },
			{ from : 500, to : 600, color : 'rgba(0, 0,  255, .25)' },
			{ from : 600, to : 700, color : 'rgba(0, 0,  255, .25)' },
			{ from : 700, to : 800, color : 'rgba(0, 0,  255, .25)' },
			{ from : 800, to : 900, color : 'rgba(0, 0,  255, .25)' },
			{ from : 900, to : 1000, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1000, to : 1100, color : 'rgba(0, 0,  255, .25)' },
			{ from : 1100, to : 1200, color : 'rgba(0, 0,  255, .25)' },
		],
		colors      : {
			plate      : '#222',
			majorTicks : '#f5f5f5',
			minorTicks : '#ddd',
			title      : '#fff',
			units      : '#ccc',
			numbers    : '#eee',
			needle     : { start : 'rgba(240, 128, 128, 1)', end : 'rgba(255, 160, 122, .9)' }
		}
	});
gauge.draw();

window.onresize= function() {
	gauge.updateConfig({
		width  : document.body.offsetWidth,
		height : document.body.offsetHeight
	});
};

      var o=new XMLHttpRequest();
      function dR() {
         o.open("GET","data.txt?r="+Math.random(),1);
         o.onload=function(){
            var a=this.responseText.replace(/\s*[\r\n=]+\s*/g, "=").replace(/^\s+/,"").replace(/\s+$/,"").match( /([^=]+)/g);
            for (var i=0, len=a.length; i< len; i+=2) try { document.getElementById(a[i]).innerText=a[i+1]; } catch(e) {};
            setTimeout("dR()", 10);
         }
         o.send();
      }


</script>
 <script type="text/javascript">
gauge.setValue(document.komnata.innerText);
//gauge.setValue(document.komnata.innerText);
//gauge.setValue(parseInt(document.getElementById("komnata").innerText));
</script>

<p><b>Температура в комнате =  <span id="komnata"></span> &#176;C</b></p> 

</body>
</html>

Евгений, не работает ни один из вариантов

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

Так стоп, а как Вы его вызывать собираетесь? Строчка

gauge.setValue(document.komnata.innerText);

должна быть не сама по себе, она должна вызываться каждый раз после обновления span. А сейчас она вызывается в начале программы один раз. Вставьте её в мой скрипт после строки

setTimeout("dR()", 10);

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
gauge.setValue(parseInt(document.getElementById("komnata").innerText));
setTimeout("dR()", 10);

Ага, Спасибо. Вот так работает.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Но

<span id="komnata"></span>

в тексте странички обязательна

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
"<canvas id='an_gauge_1' data-title='Inside'
 data-units=\"Temp. &deg;C\" width=\"500\" height=\"500\" 
data-major-ticks=\"-40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150\"
 data-type='canv-gauge' data-min-value=\"-40\" data-max-value=\"150\" data-highlights=\"
-40 0 #4D89F2, 0 10 #25B8D9, 10 30 #0BB950, 30 40 #cc5, 40 150 #f33\" data-onready=
\"setInterval( function() { Gauge.Collection.get('an_gauge_1').setValue(parseInt(document.getElementById('k1').
innerText));}, 200);\"></canvas>"

На какой символ ругается ардуино? Добавляю в код такую строку, и сервер не отвечает.

inspiritus
Offline
Зарегистрирован: 17.12.2012

Sergeyevd, а откуда Вы брали библиотеку gauge? Поделитесь ссылочкой ?

ЕвгенийП было бы здорово, если бы вдогоночку Вы рассказали про авторизацию для ардуино-сервера.

Моя проба пера на AJAX правда давняя, с год уже как. Страницу гружу с SD. Там же лог складывается.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Sergeyevd пишет:

"<canvas id='an_gauge_1' data-title='Inside'
 data-units=\"Temp. &deg;C\" width=\"500\" height=\"500\" 
data-major-ticks=\"-40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150\"
 data-type='canv-gauge' data-min-value=\"-40\" data-max-value=\"150\" data-highlights=\"
-40 0 #4D89F2, 0 10 #25B8D9, 10 30 #0BB950, 30 40 #cc5, 40 150 #f33\" data-onready=
\"setInterval( function() { Gauge.Collection.get('an_gauge_1').setValue(parseInt(document.getElementById('k1').
innerText));}, 200);\"></canvas>"

На какой символ ругается ардуино? Добавляю в код такую строку, и сервер не отвечает.

Не в ардуинке работает прекрасно

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

Sergeyevd пишет:

Но

<span id="komnata"></span>

в тексте странички обязательна

Совсем от него избавиться, это надо мой скрипт переписывать и он перестанет быть универсальны. Если хотите, чтоы его не было видно, добавьте в него style="display:none"

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

Sergeyevd пишет:

Sergeyevd пишет:

"<canvas id='an_gauge_1' data-title='Inside'
 data-units=\"Temp. &deg;C\" width=\"500\" height=\"500\" 
data-major-ticks=\"-40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150\"
 data-type='canv-gauge' data-min-value=\"-40\" data-max-value=\"150\" data-highlights=\"
-40 0 #4D89F2, 0 10 #25B8D9, 10 30 #0BB950, 30 40 #cc5, 40 150 #f33\" data-onready=
\"setInterval( function() { Gauge.Collection.get('an_gauge_1').setValue(parseInt(document.getElementById('k1').
innerText));}, 200);\"></canvas>"

На какой символ ругается ардуино? Добавляю в код такую строку, и сервер не отвечает.

Не в ардуинке работает прекрасно

Я не понимаю какой там баланс кавычек. Вы его куда и как добавляете? Кусок скетча покажите.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
// проверяем на наличие в заголовках нужных нам строк
 if (strstr(data, "GET /index.htm") || strstr(data, "GET / HTTP/1.1") ) {
bfill = ether.tcpOffset();
 bfill.emit_p(PSTR(
 "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/html\r\n"
 "\r\n"
"<html><head><meta charset=\"utf-8\"><title>Arduino Two Temperatures</title>"
"<script src=\"http://test1.ru/2termo.js\"></script></head>"
"<body onload=\"dR()\">"
"Комната1: <span id=\"k1\"></span>градусов<br>"
"Комната2: <span id=\"k2\"></span>градусов<br>"
"Комната3: <span id=\"k3\"></span>градусов<br>"
"<canvas id='an_gauge_1' data-title='Inside' data-units=\"Temp. &deg;C\" width=\"500\" height=\"500\" data-major-ticks=\"-40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150\" data-type='canv-gauge' data-min-value=\"-40\" data-max-value=\"150\" data-highlights=\"-40 0 #4D89F2, 0 10 #25B8D9, 10 30 #0BB950, 30 40 #cc5, 40 150 #f33\" data-onready=\"setInterval( function() { Gauge.Collection.get('an_gauge_1').setValue(parseInt(document.getElementById('k1').innerText));}, 200);\"></canvas>"
"</body>"
"</html>"
 ));
}

 

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

Такое ощущение, что у Вас начинаются проблемы с памятью. Строка очень большая.

С памятью тоно всё в порядке?

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Бросил это дело. Всё сохранил в скрипте на localhost, а то памяти в ардуино много ест.

Есть ли смысл запускать мою htm  и скрипты с флешки? Скорость будет маленькой?

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

Пока не попробуешь не поймёшь.

А с паиятью я бы на Вашем месте поборолся. там у Вас много расзвесистых конструкций - можно прилично сэкономить

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Пробую, но не выходит.

#include <EtherCard.h>
#include <SD.h>
File myFile;
int  text;

static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,1,100 };
 const char website[] PROGMEM = "192.168.1.100";
byte Ethernet::buffer[300];
BufferFiller bfill;

 
void setup () {
Serial.begin(250000);
Serial.print("Initializing SD card...");
pinMode(4, OUTPUT);
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");



ether.begin(sizeof Ethernet::buffer, mymac, 10);
ether.staticSetup(myip);
}

void loop () {
  
word pos = ether.packetLoop(ether.packetReceive());
if (pos){
// получаем заголовки
 char *data = (char *) Ethernet::buffer + pos;

// проверяем на наличие в заголовках нужных нам строк
 if (strstr(data, "GET /index.htm") || strstr(data, "GET / HTTP/1.1") ) {
myFile = SD.open("index.htm");
while (myFile.available()) {
//Serial.write(myFile.read());
text = myFile.read();
}
bfill = ether.tcpOffset();
bfill.emit_p(PSTR(
  "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/html\r\n"
 "\r\n"
"$D"
 ),text);
 myFile.close();
}
 
 ether.httpServerReply(bfill.position());
 }
}

Вместо того,чтобы показать мне текст index.htm показывает в браузере "62"

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Появилась ещё одна задача.

Теперь мне необходимо передать данные с html в ардуинку

К примеру

http://stanciya-skorpom.ru/reguliator/index.htm

Имею вот такой регулятор. Передвигая стрелку мышкой хочу изменять яркость светодиода.

Как организовать такую передачу?

OlegM
Offline
Зарегистрирован: 14.06.2016

а это уже надо парсер делать ))

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

Sergeyevd пишет:

Как организовать такую передачу?

Как два пальца.

Вы видели как я делаю запрос на файл data.txt?

Делаете ТОЧНО также только имя файла другое, например, kaka.htm и после имени файла ставьте знак вопроса и пишите имя параметра и значение. например:

var yarkost = 321;
var fileName = "kaka.htm?y="+yarkost;

В результате в Вашу ардуины свалится запрос такого вида: GET kaka.htm?y=321

И делайте на ардуине с ним всё, что захотите.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

Ооо, сейчас попробую.

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014
#include <EtherCard.h>
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,1,100 };
const char website[] PROGMEM = "192.168.1.100";
byte Ethernet::buffer[900];
BufferFiller bfill;

void setup () {
Serial.begin(250000);
ether.begin(sizeof Ethernet::buffer, mymac, 10);
ether.staticSetup(myip);
pinMode(3, OUTPUT);
}

void loop () {

word pos = ether.packetLoop(ether.packetReceive());
if (pos){
// получаем заголовки
 char *data = (char *) Ethernet::buffer + pos;
Serial.print(data);
// проверяем на наличие в заголовках нужных нам строк
 if (strstr(data, "GET /index.htm") || strstr(data, "GET / HTTP/1.1") ) {

  
bfill = ether.tcpOffset();
bfill.emit_p(PSTR(
  "HTTP/1.0 200 OK\r\n"
 "Content-Type: text/html\r\n"
 "\r\n"
"<html>"
"<head>"
"<meta charset=\"utf-8\">"
"<title>Яркость</title>"
"</head>"
"<body onload=\"dR()\">"
"<button onclick=\"yar()\">Установим яркость 10</button>"
"<script>"

//"function yar() {"
"var xhr = new XMLHttpRequest();"
"function dR() {"
"xhr.open('GET', 'kaka.htm?y=10', 1);"
"setTimeout(\"dR()\", 1000);"
"xhr.send();"
"}"
"</script>"
"</body>"
"</html>"
));
}
if (strstr(data, "GET /kaka.htm?y=10 HTTP/1.1")  ) {
analogWrite(3, 10);  
bfill = ether.tcpOffset();
bfill.emit_p(PSTR(
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"10"
));
 }
 ether.httpServerReply(bfill.position());
 }
}

Евгений, вот что получается.

Умею делать любую яркость, но только зная конкретный гет запрос, т.е. условие если придёт /kaka.htm?y=10 HTTP/1.1 то ярклсть установлю 10, 20 - 20 и т.д....

Допустим сделал random(255) и гет запрос будет "xhr.open('GET', 'kaka.htm?y=случайное число', 1);"

Как мне при запросе kaka.htm получить только это самое случайное число, разобрать строку

Sergeyevd
Sergeyevd аватар
Offline
Зарегистрирован: 25.03.2014

if (strstr(data, "GET /kaka.htm HTTP/1.1)  ) {
analogWrite(3, случайное число);  
bfill = ether.tcpOffset();
bfill.emit_p(PSTR(
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"случайное число"
));
}