'전체 글'에 해당되는 글 22건

  1. 2023.10.28 ESP8266 websocket (HTML 내장)
  2. 2023.10.26 Websocket with JSON
  3. 2023.10.18 Unix Timestamp 변환하기
/*
 1.PC connect the wifi : tunc5555  
              password :123456789
 2.Browser open: http://192.168.4.1/
 
 3.click the on or off button

#include <WebSockets.h>
#include <WebSockets4WebServer.h>
#include <WebSocketsClient.h>
#include <WebSocketsServer.h>
#include <WebSocketsVersion.h>

*/

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
//#include <Hash.h>
#include <ESP8266WebServer.h>
//#include <ESP8266mDNS.h>

#include <NTPClient.h>
#include <WiFiUdp.h>

#define USE_SERIAL Serial

static const char ssid[] = "Merry_2G";
static const char password[] = "Goodnews";

// MDNSResponder mdns;

static void writeLED(bool);

// ESP8266WiFiMulti WiFiMulti;

ESP8266WebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(81);

static const char PROGMEM INDEX_HTML[] = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=0">
<title>ESP8266 WebSocket Demo</title>
<style>
"body { background-color: #808080; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }"
</style>
<script>
var websock;
function start() {
  websock = new WebSocket('ws://' + window.location.hostname + ':81/');
  websock.onopen = function(evt) { console.log('websock open'); };
  websock.onclose = function(evt) { console.log('websock close'); };
  websock.onerror = function(evt) { console.log(evt); };
  websock.onmessage = function(evt) {
    console.log(evt);
    var e = document.getElementById('ledstatus');
    if (evt.data === 'ledon') {
      e.style.color = 'red';
    }
    else if (evt.data === 'ledoff') {
      e.style.color = 'black';
    }
    else {
      console.log('unknown event');
    }
  };
}
function buttonclick(e) {
  websock.send(e.id);
}
</script>
</head>
<body onload="javascript:start();">
<h1>ESP8266 WebSocket Demo</h1>
<div id="ledstatus"><b>LED</b></div>
<button id="ledon"  type="button" onclick="buttonclick(this);">On</button>
<button id="ledoff" type="button" onclick="buttonclick(this);">Off</button>
</body>
</html>
)rawliteral";


// GPIO#0 is for Adafruit ESP8266 HUZZAH board. Your board LED might be on 13.
const int LEDPIN = 0;
// Current LED status
bool LEDStatus;

// Commands sent through Web Socket
const char LEDON[] = "ledon";
const char LEDOFF[] = "ledoff";

void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
{
  USE_SERIAL.printf("webSocketEvent(%d, %d, ...)\r\n", num, type);
  switch (type) {
  case WStype_DISCONNECTED:
    USE_SERIAL.printf("[%u] Disconnected!\r\n", num);
    break;
  case WStype_CONNECTED:
  {
               IPAddress ip = webSocket.remoteIP(num);
               USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\r\n", num, ip[0], ip[1], ip[2], ip[3], payload);
               // Send the current LED status
               if (LEDStatus) {
                 webSocket.sendTXT(num, LEDON, strlen(LEDON));
               }
               else {
                 webSocket.sendTXT(num, LEDOFF, strlen(LEDOFF));
               }
  }
    break;
  case WStype_TEXT:
    USE_SERIAL.printf("[%u] get Text: %s\r\n", num, payload);

    if (strcmp(LEDON, (const char *)payload) == 0) {
      writeLED(true);
    }
    else if (strcmp(LEDOFF, (const char *)payload) == 0) {
      writeLED(false);
    }
    else {
      USE_SERIAL.println("Unknown command");
    }
    // send data to all connected clients
    webSocket.broadcastTXT(payload, length);
    break;
  case WStype_BIN:
    USE_SERIAL.printf("[%u] get binary length: %u\r\n", num, length);
    hexdump(payload, length);

    // echo data back to browser
    webSocket.sendBIN(num, payload, length);
    break;
  default:
    USE_SERIAL.printf("Invalid WStype [%d]\r\n", type);
    break;
  }
}

