<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ayoub Touba</title>
    <description>The latest articles on DEV Community by Ayoub Touba (@youba).</description>
    <link>https://dev.to/youba</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F393596%2F1d055087-799a-43d8-b1c2-dc87fe52e46a.jpeg</url>
      <title>DEV Community: Ayoub Touba</title>
      <link>https://dev.to/youba</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/youba"/>
    <language>en</language>
    <item>
      <title>ESP32/Arduino Sensor Data Visualization on Web Apps: A Beginner's Guide with Directus: Part 2</title>
      <dc:creator>Ayoub Touba</dc:creator>
      <pubDate>Sun, 17 Mar 2024 07:00:45 +0000</pubDate>
      <link>https://dev.to/youba/esp32arduino-sensor-data-visualization-on-web-apps-a-beginners-guide-with-directus-part-2-99g</link>
      <guid>https://dev.to/youba/esp32arduino-sensor-data-visualization-on-web-apps-a-beginners-guide-with-directus-part-2-99g</guid>
      <description>&lt;p&gt;Welcome back! In &lt;a href="https://dev.to/youbadev/esp32arduino-sensor-data-visualization-on-web-apps-a-beginners-guide-with-directus-part-1-d8m"&gt;Part 1&lt;/a&gt;, you built the ESP32 circuit and verified that your sensor works properly. Now, it's time to connect your ESP32 to the web world and visualize those sensor readings!&lt;/p&gt;

