• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Вывод uptime ESP8266 на веб-страницу

Melandr

Member
Добрый день!
Ковыряю код, в котором на html-страницу выводится время работы ESP после перезапуска в секундах вот таким образом
C:
void handleData() {
  String message = F("{\"");
  message += FPSTR(vccArg);
  message += F("\":");
  message += String(ESP.getVcc() / 1024.0);
  message += F(",\"");
  message += FPSTR(wifimodeArg);
  message += F("\":\"");
  switch (WiFi.getMode()) {
    case WIFI_OFF:
      message += F("OFF");
      break;
    case WIFI_STA:
      message += F("Station");
      break;
    case WIFI_AP:
      message += F("Access Point");
      break;
    case WIFI_AP_STA:
      message += F("Hybrid (AP+STA)");
      break;
    default:
      message += F("Unknown!");
  }
  message += F("\",\"");
  message += FPSTR(mqttconnectedArg);
  message += F("\":");
  if (pubsubClient.connected())
    message += F("true");
  else
    message += F("false");
  message += F(",\"");
  message += FPSTR(freeheapArg);
  message += F("\":");
  message += String(ESP.getFreeHeap());
  message += F(",\"");
  message += FPSTR(uptimeArg);
  message += F("\":");
  message += String(millis() / 1000);
  message += F(",\"");
  message += FPSTR(relayArg);
  message += F("\":");
  if (digitalRead(relayPin) == relayLevel)
    message += F("true");
  else
    message += F("false");
  message += F("}");

  httpServer.send(200, F("text/html"), message);
}
Время работы ESP обновляется на веб-странице через JS такого вида
JavaScript:
  <script type="text/javascript">
    function openUrl(url) {
      var request = new XMLHttpRequest();
      request.open('GET', url, true);
      request.send(null);
    }
    function refreshData() {
      var request = new XMLHttpRequest();
      request.open('GET', '/data', true);
      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          var data = JSON.parse(request.responseText);
          document.getElementById('vcc').innerHTML = data.vcc;
          document.getElementById('wifimode').innerHTML = data.wifimode;
          document.getElementById('mqttconnected').innerHTML = (data.mqttconnected != true ? "not " : "") + "connected";
          document.getElementById('freeheap').innerHTML = data.freeheap;
          document.getElementById('uptime').innerHTML = data.uptime;
          document.getElementById('relay').checked = data.relay;
        }
      }
      request.send(null);
    }
    setInterval(refreshData, 500);
  </script>
Вывод осуществляется в таком виде
HTML:
  <form>
    <h3>ESP Relay</h3>
    <p>
    VCC: <span id="vcc">?</span> V<br/>
    WiFi mode: <span id="wifimode">?</span><br/>
    MQTT broker: <span id="mqttconnected">?</span><br/>
    Heap free size: <span id="freeheap">0</span> bytes<br/>
    Uptime: <span id="uptime">0</span> seconds</p>
    <input type="checkbox" class="checkbox" id="relay" onchange="openUrl('/switch?on=' + this.checked);" />
    <label for="relay">Relay</label>
    <p>
    <input type="button" value="WiFi Setup" onclick="location.href='/wifi';" />
    <input type="button" value="MQTT Setup" onclick="location.href='/mqtt';" />
    <input type="button" value="Relay Setup" onclick="location.href='/relay';" />
    <input type="button" value="Reboot!" onclick="if (confirm('Are you sure to reboot?')) location.href='/reboot';" />
  </form>