void handleRoot()
{
  server.send_P(200, "text/html", INDEX_HTML);
}

void handleNotFound()
{
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i<server.args(); i++){
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}

static void writeLED(bool LEDon)
{
  LEDStatus = LEDon;
  // Note inverted logic for Adafruit HUZZAH board
  if (LEDon) {
    digitalWrite(LEDPIN, 0);
  }
  else {
    digitalWrite(LEDPIN, 1);
  }
}

void setup()
{
  pinMode(LEDPIN, OUTPUT);
  writeLED(false);

  USE_SERIAL.begin(115200);

  //Serial.setDebugOutput(true);

  USE_SERIAL.println();
  USE_SERIAL.println();
  USE_SERIAL.println();

  for (uint8_t t = 4; t > 0; t--) {
    USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\r\n", t);
    USE_SERIAL.flush();
    delay(1000);
  }

//  WiFiMulti.addAP(ssid, password);
//
//  while (WiFiMulti.run() != WL_CONNECTED) {
//    Serial.print(".");
//    delay(100);
//  }


//  WiFi.softAP(ssid, password);
//  IPAddress myIP = WiFi.softAPIP();
//  USE_SERIAL.print("AP IP address: ");
//  USE_SERIAL.println(myIP);

  // Wi-Fi 연결
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    USE_SERIAL.println("연결 중...");
  }
  USE_SERIAL.println("Wi-Fi 연결 성공!");
  USE_SERIAL.print("IP 주소: ");
  USE_SERIAL.println(WiFi.localIP());

//  USE_SERIAL.println("");
//  USE_SERIAL.print("Connected to ");
//  USE_SERIAL.println(ssid);
//  USE_SERIAL.print("IP address: ");
//  USE_SERIAL.println(WiFi.localIP());

// mdns 기능 windows 10에서는 문제가 있음
//
//  if (mdns.begin("espWebSock", WiFi.localIP())) {
//    USE_SERIAL.println("MDNS responder started");
//    mdns.addService("http", "tcp", 80);
//    mdns.addService("ws", "tcp", 81);
//  }
//  else {
//    USE_SERIAL.println("MDNS.begin failed");
//  }
//  USE_SERIAL.print("Connect to http://espWebSock.local or http://");
//  USE_SERIAL.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);

  server.begin();

  webSocket.begin();
  webSocket.onEvent(webSocketEvent);

}

void loop()
{
  webSocket.loop();
  server.handleClient();
}

'Embeded' 카테고리의 다른 글

Websocket with JSON  (0) 2023.10.26
Unix Timestamp 변환하기  (0) 2023.10.18
[ESP8266] Json in sming Framework  (0) 2023.02.04
Posted by 마인드파워
,

Websocket with JSON

Embeded 2023. 10. 26. 16:09

 

https://m1cr0lab-esp32.github.io/remote-control-with-websocket/websocket-and-json/


WebSocket Data Exchange with JSON

So far, we have only exchanged simple strings between the server and its clients using the WebSocket protocol. As long as the information transmitted remains simple to analyze, we can be satisfied with it. But sometimes we may need to exchange more complex data. In this case, it is preferable to structure the data so that it can be analysed more easily. This is where the JSON format comes in. JSON is a way to represent complex data structures as text. The resulting string is called a JSON document and can then be sent via the network or saved to a file.

For example, we may need to communicate more accurate information when the server needs to notify its clients with the LED status change:

```
{
    "device": "led",
    "status": "on",
    "time":   1591510722
}

```
The text above describes the prettifiedrepresentation in JSON format of an object composed of:

- a string named devicewith the value led,
- another string named statuswith the value on,
- an integer named timewith the value 1591510722.
JSON ignores spaces and line breaks, so the same object can be represented with the following minifiedJSON document:

```
{"device":"led","status":"on","time":1591510722}

```
Before the server can transmit this object to its clients, it will have to convert this structured data into a sequence of bytes. This is called serialization. In the context of JSON, serialization is the creation of a JSON document from an object in memory, and deserializationis the reverse operation.