&lt;p&gt;In this part, we'll focus on sending data from your ESP32 to a user-friendly web dashboard. Here, we'll leverage the power of &lt;strong&gt;Directus&lt;/strong&gt;. But before we dive in, let's address a key question you might have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Directus and Sockets?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are several reasons why Directus is a great choice for this project, and one of them is its built-in &lt;strong&gt;socket connection&lt;/strong&gt; functionality. Sockets might be a new term for some beginners, so let's break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imagine a socket as a dedicated communication channel&lt;/strong&gt; between your ESP32 and the web dashboard (Directus). It's like a direct line where data can be exchanged quickly and efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, you might wonder, "Why use sockets instead of the REST APIs that Directus also offers?" Here's the key difference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Data vs. Periodic Updates:&lt;/strong&gt; REST APIs are fantastic for various data exchange scenarios, but for our project where we want to see sensor readings &lt;strong&gt;almost instantly&lt;/strong&gt; (in milliseconds), sockets are a better fit. They provide a more real-time connection, allowing the ESP32 to send data as soon as it's collected, minimizing delays.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an analogy: Think of REST APIs like checking your mailbox for letters you might get them a few times a day. Sockets, on the other hand, are like having a live chat with someone information is exchanged almost instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short, sockets are ideal for our project because we want to see sensor readings with minimal delay.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1.Sending Sensor Data to Directus with ESP32 and WebSockets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we understand why sockets are a good choice for real-time data transmission, let's delve into the code that sends sensor data from your ESP32 to the web dashboard (Directus).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Libraries and Dependencies:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code snippet includes several libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;WiFi.h&lt;/code&gt;: Enables ESP32 to connect to your WiFi network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;WebSocketsClient.h&lt;/code&gt;: Provides functionalities for establishing WebSocket connections.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;then go to Arduino ide menu sketch manage libraries upload library&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ArduinoJson.h&lt;/code&gt;: Allows working with JSON data format for sending and receiving data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(If not installed you can install it directly from the library manager)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DHT.h&lt;/code&gt;: Specific to the DHT11 sensor, used for interacting with the sensor and reading temperature/humidity values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;User-Defined Variables:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WiFi Settings:&lt;/strong&gt; Replace &lt;code&gt;XXXXX&lt;/code&gt; with your actual WiFi network name (SSID) and password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://Socket.IO"&gt;&lt;strong&gt;Socket.IO&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;Settings:&lt;/strong&gt; These define the connection details for your Directus server. You'll need to replace placeholders like&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;host&lt;/code&gt; IP address youre connecting with to Directus (your IP machine)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;port&lt;/code&gt; : &lt;code&gt;8055&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Directus Access Token:&lt;/strong&gt; Replace &lt;code&gt;Dirctus_user_token&lt;/code&gt; with a valid access token you generated in your Directus dashboard when you created a user&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collection:&lt;/strong&gt; Set &lt;code&gt;dht_sensor&lt;/code&gt; to the collection name&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Time Variables:&lt;/strong&gt; These variables help manage the timing of sensor readings and data transmission.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;WiFi.h&amp;gt;#include &amp;lt;WebSocketsClient.h&amp;gt;#include &amp;lt;ArduinoJson.h&amp;gt;#include "DHT.h"/////////////////////////////////////////// USER DEFINED VARIABLES //////////////////////////////////////////// WIFI Settings ///const char* ssid = "ssid";const char* password = "password";/// Socket.IO Settings ///char host[] = "IP"; // Socket.IO Server Addressint port = 8055; // Socket.IO Port Addresschar path[] = "/websocket"; // Socket.IO Base Pathconst char* access_token = "DirctusToken";const char* collection = "dht_sensor";/// Pin Settings ///#define DHTPIN 2#define DHTTYPE DHT11DHT dht(DHTPIN, DHTTYPE);// time excutingunsigned long startTime;const int delayTime = 5000;unsigned long currentTime;bool isReadyToSend = false;/////////////////////////////////////////// ESP32 Socket.IO Client /////////////////////////////////////////WebSocketsClient webSocket;WiFiClient client;void authenticate() { JsonDocument doc; doc["type"] = "auth"; doc["access_token"] = access_token; String message; serializeJson(doc, message); webSocket.sendTXT(message);}void traitPayload(uint8_t* payload) { JsonDocument doc; DeserializationError error = deserializeJson(doc, payload); if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); return; } const char* typeValue = doc["type"]; const char* statusValue = doc["status"]; const char* event = doc["event"]; if (strcmp(typeValue, "auth") == 0 &amp;amp;&amp;amp; strcmp(statusValue, "ok") == 0) { Serial.println("[EVENT] SUBSCRIBE"); subscribe(); } if (strcmp(typeValue, "subscription") == 0 &amp;amp;&amp;amp; strcmp(event, "init") == 0) { Serial.println("[EVENT] INIT TO SEND"); isReadyToSend = true; } if (strcmp(typeValue, "ping") == 0) { Serial.println("[EVENT] SEND PONG"); pong(); }}void subscribe() { JsonDocument doc; doc["type"] = "subscribe"; doc["collection"] = collection; doc["query"]["fields"] = doc["query"]["fields"].to&amp;lt;JsonArray&amp;gt;(); doc["query"]["fields"].add("*"); String message; serializeJson(doc, message); Serial.println("[EVENT] SEND SUBSCRIBE"); Serial.println(message); webSocket.sendTXT(message);}void pong() { JsonDocument doc; doc["type"] = "pong"; String message; serializeJson(doc, message); webSocket.sendTXT(message);}void sendData() { float humidity = dht.readHumidity(); float temperatureC = dht.readTemperature(); if (isnan(humidity) || isnan(temperatureC)) { Serial.println("Failed to read from DHT sensor!"); return; } Serial.print("Humidity: "); Serial.println(humidity); Serial.print("Temperature C: "); Serial.println(temperatureC); JsonDocument doc; doc["type"] = "items"; doc["collection"] = collection; doc["action"] = "create"; doc["data"]["humidity"] = humidity; doc["data"]["temperatureC"] = temperatureC; String message; serializeJson(doc, message); Serial.println("[EVENT] SEND DATA"); webSocket.sendTXT(message);}void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) { switch (type) { case WStype_DISCONNECTED: Serial.printf("[WSc] Disconnected!\n"); break; case WStype_CONNECTED: Serial.printf("[WSc] Connected to url: %s\n", payload); // send Auth to server when Connected authenticate(); break; case WStype_TEXT: Serial.printf("[WSc] get text: %s\n", payload); traitPayload(payload); break; }}void setup() { startTime = millis(); Serial.begin(115200); delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); webSocket.onEvent(webSocketEvent); // Setup Connection webSocket.begin(host, port, path);}void loop() { webSocket.loop(); currentTime = millis(); if (isReadyToSend == true &amp;amp;&amp;amp; currentTime - startTime &amp;gt;= delayTime) { sendData(); startTime = currentTime; // Reset start time for next execution }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we use JSON (JavaScript Object Notation) to communicate with Directus web dashboard.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Structuring:&lt;/strong&gt; JSON is a lightweight and human-readable format for exchanging data between devices. It uses key-value pairs to represent data like temperature and humidity readings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Example here&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonDocument doc; doc["type"] = "items"; doc["collection"] = collection; doc["action"] = "create"; doc["data"]["humidity"] = humidity; doc["data"]["temperatureC"] = temperatureC; String message; serializeJson(doc, message);webSocket.sendTXT(message);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Reference to how to communicate with Directus via Socket:&lt;/em&gt;&lt;a href="https://docs.directus.io/guides/real-time/getting-started/websockets-js.html"&gt;&lt;strong&gt;&lt;em&gt;Getting Started With WebSockets&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This code creates a JSON doc&lt;a href="https://docs.directus.io/guides/real-time/getting-started/websockets-js.html#getting-started-with-websockets"&gt;u&lt;/a&gt;ment (&lt;code&gt;doc&lt;/code&gt;) with key-value pairs:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, the JSON document is converted to a string (&lt;code&gt;message&lt;/code&gt;) and sent to Directus using the WebSocket connection.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;WebSocket Client and Connection:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;webSocket&lt;/code&gt; and &lt;code&gt;client&lt;/code&gt; objects are declared for WebSocket communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Authentication Function (&lt;/strong&gt;&lt;code&gt;authenticate&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This function sends an authentication message to the Directus server using the provided access token.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Payload Processing Function (&lt;/strong&gt;&lt;code&gt;traitPayload&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This function receives data (payload) from the Directus server and parses it as JSON.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It checks for different message types like "auth," "subscription," and "ping" and performs actions accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Subscription Function (&lt;/strong&gt;&lt;code&gt;subscribe&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This function sends a subscription message to Directus, requesting data for the specified collection (&lt;code&gt;collection&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pong Function (&lt;/strong&gt;&lt;code&gt;pong&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This function sends a "pong" message in response to "ping" messages from the server, keeping the connection alive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Sending Function (&lt;/strong&gt;&lt;code&gt;sendData&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This function reads temperature and humidity values from the DHT11 sensor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It checks for successful readings and avoids sending invalid data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It creates a JSON document with sensor data (humidity and temperature) and sends it to Directus using the &lt;code&gt;webSocket.sendTXT&lt;/code&gt; function.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;WebSocket Event Handler (&lt;/strong&gt;&lt;code&gt;webSocketEvent&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This function handles different events related to the WebSocket connection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setup Function (&lt;/strong&gt;&lt;code&gt;setup&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Initializes serial communication for debugging messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connects to the specified WiFi network using the provided credentials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The code establishes a WebSocket connection to the Directus server using &lt;code&gt;webSocket.begin(host, port, path)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;webSocketEvent&lt;/code&gt; function handles different events related to the connection:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Loop Function (&lt;/strong&gt;&lt;code&gt;loop&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This function continuously runs and checks the WebSocket connection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It also checks the &lt;code&gt;isReadyToSend&lt;/code&gt; flag and the elapsed time since the last transmission.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the flag is set and enough time has passed (&lt;code&gt;delayTime&lt;/code&gt;), it calls the &lt;code&gt;sendData&lt;/code&gt; function to send the latest sensor readings to Directus.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Overall Flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The ESP32 connects to WiFi and establishes a WebSocket connection to the Directus server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication with Directus is performed using the access token.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The ESP32 subscribes to the sensor data collection in Directus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The ESP32 periodically reads temperature and humidity from the DHT11 sensor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sensor readings are packaged as JSON data, and the ESP32 sends this data to Directus through the WebSocket connection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Directus receives and stores the sensor data in the specified collection.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Important Note:&lt;/strong&gt; If you encounter the &lt;code&gt;hexdump()&lt;/code&gt; error, navigate to the file &lt;code&gt;\libraries\SocketIoClient\SocketIoClient.cpp&lt;/code&gt; mentioned in the error message and locate the &lt;code&gt;hexdump()&lt;/code&gt; function. Then, comment it out.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1.2 Uploading and Running the Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before Uploading:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secure Directus Server:&lt;/strong&gt; Ensure your Directus server is up and running before connecting from the ESP32. A non-running server will prevent successful communication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify Connectivity:&lt;/strong&gt; Double-check that your ESP32 is properly connected to the same network as your Directus server. Network connectivity is crucial for data transmission.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Token:&lt;/strong&gt; Confirm that you've included a valid access token for authentication in your ESP32 code. Without a valid token, Directus will not allow access to send data.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Uploading and Observing Data Transmission:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Upload the Code:&lt;/strong&gt; Use the Arduino IDE to upload the code to your ESP32 board.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open Port Monitor:&lt;/strong&gt; After successful upload, open the serial monitor or terminal in your Arduino IDE. This will display logs and messages from the ESP32.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Review Logs:&lt;/strong&gt; Inspect the serial monitor output carefully. You should see messages indicating:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sAeqZhXk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1710522181245/716612dc-141b-461f-b93c-ada30d15388b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sAeqZhXk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1710522181245/716612dc-141b-461f-b93c-ada30d15388b.png" alt="" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Visualizing Your Sensor Data in Directus&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ready to See Your Data?&lt;/strong&gt; Now that you've uploaded the code and verified successful data transmission to Directus via WebSocket based on the logs, let's explore how to visualize your sensor data in the dashboard and create graphs (timelines) for clear representation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessing Your Data:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Head to Directus Dashboard:&lt;/strong&gt; Open your Directus dashboard in a web browser and log in with your credentials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Locate Your Collection:&lt;/strong&gt; Navigate to the collection you specifically created for the sensor data (e.g., "dht_sensor").&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Behold Your Data!:&lt;/strong&gt; You should now see a list of entries in the collection, each representing a data point sent from your ESP32. The data will be displayed in a table format by default.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2.1 Visualizing Time Series Data&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To visualize the data as a &lt;strong&gt;time series graph&lt;/strong&gt; , as there are a couple of steps I let you watch this video to create it effortlessly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=TdYNmKdWgzU"&gt;https://www.youtube.com/watch?v=TdYNmKdWgzU&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's explain what we did, we chose the time series graph.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choosing the Chart Type:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We opted for a time series graph, which is ideal for visualizing data points over time. This allows you to observe trends and patterns in your sensor readings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Source:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collection:&lt;/strong&gt; We selected the specific collection in Directus where your sensor data is stored (e.g., "dht_sensor").&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Date Field:&lt;/strong&gt; Directus automatically creates a date field to record the creation time of each data entry. This field serves as the time reference for the graph.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value Field:&lt;/strong&gt; We identified the specific field within the collection that contains the sensor readings you want to visualize (e.g., "humidity").&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Aggregation(Group Aggregation/Group Precision):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Concept:&lt;/strong&gt; Aggregation refers to combining multiple data points into a single value. This is often achieved using functions like SUM, COUNT, and AVG.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Our Choice:&lt;/strong&gt; We chose the AVERAGE aggregation to calculate the average value (e.g., average humidity) within a specific time interval.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Group Precision:&lt;/strong&gt; We opted for "Second" as our group precision. This means the average will be calculated for each second of data received. You can adjust this based on your data collection frequency (e.g., per minute or hour).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Additional Considerations:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Directus offers various aggregation functions and group precision options. Explore these options to customize visualizations based on your specific needs. While we focused on basic configurations here, advanced data manipulation and visualization tools can be integrated with Directus for in-depth analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Expanding Your Sensor Network&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Remember, these steps can be adapted for data from other sensors. Just ensure you create the appropriate collection with relevant fields in Directus to accommodate your specific sensor. and edit the socket code to send the correct data in the correct fields&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Congratulations! You've successfully connected your ESP32 to the web world and established a real-time data pipeline to Directus. The provided code effectively transmits sensor readings, leveraging WebSockets for efficient communication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-time Data Visualization:&lt;/strong&gt; By harnessing WebSockets, we achieved near-instantaneous data transmission, allowing you to visualize sensor readings with minimal delay in the Directus dashboard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility for Diverse Sensors:&lt;/strong&gt; This approach can be adapted to work with various sensors. Simply create the appropriate collection with relevant fields in Directus and modify the code to send the correct data accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Remember:&lt;/strong&gt; The provided &lt;a href="https://github.com/AyubTouba/esp32-directus"&gt;code snippet&lt;/a&gt; serves as a solid foundation. Feel free to experiment and customize it further to suit your specific project requirements and desired sensor data.&lt;/p&gt;

</description>
      <category>yaffalab</category>
      <category>node</category>
      <category>directus</category>
      <category>esp32</category>
    </item>
    <item>
      <title>ESP32/Arduino Sensor Data Visualization on Web Apps: A Beginner's Guide with Directus: Part 1</title>
      <dc:creator>Ayoub Touba</dc:creator>
      <pubDate>Sat, 16 Mar 2024 15:40:29 +0000</pubDate>
      <link>https://dev.to/youba/esp32arduino-sensor-data-visualization-on-web-apps-a-beginners-guide-with-directus-part-1-d8m</link>
      <guid>https://dev.to/youba/esp32arduino-sensor-data-visualization-on-web-apps-a-beginners-guide-with-directus-part-1-d8m</guid>
      <description>&lt;p&gt;&lt;strong&gt;Ever wanted to build a project that bridges the physical world with the web, but coding a web application seems daunting? This guide is for you! We'll embark on a journey to create a system that collects sensor data and displays it on a user-friendly web interface without writing any code for the web app itself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our secret weapon? &lt;a href="https://directus.io/"&gt;&lt;strong&gt;Directus&lt;/strong&gt;&lt;/a&gt;, a powerful open-source platform that acts as a bridge between your data and web applications. Directus takes care of storing and managing sensor readings, eliminating the need for complex back-end coding. It even automatically generates APIs for your data, making it accessible to your project with ease.&lt;/p&gt;

&lt;p&gt;This project is perfect for beginners interested in working with real-world sensors and visualizing data on the web. Let's dive in!&lt;/p&gt;

&lt;p&gt;To get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We'll use an &lt;strong&gt;ESP32&lt;/strong&gt; microcontroller to grab data from a sensor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The sensor, in this case, will be a &lt;strong&gt;DHT11&lt;/strong&gt; , measuring both temperature and humidity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nodejs&lt;/strong&gt; ( We'll talk about it later)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you'll need:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ESP32 development board&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DHT11 sensor&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Breadboard and jumper wires&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's embark on this journey!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Building the Circuit&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First, we need to build the circuit that connects your ESP32 to the DHT11 sensor. Here's what you'll do:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7SAHuG8k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1710332963738/530dfaf2-56af-4d56-8f8c-1a6613fb3f82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7SAHuG8k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1710332963738/530dfaf2-56af-4d56-8f8c-1a6613fb3f82.png" alt="" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1.2 Coding part&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that you have your ESP32 circuit built, it's time to write the code that will interact with the sensor and verify its functionality. This code will be uploaded to your ESP32 board.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's a breakdown of the code and its explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Libraries and Pin Definition:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include "DHT.h"#define TYPE DHT11 int sensePin = 2;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;#include "DHT.h"&lt;/code&gt;: This line includes the DHT library, which provides functions for communicating with DHT sensors like the DHT11.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;#define TYPE DHT11&lt;/code&gt;: This line defines the type of sensor you're using. In this case, we're specifying DHT11.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;int sensePin = 2;&lt;/code&gt;: This line declares a variable named &lt;code&gt;sensePin&lt;/code&gt; and assigns it the value &lt;code&gt;2&lt;/code&gt;. This variable stores the pin number on your ESP32 that is connected to the data pin of the DHT11 sensor. You might need to adjust this value depending on your specific circuit wiring.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Object Creation and Setup:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DHT HT(sensePin, TYPE); void setup() { Serial.begin(9600); HT.begin(); }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;DHT HT(sensePin, TYPE);&lt;/code&gt;: This line creates an object named &lt;code&gt;HT&lt;/code&gt; of type &lt;code&gt;DHT&lt;/code&gt;. It provides methods to interact with the sensor connected to the &lt;code&gt;sensePin&lt;/code&gt;. We're passing the previously defined &lt;code&gt;sensePin&lt;/code&gt; variable and the sensor type (&lt;code&gt;DHT11&lt;/code&gt;) to the constructor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;void setup()&lt;/code&gt;: This function runs once when the ESP32 starts up. Inside the setup function:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Reading Sensor Data and Printing to Serial Monitor:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void loop() { humidity = HT.readHumidity(); tempC = HT.readTemperature(); Serial.print("Humidity: "); Serial.println(humidity); Serial.print("Temperature C: "); Serial.println(tempC); delay(setTime); }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;void loop()&lt;/code&gt;: This function runs repeatedly after the &lt;code&gt;setup()&lt;/code&gt; function finishes. This is where the actual sensor data reading and processing happen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You find the code here: &lt;a href="https://github.com/AyubTouba/esp32-directus"&gt;esp32-directus&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2.Setting Up the Web Environment (Directus)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that you've verified your ESP32 circuit and sensor functionality, let's prepare the web environment to receive and visualize that data! Here, we'll leverage the power of &lt;strong&gt;Directus&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Directus?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Directus is an open-source data platform that acts as a bridge between your databases and web applications. It offers a user-friendly interface to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Store and Manage Data:&lt;/strong&gt; Directus eliminates the need for complex back-end coding. It allows you to create data models (like tables) and manage sensor readings efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build APIs in Minutes:&lt;/strong&gt; Directus automatically generates RESTful APIs for your data, making it accessible to your ESP32 code or any web application for seamless data exchange. moreover, it provides a socket connection (that we will use in our project to send the data)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Beautiful User Interface:&lt;/strong&gt; Directus provides a clean and intuitive web interface for users to view, edit, and even filter sensor data. Imagine viewing real-time temperature and humidity readings from your web browser!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In essence, Directus acts as the central hub for your sensor data, streamlining the process of storing, managing, and ultimately visualizing it on a web application.&lt;/p&gt;

&lt;p&gt;Here's a breakdown of how we'll use Directus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Installation:&lt;/strong&gt; We'll install Directus using Node.js, a popular tool for building web applications. Don't worry if you haven't used Node.js before - we'll walk you through the simple installation process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Project Creation:&lt;/strong&gt; We'll create a new Directus project specifically for your sensor data. Think of it as a dedicated space within Directus to manage data from your ESP32.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collection:&lt;/strong&gt; We'll define a data table within your Directus project. This table will have columns to store the sensor readings (humidity and temperature) received from your ESP32.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2.1 Setting Up the Environment (Node.js)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To install Directus, we need Node.js on our computer. It's a free and easy download. Here's how to get it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Head over to the official Node.js website: &lt;a href="https://nodejs.org/en"&gt;https://nodejs.org/en&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Download the installer suitable for your operating system (Windows, Mac, or Linux).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the downloaded installer and follow the on-screen instructions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once Node.js is installed, you can verify it by opening a command prompt ( &lt;strong&gt;Command Prompt&lt;/strong&gt; on Windows, &lt;strong&gt;Terminal&lt;/strong&gt; on Mac/Linux) and typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should display the installed Node.js version. Now you're ready to use Node.js for setting up Directus!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.2 Install Directus: Your Data Management Hub&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that you have Node.js set up, it's time to install Directus! Think of Directus as a central hub where all your sensor data will be stored and organized. Here's how to install it with ease:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Open your Command Prompt (Windows) or Terminal (Mac/Linux):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You'll use the command prompt to interact with Node.js and install Directus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Navigate to your project folder (optional):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're working within a specific folder for this project, use the &lt;code&gt;cd&lt;/code&gt; command to navigate to that directory. For example, if your project folder is named "web_project", you'd type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd web_project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Run the installation command:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the magic spell (command) to install Directus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init directus-project@latest &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Replace&lt;/strong&gt; &lt;code&gt;&amp;lt;project-name&amp;gt;&lt;/code&gt; with your desired name for this project. For instance, you could name it "sensor_app". So, the complete command would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init directus-project@latest sensor_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Hit Enter!&lt;/strong&gt; This command will download and install all the necessary files for Directus within your project folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Follow the interactive setup:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you run the installation command, Directus will ask you a few questions to configure your project. Here's what to expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Choose your database client:&lt;/strong&gt; Select "SQLite" as it doesn't require separate installation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database File Path:&lt;/strong&gt; Press Enter to accept the default path within your project folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create your first admin user:&lt;/strong&gt; Enter a valid email address&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enter your password:&lt;/strong&gt; Create a password for your Directus admin account.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;That's it!&lt;/strong&gt; Directus is now installed and ready to be configured. We'll explore setting up your Directus project and creating a data table for your sensor readings in the next steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i8nTqs2K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1710514330882/373cf1eb-276b-4b20-9477-f11d564a2a7c.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i8nTqs2K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1710514330882/373cf1eb-276b-4b20-9477-f11d564a2a7c.gif" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IP Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;we need to configure Directus to receive data from your ESP32. Here's how:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Find your IP address:&lt;/strong&gt; Open a command prompt and type &lt;code&gt;ipconfig&lt;/code&gt; (Windows) or &lt;code&gt;ifconfig&lt;/code&gt; (Linux). Locate the "IPv4 Address" section and copy the IP address displayed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modify the&lt;/strong&gt; &lt;code&gt;.env&lt;/code&gt; file: In your project folder, locate a file named ".env". Open it with a text editor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Change the HOST:&lt;/strong&gt; Find the line that reads &lt;code&gt;HOST="0.0.0.0"&lt;/code&gt; and replace it with &lt;code&gt;HOST="&amp;lt;YOUR_IP&amp;gt;"&lt;/code&gt;. Replace "" with the actual IP address you copied in the previous step.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add new parameter:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Save the changes.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Start the Directus application:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Navigate back to your project folder in the command prompt and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx directus start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start the Directus application. You can now access the Directus interface in your web browser by visiting &lt;code&gt;http://&amp;lt;YOUR_IP&amp;gt;:8055&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Setting Up Data Collection and Users&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that Directus is installed and running, let's configure it to manage your sensor data:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.1 Create a Collection (Table)&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create Collection:&lt;/strong&gt; Click on "Create Collection" in the Directus interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name the Collection:&lt;/strong&gt; In the pop-up window, enter a name for your collection. Let's call it "dht_sensor". This will be the table where your sensor readings (humidity and temperature) will be stored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Define Fields:&lt;/strong&gt; Click "Next" and select &lt;strong&gt;created_at&lt;/strong&gt; and let other optional fields untouched for now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add Fields for Sensor Data:&lt;/strong&gt; Click "Add Field". Choose "Input" for the field &amp;amp; Float as the type.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; You can refer to the provided video for a visual reference on these steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=eykeYjh33fs"&gt;https://www.youtube.com/watch?v=eykeYjh33fs&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.2 Create a User&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While you can use your existing login to create the collection, creating a dedicated user for your ESP32 offers some benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security:&lt;/strong&gt; It keeps data originating from the ESP32 separate from your admin account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Control:&lt;/strong&gt; You can restrict this user's access to specific functionalities in the future (advanced topic).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;To create a user:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Navigate to Users:&lt;/strong&gt; Click on the "Users" icon (second button on the menu bar).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a User:&lt;/strong&gt; Click the "Create Item" button (top right corner).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fill User Details:&lt;/strong&gt; Enter a name, email address, and a strong password for this user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assign Role:&lt;/strong&gt; Scroll down and select the "Administrator" role.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generate an API Token:&lt;/strong&gt; Click on "Generate Token" and save the generated token securely. You'll need this token in your ESP32 code to send data to Directus.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Congratulations!&lt;/strong&gt; You've successfully set up Directus to store your sensor data. In the next article, we'll explore how to send data from your ESP32 to this Directus application and visualize the readings in charts!&lt;/p&gt;