Пробую в скетче преобразовать секунды в вид 00:00:00 в виде строки такой функцией
Код:
String millis2time(){
  String Time="";
  unsigned long ss;
  byte mm,hh;
  ss=millis()/1000;
  hh=ss/3600;
  mm=(ss-hh*3600)/60;
  ss=(ss-hh*3600)-mm*60;
  if(hh<10)Time+="0";
  Time+=(String)hh+":";
  if(mm<10)Time+="0";
  Time+=(String)mm+":";
  if(ss<10)Time+="0";
  Time+=(String)ss;
  return Time;
}
Скетч компилируется, но данные на странице не отображаются, при этом, если ввести в браузере в адресной строке IP_адрес_ESP/data
то отображается JSON файл, с актуальным временем работы ESP. При обновлении страницы время работы меняется, но на саму веб-страницу переменные не выводятся.
Также пробовал подставить просто строку
String uptime = "456";
message += String(uptime);
Все равно не выводится это значение.
При этом, если выводит так
int uptime = 456;
message += String(uptime);
тогда выводится значение на веб-страницу.
Если пробовать вывести строку
message += millis2time();
то в JSON файле информация обновляется, но на страницу также не выводится
Буду рад, если подскажете, в какую сторону копать. Заранее спасибо.
 

Melandr

Member
'Выдает ошибку unexpected number in JSON at position at JSON.parse:
которая означает, что JSON объект не может начинаться с 0. Как это можно обойти?
 

enjoynering

Well-known member
Очевидно же - сделать проверку на null и undefined

If (time != null || time != unidentified)
{
//Your code here
}
 

Melandr

Member
Для меня не очевидно, я только учусь. Не могли бы поподробнее объяснить. Нужно проверку делать в js? Для меня js вообще пока темный лес. Насколько я понял, при использовании метода JSON.parse в строке, которой передается время работы имеются два символа, которые парсер не может разобрать, так как они конфликтуют с синтаксисом. Первое - ноль в начале, второе - разделитель "двоеточее" в строке.
Тут https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/JSON написано , что ведущие нули запрещены.
вот эта строка document.getElementById('uptime').innerHTML = data.uptime; должна получить время наработки, но не идет.
ЗЫ: при этом json открываю {"vcc":2.93,"wifimode":"Station","mqttconnected":false,"freeheap":40776,"uptime": 02:03:14,"relay":false}
 

Melandr

Member
Попробовал на сайте https://jsonlint.com/ проверить получаемую строку json
{"vcc":2.93,"wifimode":"Station","mqttconnected":false,"freeheap":41000,"uptime":00:02:25,"relay":false}
после проверки получаем
{
"vcc": 2.93,
"wifimode": "Station",
"mqttconnected": false,
"freeheap": 41000,
"uptime": 00: 02: 25,
"relay": false
}
и ругается на 6 строку - "uptime": 00: 02: 25,
Error: Parse error on line 6:
...: 41000, "uptime": 00: 02: 25, "relay"
----------------------^
Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined'
Можно ли как-то обойти это ограничение?
 

Melandr

Member
Судя по строке json, метод JSON.parse(request.responseText); неправильно преобразует "uptime". Я хочу отображать строку, а он переводит ее в число. Можно ли как-то принудительно указать, что это строка?
 

l15ar

Member
ни фига се!
в скринах:
"uptime":00:06:37,
что за бардак!!!?
можно так: "uptime":"00:06:37",
или так: "uptime":[00,06,37],
но не так "uptime":00:06:37,
_________________^__^______нельзя использовать этот символ, кроме как разделитель полей.
имя_поля : значение_поля, ...
лучше преобразовать время в секунды.
 

Melandr

Member
Так я об этом же и пишу. ESP формирует uptime следующим кодом:
Код:
String millis2time(){
  String Time="";
  unsigned long ss;
  byte mm,hh;
  ss=millis()/1000;
  hh=ss/3600;
  mm=(ss-hh*3600)/60;
  ss=(ss-hh*3600)-mm*60;
  if(hh<10)Time+="0";
  Time+=(String)hh+":";
  if(mm<10)Time+="0";
  Time+=(String)mm+":";
  if(ss<10)Time+="0";
  Time+=(String)ss;
  return Time;
}
То есть , я передаю uptime в виде строки "00:00:00".
Почему на скриншотах уже отображается uptime как 00:00:00 я не знаю
javascript, возможно, при использовании метода parse преобразует полученное значение "uptime" в number. И, соответственно, выдает ошибку, так как используется ведущий 0 и разделитель ":"
время работы передавалось в секундах в исходном коде, но я хочу уже на веб-странице отобразить его в формате ХХ дней 00:00:00
В JS я еще плохо разбираюсь, потому как сделать правильно не могу понять. пробовал использовать второй необязательный параметр метода parse в виде, указанном ниже,, но тоже не идет
JavaScript:
  <script type="text/javascript">
    function openUrl(url) {
      var request = new XMLHttpRequest();
      request.open('GET', url, true);
      request.send(null);
    }
    function refreshData() {
      var request = new XMLHttpRequest();
      request.open('GET', '/data', true);
      request.onreadystatechange = function() {
        if (request.readyState == 4) {
          var data = JSON.parse(request.responseText, function(key, value) {
            if (key == 'uptime') return new Date(value);
            return value;
          });
          document.getElementById('vcc').innerHTML = data.vcc;
          document.getElementById('wifimode').innerHTML = data.wifimode;
          document.getElementById('mqttconnected').innerHTML = (data.mqttconnected != true ? "not " : "") + "connected";
          document.getElementById('freeheap').innerHTML = data.freeheap;
          document.getElementById('uptime').innerHTML = data.uptime;
          document.getElementById('relay').checked = data.relay;
        }
      }
      request.send(null);
    }
    setInterval(refreshData, 500);
  </script>
 

l15ar

Member
не занимайтесь фигнёй, преобразуйте в кол-во секунд, ещё лучше - 30сек интервалов(минутных).
выводите целое число, там, в javascript пересчитать в минуты, часы, дни, ерунда, школьник сделает..
ИМХО
 

Melandr

Member
Я думал, что проще сделать преобразование на ESP,и выводить в JS уже строку.
 

l15ar

Member
Я думал, что проще сделать преобразование на ESP,и выводить в JS уже строку.
Поймите одну вещь, не нужно делать бесполезную работу на устройстве, которое и так ограниченно в ресурсах!
Поэтому, если есть параметр(ы) который(е) можно выдать наружу без обработки внутри, выдавайте наружу как есть, с минимальной обработкой!
Не нужно выдавать наружу никаких строк, кроме тех, которые нельзя предугадать, во остальных случаях - выдавайте целочисленный код(вместо строк).
Если можно не использовать JSON, нужно не использовать, было бы желание, не используйте, это трата памяти и ресурсов!
Если можно не использовать строковых преобразований, не используйте их, это трата ресурсов..
По факту получается, пытаются собрать веб-страницу прямо в контроллере(ESP), это извините - бред..
Всё что нужно для динамики веб-страницы, делается средствами AJAX, веб-сокеты, UDP, отрисовывается обычным Javascript, на котором можно сделать всё!
Короткие серии обмена между ESP и веб-клиентом использующий javascript. Не нужно ничего более этого.
Более того, на том nodejs можно сделать локальный сервер статистики и управления.
:\
 

l15ar

Member
Касаемо ресурсов, которые нужно отдать веб-клиенту(браузеру), необходимо делать редирект на соответствующий ресурс(сервер,сервис,..), на котором они будут лежат(вы туда их запишите).
Не нужно их отдавать непосредственно с контроллера(ESP). По факту, большинство так и делают, отдают с контроллера.. :\
 

l15ar

Member
И ещё, если можно выполнить какую то работу на внешнем устройстве(расчёт), нужно выполнять эту работу на внешнем устройстве, результат вернуть контроллеру(не нужно мучить контроллер).
 

enjoynering

Well-known member
ИМХО, автор взялся за не посильную ю, для него, задачу. Вам все показали, но все рано топчетесь в трёх соснах. Я бы вам посоветовал прочесть какую-нибудь книгу по JS. И вот увидите ваш вопрос отпадёт сам собой.
 

Melandr

Member
Всем большое спасибо за очень "конструктивную" помощь. Ответ лежал на поверхности, в первом посте темы. Проблема была в формировании строки с правильным использованием обратного слеша и кавычек.
2020-09-12_095751.jpg
l15ar
Спасибо за ссылки, интересно будет посмотреть, так как весь фронтэнд для ESP делается через JS и не хватает знаний.
 
Сверху Снизу