Как сделать веб-хостинг, если весь код сайта хранится на SD-карте?
Я выполняю этот проект, в котором arduino выступает в качестве веб-сервера и размещает веб-сайт, на котором я показываю постоянно обновляемую температуру в лаборатории.
Проблема в том, что при запуске всего этого кода в arduino легко заканчивается память.
void loop() {
int value= analogRead(PIN_LM35);
float temperature= value/ 2.046;
myFile = SD.open("temperature.txt");
if (myFile) {
Serial.println(temperature);
}
myFile.close();
EthernetClient client = server.available();
if (client) {
while (client.connected()) {
if (client.available()) {
char c = client.read();
//read char by char HTTP request
if (readString.length() < 100) {
//store characters to string
readString += c;
//Serial.print(c);
}
//if HTTP request has ended
if (c == '\n') {
Serial.println(readString); //print to serial monitor for debuging
client.println(F("HTTP/1.1 200 OK")); //send new page
client.println(F("Content-Type: text/html"));
client.println();
refreshcounter=refreshcounter+1;
client.println(F("<HTML>"));
client.println(F("<HEAD>"));
client.print(F("<meta http-equiv=\"refresh\" content=\"2\">"));
client.println(F("<meta name='apple-mobile-web-app-capable' content='yes' />"));
client.println(F("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />"));
client.println(F("<TITLE>TEMPERATURE SENSOR LAB01</TITLE>"));
client.println(F("</HEAD>"));
client.println(F("<BODY>"));
client.println(F("<H1>TEMPERATURE SENSOR LAB01</H1>"));
client.println(F("<hr />"));
client.println(F("<br />"));
client.println(F("<H2>Arduino with Ethernet Shield</H2>"));
client.println(F("<br />"));
if(temperatura<24){
client.println("<p style=\"font-size:50px; color:#8eff59; font-weight:bold; font-style:italic;\">");
client.println(temperature);
client.println("</p>");
}
else if(temperature>=24 && temperature<=26){
client.println("<p style=\"font-size:50px; color:#ffbc03; font-weight:bold; font-style:italic;\">");
client.println(temperature);
client.println("</p>");
}
else{
client.println("<p style=\"font-size:50px; color:#ff0303; font-weight:bold; font-style:italic;\">");
client.println(temperature);
client.println(F("<H2>It is recommended to activate the air conditioner.</H2>"));
client.println("</p>");
}
client.println(F("<p style=\"font-size:30px; color:#000000; font-weight:bold; ;\">Date/Time: <span id=\"datetime\"></span></p>"));
client.println(F("<script>"));
client.println(F("var dt = new Date();"));
client.println(F("document.getElementById(\"datetime\").innerHTML = ((\"0\"+dt.getDate()).slice(-2)) +\".\"+ ((\"0\"+(dt.getMonth()+1)).slice(-2)) +\".\"+ (dt.getFullYear()) +\" \"+ ((\"0\"+dt.getHours()).slice(-2)) +\":\"+ ((\"0\"+dt.getMinutes()).slice(-2));"));
client.println(F("</script>"));
client.println("<svg width=\"1000\" height=\"250\">");
client.println("<rect width=\"150\" height=\"5\" fill=\"gray\">");
client.println("<animate attributeName=\"x\" from = \"0\" to =\"10000\" dur=\"10s\" fill=\"freeze\" />");
client.println("</rect");
client.println("</svg>");
client.println("<br />");
client.println("</BODY>");
client.println("</HTML>");
delay(1);
//stopping client
client.stop();
//clearing string for next read
readString="";
}
}
}
}
}
</p>"));
client.println(F("<скрипт>"));
client.println(F("var dt = новая дата();"));
client.println(F("document.getElementById(\"datetime\").innerHTML = ((\"0\"+dt.getDate()).срез(-2)) +\".\"+ ((\"0\"+( дт.getMonth()+1)).нарезать ломтиками(-2)) +\".\"+ ( dt.Получить полностью год()) +\" \"+ ((\"0\"+ dt.getHours()).нарезать(-2)) +\":\"+ ((\"0\"+dt.getMinutes()).slice(-2));"));
client.println(F("</script>"));
client.println("<svg width=\"1000\" height=\"250\">");
клиент.println("<ширина прямоугольника = \"150 \" высота = \"5 \" заливка= \"серый \">");
client.println("<имя атрибута анимации = \"x \" от = \"0 \" до = \"10000 \" dur= \"10s \" fill=\"freeze \" />");
клиент.println("</rect");
клиент.println("</svg>");
client.println("<br />");
client.println("</BODY>");
client.println("</HTML>") клиент.println("</HTML>");
задержка (1);
//остановка клиента
клиент.стоп();
//очистка строки для следующего чтения
Строка чтения="";
}
}
}
}
}
Я подумал сэкономить память, чтобы поместить весь код веб-страницы на внешнюю SD-карту. Однако я действительно не знаю, как использовать его с SD-карты.
Проблема, которая меня останавливает, заключается в том факте, что сайт не обязательно должен быть статичным, но постоянно обновляться новыми данными о температуре.
Как я могу это сделать?
@Leo, 👍2
Обсуждение1 ответ
Лучший ответ:
Вы написали:
сайт не обязательно должен быть статичным, но постоянно обновляться новыми данными о температуре.
Хорошим вариантом является использование Ajax. Основная идея состоит в том, чтобы разделить сайт на две части:
- статичная часть, потенциально большая, которая содержит весь пользовательский интерфейс, стиль, навороты и навороты...
- крошечная динамическая часть, содержащая данные, которые постоянно обновляются и ничего больше.
Статическая часть будет передаваться с SD-карты, когда клиент отправляет
GET /
request. Динамическая часть будет обслуживаться с другой конечной точки,
например, в качестве ответа на GET / temperature
. Обслуживание динамической части
должно быть очень простым, что-то вроде:
client.println(temperature);
Да, просто отправьте номер в формате ASCII, без форматирования HTML. Если вам когда-нибудь понадобится
отправить более одного числа (например, несколько значений температуры или температуры
и влажности), отформатируйте их в формате JSON. Для этого не нужно использовать библиотеку
, обычная функция print()
должна быть дешевле и достаточно хороша:
client.print(F("{\"temperature\":"));
client.print(temperature);
client.print(F(",\"humidity\":"));
client.print(humidity);
client.print('}');
На стороне клиента JSON.parse()
возвращает данные в виде простой в использовании
структуры данных.
Вот минимальный пример того, как может выглядеть статическая часть. Обратите внимание на код JavaScript, отправленный клиенту. Этот код отвечает за запрос температуры каждые 1000 миллисекунд и обновление Веб-страница с новыми данными;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Ajax test</title>
</head>
<body>
<h1>Ajax test</h1>
<p>Temperature: <span id="temperature">---</span> °C</p>
<script>
var data_field = document.getElementById("temperature");
setInterval(function() {
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState != 4) return;
data_field.innerText = JSON.parse(request.responseText);
};
request.open("GET", "/temperature");
request.send();
}, 1000);
</script>
</body>
</html>
°C</p>
<сценарий>
var data_field = document.getElementById("температура");
setInterval(функция() {
var запрос = новый XMLHttpRequest();
request.onreadystatechange = функция() {
if (request.readyState != 4) возвращает;
data_field.innerText = JSON.parse(запрос.responseText);
};
запрос.открыть ("ПОЛУЧИТЬ", "/температура");
запрос.отправить();
}, 1000);
</скрипт>
</тело>
</html>
Несколько замечаний:
В примере используется старый добрый
XMLHttpRequest. Возможно, вместо этого вы захотите попробовать более современный fetch API
setInterval(функция() { выборка ("/ температура") .затем(response => response.json()) .затем(data => { data_field.innerText = данные; }); }, 1000);setInterval(function() { fetch("/temperature") .then(response => response.json()) .then(data => { data_field.innerText = data; }); }, 1000);
Если вы отправляете обновления достаточно часто, чтобы значительно загрузить свой Arduino, вы можете посмотреть на события, отправляемые сервером
. Это метод, который позволяет значительно сократить накладные расходы на отправку обновлений данных. Он не так популярен, как веб-сокеты, но имеет то преимущество, что его проще реализовать на стороне сервера.Если вы можете установить обратный прокси-сервер между вашим Arduino и Интернетом, прокси-сервер может обрабатывать статический контент. Тогда ваш Arduino будет обрабатывать только динамические данные и не будет нуждаться в SD-карте. Если вы отменяете события, отправленные прокси-сервером, убедитесь, что прокси-сервер не буферизует ответ сервера. См., например, эти советы по настройке Nginx
для этой цели.Сервер Arduino должен добавить заголовок
Access-Control-Allow-Origin: *В клиентском коде вы должны указать полный URL-адрес Arduino в качестве аргумента
request.open(),
fetch()или
new EventSource()
Как только вы освоите базовую схему, веб-технологии позволят вам делать все, что вам заблагорассудится. Вы могли бы создать аналоговый датчик (с помощью SVG transform rotate). Вы даже можете добавить график
, обновляемый в режиме реального времени, который показывает изменение температуры во времени и полностью обрабатывается клиентом.
- Простая веб-страница с Ethernet-шилдом Arduino на SD-карте
- Загрузить сайт с SD-карты
- Как импортировать данные с SD-карты на Arduino на компьютер, используя последовательный/COM-порт Arduino?
- Отправка данных на сервер
- Как увеличить скорость записи на SD-карту в Ардуино
- Несколько клиентских серверов через Wi-Fi
- WebSocketsServer.h: No such file or directory
- SD-карта не инициализируется
почему вы не используете F() для каждой строки? С Arduino Uno, если вы используете библиотеку Ethernet и библиотеку SD, у вас очень быстро заканчиваются flash и SRAM., @Juraj
Я пытался, но у меня тоже заканчивалась флэш-память, @Leo
Возможно, вам захочется подробно описать, какую библиотеку, экран и плату вы используете. Это один из стандартных AVR Arduino? Какое у него есть оборудование и библиотека, которые позволяют запускать его в первую очередь как сервер?, @RDragonrydr
Я бы посоветовал ознакомиться с примерами библиотеки экранов wifi / ethernet или примерами библиотеки SD-карт. Возможно, вы найдете тот, который уже делает то, что вам нужно. В самом худшем случае вы можете написать цикл, который считывает символы или строки с карты и сервера.печатает их. Создайте на карте два файла, примыкающих к линии печати, чтобы вставить значение температуры, затем распечатайте файл 1, Температура, файл 2., @RDragonrydr