Week 12: Networking

Welcome to N-n-n-n-NETWORKING week.

For Networking my idea was to use the touch capacitive component change the color of the circle on my website remotely! So anywhere any time i can touch the device and it changes the color of the circle for ANYONE viewing my website! (I also added a button to the top of my website to simulate this :p)

Here's a video of the final product in action:

And here's how the networking feature appears on every page of this website:

Network feature screenshot

I worked with Kye to program an ESP32 C6 microcontroller to make HTTP POST requests to a web server. The code below shows how we implemented the touch sensing and networking functionality:


        #include 
            #include 
            
            #define SENSE_PIN 2      // Pin used for analog input reading (sensor pin)
            #define LED_PIN 17       // Pin used to control an LED based on sensor data
            #define SOUND_PIN 16     // Pin used for sound output (buzzer or speaker)
            #define SETTLE 5         // Delay time (not used in this version of the code)
            #define N_SAMPLES 256    // Number of samples to take for averaging the sensor readings
            #define THRESHOLD 180000 // The threshold to trigger the LED and sound
            
            #define STASSID "MIT" // Replace with your WiFi SSID
            #define STAPSK "******"  // Replace with your WiFi password
            #define URL "https://postreqtest.glitch.me/update-value"
            
            
            
            void setup() {
              // Initialize the serial communication at 115200 baud rate for debugging or output
               Serial.begin(115200);
            
                Serial.println();
                Serial.println();
                Serial.println();
            
                WiFi.begin(STASSID, STAPSK);
            
                while (WiFi.status() != WL_CONNECTED) {
                  delay(500);
                  Serial.print(".");
                }
                Serial.println("");
                Serial.print("Connected! IP address: ");
                Serial.println(WiFi.localIP());
            
              // Set the analog reading resolution to 10 bits (0-1023 range)
              analogReadResolution(10);  
            
              // Set the LED pin and sound pin as output pins
              pinMode(LED_PIN, OUTPUT);
              pinMode(SOUND_PIN, OUTPUT);
            }
            
            void loop() {
              // Initialize count as a 64-bit integer to accumulate the sensor readings
              int64_t count = 0;
            
              // Loop to take N_SAMPLES (256) analog readings from the sensor pin
              for (int i = 0; i < N_SAMPLES; ++i) {
                // Set the sense pin to output, then drive it HIGH
                pinMode(SENSE_PIN, OUTPUT); 
                digitalWrite(SENSE_PIN, HIGH);  // Drive the pin high to charge any capacitance on the pin
            
                // Change the sense pin back to input, so it can read the analog signal
                pinMode(SENSE_PIN, INPUT);
            
                // Read the analog value from the sensor pin and add it to the count
                count += analogRead(SENSE_PIN); 
              }
            
              // Check if the accumulated count from sensor readings exceeds the threshold
              if (count > THRESHOLD) {  // If count exceeds 180,000 (a threshold for sensor readings)
                // If threshold is surpassed, turn on the LED
            
                 if ((WiFi.status() == WL_CONNECTED)) {
            
                HTTPClient http;
            
                Serial.print("[HTTP] begin...\n");
                // configure target server and URL
                http.begin(URL);
                http.addHeader("Content-Type", "application/json");
            
                Serial.print("[HTTP] POST...\n");
            
                // Prepare JSON payload
                String payload = "{\"value\": 1}";
            
                // start connection and send HTTP header and body
                int httpCode = http.POST(payload);
            
                // httpCode will be negative on error
                if (httpCode > 0) {
                  // HTTP header has been sent and Server response header has been handled
                  Serial.printf("[HTTP] POST... code: %d\n", httpCode);
            
                  // file found at server
                  if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_CREATED) {
                    const String& response = http.getString();
                    Serial.println("Received response:\n<<");
                    Serial.println(response);
                    Serial.println(">>");
                  }
                } else {
                  Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
                }
            
                http.end();
              }
                digitalWrite(LED_PIN, HIGH); 
                
                // Play a sound using the buzzer/speaker
                tone(SOUND_PIN, 1000);  // Play a 1000 Hz tone (you can change the frequency as needed)
            
            
               
              } else {
                // If the threshold is not surpassed, turn off the LED
                digitalWrite(LED_PIN, LOW);  
                
                // Stop playing the sound
                noTone(SOUND_PIN);  // Stop any sound that is currently playing
              }
            
            
              // Delay for 2 milliseconds before taking the next set of samples
              delay(2);  
            }
      




After consulting with Char about server implementation, I set up a server on Glitch with some help from Claude. I ran into CORS issues initially, but Kai helped me resolve them by adding CORS support using Node.js.

For the server side, I created a simple Express.js server on Glitch that listens for POST requests. The server stores the most recent value and serves it to any clients that request it. Initially, we ran into CORS issues when trying to access the server from different domains, but we resolved this by adding proper CORS middleware to the Express server.

Server Code (Node.js)


        const express = require('express');
        const bodyParser = require('body-parser');
        
        const app = express();
        const cors = require('cors');
        let currentValue = 0;
        
        app.use(bodyParser.json());
        app.use(cors());
        
        // Serve the static HTML file
        app.use(express.static('path_to_html_directory')); // Replace with the directory containing your HTML file
        
        // Endpoint to get the current value
        app.get('/get-value', (req, res) => {
            res.json({ value: currentValue });
        });
        app.use(express.static(__dirname)); // Serve files from the current directory
        
        // Endpoint to update the value
        app.post('/update-value', (req, res) => {
            if (req.body.value !== undefined) {
                currentValue = currentValue + req.body.value;
                res.status(200).send('Value updated successfully');
            } else {
                res.status(400).send('Invalid value');
            }
        });
        
        // Start the server
        app.listen(3000, () => {
            console.log('Server running on http://localhost:3000');
        });
      

Client Code (JavaScript)


       


  function windowResized() {
    resizeCanvas(windowWidth, windowHeight); // Ensure canvas resizes with window
  }

let val = 0;
let currentValue = 0;
  let circleColor;

  // p5.js setup function
  function setup() {
    let canvas = createCanvas(windowWidth, windowHeight);
    canvas.position(0, 0);
    canvas.style('z-index', '-1'); // Ensure the canvas is behind the HTML
    circleColor = color(255,255,255); // Start with red

  }

  // p5.js draw function
  function draw() {
      fill(circleColor);
      ellipse(mouseX, mouseY, 50, 50);
  }

  // Function to update the HTML content with the current value
  function updateDisplay() {

    if(val != currentValue){
      // Change circle color when value updates
      circleColor = color(
          random(255),
          random(255),
          random(255)
      );
    }
      val = currentValue;

  }

  // Listen for updates via polling mechanism
  async function pollForUpdates() {
      while (true) {
          try {
              const response = await fetch('/get-value');
              if (response.ok) {
                  const data = await response.json();
                  currentValue = data.value;
                  updateDisplay();
              }
          } catch (error) {
              console.error('Error fetching value:', error);
          }
          // Poll every 2 seconds
          await new Promise(resolve => setTimeout(resolve, 2000));
      }
  }

  // Start polling for updates
  pollForUpdates();
      

The hardware was built for my final project