Here the serialization remains quite simple and can be done easily with the sprintf()function:

```
sprintf(
    buffer,
    "{\"device\":\"%s\",\"status\":\"%s\",\"time\":\"%u\"}", // format
    "led",                                                   // device
    led.on ? "on" : "off",                                   // status
    millis()                                                 // time
);

```
You must of course provide a bufferlarge enough to hold the entire serialized data.

JSON makes it possible to structure much more complex data than that. It allows you to manage arrays of objects. Each object can encapsulate other objects in turn, or even arrays, etc.

As a result, serialization and deserialization processes can be laborious to implement. But, fortunately, there are plenty of libraries that can handle this for us. In this tutorial, we’ll use the excellentArduinoJsonlibrary developed by Benoît Blanchon.

ImportantThe following explanations are only compatible with version 6of the ArduinoJsonlibrary, which is the most recent version at the time of writing this tutorial.

My intention here is not to give you a complete course on the JSON format and its implementation with the ArduinoJsonlibrary. For that, please refer to its documentation, which is very complete. Nevertheless, I will present some basics to introduce you to its use.


Client notification


On the server side

When the LED changes state, the server transmits the new state to all clients. And so far, we’ve been doing it like this:

```
void notifyClients() {
    ws.textAll(led.on ? "on" : "off");
}

```
As long as the data to be transmitted is simple, one can simply proceed as follows, without the need to use a library specialized in the processing of the JSON format:

```
void notifyClients() {
    char buffer[17];
    sprintf(buffer, "{\"status\":\"%s\"}", led.on ? "on" : "off");
    ws.textAll(buffer);
}

```
Note that to store the string encoded in JSON format, a sufficiently large bufferis required. Indeed, depending on the state of the LED, onor off, the longest string to be encoded is the following:

```
{"status":"off"}

```
This string is exactly 16 characters long, to which it is necessary to think of adding the termination character \0of the strings in C. Our buffer must therefore be able to hold a maximum of 17characters. This is the reason for the following statement:

```
char buffer[17];

```
But let’s look instead at how to implement the same thing using the ArduinoJsonlibrary. First of all, we need to add the library to our project. To do this, we just need to edit our platformio.inifile and add a new dependency:

```
[env:esp32doit-devkit-v1]
platform      = espressif32
board         = esp32doit-devkit-v1
framework     = arduino
upload_speed  = 921600
monitor_speed = 115200
lib_deps      = ESP Async WebServer, ArduinoJson

```
Then we need to include the library header file at the beginning of our program:

```
#include <Arduino.h>
#include <SPIFFS.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>

```
One of the fundamental characteristics of the ArduinoJsonlibrary is its fixed memory allocation strategy. You first have to create a JsonDocumentto reserve a specified amount of memory. The memory of the JsonDocumentcan be either in the stackor in the heap. The location depends on the derived class you choose. If you use a StaticJsonDocument, it will be in the stack. If you use a DynamicJsonDocument, it will be in the heap.

Since our JsonDocumentis small, we can keep it in the stack. By using the stack, we reduce the size of the executable and improve the performance, because we avoid the overhead due to the management of the heap. We don’t need to engage a dynamic allocation strategy here, and we will avoid the problem of memory fragmentation at the same time.

When you create a JsonDocument, you must specify its capacity in bytes. In the case of a StaticJsonDocument, you set the capacity via a template parameter:

```
StaticJsonDocument<size> json;

```
As sizeis a template parameter, you cannot use a variable. Instead, you must use a constant expression, which means that the value must be computed at compile-time. The compiler manages the stack, so it needs to know the size of each variable when it compiles the program.

How to determine the capacity? To answer this question, you need to know what ArduinoJsonstores in the JsonDocument. ArduinoJsonneeds to store a data structure that mirrors the hierarchy of objects in the JSON document. In other words, the JsonDocumentcontains objects which relate to one another the same way they do in the JSON document.