</description>
      <category>yaffalab</category>
      <category>node</category>
      <category>directus</category>
      <category>esp32</category>
    </item>
    <item>
      <title>Understanding Serial Ports: Lamp Control via Web App and Serial Communication</title>
      <dc:creator>Ayoub Touba</dc:creator>
      <pubDate>Wed, 21 Feb 2024 11:00:15 +0000</pubDate>
      <link>https://dev.to/youba/understanding-serial-ports-lamp-control-via-web-app-and-serial-communication-55ml</link>
      <guid>https://dev.to/youba/understanding-serial-ports-lamp-control-via-web-app-and-serial-communication-55ml</guid>
      <description>&lt;p&gt;Are you interested in &lt;strong&gt;connecting Arduino boards (or other microcontrollers) to the web&lt;/strong&gt; to create interactive projects? If so, this project is for you! We'll guide you through the process of building a web-controlled lamp, showcasing the power of serial communication and laying the foundation for further &lt;a href="http://exploration.ly"&gt;exploration&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Unleashing the Power of Serial Ports:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine a bridge connecting the digital realm of your computer to the tangible world of sensors and actuators. That's what a serial port does, allowing data to flow bi-directionally, one bit at a time. This project hinges on this simple yet powerful technology.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hardware and Software:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Arduino Board:&lt;/strong&gt; Any Arduino board with a USB port will do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RGB LED:&lt;/strong&gt; A common component to add color to your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Jumper Wires:&lt;/strong&gt; Connect various components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Breadboard:&lt;/strong&gt; Simplifies prototyping and wiring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node.js and npm:&lt;/strong&gt; Used for creating the web server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Serial Port Monitor (optional):&lt;/strong&gt; For initial testing and debugging.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Building the Lamp Circuit:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t7gN5c00--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1708440623879/420a8503-7236-4f75-9b7a-cf793499cb4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t7gN5c00--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1708440623879/420a8503-7236-4f75-9b7a-cf793499cb4b.png" alt="" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before the code comes to life, we need to assemble the hardware. Gather your Arduino board, an RGB LED, resistors, and some jumper wires. Connect the components as shown in the diagram, powering the LED from the Arduino and controlling its individual red, green, and blue channels with separate pins. (red to Pin 3, green to Pin 5, and blue to Pin 6)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Crafting the Code Symphony:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, let's orchestrate the communication between our devices. The Arduino code listens for incoming data through the serial port, parses it as color information, and then uses that information to adjust the LED's brightness accordingly. The Node.js server acts as the middleman, receiving color selections from the web app and relaying them to the Arduino. Finally, the React.js frontend provides a user-friendly interface where you can choose your desired lamp color.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delving into the Code Details:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arduino Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const byte PIN_LED_R = 3;const byte PIN_LED_G = 5;const byte PIN_LED_B = 6;const byte dt = 1000;void setup() { Serial.begin(9600); pinMode(PIN_LED_R, OUTPUT); pinMode(PIN_LED_G, OUTPUT); pinMode(PIN_LED_B, OUTPUT);}void loop() { // Check if there is serial data available if (Serial.available() &amp;gt; 0) { // Read the incoming data String data = Serial.readStringUntil('\\n'); Serial.println(data); Serial.print("Getting Color : "); Serial.println(data); // Parse the data and extract RGB values parseAndDisplayColor(data); } delay(dt);}void displayColor(byte r, byte g, byte b) { analogWrite(PIN_LED_R, r); analogWrite(PIN_LED_G, g); analogWrite(PIN_LED_B, b);}void parseAndDisplayColor(String data) { if (data.length() == 7 &amp;amp;&amp;amp; data[0] == '#') { // Extract hexadecimal values for R, G, and B long hexValue = strtol(data.substring(1).c_str(), NULL, 16); int r = (hexValue &amp;gt;&amp;gt; 16) &amp;amp; 0xFF; int g = (hexValue &amp;gt;&amp;gt; 8) &amp;amp; 0xFF; int b = hexValue &amp;amp; 0xFF; // Display the color displayColor(r, g, b); }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the &lt;code&gt;void loop()&lt;/code&gt; part of the Arduino code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Serial Data Reception&lt;/strong&gt; &lt;code&gt;if (Serial.available() &amp;gt; 0) { ...}&lt;/code&gt;This line checks if there is any data available to be read from the serial port. If there is, it proceeds to read the incoming data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reading:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parsing and Displaying Color:&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, let's take a look at the helper functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void displayColor(byte r, byte g, byte b) { analogWrite(PIN_LED_R, r); analogWrite(PIN_LED_G, g); analogWrite(PIN_LED_B, b);}void parseAndDisplayColor(String data) { if (data.length() == 7 &amp;amp;&amp;amp; data[0] == '#') { // Extract hexadecimal values for R, G, and B long hexValue = strtol(data.substring(1).c_str(), NULL, 16); int r = (hexValue &amp;gt;&amp;gt; 16) &amp;amp; 0xFF; int g = (hexValue &amp;gt;&amp;gt; 8) &amp;amp; 0xFF; int b = hexValue &amp;amp; 0xFF; // Display the color displayColor(r, g, b); }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;displayColor&lt;/code&gt; Function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;analogWrite(PIN_LED_R, r);&lt;/code&gt;: Sets the intensity of the red LED based on the value of &lt;code&gt;r&lt;/code&gt;. Similar statements apply to the green and blue LEDs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;parseAndDisplayColor&lt;/code&gt; Function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Check if the received data has a length of 7 characters and starts with the '#' character, ensuring it is a valid color representation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extracts the hexadecimal value from the color data (excluding the '#').&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Separates the hexadecimal value into individual R, G, and B components.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, the &lt;code&gt;void loop()&lt;/code&gt; continuously checks for incoming serial data, reads and prints the data, then parses and displays the color on the RGB LED based on the received information. The delay between iterations helps control the loop's execution speed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js Server Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require("express");const { SerialPort } = require("serialport");const { ReadlineParser } = require("@serialport/parser-readline");const cors = require("cors");const app = express();const port = 3001;const portName = "COM3"; // Change 'COM3' to your Arduino portconst portNumber = 9600;const arduinoPort = new SerialPort({ path: portName, baudRate: portNumber });const parser = arduinoPort.pipe(new ReadlineParser({ delimiter: "\\r\\n" }));app.use(express.json());app.use(cors());app.post("/sendData", (req, res) =&amp;gt; { const { data } = req.body; console.log(`Sending data to Arduino: ${data}`); arduinoPort.write(data); res.send("Data sent to Arduino");});app.listen(port, () =&amp;gt; { console.log(`Server is running on &amp;lt;http://localhost&amp;gt;:${port}`);});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;const arduinoPort = new SerialPort({ path: portName, baudRate: portNumber });&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SerialPort&lt;/code&gt; class from the &lt;code&gt;serialport&lt;/code&gt; library is used to create an instance called &lt;code&gt;arduinoPort&lt;/code&gt;. This instance represents the communication channel between the Node.js server and the connected Arduino. The parameters passed to the &lt;code&gt;SerialPort&lt;/code&gt; constructor include the path to the Arduino's serial port (&lt;code&gt;portName&lt;/code&gt;) and the baud rate (&lt;code&gt;portNumber&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const parser = arduinoPort.pipe(new ReadlineParser({ delimiter: "\\r\\n" }));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ReadlineParser&lt;/code&gt; is created and attached to the &lt;code&gt;arduinoPort&lt;/code&gt;. This parser is essential for handling the incoming data as lines, which is crucial when dealing with data sent over serial communication. The &lt;code&gt;delimiter&lt;/code&gt; option specifies the line ending character(s) that indicate the end of a message.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API Endpoint for Sending Data:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;React.js Frontend Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";import "./App.css";import Lamp from "./Lamp";import axios from "axios";function App() { const [lampColor, setLampColor] = useState("#f1c40f"); const handleColorChange = (e) =&amp;gt; { setLampColor(e.target.value); sendDataToArduino(); }; const sendDataToArduino = () =&amp;gt; { axios .post("&amp;lt;http://localhost:3001/sendData&amp;gt;", { data: lampColor + "\\n" }) .then((response) =&amp;gt; { console.log(response.data); }) .catch((error) =&amp;gt; { console.error("Error sending data to Arduino:", error); }); }; return ( &amp;lt;div className="flex h-screen items-center justify-center"&amp;gt; &amp;lt;Lamp color={lampColor} /&amp;gt; &amp;lt;div className="ml-4"&amp;gt; &amp;lt;label htmlFor="colorInput" className="text-gray-700"&amp;gt; Lamp Color: &amp;lt;/label&amp;gt; &amp;lt;input type="color" id="colorInput" value={lampColor} onChange={handleColorChange} className="ml-2" /&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; );}export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A color picker allows users to select colors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;handleColorChange()&lt;/code&gt; updates the selected color and triggers data transmission.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;axios.post()&lt;/code&gt; sends color data to the Node.js server.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Dive into the Project Code:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This project code is available on GitHub: &lt;a href="https://github.com/AyubTouba/serialport-communication"&gt;serialport-communication&lt;/a&gt; The repository contains all the necessary files and a detailed readme explaining the setup, code, and usage instructions. Feel free to explore and customize the code further based on your preferences.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Components Explained:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Serial Communication:&lt;/strong&gt; This project hinges on serial communication, a method of transmitting data one bit at a time. It acts as the bridge between your computer and the Arduino, enabling control over the lamp.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Libraries and Frameworks:&lt;/strong&gt; The code leverages powerful libraries and frameworks to simplify development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Parsing:&lt;/strong&gt; The Node.js server plays a crucial role in parsing the incoming color data from the web app. It extracts the relevant information and transmits it to the Arduino in a compatible format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Interaction:&lt;/strong&gt; The React.js frontend provides a seamless user experience. You can choose your desired lamp color using a convenient color picker, and the changes are instantly reflected in the real world.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Beyond the Basics:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This project serves as a springboard for your journey into the exciting world of interactive electronics. Feel free to experiment and expand upon this foundation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sensory Integration:&lt;/strong&gt; Incorporate sensors to gather environmental data (e.g., temperature, light levels) and adjust the lamp color accordingly, creating an interactive and responsive environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-LED Control:&lt;/strong&gt; Connect and control multiple LEDs to create dynamic lighting effects, transforming your space with vibrant colors and animations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't hesitate to explore and build upon this project! With your imagination and ingenuity, you can unlock endless possibilities in the realm of interactive electronics. So, grab your Arduino, delve into the code, and start creating!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember:&lt;/strong&gt; The GitHub repository mentioned above holds all the essential resources to get you started. Embrace the learning process, experiment, and have fun!&lt;/p&gt;

</description>
      <category>esp32</category>
      <category>node</category>
      <category>arduino</category>
      <category>react</category>
    </item>
    <item>
      <title>Unlocking Algorithmic Efficiency with Big O Notation</title>
      <dc:creator>Ayoub Touba</dc:creator>
      <pubDate>Fri, 16 Feb 2024 17:52:52 +0000</pubDate>
      <link>https://dev.to/youba/unlocking-algorithmic-efficiency-with-big-o-notation-3mih</link>
      <guid>https://dev.to/youba/unlocking-algorithmic-efficiency-with-big-o-notation-3mih</guid>
      <description>&lt;p&gt;Remember the last time you searched for something online? Whether it was finding the perfect recipe, booking a dream vacation, or simply catching up with friends on social media, algorithms silently powered your experience. But have you ever wondered how these algorithms navigate mountains of data so swiftly? The answer lies in a fascinating tool called Big O notation, and understanding it can be your secret weapon to writing efficient and impressive code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Decoding Big O: Your Map to Algorithmic Efficiency&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine yourself lost in a vast library, desperately searching for a specific book. Would you blindly check every shelf, page by page? Or would you employ a more strategic approach, perhaps utilizing the alphabetical order or genre sections? Big O notation works similarly, analyzing algorithms like resourceful explorers traversing "data landscapes." It estimates the &lt;strong&gt;worst-case time complexity&lt;/strong&gt; how long an algorithm might take to complete a task as the amount of data (books in the library) grows infinitely. By focusing on the key factor impacting execution time, it provides a valuable roadmap for choosing the right algorithm for the job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Understanding Big O Matters:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the digital age, where milliseconds can make a difference, Big O empowers you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be an algorithm aficionado:&lt;/strong&gt; Select the most efficient algorithm for your task, akin to picking the fastest route through the library. Imagine comparing linear search (checking every shelf) to binary search (repeatedly halving the search space) for a specific book Big O helps you make the optimal choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Predict future performance:&lt;/strong&gt; Anticipate how algorithms will handle data growth. Think of preparing the library for an influx of new books. By understanding an algorithm's Big O, you can ensure it stays efficient even as data volumes increase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Become an optimization wizard:&lt;/strong&gt; Identify and fix bottlenecks that slow down algorithms, just like streamlining library organization for quicker searches. Big O helps you pinpoint areas for improvement, making your code run smoother and faster.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Exploring the Big O Spectrum: From Constant to Complex&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, let's embark on a journey through different Big O types, each representing a distinct level of efficiency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;O(1) - Constant Time:&lt;/strong&gt; Imagine finding the book instantly because you know its exact location, like remembering the Dewey Decimal code. This algorithm's execution time remains constant regardless of data size, making it incredibly efficient for specific lookups.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function findBookByCode(library, code) { // Access book directly using unique code (O(1)) return library[code];}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;O(n) - Linear Time:&lt;/strong&gt; Think of checking each book on a shelf one by one until you find the one you're looking for. This algorithm's execution time grows linearly with the number of books, suitable for smaller datasets but potentially slow for massive libraries.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function findBookByTitleLinear(library, title) { for (const book of library) { if (book.title === title) { return book; } } return null; // O(n)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;O(log n) - Logarithmic Time:&lt;/strong&gt; Imagine repeatedly dividing the library in half based on alphabetical order until you find the book. This algorithm's execution time grows logarithmically, meaning it significantly outperforms linear search for vast data volumes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function findBookByTitleBinary(library, title) { let low = 0; let high = library.length - 1; while (low &amp;lt;= high) { const mid = Math.floor((low + high) / 2); if (library[mid].title === title) { return library[mid]; } else if (library[mid].title &amp;lt; title) { low = mid + 1; } else { high = mid - 1; } } return null; // O(log n)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;O(n^2) - Quadratic Time:&lt;/strong&gt; Imagine checking every possible pair of books in the library to find two that match a certain criteria. This algorithm's execution time explodes quadratically with the number of books, becoming inefficient for large datasets.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function findMatchingBookPairs(library, criteria) { for (let i = 0; i &amp;lt; library.length; i++) { for (let j = i + 1; j &amp;lt; library.length; j++) { if (library[i].matchesCriteria(criteria) &amp;amp;&amp;amp; library[j].matchesCriteria(criteria)) { // Process matching pair
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Visualizing and Comparing Performance with YubaPerf (Node.js)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While Big O notation provides a theoretical understanding of an algorithm's efficiency, sometimes you need a more concrete and visual representation to compare different algorithms or track performance changes in your Node.js code. This is where libraries like &lt;a href="https://github.com/AyubTouba/yubaperf"&gt;YubaPerf&lt;/a&gt; come in handy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YubaPerf in Action:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AyubTouba/yubaperf"&gt;YubaPerf&lt;/a&gt;, is a &lt;strong&gt;Node.js&lt;/strong&gt; library specifically designed to assist you in measuring and comparing the performance of code and algorithms. It offers several key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Function Comparison and Charting:&lt;/strong&gt; Directly compare the performance of multiple functions with different arguments, generating an interactive chart to visualize the results. This makes it easy to identify performance bottlenecks and select the most efficient algorithm for your task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Argument Support:&lt;/strong&gt; Pass a single function with multiple arguments to measure its performance under various input conditions. This helps you gain a comprehensive understanding of how your code behaves under different loads.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose you're implementing two sorting algorithms in Node.js: bubble sort and merge sort. You can use YubaPerf to compare their performance on different array sizes and create an interactive chart to visualize the results. This would help you determine which algorithm is more efficient for your specific use case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beyond the Basics:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While YubaPerf excels at performance measurement and comparison, it can also be used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benchmarking:&lt;/strong&gt; Compare the performance of your code against existing libraries or frameworks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Educational Tool:&lt;/strong&gt; Visualize the impact of algorithmic complexity on performance, making Big O notation more concrete and intuitive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Getting Started with YubaPerf:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install YubaPerf using npm or yarn:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Import the necessary functions from YubaPerf in your Node.js code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;perfom.setfuncsToCompareSync&lt;/code&gt; to specify the functions and arguments you want to compare.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call &lt;code&gt;perfom.generateChart()&lt;/code&gt; to generate an interactive chart visualizing the performance comparison.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(Optional) Use &lt;code&gt;perf.start&lt;/code&gt; and &lt;code&gt;perf.end&lt;/code&gt; to measure the execution time of specific code sections within a function for detailed profiling.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Perfom } from "@youba/yubaperf";function addUpToFirst(n) { var total = 0; for (var i = 0; i &amp;lt;= n; i++) { total += i; } return total;}function addUpToSecond(n) { return (n * (n + 1)) / 2;}let args = [1, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,];Perfom.setfuncsToCompareSync([addUpToFirst, addUpToSecond], args);Perfom.generateChart(); // The chart created in the perf //folder in the root of the project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Big O notation unlocks a hidden superpower: the ability to write efficient and scalable code. By understanding how algorithms behave with increasing data loads, you can make informed decisions, avoid performance bottlenecks, and create applications that excel in the data-driven world. Start your journey into the fascinating realm of Big O today, and unleash the full potential of your code!&lt;/p&gt;

</description>
      <category>bigonotation</category>
      <category>softwareengineer</category>
      <category>node</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Finding the Sweet Spot: Why Knowing Business Stuff Makes You a Better Developer</title>
      <dc:creator>Ayoub Touba</dc:creator>
      <pubDate>Sat, 10 Feb 2024 18:15:53 +0000</pubDate>
      <link>https://dev.to/youba/finding-the-sweet-spot-why-knowing-business-stuff-makes-you-a-better-developer-5938</link>
      <guid>https://dev.to/youba/finding-the-sweet-spot-why-knowing-business-stuff-makes-you-a-better-developer-5938</guid>
      <description>&lt;p&gt;You know how we're constantly immersed in intricate lines of code, ensuring seamless functionality? Well, here's the scoop: it's crucial to occasionally step away from our coding realms and delve into the intricacies of the business world. Trust me, it's not merely about earning brownie points with the higher-ups; it's about elevating our professional trajectories and imbuing our code with genuine significance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the Bigger Picture:
&lt;/h3&gt;

&lt;p&gt;Envision this: you're architecting an incredible app, but do you truly comprehend the raison d'tre behind its creation? Taking a minute to understand what the boss and the business experts want can make a huge difference. It's like knowing the game plan before you hit the field. Understanding the big picture helps us write code that's not just fancy but also helps the business win.&lt;/p&gt;

&lt;h3&gt;
  
  
  Communicating in Layman's Terms:
&lt;/h3&gt;

&lt;p&gt;We're great at coding, but sometimes our non-techy friends get lost in our tech-talk. Learning to speak their language is like adding a secret weapon to our arsenal. When we can explain our brilliant code in a way that makes sense to everyone, it's like turning on a magic switch. Suddenly, everyone gets it, and the project sails smoothly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making Code Count for Something:
&lt;/h3&gt;

&lt;p&gt;Ever sensed that your code is a formidable force lacking direction? By forging connections with the business side, we breathe purpose into our code. Rather than merely solving technical puzzles, we contribute directly to business growth be it enhancing revenue or fostering customer satisfaction. Our code transforms into a powerhouse with a mission and impact!&lt;/p&gt;

&lt;h3&gt;
  
  
  Advancing Your Career:
&lt;/h3&gt;

&lt;p&gt;We all want to climb that career ladder, right? Well, being a coding maestro is just the first step. Employers drool over developers who get the business side too. It's like having a double skill set. Suddenly, you're not just a coder; you emerge as a genuine developer who comprehends how to not only write stellar code but also catalyze business prosperity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making Smart Choices:
&lt;/h3&gt;

&lt;p&gt;In our coding adventures, we face choices like champions facing challenges. Knowing the business goals helps us make champion-level decisions. We can pick the features that matter most, use our coding skills wisely, and be the champions who save the day without breaking a sweat.&lt;/p&gt;

&lt;p&gt;So, dear readers, it's time to put on our business hats alongside our coding caps. Balancing both worlds isn't just about meetings and reports; it's about making our code count and making us champions in the tech world. Let's not just write awesome code; let's write code that changes the game for the business too!&lt;/p&gt;

</description>
      <category>yaffalab</category>
      <category>career</category>
      <category>softwareenginner</category>
      <category>bussiness</category>
    </item>
    <item>
      <title>Unlock the Power of Project Narratives: Why Documenting Your Code Journey Matters</title>
      <dc:creator>Ayoub Touba</dc:creator>
      <pubDate>Fri, 09 Feb 2024 21:02:44 +0000</pubDate>
      <link>https://dev.to/youba/unlock-the-power-of-project-narratives-why-documenting-your-code-journey-matters-hnp</link>
      <guid>https://dev.to/youba/unlock-the-power-of-project-narratives-why-documenting-your-code-journey-matters-hnp</guid>
      <description>&lt;p&gt;After tackling numerous projects, both professionally and personally, one valuable lesson has stood out documenting your code and project journey is just as crucial as writing the code itself. It's tempting to think that every detail will be etched in memory, but over time, the intricacies tend to fade away.&lt;/p&gt;

