Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
July 05, 2025, 12:56:38 00:56


Login with username, password and session length


Pages: [1]
Print
Author Topic: HTML help  (Read 400 times)
0 Members and 1 Guest are viewing this topic.
Wizpic
Global Moderator
Hero Member
*****
Offline Offline

Posts: 1208

Thank You
-Given: 566
-Receive: 409



« on: June 20, 2025, 08:39:03 20:39 »

I've been playing with an ESP32 as a canbus reader, this create a server where I can log on to sing phone through web page I can see the Error's and RX counter, It's all working but now I've found a better lay out but not really fully understand HTML and after some tips/advise.
This is the working layout (old)
Code:
<html>
<head>
  <title>CAN TOOL</title>
</head>
<head>
     <style>
        div.relative {
  position: relative;
  margin-left:200px;
  }
    div.relative1 {
  position: relative;
  margin-left:0px;
  }
    div.relative2 {
  position: relative;
  margin-left:0px;
  }
      .button {
       
        background-color: blue;
        border: none;
        color: white;
        padding: 20px 34px;
        text-align: center;
        text-decoration: none;
        display: inline-block;
        font-size: 48px;
        margin: 4px 2px;
        cursor: pointer;
        border-radius: 15px;
      }
       body   {background-color:white}
    h1     {font-size: 36px; color:black; text-align:center; font-family:calibri}
    div.h1 {background-color:whites;}
    </style>
    <title>CAN TOOL</title>
</head>

<body>
 <style>
     table {
      border-collapse: collapse;
        width:100%;
        margin: 20px;
        margin-left:auto;
        margin-right:auto;
    }
    tr {
      border: 2px solid black;
      font-family: "Verdana", "Arial", sans-serif;
      font-size: 36px;
    }
    th {
      padding: 5px;
        background-color: #0043af;
        color: white;
      }
    td {
      height: 10px;
       padding: 3px 15px;
    }
    .tabledata {
      font-size: 36px;
      text-align: center;
      position: center;
      padding-left: 15px;
      padding-top: 15px;
      height:   60px;
      border-radius: 5px;
      color: #343a40;
      line-height: 60px;
      transition: all 200ms ease-in-out;
      fill:false
      background-color: #00AA00; //box colour
    }
      .bodytext {
      font-family: "Verdana", "Arial", sans-serif;
      font-size: 36px;
      text-align: left;
      font-weight: light;
      border-radius: 5px;
      display:inline;
    }
    .category {
      font-family: "Verdana", "Arial", sans-serif;
      font-weight: bold;
      font-size: 36px;
      line-height: 50px;
      padding: 20px 10px 0px 10px;
      color: #000000;
    }
    .container {
       text-align: center;
      max-width: 1800px;
      margin: 0 auto;
    }
     
    body   {background-color:white}
    h1     {font-size: 42px; color:black; text-align:center; font-family:calibri}
    div.h1 {background-color: whites;}
    h3     {font-size: 40px; color:black; text-align:center; font-family:calibri}
    div.h3 {background-color: whites;}
   
</style>
<body>
       
       <h1><div class="h1">CAN TOOL<br>ERROR COUNTER</div></h1>
     <main class="container" style="margin-top:10px">
      <table style="width:30%">
     
      <tr>
        <th colspan="1"><div class="heading">ERROR COUNTER</div></th>
         </tr>
      <tr>
        <td><div class="tabledata" id = "ERRORS"></div></td>
        </tr>
      </table>
      <main/>
        <h2 style="text-align:center;">You may get some small error count</h2>
       <h2 style="text-align:center;">But must remain less than 128</h2>
    <main class="container" style="margin-top:10px">
      <table style="width:30%">
     
      <tr>
        <th colspan="1"><div class="heading">RX COUNTER</div></th>
       
        </tr>
      <tr>
        <td><div class="tabledata" id = "RXCOUNTER"></div></td>
      </tr>
      <main/>
        <main class="container" style="margin-top:10px">
      <table style="width:30%">
      <tr>
      <th colspan="1"><div class="heading">ERROR FRAME</div></th>
      </tr>
      <tr>
        <td><div class="tabledata" id = "FRAMECOUNTER"></div></td>
      </tr>
     
      </table>
   
  </main>