Therefore, the capacity of the JsonDocumenthighly depends on the complexity of the JSON document. If it’s just one object with few members, like our example, a few dozens of bytes are enough. If it’s a massive JSON document, like OpenWeatherMap’s response, up to a hundred kilobytes are needed.

ArduinoJsonprovides macros for computing precisely the capacity of the JsonDocument. The macro to compute the size of an object is JSON_OBJECT_SIZE(). It takes one argument: the number of members in the object. Here is how to compute the capacity for our sample document:

```
const uint8_t size = JSON_OBJECT_SIZE(1);
StaticJsonDocument<size> json;

```
The JsonDocumentis currently empty. An empty JsonDocumentautomatically becomes an object when we add members to it. We do that with the subscript operator []:

```
const uint8_t size = JSON_OBJECT_SIZE(1);
StaticJsonDocument<size> json;
json["status"] = led.on ? "on" : "off";

```
The memory usage is now JSON_OBJECT_SIZE(1), so the JsonDocumentis full. When the JsonDocumentis full, you cannot add more members, so don’t forget to increase the capacity if you need.

Now, it’s time to serialize it into a JSON document. There are several ways to do that. Here we will look at how to write the JSON document to memory. We could use a String, but as you know, I prefer avoiding dynamic memory allocation. Instead, we’d use a good old char[]with enough space to receive the longest formatted string we need to encode:

```
char data[17];

```
Then, to produce a JSON document from a JsonDocument, we simply need to call serializeJson():

```
char data[17];
size_t len = serializeJson(json, data);

```
The serializeJson()function returns the effective length of the serialized JSON document. The value of this lenvariable will be useful for sending the JSON document to WebSocket clients. Here is the complete definition of the rewritten notifyClients()function:

```
void notifyClients() {
    const uint8_t size = JSON_OBJECT_SIZE(1);
    StaticJsonDocument<size> json;
    json["status"] = led.on ? "on" : "off";

    char data[17];
    size_t len = serializeJson(json, data);
    ws.textAll(data, len);
}

```
Using the ArduinoJsonlibrary on this very simple case probably seems overkill, and you’re right. But I wanted to make you aware of its use, which will prove extremely life-saving in the case of more complex data. I encourage you to carefully read the documentationof this library, which details many useful use cases.


On the client side

Now that the server broadcasts its notifications in JSON format, we need to take this into account on the client side and rewrite the onMessage()function that receives these notifications in the index.jsfile:

```
function onMessage(event) {
    let data = JSON.parse(event.data);
    document.getElementById('led').className = data.status;
}

```
You can see that this new data processing is extremely simple. We start by decoding the received object in JSON format to make it a Javascript object. And then we can easily read the value of its statusmember. It’s as simple as that!


Server notification

This time, when the user presses the Togglebutton on the web interface, we will send a notification to the server in the form of a message in JSON format.


On the client side

We’ll slightly modify the onToggle()function in the index.jsfile to send the following JSON message:

```
{"action":"toggle"}

```
It’s quite simple:

```
function onToggle(event) {
    websocket.send(JSON.stringify({'action':'toggle'}));
}

```

On the server side

To make things a little easier, we assume here that the structure of the expected JSON message is known in advance. The JSON document consists of a JSON object with a single member named action, whose value is a string.

We will rewrite the handleWebSocketMessage()function to handle messages received in JSON format:

```
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) {

        // We'll see in the following how to decode the received message
        
    }
}

```
Since our JsonDocumentis small, we can keep it in the stack:

```
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) {

        const uint8_t size = JSON_OBJECT_SIZE(1);
        StaticJsonDocument<size> json;
        
    }
}

```
Now that the JsonDocumentis ready, we can parse the input data with the deserializeJson()function:

```
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) {

        const uint8_t size = JSON_OBJECT_SIZE(1);
        StaticJsonDocument<size> json;
        DeserializationError err = deserializeJson(json, data);
        
    }
}

```
The deserializeJson()function returns a DeserializationErrorthat tells whether the operation was successful. DeserializationErrorconverts implicitly to bool, so we don’t need to identify the nature of the error by searching for the error code and comparing it to the predefined constants of the DeserializationErrorclass. We can simply write:

```
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) {

        const uint8_t size = JSON_OBJECT_SIZE(1);
        StaticJsonDocument<size> json;
        DeserializationError err = deserializeJson(json, data);
        if (err) {
            Serial.print(F("deserializeJson() failed with code "));
            Serial.println(err.c_str());
            return;
        }
        
    }
}

```
If no error occurs at the time of deserialization, we can extract the value of the actionmember and compare it to the expected value, i.e. toggle:

```
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) {

        const uint8_t size = JSON_OBJECT_SIZE(1);
        StaticJsonDocument<size> json;
        DeserializationError err = deserializeJson(json, data);
        if (err) {
            Serial.print(F("deserializeJson() failed with code "));
            Serial.println(err.c_str());
            return;
        }

        const char *action = json["action"];
        if (strcmp(action, "toggle") == 0) {
            led.on = !led.on;
            notifyClients();
        }
        
    }
}

```
If successful, the status of the LED is reversed and all connected clients are notified.

There you go! This time we’ve come full circle.You can upload the contents of the datafolder to the SPIFFS to update the index.jsfile:


Then compile and upload the C++ program to the ESP32. Reload the web user interface in the browser and you will see that everything works exactly as in the previous chapter, except that now the server and clients communicate with messages in JSON format.

You can now update the baseline project by going to the remote-control-with-websocketdirectory and executing the following gitcommand:

```
git checkout v1.0

```
You can also download the updated main.cppand index.jsfiles and replace yours in your own project:


main.cpp


index.js

Here is the complete code for this chapter:


Server side

