m1cr0lab-esp32 / remote-control-with-websocket

ESP32 Remote Control with WebSocket
MIT License
37 stars 20 forks source link

ESP32 WebSocket Server #12

Open jmobashery opened 3 years ago

jmobashery commented 3 years ago

Hi, It was explained very professionally and in detailed. I enjoyed reading it all. I would like to know how you could make the same project full-duplex e.g. by sending a temperature data from server to client and what is the best commercial way to access the device from anywhere in the world. thank you, Jim

m1cr0lab commented 3 years ago

Hi Jim,

Thank you for your feedback. I am very happy to know that you enjoyed my tutorial.

The client-server communications discussed in this tutorial are already in full-duplex, and this is what the WebSocket protocol is all about.

When the physical LED changes state, the server (ESP32) notifies all its clients (smartphones) at the same time as follows:

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

They can then update the web interface to reflect this state on the graphical LED:

function onMessage(event) {
    document.getElementById('led').className = event.data;
}

Reciprocally, when the user presses the graphic button of the web interface on his smartphone, Javascript allows to notify the server in the following way :

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

function onToggle(event) {
    websocket.send('toggle');
}

When the server receives this notification, it can in turn update the status of the physical LED:

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) {
            led.on = !led.on;
            notifyClients();
        }
    }
}

He takes the opportunity to warn all his clients by calling the notifyClients() function, so that everyone takes into account the new state of the physical LED.

Getting back to your question, here the server just broadcasts the status of the physical LED to all its clients. But it could just as well send them the temperature read on a sensor. The principle would be the same.

The ESPAsyncWebServer library provides several notification methods for sending various types of data. It's up to you to choose the one that's right for you. For example, you can do the following, if you read the temperature on a DHT11 or DHT22 sensor:

void notifyClients() {
    ws.printfAll("%2.1f", dht.readTemperature());
}

It's as simple as that!

Now, if you want to be able to access your ESP32, connected locally to a WiFi router, from anywhere in the world, just configure your router to do port forwarding, so that it routes HTTP(S) requests to the listening port of the web server running on the ESP32. This configuration depends of course on your router, but it's very simple to configure. I refer you to the documentation of your router for that. Then, to reach your router from anywhere, you will need to know its public IP address. You can also register it by a public DNS if you prefer to be able to access your router by a domain name, more intelligible than a simple IP address.

Hoping to have answered your question.

Thanks again for your feedback. Regards, Steph

jmobashery commented 3 years ago

Hi Stephane, I enjoyed one more time your detailed explanation. I believe you have a passion for this. As you pointed out I want to display the DHT22 values as well as controlling with the buttons. I guess I could create a timer and send a notification to clients with Temp and Humidity values every 3 minutes for example. Then I should probably use text rather than textAll or printf member function with Id and data. I will try this soon. But I am worried about controlling from any where in the world. I see a lot of tutorials and so many different ways that I don't know which one is better to invest. For example with DNS and router it is more like custom made and others like ngrok tool or MQTT and making a server with raspberry pi, etc are just for tutorials. But I am wondering what method the commercial products such as smart home thermostat or smart garage door opener or smart power switch and so on are using. Is that possible they all use Cloud Server?With cloud server you need to take care of php script and MySQL database. What do you think? thank you, Jim

m1cr0lab commented 3 years ago

Hi Jim,

It would be better if you came to feed our discussion directly on GitHub by following this link : https://github.com/m1cr0lab-esp32/remote-control-with-websocket/issues/12

Indeed, when you reply to a comment by email, it is automatically included in your reply, which introduces redundancy but, at the same time, loses all the benefit of the Markdown formatting.

Now, to get back to your questioning... well, the field of possibilities is quite wide. In fact, it all depends on the level of availability you wish to guarantee.

It would be wrong to think that the use of a simple Raspberry Pi is limited to the demonstrations presented in tutorials! I myself have a Raspberry Pi 3 that works 24/24 at home, and that remains available and accessible at all times from anywhere in the world (except when there is a power outage, but this is very rare, especially since I power my equipment through an APS).

But if your confidence level in the availability of your equipment is low, then yes you can consider hosting your applications with a cloud hosting provider, who will offer you redundant equipment to avoid service outages. And that's what most commercial solutions do: they focus on infrastructures that guarantee accessibility and availability 24 hours a day.

But the most fragile part of the application is ESP32 itself. Indeed, it can become inaccessible for many reasons. And if the data it collects in your local network (through a sensor network for example) is valuable, i.e. you can't afford to lose it, then you can't just host this data in the microcontroller's RAM for too long. At the very least, you will have to store them in its Flash memory (using SPIFFS for example), or use an SD card. But multiple writings on the Flash memory will inevitably damage it in the long run... This solution is therefore not satisfactory for a long term project.

It is preferable in this case to send the data to a server that will inject them into a real database so that they remain available no matter what happens to ESP32. This can be done in many ways, using WebSockets, or the MQTT protocol, or simply by sending the data to a REST API with HTTP (implemented with PHP or another means).

This is precisely what I do at home. My Raspberry Pi hosts a MySQL database and an HTTP server with PHP. I have a network of sensors whose nodes spend most of their time sleeping. They wake up from time to time (the frequency depends on the nature of the data) to take a reading on their sensor, transmit the read data via the ESP-NOW protocol to an ESP32 which acts as a gateway with my WiFi network. The gateway node in turn transmits the collected data in real time to the Raspberry Pi through a REST API developed in PHP, which stores it in its database. I don't necessarily need to notify many clients in real time each time a data is transmitted. And when this is the case, I use either WebSockets or MQTT protocol to notify third party devices that are on the lookout for certain types of events.

The implementation solutions are numerous. And it all depends on your needs for reactivity to certain types of events. A simple temperature reading does not necessarily have to be urgent and can simply be stored in a database, waiting for you to come and consult the complete record of the day. If, on the contrary, you wish to open your garage door, then you will have to send the event quickly to the equipment concerned. In this case, they must subscribe to this type of event to be notified immediately when the event occurs. And that's the point of protocols like WebSockets or MQTT.

But then again, you can decide to host it all at home, if you trust your facilities, or you can bridge to a service hosted in the cloud. But in any case, you will need to maintain accessibility of the devices involved.

I personally chose to host everything in my home.

It is difficult to give you a clear-cut answer because there are so many options. It all depends on what you want to do. Nevertheless, I hope I was able to bring water to your mill.

All the best, Steph

marcio0408 commented 3 years ago

Hello, congratulations on the great project. It was exactly what I was looking for for my project. However for my project I will use more than one LED virtual on the Web page. I am unable to increment on project more than one led. Can you please help me? Thank you very much ... I'm from Brazil: D

m1cr0lab commented 3 years ago

Hi @marcio0408,

Thanks for your feedback. I'm glad the tutorial helped you. If you want several LEDs, you can have a look at #13. That should tell you how to do it.

Regards, Steph