<!-------------------------------------JavaScript--------------------------------------->
<script>
  InitWebSocket()
  function InitWebSocket()
  {
    websock = new WebSocket('ws://'+window.location.hostname+':81/');
    websock.onmessage=function(evt)
    {
       JSONobj = JSON.parse(evt.data);
       document.getElementById('ERRORS').innerHTML = JSONobj.ER;       
       document.getElementById('RXCOUNTER').innerHTML = JSONobj.RX;
       document.getElementById('FRAMECOUNTER').innerHTML = JSONobj.EER;
       document.getElementById('btn').innerHTML = JSONobj.LEDonoff;
    }
  }
  //-------------------------------------------------------------
     function button()
     {
        btn = 'LEDonoff=ON';
        if(document.getElementById('btn').innerHTML == 'RESET')
        {
          btn = 'LEDonoff=0';
        }
        websock.send(btn);
     }
  </script>
</html>
This is the new layout (new)
Code:
<html>
<head>
  <title>CAN TOOL</title>
</head>
<head>
<body bgcolor="#F2EDD1" onload="fLoad()" onkeydown="top.window.INFO_WINDOW.keyTest()" onbeforeunload="top.window.INFO_WINDOW.attachSomeEventsFirst()">

<p>
  <object id="HiResTimer1" classid="CLSID:F36F6847-D389-11D1-8968-006097AA579E">
  </object>
</p>






 <title>CAN TOOL</title>
 // <input type="hidden" name="ID" value="0">

 <table style="position: relative" align="center" border="2" cellpadding="1%" width="80%">
  <col width=50%>
  <col width=50%>
  <tr>
    <td id=TextCANActive>ERROR COUNTER</td>
    <td align="center">
      <input type="text" size="8" value="0" name="RXCOUNTER" MinValue = "0"
      style="text-align:right" FieldDescription="CAN Receive Counter" TextType="TextNoYesType" Corr="200">
    </td>
  </tr>
  <tr>
    <td id="RXCOUNTER">RX COUNTER</td>
    <td align="center">
      <input type="text" size="6" value="0" name="RXCOUNTER" MinValue = "0"
      style="text-align:right" FieldDescription="RXCOUNTER"  Corr="0.1">
    </td>
  </tr>
  <tr>
    <td id=TextSafetyLoad>ERROR FRAME</td>
    <td align="center">
      <input type="text" size="6" value="0" name="uiSafetyLoadKg" MinValue = "0"
      style="text-align:right" FieldDescription="Safety Load Kgs"  Corr="0.1">
    </td>
  </tr>
 
 
  </table>
<!-------------------------------------JavaScript--------------------------------------->
<script>
  InitWebSocket()
  function InitWebSocket()
  {
    websock = new WebSocket('ws://'+window.location.hostname+':81/');
    websock.onmessage=function(evt)
    {
       JSONobj = JSON.parse(evt.data);
       document.getElementById('ERRORS').innerHTML = JSONobj.ER;       
       document.getElementById('RXCOUNTER').innerHTML = JSONobj.RX;
       document.getElementById('FRAMECOUNTER').innerHTML = JSONobj.EER;
       document.getElementById('btn').innerHTML = JSONobj.LEDonoff;
    }
  }
  //-------------------------------------------------------------
     function button()
     {
        btn = 'LEDonoff=ON';
        if(document.getElementById('btn').innerHTML == 'RESET')
        {
          btn = 'LEDonoff=0';
        }
        websock.send(btn);
     }
  </script>







Below are the images of old and new laout.

to start as learning curve.
 I've been trying to get it to display the RX counter the the white box in the new layout next to the RX counter box but can't seem to get it to work it just shows  0 not fully understanding HTML.
So any advise tips would help.
I use W3Schools to display the lay out to see what it looks like.


 
Logged

When you think, "I can't do anymore. I need a break," that is the time to challenge yourself to keep going another five minutes. Those who persevere for even an extra five minutes will win in life..
mars01
V.I.P
Hero Member
*****
Offline Offline

Posts: 543

Thank You
-Given: 702
-Receive: 1803



« Reply #1 on: June 21, 2025, 10:25:37 10:25 »

Hi,

I've added your question to Google Gemini 2.5 PRO AI and here is what it came up with:

Code:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ESP32 CAN Bus Monitor</title>
    <!-- Using Tailwind CSS for modern, responsive styling -->
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&family=Roboto+Mono:wght@400;700&display=swap" rel="stylesheet">
    <style>
        /* Using the Inter font for general text and Roboto Mono for data values */
        body {
            font-family: 'Inter', sans-serif;
        }
        .data-value {
            font-family: 'Roboto Mono', monospace;
        }
    </style>
</head>
<body class="bg-gray-100 flex items-center justify-center min-h-screen">

    <div class="w-full max-w-2xl mx-auto p-4 md:p-6">
        
        <!-- Header -->
        <header class="text-center mb-8">
            <h1 class="text-3xl md:text-4xl font-bold text-gray-800">CAN Bus Monitor</h1>
            <p class="text-gray-600 mt-2">Live data from ESP32</p>
        </header>

        <!-- Data Display Grid -->
        <div class="bg-white rounded-xl shadow-lg p-6 space-y-6">

            <!-- Row 1: Error Counter -->
            <div class="grid grid-cols-2 items-center gap-4">
                <label for="error-counter" class="text-lg font-medium text-gray-700">Error Counter</label>
                <input
                    type="text"
                    id="error-counter"
                    value="Connecting..."
                    readonly
                    class="data-value text-xl md:text-2xl font-bold text-right bg-gray-100 border-2 border-gray-300 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-500 transition"
                >
            </div>

            <!-- Row 2: RX Counter -->
            <div class="grid grid-cols-2 items-center gap-4">
                <label for="rx-counter" class="text-lg font-medium text-gray-700">RX Counter</label>
                <input
                    type="text"
                    id="rx-counter"
                    value="Connecting..."
                    readonly
                    class="data-value text-xl md:text-2xl font-bold text-right bg-gray-100 border-2 border-gray-300 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-500 transition"
                >
            </div>

            <!-- Row 3: Error Frame Counter -->
            <div class="grid grid-cols-2 items-center gap-4">
                <label for="frame-counter" class="text-lg font-medium text-gray-700">Error Frame Counter</label>
                <input
                    type="text"
                    id="frame-counter"
                    value="Connecting..."
                    readonly
                    class="data-value text-xl md:text-2xl font-bold text-right bg-gray-100 border-2 border-gray-300 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-500 transition"
                >
            </div>
        </div>

        <!-- Informational Text -->
        <div class="text-center mt-8 text-gray-600">
            <p>A low error count is normal.</p>
            <p>The count should ideally remain below 128.</p>
        </div>

    </div>

    <!-------------------------------------JavaScript--------------------------------------->
    <script>
        /**
         * This is the main function that sets up the WebSocket connection.
         * A WebSocket is a persistent, two-way communication channel between this web browser
         * and the ESP32 server. It allows the ESP32 to push data to the webpage instantly.
         */
        function InitWebSocket() {
            // 'window.location.hostname' gets the IP address or hostname from the browser's address bar.
            // When you connect to your ESP32 (e.g., at http://192.168.1.100), this will be "192.168.1.100".
            const hostname = window.location.hostname;

            // --- SAFETY CHECK ---
            // Sometimes, the hostname might be empty (e.g., when opening the file directly on a computer).
            // An empty hostname would create an invalid WebSocket URL and cause an error.
            // This 'if' statement checks if the hostname is valid before proceeding.
            if (!hostname) {
                // Log an error to the browser's developer console (press F12 to see it).
                console.error("Connection failed: Hostname is not available.");
                // Update the user interface to show that the connection failed.
                const errorMsg = "Conn. Failed";
                document.getElementById('error-counter').value = errorMsg;
                document.getElementById('rx-counter').value = errorMsg;
                document.getElementById('frame-counter').value = errorMsg;
                // 'return' stops the function from running any further.
                return;
            }
            
            // Construct the full WebSocket URL.
            // 'ws://' is the protocol for WebSockets, similar to 'http://'.
            // The ESP32 WebSocket server must be listening on port 81 for this to work.
            const wsUrl = `ws://${hostname}:81/`;
            console.log(`Attempting to connect to: ${wsUrl}`);

            // This line creates a new WebSocket object and tells it to connect to the ESP32 server.
            const websock = new WebSocket(wsUrl);

            /**
             * --- EVENT LISTENERS ---
             * These functions define what happens when different WebSocket events occur.
             */

            /**
             * 'onmessage' is triggered every time the ESP32 server sends a message to this webpage.
             * This is where we receive and display the CAN bus data.
             * 'evt' is an event object that contains the data sent by the server.
             */
            websock.onmessage = function(evt) {
                // The data from the server arrives as a string in JSON format (e.g., '{"ER":5,"RX":100,"EER":2}').
                // 'JSON.parse(evt.data)' converts this string into a JavaScript object, which is easier to work with.
                const JSONobj = JSON.parse(evt.data);
                
                // Now, we update the values of the input fields on the webpage.
                // 'document.getElementById()' finds an HTML element by its unique 'id'.
                // We update the '.value' property because we are working with <input> elements.

                // Find the input with id="error-counter" and set its value.
                const errorCounterElement = document.getElementById('error-counter');
                if (errorCounterElement) {
                    errorCounterElement.value = JSONobj.ER; // Get the value for the key "ER" from the JSON object.
                }

                // Find the input with id="rx-counter" and set its value.
                const rxCounterElement = document.getElementById('rx-counter');
                if (rxCounterElement) {
                    rxCounterElement.value = JSONobj.RX; // Get the value for the key "RX".
                }

                // Find the input with id="frame-counter" and set its value.
                const frameCounterElement = document.getElementById('frame-counter');
                if (frameCounterElement) {
                    frameCounterElement.value = JSONobj.EER; // Get the value for the key "EER".
                }
            };

            /**
             * 'onopen' is triggered once the WebSocket connection is successfully established.
             * It's useful for debugging to confirm the connection worked.
             */
            websock.onopen = function(evt) {
                console.log('Connection opened');
            };

            /**
             * 'onclose' is triggered if the connection is closed for any reason
             * (e.g., the ESP32 restarts, or the network is lost).
             */
            websock.onclose = function(evt) {
                console.log('Connection closed');
                // Update the UI to let the user know they are no longer receiving live data.
                const disconnectedMsg = "Disconnected";
                document.getElementById('error-counter').value = disconnectedMsg;
                document.getElementById('rx-counter').value = disconnectedMsg;
                document.getElementById('frame-counter').value = disconnectedMsg;
            };

            /**
             * 'onerror' is triggered if there is a communication error.
             */
            websock.onerror = function(evt) {
                console.error('WebSocket error:', evt);
                // Update the UI to show that an error occurred.
                const errorMsg = "WS Error";
                document.getElementById('error-counter').value = errorMsg;
                document.getElementById('rx-counter').value = errorMsg;
                document.getElementById('frame-counter').value = errorMsg;
            };
        }

        /**
         * This is a crucial line. It tells the browser to wait until the entire HTML
         * page has been loaded and is ready before it tries to run our InitWebSocket function.
         * If we tried to run it immediately, 'document.getElementById(...)' might fail because
         * the HTML elements wouldn't exist yet.
         */
        document.addEventListener('DOMContentLoaded', InitWebSocket);

    </script>