```
/**
 * ----------------------------------------------------------------------------
 * ESP32 Remote Control with WebSocket
 * ----------------------------------------------------------------------------
 * © 2020 Stéphane Calderoni
 * ----------------------------------------------------------------------------
 */

#include <Arduino.h>
#include <SPIFFS.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>

// ----------------------------------------------------------------------------
// Definition of macros
// ----------------------------------------------------------------------------

#define LED_PIN   26
#define BTN_PIN   22
#define HTTP_PORT 80

// ----------------------------------------------------------------------------
// Definition of global constants
// ----------------------------------------------------------------------------

// Button debouncing
const uint8_t DEBOUNCE_DELAY = 10; // in milliseconds

// WiFi credentials
const char *WIFI_SSID = "YOUR_WIFI_SSID";
const char *WIFI_PASS = "YOUR_WIFI_PASSWORD";

// ----------------------------------------------------------------------------
// Definition of the LED component
// ----------------------------------------------------------------------------

struct Led {
    // state variables
    uint8_t pin;
    bool    on;

    // methods
    void update() {
        digitalWrite(pin, on ? HIGH : LOW);
    }
};

// ----------------------------------------------------------------------------
// Definition of the Button component
// ----------------------------------------------------------------------------

struct Button {
    // state variables
    uint8_t  pin;
    bool     lastReading;
    uint32_t lastDebounceTime;
    uint16_t state;

    // methods determining the logical state of the button
    bool pressed()                { return state == 1; }
    bool released()               { return state == 0xffff; }
    bool held(uint16_t count = 0) { return state > 1 + count && state < 0xffff; }

    // method for reading the physical state of the button
    void read() {
        // reads the voltage on the pin connected to the button
        bool reading = digitalRead(pin);

        // if the logic level has changed since the last reading,
        // we reset the timer which counts down the necessary time
        // beyond which we can consider that the bouncing effect
        // has passed.
        if (reading != lastReading) {
            lastDebounceTime = millis();
        }

        // from the moment we're out of the bouncing phase
        // the actual status of the button can be determined
        if (millis() - lastDebounceTime > DEBOUNCE_DELAY) {
            // don't forget that the read pin is pulled-up
            bool pressed = reading == LOW;
            if (pressed) {
                     if (state  < 0xfffe) state++;
                else if (state == 0xfffe) state = 2;
            } else if (state) {
                state = state == 0xffff ? 0 : 0xffff;
            }
        }

        // finally, each new reading is saved
        lastReading = reading;
    }
};

// ----------------------------------------------------------------------------
// Definition of global variables
// ----------------------------------------------------------------------------

Led    onboard_led = { LED_BUILTIN, false };
Led    led         = { LED_PIN, false };
Button button      = { BTN_PIN, HIGH, 0, 0 };

AsyncWebServer server(HTTP_PORT);
AsyncWebSocket ws("/ws");

// ----------------------------------------------------------------------------
// SPIFFS initialization
// ----------------------------------------------------------------------------

void initSPIFFS() {
  if (!SPIFFS.begin()) {
    Serial.println("Cannot mount SPIFFS volume...");
    while (1) {
        onboard_led.on = millis() % 200 < 50;
        onboard_led.update();
    }
  }
}

// ----------------------------------------------------------------------------
// Connecting to the WiFi network
// ----------------------------------------------------------------------------

void initWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.printf("Trying to connect [%s] ", WiFi.macAddress().c_str());
  while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(500);
  }
  Serial.printf(" %s\n", WiFi.localIP().toString().c_str());
}

// ----------------------------------------------------------------------------
// Web server initialization
// ----------------------------------------------------------------------------

String processor(const String &var) {
    return String(var == "STATE" && led.on ? "on" : "off");
}

void onRootRequest(AsyncWebServerRequest *request) {
  request->send(SPIFFS, "/index.html", "text/html", false, processor);
}

void initWebServer() {
    server.on("/", onRootRequest);
    server.serveStatic("/", SPIFFS, "/");
    server.begin();
}

// ----------------------------------------------------------------------------
// WebSocket initialization
// ----------------------------------------------------------------------------

void notifyClients() {
    const uint8_t size = JSON_OBJECT_SIZE(1);
    StaticJsonDocument<size> json;
    json["status"] = led.on ? "on" : "off";

    char data[17];
    size_t len = serializeJson(json, data);
    ws.textAll(data, len);
}

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) {

        const uint8_t size = JSON_OBJECT_SIZE(1);
        StaticJsonDocument<size> json;
        DeserializationError err = deserializeJson(json, data);
        if (err) {
            Serial.print(F("deserializeJson() failed with code "));
            Serial.println(err.c_str());
            return;
        }

        const char *action = json["action"];
        if (strcmp(action, "toggle") == 0) {
            led.on = !led.on;
            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);
}

// ----------------------------------------------------------------------------
// Initialization
// ----------------------------------------------------------------------------

void setup() {
    pinMode(onboard_led.pin, OUTPUT);
    pinMode(led.pin,         OUTPUT);
    pinMode(button.pin,      INPUT);

    Serial.begin(115200); delay(500);

    initSPIFFS();
    initWiFi();
    initWebSocket();
    initWebServer();
}

// ----------------------------------------------------------------------------
// Main control loop
// ----------------------------------------------------------------------------

void loop() {
    ws.cleanupClients();

    button.read();

    if (button.pressed()) {
        led.on = !led.on;
        notifyClients();
    }
    
    onboard_led.on = millis() % 1000 < 50;

    led.update();
    onboard_led.update();
}

```

Client side

```
/**
 * ----------------------------------------------------------------------------
 * ESP32 Remote Control with WebSocket
 * ----------------------------------------------------------------------------
 * © 2020 Stéphane Calderoni
 * ----------------------------------------------------------------------------
 */

var gateway = `ws://${window.location.hostname}/ws`;
var websocket;

// ----------------------------------------------------------------------------
// Initialization
// ----------------------------------------------------------------------------

window.addEventListener('load', onLoad);

function onLoad(event) {
    initWebSocket();
    initButton();
}

// ----------------------------------------------------------------------------
// WebSocket handling
// ----------------------------------------------------------------------------

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) {
    let data = JSON.parse(event.data);
    document.getElementById('led').className = data.status;
}

// ----------------------------------------------------------------------------
// Button handling
// ----------------------------------------------------------------------------

function initButton() {
    document.getElementById('toggle').addEventListener('click', onToggle);
}

function onToggle(event) {
    websocket.send(JSON.stringify({'action':'toggle'}));
}

```

WebSocket Data ExchangeTime for Discussion

'Embeded' 카테고리의 다른 글

ESP8266 websocket (HTML 내장)  (0) 2023.10.28
Unix Timestamp 변환하기  (0) 2023.10.18
[ESP8266] Json in sming Framework  (0) 2023.02.04
Posted by 마인드파워
,

Unix Timestamp 변환하기

Embeded 2023. 10. 18. 22:36
typedef uint32_t timestamp_t;  //seconds  타임 스탬프 변수형

// 데이트타임 구조체
typedef struct {
  uint16_t    year;
  uint8_t     month;
  uint8_t     day;  
  uint8_t     hour;  
  uint8_t     minute;
  uint8_t     second;
  uint8_t     week;
  uint8_t     weekday;
} datetime_t;

// 1일을 초로
#define ONE_DAY  (1*60*60*24)

// UTC 시작 시간
#define UTC_TIME_WEEKDAY_OFFSET (4)  /* 1970,1,1은 목요일이기때문에 */

//날짜                    x, 1월, 2월 ..... 11월, 12월
uint8_t month_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

// Globals
time_t now;   // this are the seconds since Epoch (1970) - UTC
tm tm;        // the structure tm holds time information in a more convenient way
//요일 얻기
uint8_t timestamp_to_weekday(timestamp_t timestamp_sec)
{
  uint8_t result=(timestamp_sec / ONE_DAY + UTC_TIME_WEEKDAY_OFFSET) % 7;
  if (result==0){
    result = 7;
  }
  return result;
}

//윤달 확인
int is_leap_year(uint16_t year)
{
  if ( year % 4 == 0 && ((year % 100) != 0) || ((year % 400)==0) ) {
    return true;
  } else {
    return false;
  }
}

//UTC 타임 스탬프를 날짜로 변환
void utc_timestamp_to_date(timestamp_t timestamp, datetime_t* datetime)
{
  uint8_t month;
  uint32_t days;
  uint16_t days_in_year;
  uint16_t year;
  timestamp_t second_in_day;

  //날짜
  second_in_day = (timestamp + (9*60*60)) % ONE_DAY;

  //초
  datetime->second=second_in_day%60;

  //분
  second_in_day /= 60;
  datetime->minute=second_in_day%60;

  //시
  second_in_day /=60;
  datetime->hour=second_in_day % 24;

  //1970-1-1 부터 현재까지 총 일수
  days = (timestamp + (9*60*60)) / ONE_DAY;

  //days를 계속 차감하면서 해당 년도 계산
  for (year=1970;year<=2100;year++){
    if(is_leap_year(year))
      days_in_year=366;
    else
      days_in_year=365;

    if(days>=days_in_year)
      days -= days_in_year;
    else
      break;
   
  }

  //년
  datetime->year=year;

  //요일
  datetime->weekday=timestamp_to_weekday(timestamp);

  //해당 년도 1월1일을 기준으로 지금까지의 주(week) 계산
  datetime->week=(days+11-datetime->weekday)/7;

  //월 계산
  if(is_leap_year(datetime->year))  //윤달의 경우 2월이 29일이다.
    month_days[2]=29;
  else
    month_days[2]=28;

  //년도와 마찬가지로 일에서 계속 차감해서 찾는다.
  for (month=1; month<=12; month++){
    if (days>=month_days[month])
      days -= month_days[month];
    else
      break;  

  }

  datetime->month=month;
  datetime->day=days+1;
 
  Serial.print(datetime->year);
  Serial.print(datetime->month);
  Serial.print(datetime->day);
  Serial.print(datetime->hour);
  Serial.println(datetime->minute);

}

'Embeded' 카테고리의 다른 글

ESP8266 websocket (HTML 내장)  (0) 2023.10.28
Websocket with JSON  (0) 2023.10.26
[ESP8266] Json in sming Framework  (0) 2023.02.04
Posted by 마인드파워
,