• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Отправить время в браузер

humaxoid

New member
Приветсвую! На страницу необходимо вывести время. Нашел простой ntp клиент.
Собственно вопрос. Не знаю как в джава скрипт передать данные о времени?

C++:
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 10800;    // GMT+3
const int daylightOffset_sec = 3600;

void printLocalTime()
{
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo))
  {
    Serial.println("Couldn't get the time");
    return;
  }
  Serial.println(&timeinfo, "%d %B %H:%M:%S");
    
void setup()
{   
      configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  printLocalTime();
}
    
void loop() {
 delay(1000);
 printLocalTime();
}

JavaScript:
document.getElementById("dateTime").innerHTML = test;

В html пологаю будет так.

HTML:
<span id="dateTime"></span>
 

Vovka

Member
Если один раз, перед выводом HTML-странички, то в этой страничке объявите например так:
Код:
var test=<!--TEST-->;
а перед выводом странички делайте поиск-замену "<!--TEST-->"

Если нужно постоянно менять на страничке время, то есть два решения: XMLHttpRequest или WebSocket
 

fps

Active member
А для чего если не секрет вам передавать время из esp, если устройство, на котором вы будете время отображать, наверняка и так его знает?

Вот так напишите и получите динамически обновляемое время. Без смс и регистрации ajax и вебсокетов.

HTML:
<span id="dateTime"></span>
JavaScript:
setInterval("document.getElementById('dateTime').innerHTML = Date()", 1000);
 

Vovka

Member
некоторые браузеры, если эта конструкция используется в таблице с одной колонкой, без неразрывного пробела вырезают эту строку! А когда добавляем данные, то строка появляется. В итоге прыгает высота таблицы!
 

fps

Active member
некоторые браузеры
Да вроде нынче кроме хромиумов и фаерфокс больше и нет ничего.

В итоге прыгает высота таблицы!
Это решается не костылями nbsp, а с помощью css :)

И само собой, мой пример - это просто пример. Он хоть и работоспособен, но как есть его использовать никто не станет ведь.
 

Vovka

Member
Да вроде нынче кроме хромиумов и фаерфокс больше и нет ничего.
А родные браузеры мобильных телефонов?
Это решается не костылями nbsp, а с помощью css :)
Для мобильников лучше nbsp, чем вычислять что из css не понимает!
 

humaxoid

New member
Ну да, дополнительный пробел не решает проблемы )) Вопрос был в другом!
У меня вэбсокет вот такой конструкции.
C++:
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

// Replace with your network credentials
const char* ssid = "ssid";
const char* password = "******";

bool ledState = 0;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");

void notifyClients() {
  ws.textAll(String(ledState));
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    if (strcmp((char*)data, "toggle") == 0) {
      ledState = !ledState;
      notifyClients();
    }
  }
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type,
             void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

String processor(const String& var){
  Serial.println(var);
  if(var == "STATE"){
    if (ledState){
      return "ON";
    }
    else{
      return "OFF";
    }
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  pinMode(25, OUTPUT);
  digitalWrite(25, LOW);
 
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  initWebSocket();

  // Инициализируем SPIFFS:
  if (!SPIFFS.begin(true))
  {
  //   Serial.println("При монтировании SPIFFS произошла ошибка");
    return;
  }

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
            { request->send(SPIFFS, "/index.html", "text/html", false, processor); });

  // Start server
  server.begin();
}

void loop() {
  ws.cleanupClients();
  digitalWrite(25, ledState);
}
HTML:
<!DOCTYPE HTML><html>
<head>
  <title>ESP Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
 
<title>ESP Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
</head>
<body>
  <div class="topnav">
    <h1>ESP WebSocket Server</h1>
  </div>
  <div class="content">
    <div class="card">
      <h2>Output - GPIO 2</h2>
      <p class="state">state: <span id="state">%STATE%</span></p>
      <p><button id="button" class="button">Toggle</button></p>
    </div>
  </div>
</body>
</html>
JavaScript:
  var gateway = `ws://${window.location.hostname}/ws`;
  var websocket;
  window.addEventListener('load', onLoad);
  function initWebSocket() {
    console.log('Trying to open a WebSocket connection...');
    websocket = new WebSocket(gateway);
    websocket.onopen    = onOpen;
    websocket.onclose   = onClose;
    websocket.onmessage = onMessage;
  }
  function onOpen(event) {
    console.log('Connection opened');
  }
  function onClose(event) {
    console.log('Connection closed');
    setTimeout(initWebSocket, 2000);
  }
  function onMessage(event) {
    var state;
    if (event.data == "1"){
      state = "ON";
    }
    else{
      state = "OFF";
    }
    document.getElementById('state').innerHTML = state;
  }
  function onLoad(event) {
    initWebSocket();
    initButton();
  }
  function initButton() {
    document.getElementById('button').addEventListener('click', toggle);
  }
  function toggle(){
    websocket.send('toggle');
  }
setInterval("document.getElementById('dateTime').innerHTML = Date()", 1000);
Так он не будет время тащить с ntp сервера. Скажем если я в будущем прикручу таймеры, мне нужна будет переодическая синхронизация времени.
 

fps

Active member
Так он не будет время тащить с ntp сервера.
мне нужна будет переодическая синхронизация времени.
А причем тут вообще js и вебсокеты тогда?
Если надо время синхронизировать - используйте NTP, он для того и придуман.
 

humaxoid

New member
А причем тут вообще js и вебсокеты тогда?
Если надо время синхронизировать - используйте NTP, он для того и придуман.
Ну так я об этом с самого начала и говорил. Первый код и есть ntp клиент! Вебсокет, отличное решение что бы вывести время на страничку. А без js вообще никак! Любые динамические изменения голым html не выполнить. Можно из loop в js отправить, но это не самое лучшее решение т.к loop в цикле. Если там еще delay крутится, дело ваааще труба. Оно мне надо? Тем более есть действующий вэбсокет.
 

pvvx

Активный участник сообщества
У ntp и передаваемое время в формате linux (в секундах от 1970.01.01) ?
JavaScript:
  let dt = new Date(devtime*1000);
  console.log('Device Date: '+(dt.toISOString().slice(0, -1)).replace('T',' '));
Будет выведено как "Device Date: 2022-02-19 00:08:00.000"
В UTC или Local?
JavaScript:
  let time = Date.now()/1000;
  time -= (new Date()).getTimezoneOffset() * 60;
 
Сверху Снизу