</body>
</html>


The result looks like this:




And the explanation of what it did to fix your code:

Quote
The issue in your "new layout" is that the JavaScript is trying to update elements by an id that doesn't exist or is on the wrong element. You're trying to update the text inside a table cell (<td>) when you should be updating the value of the text box (<input>).

I've created a clean, modernized version of your CAN bus monitor page. This new code combines the layout you wanted with the working WebSocket logic from your original file. It's built to be responsive, easy to read, and simple to modify.

I've made the following key changes to fix your layout and make it more robust:

    - Correct JavaScript Targeting: The main issue is fixed. The JavaScript now correctly targets each <input> field by its unique id (error-counter, rx-counter, frame-counter) and updates its value.
    - Modern HTML & CSS: The code uses Tailwind CSS for a clean, responsive design that looks great on both mobile phones and desktop browsers. The layout is managed with a CSS Grid, which is more flexible than tables for this purpose.
    - Readability: I've cleaned up the structure, removed redundant tags, and added comments to both the HTML and JavaScript to explain what each part does.
    - User Experience: The input fields are set to readonly since they are for display only. I've also added a "Connecting..." message so you know the page is waiting for data.

The HTML and JavaScript code in the canvas is designed specifically to work with an ESP32.

Here’s a simple breakdown of how it all fits together:

    1. Your ESP32's Role (The Server): You will program your ESP32 using the Arduino IDE or a similar tool. Your C++/Arduino code needs to do three things:
        - Act as a Web Server: It will store this HTML file in its memory (usually in SPIFFS or LittleFS) and send it to any web browser that connects to the ESP32's IP address.
        - Create a WebSocket Server: This is the critical part. The ESP32 must run a WebSocket server on port 81, just as the JavaScript expects (ws://${hostname}:81/).
        - Send Data: The ESP32 will read your CAN bus data, format it into a JSON string like {"ER":5, "RX":1234, "EER":1}, and send this string over the WebSocket connection at regular intervals.

    2. This Code's Role (The Client): The HTML file you see in the canvas is the "client-side" code. It runs entirely in the web browser on your phone or computer after being loaded from the ESP32. It listens for the JSON messages from the ESP32's WebSocket server and uses them to update the values in the text boxes.

Your next step is to write the ESP32 code that serves this file and provides the data.
« Last Edit: June 21, 2025, 10:29:16 10:29 by mars01 » Logged
Wizpic
Global Moderator
Hero Member
*****
Offline Offline

Posts: 1208

Thank You
-Given: 566
-Receive: 409



« Reply #2 on: June 21, 2025, 01:30:21 13:30 »

Thank you, I never thought about that way, I like the layout of it better than my 2 versions , so I tested it and works perfectly, I can play around with the layout and stuff like that and I also like that it shows connecting/disconnected part
Logged

When you think, "I can't do anymore. I need a break," that is the time to challenge yourself to keep going another five minutes. Those who persevere for even an extra five minutes will win in life..
Wizpic
Global Moderator
Hero Member
*****
Offline Offline

Posts: 1208

Thank You
-Given: 566
-Receive: 409



« Reply #3 on: June 21, 2025, 05:21:33 17:21 »

I've done some playing around and the only trouble it that is will be a standalone server and has no internet connection as the ESP32 is the sever that the IP connects to
When I take out this bit as this needs an internet connection I gather
Code:
 <!-- Using Tailwind CSS for modern, responsive styling -->
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&family=Roboto+Mono:wght@400;700&display=swap" rel="stylesheet">
I get the layout shown below and lose all color and formatting of the layout but evertything else works

I'll do some more playing and round with it 


Logged

When you think, "I can't do anymore. I need a break," that is the time to challenge yourself to keep going another five minutes. Those who persevere for even an extra five minutes will win in life..
mars01
V.I.P
Hero Member
*****
Offline Offline

Posts: 543

Thank You
-Given: 702
-Receive: 1803



« Reply #4 on: June 22, 2025, 01:41:12 01:41 »

Hi,

From Google Gemini:

"I have refactored the code to be completely self-contained. All the styling that was previously handled by Tailwind CSS has been recreated using standard, inline CSS within a <style> block in the <head> of the document. This means the file has no external dependencies and will render correctly when served from your ESP32, even when it's completely offline.

The layout and functionality remain the same, but it's now a single, portable file."

The new code:
Code:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ESP32 CAN Bus Monitor</title>
   
    <!--
      All styling is now included directly in this HTML file.
      No external resources are needed, making this perfect for an offline ESP32.
    -->
    <style>
        /* A simple CSS reset to ensure consistent styling across browsers */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        /* Use common system fonts that are available on almost any device */
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
            background-color: #f1f5f9; /* A light gray background, similar to Tailwind's gray-100 */
            color: #334155; /* A dark gray for text */
           
            /* Flexbox properties to center the content on the page */
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 1rem; /* Add some padding for smaller screens */
        }

        /* The main container for all content */
        .main-container {
            width: 100%;
            max-width: 600px; /* Limit the max width on larger screens */
        }

        /* Header styling */
        header {
            text-align: center;
            margin-bottom: 2rem;
        }

        h1 {
            font-size: 2.25rem; /* 36px */
            font-weight: 700;
            color: #1e293b; /* A darker text color for the title */
        }

        header p {
            margin-top: 0.5rem;
            color: #64748b; /* A lighter gray for the subtitle */
        }

        /* The white card that holds the data fields */
        .data-card {
            background-color: #ffffff;
            border-radius: 0.75rem; /* Rounded corners */
            padding: 1.5rem;
            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* A nice shadow effect */
        }
       
        /* Each row containing a label and an input field */
        .data-row {
            display: grid;
            grid-template-columns: 1fr 1fr; /* Create a two-column layout */
            gap: 1rem; /* Space between the columns */
            align-items: center;
        }

        /* Add space between each row, but not after the last one */
        .data-row:not(:last-child) {
            margin-bottom: 1.5rem;
        }
       
        /* Styling for the text labels (e.g., "Error Counter") */
        .data-label {
            font-size: 1.125rem; /* 18px */
            font-weight: 500;
        }

        /* Styling for the data input fields */
        .data-input {
            font-family: "Courier New", Courier, monospace; /* Use a common monospace font for data */
            font-size: 1.5rem; /* 24px */
            font-weight: 700;
            text-align: right;
            padding: 0.75rem;
            background-color: #f1f5f9; /* Light gray background */
            border: 1px solid #cbd5e1; /* A light gray border */
            border-radius: 0.5rem; /* Rounded corners */
            color: #1e293b;
            width: 100%; /* Make the input fill its column */
        }
       
        /* The informational text at the bottom */
        .info-text {
            text-align: center;
            margin-top: 2rem;
            color: #64748b;
            font-size: 0.875rem; /* 14px */
        }

    </style>