&lt;p&gt;Acknowledging that starting a documentation habit can be daunting, especially if it's not part of your routine, is the first step. The task of creating a comprehensive documentation often feels overwhelming, leaving us unsure of where to even begin. To overcome this challenge, here's a practical solution: develop a simple template that requires filling in the details. Additionally, consider using tools like ChatGPT to generate relevant questions, streamlining the documentation process.&lt;/p&gt;

&lt;p&gt;Imagine a template like this:&lt;/p&gt;

&lt;p&gt;[PROJECT]-[DATE]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="//e.g.,%20mastering%20SSH%20to%20deploy%20the%20app:%20ssh%20_@_*"&gt;Unfamiliar tasks undertaken&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[Impact of client requests on code, leading to shifts in our development strategy]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Archiving the latest client discussion highlights&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structured approach not only ensures consistency but also prompts reflection on specific aspects of your work. It becomes a valuable resource, especially when revisiting projects or onboarding new team members.&lt;/p&gt;

&lt;p&gt;Conclusion:&lt;/p&gt;

&lt;p&gt;In summary, taking the time to document your code journey and project history is a small investment that yields significant returns in the long run. Whether you're a seasoned professional or just starting out, the benefits of maintaining a well-documented log go beyond personal convenience. It fosters collaboration, aids in troubleshooting, and provides a comprehensive overview of the project's evolution. So, don't procrastinate start logging your history today and empower yourself for a more efficient and informed coding future.&lt;/p&gt;

</description>
      <category>documentation</category>
      <category>career</category>
      <category>yaffalab</category>
      <category>advice</category>
    </item>
    <item>
      <title>Announcing Version 2.0 of nestjs-DbValidator</title>
      <dc:creator>Ayoub Touba</dc:creator>
      <pubDate>Fri, 09 Feb 2024 20:45:22 +0000</pubDate>
      <link>https://dev.to/youba/announcing-version-20-of-nestjs-dbvalidator-22ob</link>
      <guid>https://dev.to/youba/announcing-version-20-of-nestjs-dbvalidator-22ob</guid>
      <description>&lt;p&gt;We are excited to unveil version 2.0 of &lt;a href="https://github.com/AyubTouba/nestjs-dbvalidator"&gt;nestjs-DbValidator&lt;/a&gt;, a feature-packed module providing custom database validators using class-validator and typeorm for Nest.js applications. This latest release comes with an array of enhancements, new features, and bug fixes, making it even more versatile and compatible with the latest Nest.js versions.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's New in Version 2.0
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Custom Type Support&lt;/strong&gt; In version 2.0, we introduce the ability to customize the type of the column for validation. Now you can specify the type using the customType parameter, allowing for more flexibility in handling different data types.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@isExistDb({ table: 'user', column: 'firstName', customType: TYPECOLUMN.STRING })idcities: any;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Nest.js 9 and Above Compatibility&lt;/strong&gt; We are excited to announce that nestjs-DbValidator has been upgraded to support Nest.js version 9 and above. This ensures seamless integration with the latest features and improvements introduced in the Nest.js framework. Thanks to &lt;a href="https://github.com/DevDeNiro"&gt;@DevDeNiro&lt;/a&gt; for their significant contribution in the upgrade.&lt;/p&gt;

&lt;p&gt;To upgrade to version 2.0, simply update your package using the following command:&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Getting Started with Version 2.0&lt;/strong&gt;
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm update @youba/nestjs-dbvalidator# oryarn upgrade @youba/nestjs-dbvalidator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After updating, be sure to check the documentation for any additional configuration changes and new features introduced in this release.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Brief Review of nestjs-DbValidator
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;nestjs-DbValidator is a Nest.js module that simplifies database validation in your applications. It leverages the power of class-validator and typeorm to offer a seamless and intuitive way to validate data against your database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;isExistDb&lt;/code&gt; &lt;strong&gt;:&lt;/strong&gt; Checks if a value already exists in the specified table and column. &lt;code&gt;isUniqueDb&lt;/code&gt; &lt;strong&gt;:&lt;/strong&gt; Verifies if a value is unique within the specified table and column. &lt;code&gt;isLowerDb&lt;/code&gt; &lt;strong&gt;:&lt;/strong&gt; Validates if a value is lower, useful for scenarios such as checking client credits.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;isBiggerDb&lt;/code&gt; &lt;strong&gt;:&lt;/strong&gt; Validates if a value is bigger, suitable for cases like checking stock levels.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy Integration
&lt;/h3&gt;

&lt;p&gt;The library is easy to integrate into your Nest.js application. By adding a few lines of code, you can enhance the validation capabilities of your DTOs and entities.&lt;/p&gt;

&lt;p&gt;Version 2.0 Improvements Version 2.0 builds upon the success of the previous release by introducing custom-type support and ensuring compatibility with Nest.js 9 and above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Feel free to provide feedback, report issues, or contribute to the project on GitHub.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>node</category>
      <category>typeorm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Release new Library to measure &amp; compare your Code!!</title>
      <dc:creator>Ayoub Touba</dc:creator>
      <pubDate>Mon, 01 Nov 2021 10:38:58 +0000</pubDate>
      <link>https://dev.to/youba/release-new-library-to-measure-compare-your-code-1892</link>
      <guid>https://dev.to/youba/release-new-library-to-measure-compare-your-code-1892</guid>
      <description>&lt;p&gt;Hello Guys, I hope All of you doing well.&lt;/p&gt;

&lt;p&gt;Sometimes we want to measure our code to check how much time it took to work, Moreover, after improving the code we'd like to check if it works more efficiently than the older version, Or for academic purpose we want to compare algorithms to check the time complexity on a chart, For that reason I Present you &lt;strong&gt;YubaPerf&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How To install it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @youba/yubaperf
# OR
yarn add @youba/yubaperf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Measuring your code:
&lt;/h4&gt;

&lt;p&gt;To measure your code, you need to use these functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Perf.start("Algorithm1");
//The code you want to measure
Perf.end("Algorithm1");
console.log(perf.result("Algorithm1"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Comparing Sync functions:
&lt;/h4&gt;

&lt;p&gt;The concept here is to pass one or more than function with multiple args to measure and compare between them,&lt;/p&gt;

&lt;p&gt;You simply need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Perfom.setfuncsToCompareSync([addUpToFirst, addUpToSecond], args);
Perfom.generateChart(); // the chart located on perf/index.html file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Passing Array of functions &amp;amp; Another one for arguments .the arguments may be a simple Array like :&lt;br&gt;
&lt;code&gt;[1,10,1000,1000,122]&lt;/code&gt; Or dimensional one for Functions who has more than input like &lt;code&gt;[['yes',19],['yes',1900],['yes',19999]]&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Chart: &lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzl33uy7tyep05eas6aj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdzl33uy7tyep05eas6aj.png" alt="Chart" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The lib is on development,the next version will have more features like: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comparing async functions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setfuncsToCompareSync&lt;/code&gt; Return an object of the result &lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more information on the library you can check the repo &lt;a href="https://github.com/AyubTouba/yubaperf"&gt;HERE&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