</head>
<body>

    <div class="main-container">
       
        <!-- Header -->
        <header>
            <h1>CAN Bus Monitor</h1>
            <p>Live data from ESP32</p>
        </header>

        <!-- Data Display Card -->
        <div class="data-card">

            <!-- Row 1: Error Counter -->
            <div class="data-row">
                <label for="error-counter" class="data-label">Error Counter</label>
                <input type="text" id="error-counter" value="Connecting..." readonly class="data-input">
            </div>

            <!-- Row 2: RX Counter -->
            <div class="data-row">
                <label for="rx-counter" class="data-label">RX Counter</label>
                <input type="text" id="rx-counter" value="Connecting..." readonly class="data-input">
            </div>

            <!-- Row 3: Error Frame Counter -->
            <div class="data-row">
                <label for="frame-counter" class="data-label">Error Frame Counter</label>
                <input type="text" id="frame-counter" value="Connecting..." readonly class="data-input">
            </div>
        </div>

        <!-- Informational Text -->
        <div class="info-text">
            <p>A low error count is normal. The count should ideally remain below 128.</p>
        </div>

    </div>

    <!-------------------------------------JavaScript--------------------------------------->
    <script>
        /**
         * This is the main function that sets up the WebSocket connection.
         * A WebSocket is a persistent, two-way communication channel between this web browser
         * and the ESP32 server. It allows the ESP32 to push data to the webpage instantly.
         */
        function InitWebSocket() {
            // 'window.location.hostname' gets the IP address or hostname from the browser's address bar.
            // When you connect to your ESP32 (e.g., at http://192.168.1.100), this will be "192.168.1.100".
            const hostname = window.location.hostname;

            // --- SAFETY CHECK ---
            // Sometimes, the hostname might be empty (e.g., when opening the file directly on a computer).
            // An empty hostname would create an invalid WebSocket URL and cause an error.
            // This 'if' statement checks if the hostname is valid before proceeding.
            if (!hostname) {
                // Log an error to the browser's developer console (press F12 to see it).
                console.error("Connection failed: Hostname is not available.");
                // Update the user interface to show that the connection failed.
                const errorMsg = "Conn. Failed";
                document.getElementById('error-counter').value = errorMsg;
                document.getElementById('rx-counter').value = errorMsg;
                document.getElementById('frame-counter').value = errorMsg;
                // 'return' stops the function from running any further.
                return;
            }
           
            // Construct the full WebSocket URL.
            // 'ws://' is the protocol for WebSockets, similar to 'http://'.
            // The ESP32 WebSocket server must be listening on port 81 for this to work.
            const wsUrl = `ws://${hostname}:81/`;
            console.log(`Attempting to connect to: ${wsUrl}`);

            // This line creates a new WebSocket object and tells it to connect to the ESP32 server.
            const websock = new WebSocket(wsUrl);

            /**
             * --- EVENT LISTENERS ---
             * These functions define what happens when different WebSocket events occur.
             */

            /**
             * 'onmessage' is triggered every time the ESP32 server sends a message to this webpage.
             * This is where we receive and display the CAN bus data.
             * 'evt' is an event object that contains the data sent by the server.
             */
            websock.onmessage = function(evt) {
                // The data from the server arrives as a string in JSON format (e.g., '{"ER":5,"RX":100,"EER":2}').
                // 'JSON.parse(evt.data)' converts this string into a JavaScript object, which is easier to work with.
                const JSONobj = JSON.parse(evt.data);
               
                // Now, we update the values of the input fields on the webpage.
                // 'document.getElementById()' finds an HTML element by its unique 'id'.
                // We update the '.value' property because we are working with <input> elements.

                // Find the input with id="error-counter" and set its value.
                const errorCounterElement = document.getElementById('error-counter');
                if (errorCounterElement) {
                    errorCounterElement.value = JSONobj.ER; // Get the value for the key "ER" from the JSON object.
                }

                // Find the input with id="rx-counter" and set its value.
                const rxCounterElement = document.getElementById('rx-counter');
                if (rxCounterElement) {
                    rxCounterElement.value = JSONobj.RX; // Get the value for the key "RX".
                }

                // Find the input with id="frame-counter" and set its value.
                const frameCounterElement = document.getElementById('frame-counter');
                if (frameCounterElement) {
                    frameCounterElement.value = JSONobj.EER; // Get the value for the key "EER".
                }
            };

            /**
             * 'onopen' is triggered once the WebSocket connection is successfully established.
             * It's useful for debugging to confirm the connection worked.
             */
            websock.onopen = function(evt) {
                console.log('Connection opened');
            };

            /**
             * 'onclose' is triggered if the connection is closed for any reason
             * (e.g., the ESP32 restarts, or the network is lost).
             * We can try to reconnect after a short delay.
             */
            websock.onclose = function(evt) {
                console.log('Connection closed. Retrying in 3 seconds...');
                // Update the UI to let the user know they are no longer receiving live data.
                const disconnectedMsg = "Disconnected";
                document.getElementById('error-counter').value = disconnectedMsg;
                document.getElementById('rx-counter').value = disconnectedMsg;
                document.getElementById('frame-counter').value = disconnectedMsg;
                // Attempt to reconnect after 3 seconds
                setTimeout(InitWebSocket, 3000);
            };

            /**
             * 'onerror' is triggered if there is a communication error.
             */
            websock.onerror = function(evt) {
                console.error('WebSocket error:', evt);
                // Update the UI to show that an error occurred.
                const errorMsg = "WS Error";
                document.getElementById('error-counter').value = errorMsg;
                document.getElementById('rx-counter').value = errorMsg;
                document.getElementById('frame-counter').value = errorMsg;
            };
        }

        /**
         * This is a crucial line. It tells the browser to wait until the entire HTML
         * page has been loaded and is ready before it tries to run our InitWebSocket function.
         * If we tried to run it immediately, 'document.getElementById(...)' might fail because
         * the HTML elements wouldn't exist yet.
         */
        document.addEventListener('DOMContentLoaded', InitWebSocket);

    </script>
</body>
</html>

And the result looks like this:

Logged
Wizpic
Global Moderator
Hero Member
*****
Offline Offline

Posts: 1208

Thank You
-Given: 566
-Receive: 409



« Reply #5 on: June 22, 2025, 08:34:15 08:34 »

Thanks that’s perfectly working, I’ll have to have a look into this Google Gemini thing technology today is surprising good
Logged

When you think, "I can't do anymore. I need a break," that is the time to challenge yourself to keep going another five minutes. Those who persevere for even an extra five minutes will win in life..
mars01
V.I.P
Hero Member
*****
Offline Offline

Posts: 543

Thank You
-Given: 702
-Receive: 1803



« Reply #6 on: June 22, 2025, 11:07:31 11:07 »

The result depends on the prompt. You need to be thorough.
If you want to use Gemini Pro for free (with some limits) you need to have a GMAIL account. You can log in with the gmail account in Google AI Studio here:

https://aistudio.google.com/prompts/new_chat

I advice you to use a Temperature parameter of 0.7 and limit the amount of tokens for Thinking mode.
Logged
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright © 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC